1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ResourceDemo.cpp
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision: 28152 $
14  *---------------------------------------------------------------------------*/
15 
16 #define NW_DEBUG_CHECK_MEMORY_LEAK
17 
18 #include <nn/os.h>
19 #include <nn/fs.h>
20 
21 #include <nw/types.h>
22 #include <nw/demo.h>
23 #include <nw/dev.h>
24 #include <nw/gfx.h>
25 #include <nw/ut.h>
26 
27 namespace
28 {
29 
30 //----------------------------------------
31 // メモリ関係
32 
33 // デバイスメモリを確保するためのアロケータです。
34 nw::demo::DemoAllocator s_DeviceAllocator;
35 
36 //----------------------------------------
37 // リソース関係
38 nw::demo::ResourceSet* s_ShaderResource;
39 nw::demo::ResourceArray s_LutResources;
40 nw::demo::ResourceArray s_Resources;
41 
42 struct ResourceData
43 {
ResourceData__anon25f74af20111::ResourceData44     ResourceData(
45         wchar_t* modelName,
46         s32 lutIndex,
47         nw::math::VEC3 position)
48         : modelName(modelName),
49           lutIndex(lutIndex),
50           position(position)
51     {}
52 
53     const wchar_t* modelName;
54     const s32 lutIndex;
55     const nw::math::VEC3 position;
56 };
57 
58 enum LutResource
59 {
60     //! @brief 共通のLUTセットです。
61     DemoLutSet,
62 
63     //! @brief マテリアルサンプルのLUTセットです。
64     MaterialSampleLutSet
65 };
66 
67 static const wchar_t* LUT_RESOURCE_FILES[] =
68 {
69     NW_DEMO_FILE_PATH(L"Lutset.bclts"),
70     NW_DEMO_FILE_PATH(L"SampleLutset.bclts"),
71 };
72 
73 static const ResourceData MODEL_RESOURCE_DATA[] =
74 {
75     ResourceData(NW_DEMO_FILE_PATH(L"Phong.bcmdl"), DemoLutSet, nw::math::VEC3(0.0f, 0.0f, 0.0f)),
76     ResourceData(NW_DEMO_FILE_PATH(L"Blinn.bcmdl"), DemoLutSet, nw::math::VEC3(2.5f, 0.0f, 0.0f)),
77     ResourceData(NW_DEMO_FILE_PATH(L"VertexLight.bcmdl"), DemoLutSet, nw::math::VEC3(5.0f, 0.0f, 0.0f)),
78     ResourceData(NW_DEMO_FILE_PATH(L"CarPaint.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(7.5f, 0.0f, 0.0f)),
79     ResourceData(NW_DEMO_FILE_PATH(L"Sss.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(10.0f, 0.0f, 0.0f)),
80     ResourceData(NW_DEMO_FILE_PATH(L"ThinFilm.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(12.5f, 0.0f, 0.0f)),
81     ResourceData(NW_DEMO_FILE_PATH(L"Toon.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(15.0f, 0.0f, 0.0f)),
82 };
83 
84 const wchar_t* SKY_SPHERE_FILE_NAME  = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
85 
86 static const wchar_t* RESOURCE_FILES[] =
87 {
88     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
89     NW_DEMO_FILE_PATH(L"Camera.bcenv"),
90     NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
91     NW_DEMO_FILE_PATH(L"HemisphereLight.bcenv"),
92     NW_DEMO_FILE_PATH(L"VertexLight.bcenv"),
93     NW_DEMO_FILE_PATH(L"Fog.bcenv"),
94 };
95 
96 static const wchar_t* SHADER_RESOURCE_FILE_NAME = NW_DEMO_FILE_PATH(L"nwgfx_DefaultShader.bcsdr");
97 
98 //----------------------------------------
99 // 描画関係
100 const int RENDER_TARGET_COUNT = 1;
101 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
102 
103 RenderTargetArray s_RenderTargets;
104 nw::demo::SceneSystem*  s_SceneSystem = NULL;
105 nw::demo::RenderSystem* s_RenderSystem = NULL;
106 
107 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
108 
109 //----------------------------------------
110 // シーン関係
111 const int SCENE_NODE_COUNT = 16;
112 nw::gfx::SceneNode* s_SceneRoot = NULL;
113 s32 s_FrameCount = 0;
114 nw::gfx::Camera* s_BaseCamera = NULL;
115 nw::gfx::Camera* s_LeftCamera = NULL;
116 nw::gfx::Camera* s_RightCamera = NULL;
117 const f32 s_fNearPlane = 0.1f;
118 
119 //----------------------------------------
120 // シーン環境関係
121 const int ENVIRONMENT_SETTINGS_COUNT = 1;
122 
123 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
124 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
125 
126 const s32 s_BaseCameraIndex = 0;
127 
128 /*!--------------------------------------------------------------------------*
129   @brief        グラフィックス関連の初期化を行います。
130  *---------------------------------------------------------------------------*/
131 void
InitializeGraphics()132 InitializeGraphics()
133 {
134     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
135 
136     // renderDescriptionへステレオの設定を行います。
137     nw::demo::RenderSystem::Description renderDescription;
138 
139     renderDescription.reusableCommandBufferSize = 0x100000;
140     renderDescription.reusableCommandRequestCount      = 512;
141     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
142 
143     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
144 
145     s_GraphicsDrawing.SetScreenSize(
146         renderDescription.lowerScreenDescription.width,
147         renderDescription.lowerScreenDescription.height
148     );
149 
150     nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
151 
152     s_RenderTargets.push_back(
153         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
154     );
155     NW_ASSERT(!s_RenderTargets.empty());
156     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
157 
158     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
159     nw::demo::SceneSystem::Description sceneDescription;
160     sceneDescription.isFixedSizeMemory = true;
161     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
162 
163     // ファイルからシェーダリソースを読み込みます。
164     // シェーダの作り方は CreativeStudio の シェーダクリエーションパネルの説明を参照してください。
165     s_ShaderResource = s_DeviceAllocator.AllocAndConstruct<nw::demo::ResourceSet>(1);
166     s_ShaderResource->buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , SHADER_RESOURCE_FILE_NAME);
167 
168     NW_NULL_ASSERT(s_ShaderResource->buffer);
169 
170     s_ShaderResource->resource = nw::gfx::ResGraphicsFile(&(s_ShaderResource->buffer.front()));
171 
172     // デモ用の最遠景モデルをレンダリングシステムに設定します。
173     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
174     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
175 
176     NW_GL_ASSERT();
177 }
178 
179 /*!--------------------------------------------------------------------------*
180   @brief        グラフィックス関連の後始末をします。
181  *---------------------------------------------------------------------------*/
182 void
TerminateGraphics()183 TerminateGraphics()
184 {
185     s_DeviceAllocator.DestructAndFree(s_ShaderResource, 1);
186 
187     nw::gfx::SafeDestroy(s_LeftCamera);
188 
189     nw::gfx::SafeDestroy(s_RightCamera);
190 
191     nw::gfx::SafeDestroy(s_SceneSystem);
192 
193     nw::gfx::SafeDestroyAll(s_RenderTargets);
194 
195     s_GraphicsDrawing.Finalize();
196 
197     nw::gfx::SafeDestroy(s_RenderSystem);
198 
199     NW_GL_ASSERT();
200 }
201 
202 /*!--------------------------------------------------------------------------*
203   @brief        ルートノード関連の構築をします。
204  *---------------------------------------------------------------------------*/
205 void
BuildRootNodes()206 BuildRootNodes()
207 {
208     NW_ASSERT(s_SceneRoot == NULL);
209     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
210         .MaxChildren(16)
211         .Create(&s_DeviceAllocator);
212     NW_NULL_ASSERT(s_SceneRoot);
213 }
214 
215 /*!--------------------------------------------------------------------------*
216   @brief        カメラ関連の構築をします。
217  *---------------------------------------------------------------------------*/
218 void
BuildCameras()219 BuildCameras()
220 {
221     s_LeftCamera =
222         nw::gfx::Camera::DynamicBuilder()
223         .MaxChildren(0)
224         .MaxCallbacks(0)
225         .Create(&s_DeviceAllocator);
226 
227     NW_POINTER_ASSERT(s_LeftCamera);
228 
229     s_RightCamera =
230         nw::gfx::Camera::DynamicBuilder()
231         .MaxChildren(0)
232         .MaxCallbacks(0)
233         .Create(&s_DeviceAllocator);
234 
235     NW_POINTER_ASSERT(s_RightCamera);
236 
237     s_BaseCamera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin());
238     s_SceneRoot->AttachChild(s_BaseCamera);
239     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
240 }
241 
242 /*!--------------------------------------------------------------------------*
243   @brief        シーンを初期化します。
244  *---------------------------------------------------------------------------*/
245 void
InitializeScenes()246 InitializeScenes()
247 {
248     BuildRootNodes();
249 
250     // ファイルから LUT Set を読み込みます。
251     NW_FOREACH(const wchar_t* name, LUT_RESOURCE_FILES)
252     {
253         nw::demo::ResourceSet resourceSet;
254         resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , name);
255 
256         NW_NULL_ASSERT(resourceSet.buffer);
257 
258         resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
259 
260         s_LutResources.push_back(resourceSet);
261     }
262 
263     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
264 
265     // モデルリソースを読み込みます。
266     NW_FOREACH(const ResourceData resourceData, MODEL_RESOURCE_DATA)
267     {
268         nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, resourceData.modelName, &s_DeviceAllocator);
269 
270         resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
271         resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
272         resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
273 
274         nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
275         if (result.IsFailure())
276         {
277             if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_SHADER)
278             {
279                 // シェーダーが見つからなかったときは、外部ファイルを指定して再びセットアップします。
280                 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_ShaderResource->resource);
281             }
282 
283             if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_LUT)
284             {
285                 // 参照テーブルが見つからなかったときは、外部ファイルを指定して再びセットアップします。
286                 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_LutResources[resourceData.lutIndex].resource);
287             }
288 
289             if (result.IsFailure())
290             {
291                 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
292             }
293         }
294 
295         nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
296         nw::gfx::ResModelArray::iterator modelsEnd = models.end();
297         for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
298              modelResource != modelsEnd; ++modelResource)
299         {
300             nw::math::VEC3& translate = (*modelResource).GetTransform().translate;
301             translate += resourceData.position;
302 
303             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
304                 &s_DeviceAllocator,
305                 (*modelResource),
306                 false
307             );
308             NW_NULL_ASSERT(node);
309             sceneNodeArray.push_back(node);
310         }
311     }
312 
313     // モデル以外のリソースを読み込みます。
314     NW_FOREACH(const wchar_t* name, RESOURCE_FILES)
315     {
316         nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator);
317 
318         nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
319         if (result.IsFailure())
320         {
321             NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
322         }
323 
324         nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
325         nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
326         for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
327              lightResource != lightsEnd; ++lightResource)
328         {
329             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
330                 &s_DeviceAllocator,
331                 (*lightResource)
332             );
333             NW_NULL_ASSERT(node);
334             sceneNodeArray.push_back(node);
335         }
336 
337         nw::gfx::ResCameraArray cameras = resourceSet->resource.GetCameras();
338         nw::gfx::ResCameraArray::iterator camerasEnd = cameras.end();
339         for (nw::gfx::ResCameraArray::iterator cameraResource = cameras.begin();
340              cameraResource != camerasEnd; ++cameraResource)
341         {
342             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
343                 &s_DeviceAllocator,
344                 (*cameraResource)
345             );
346             NW_NULL_ASSERT(node);
347             sceneNodeArray.push_back(node);
348         }
349 
350         nw::gfx::ResFogArray fogs = resourceSet->resource.GetFogs();
351         nw::gfx::ResFogArray::iterator fogsEnd = fogs.end();
352         for (nw::gfx::ResFogArray::iterator fogResource = fogs.begin();
353              fogResource != fogsEnd; ++fogResource)
354         {
355             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
356                 &s_DeviceAllocator,
357                 (*fogResource)
358             );
359             NW_NULL_ASSERT(node);
360             sceneNodeArray.push_back(node);
361         }
362 
363         nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
364         nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
365         for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
366             settingResource != settingsEnd; ++settingResource)
367         {
368             nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
369                 .Resource(*settingResource)
370                 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
371 
372             nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
373                 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
374 
375             NW_NULL_ASSERT(sceneEnvironmentSetting);
376             s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
377         }
378     }
379 
380     // 親子付け参照関係を解決
381     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
382 
383     // モデルをシーンに追加
384     nw::gfx::SceneHelper::ForeachRootNodes(
385         sceneNodeArray.Begin(),
386         sceneNodeArray.End(),
387         nw::gfx::AttachNode(s_SceneRoot)
388     );
389 
390     // シーンツリーを巡回して初期化を行います。
391     s_SceneSystem->InitializeScene(s_SceneRoot);
392 
393     BuildCameras();
394 
395     // シーン環境の参照解決を行い設定します。
396     s_RenderSystem->SetSceneEnvironmentSettings(
397         s_SceneSystem,
398         &s_SceneEnvironmentSettings);
399 
400     s_SceneSystem->UpdateScene();
401 
402     NW_GL_ASSERT();
403 
404     //-----------------------------------------------------------------------------
405 
406     s_FrameCount = 0;
407 }
408 
409 /*!--------------------------------------------------------------------------*
410   @brief        シーン関連の後始末をします。
411  *---------------------------------------------------------------------------*/
412 void
TerminateScenes()413 TerminateScenes()
414 {
415     nw::gfx::SafeDestroyBranch(s_SceneRoot);
416     nw::demo::SafeCleanupResources(s_Resources);
417     nw::demo::SafeCleanupResources(s_LutResources);
418     nw::ut::SafeCleanup(s_ShaderResource->resource);
419     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
420 
421     NW_GL_ASSERT();
422 
423     s_Resources.clear();
424     s_LutResources.clear();
425     s_SceneEnvironmentSettings.clear();
426 }
427 
428 /*!--------------------------------------------------------------------------*
429   @brief        シーンを更新します。
430  *---------------------------------------------------------------------------*/
431 void
UpdateScene()432 UpdateScene()
433 {
434     s_SceneSystem->GetCameraController()->Update();
435 
436     s_SceneSystem->UpdateScene();
437 
438     s_BaseCamera->UpdateCameraMatrix();
439 
440     s_RenderSystem->CalcStereoCamera(
441         s_LeftCamera,
442         s_RightCamera,
443         *(s_SceneSystem->GetSceneContext()->GetCameraBegin()),
444         s_fNearPlane + 5.0f
445     );
446 
447     ++s_FrameCount;
448 }
449 
450 /*!--------------------------------------------------------------------------*
451   @brief        負荷表示やテスト機能の処理をおこないます。
452  *---------------------------------------------------------------------------*/
453 void
ReportDemo()454 ReportDemo()
455 {
456     NW_PROFILE("ReportDemo");
457 
458     // 負荷表示からはこれらの負荷は除きます。
459     s_RenderSystem->SuspendLoadMeter();
460 
461     nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
462 
463     s_GraphicsDrawing.BeginDrawingShape();
464 
465     nw::demo::DebugUtility::DrawLoadMeter(
466         s_RenderSystem,
467         &s_GraphicsDrawing
468     );
469 
470     s_GraphicsDrawing.EndDrawingShape();
471 
472     s_GraphicsDrawing.BeginDrawingString();
473 
474     nw::demo::DebugUtility::DrawLoadMeterText(
475         s_RenderSystem,
476         &s_GraphicsDrawing
477     );
478 
479     s_GraphicsDrawing.EndDrawingString();
480 
481     s_RenderSystem->ResumeLoadMeter();
482 }
483 
484 /*!--------------------------------------------------------------------------*
485   @brief        シーンをデモンストレーションします。
486  *---------------------------------------------------------------------------*/
487 void
DemoScene()488 DemoScene()
489 {
490     NW_ASSERT(!s_RenderTargets.empty());
491 
492     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
493 
494     InitializeScenes();
495 
496     nw::demo::DebugUtility::PostInitializeScenes();
497     nw::gfx::Camera* camera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin());
498     nw::demo::Utility::SetCameraAspectRatio(camera, s_RenderTargets[0]);
499 
500     bool isContinuing = true;
501 
502     while ( isContinuing )
503     {
504         nw::demo::DebugUtility::AdvanceAutoTestFrame();
505 
506         nw::demo::PadFactory::GetPad()->Update();
507 
508         UpdateScene();
509 
510         renderContext->SetActiveCamera(s_BaseCameraIndex);
511         s_RenderSystem->SubmitView(s_SceneSystem);
512 
513         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
514         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
515 
516         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
517         ReportDemo();
518         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
519 
520         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
521 
522         renderContext->ResetState();
523 
524         if (nw::demo::Utility::IsTerminating())
525         {
526             isContinuing = false;
527         }
528     }
529 
530     nw::demo::DebugUtility::PreTerminateScenes();
531 
532     TerminateScenes();
533 }
534 
535 } // namespace
536 
537 /*!--------------------------------------------------------------------------*
538   @brief        メイン関数です。
539  *---------------------------------------------------------------------------*/
540 void
nnMain()541 nnMain()
542 {
543     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
544 
545     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
546 
547     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
548     {
549         InitializeGraphics();
550 
551         DemoScene();
552 
553         TerminateGraphics();
554     }
555 
556     nw::demo::PadFactory::Finalize();
557 
558     nw::demo::FinalizeGraphicsSystem();
559 }
560