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