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: 25401 $
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__anon4f7e08030111::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* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
85 const wchar_t* FONT_FILE_NAME        = NW_DEMO_FILE_PATH(L"Font.bcfnt");
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 NW_LOAD_METER_INTERVAL = 60;
103 
104 //----------------------------------------
105 // 描画関係
106 const int RENDER_TARGET_COUNT = 1;
107 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
108 
109 RenderTargetArray s_RenderTargets;
110 nw::demo::SceneSystem*  s_SceneSystem = NULL;
111 nw::demo::RenderSystem* s_RenderSystem = NULL;
112 
113 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
114 
115 //----------------------------------------
116 // シーン関係
117 const int SCENE_NODE_COUNT = 16;
118 nw::gfx::SceneNode* s_SceneRoot = NULL;
119 s32 s_FrameCount = 0;
120 nw::gfx::Camera* s_BaseCamera = NULL;
121 nw::gfx::Camera* s_LeftCamera = NULL;
122 nw::gfx::Camera* s_RightCamera = NULL;
123 const f32 s_fNearPlane = 0.1f;
124 
125 //----------------------------------------
126 // シーン環境関係
127 const int ENVIRONMENT_SETTINGS_COUNT = 1;
128 
129 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
130 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
131 
132 const s32 s_BaseCameraIndex = 0;
133 
134 /*!--------------------------------------------------------------------------*
135   @brief        グラフィックス関連の初期化を行います。
136  *---------------------------------------------------------------------------*/
137 void
InitializeGraphics()138 InitializeGraphics()
139 {
140     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
141 
142     // renderDescriptionへステレオの設定を行います。
143     nw::demo::RenderSystem::Description renderDescription;
144 
145     renderDescription.reusableCommandBufferSize = 0x100000;
146     renderDescription.reusableCommandRequestCount      = 512;
147     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
148 
149     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
150 
151     s_GraphicsDrawing.SetScreenSize(
152         renderDescription.lowerScreenDescription.width,
153         renderDescription.lowerScreenDescription.height
154     );
155     bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
156 
157     NN_ASSERTMSG(result, "Fail to load Font.");
158 
159     s_RenderTargets.push_back(
160         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
161     );
162     NW_ASSERT(!s_RenderTargets.empty());
163     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
164 
165     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
166     nw::demo::SceneSystem::Description sceneDescription;
167     sceneDescription.isFixedSizeMemory = true;
168     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
169 
170     // ファイルからシェーダリソースを読み込みます。
171     // シェーダの作り方は CreativeStudio の シェーダクリエーションパネルの説明を参照してください。
172     s_ShaderResource = s_DeviceAllocator.AllocAndConstruct<nw::demo::ResourceSet>(1);
173     s_ShaderResource->buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , SHADER_RESOURCE_FILE_NAME);
174 
175     NW_NULL_ASSERT(s_ShaderResource->buffer);
176 
177     s_ShaderResource->resource = nw::gfx::ResGraphicsFile(&(s_ShaderResource->buffer.front()));
178 
179     // デモ用の最遠景モデルをレンダリングシステムに設定します。
180     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
181     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
182 
183     NW_GL_ASSERT();
184 }
185 
186 /*!--------------------------------------------------------------------------*
187   @brief        グラフィックス関連の後始末をします。
188  *---------------------------------------------------------------------------*/
189 void
TerminateGraphics()190 TerminateGraphics()
191 {
192     s_DeviceAllocator.DestructAndFree(s_ShaderResource, 1);
193 
194     nw::gfx::SafeDestroy(s_LeftCamera);
195 
196     nw::gfx::SafeDestroy(s_RightCamera);
197 
198     nw::gfx::SafeDestroy(s_SceneSystem);
199 
200     nw::gfx::SafeDestroyAll(s_RenderTargets);
201 
202     s_GraphicsDrawing.Finalize();
203 
204     nw::gfx::SafeDestroy(s_RenderSystem);
205 
206     NW_GL_ASSERT();
207 }
208 
209 /*!--------------------------------------------------------------------------*
210   @brief        ルートノード関連の構築をします。
211  *---------------------------------------------------------------------------*/
212 void
BuildRootNodes()213 BuildRootNodes()
214 {
215     NW_ASSERT(s_SceneRoot == NULL);
216     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
217         .MaxChildren(16)
218         .Create(&s_DeviceAllocator);
219     NW_NULL_ASSERT(s_SceneRoot);
220 }
221 
222 /*!--------------------------------------------------------------------------*
223   @brief        カメラ関連の構築をします。
224  *---------------------------------------------------------------------------*/
225 void
BuildCameras()226 BuildCameras()
227 {
228     s_LeftCamera =
229         nw::gfx::Camera::DynamicBuilder()
230         .MaxChildren(0)
231         .MaxCallbacks(0)
232         .Create(&s_DeviceAllocator);
233 
234     NW_POINTER_ASSERT(s_LeftCamera);
235 
236     s_RightCamera =
237         nw::gfx::Camera::DynamicBuilder()
238         .MaxChildren(0)
239         .MaxCallbacks(0)
240         .Create(&s_DeviceAllocator);
241 
242     NW_POINTER_ASSERT(s_RightCamera);
243 
244     s_BaseCamera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin());
245     s_SceneRoot->AttachChild(s_BaseCamera);
246     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
247 }
248 
249 /*!--------------------------------------------------------------------------*
250   @brief        シーンを初期化します。
251  *---------------------------------------------------------------------------*/
252 void
InitializeScenes()253 InitializeScenes()
254 {
255     BuildRootNodes();
256 
257     // ファイルから LUT Set を読み込みます。
258     NW_FOREACH(const wchar_t* name, LUT_RESOURCE_FILES)
259     {
260         nw::demo::ResourceSet resourceSet;
261         resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , name);
262 
263         NW_NULL_ASSERT(resourceSet.buffer);
264 
265         resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
266 
267         s_LutResources.push_back(resourceSet);
268     }
269 
270     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
271 
272     // モデルリソースを読み込みます。
273     NW_FOREACH(const ResourceData resourceData, MODEL_RESOURCE_DATA)
274     {
275         nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, resourceData.modelName, &s_DeviceAllocator);
276 
277         resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
278         resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
279         resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
280 
281         nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
282         if (result.IsFailure())
283         {
284             if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_SHADER)
285             {
286                 // シェーダーが見つからなかったときは、外部ファイルを指定して再びセットアップします。
287                 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_ShaderResource->resource);
288             }
289 
290             if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_LUT)
291             {
292                 // 参照テーブルが見つからなかったときは、外部ファイルを指定して再びセットアップします。
293                 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_LutResources[resourceData.lutIndex].resource);
294             }
295 
296             if (result.IsFailure())
297             {
298                 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
299             }
300         }
301 
302         nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
303         nw::gfx::ResModelArray::iterator modelsEnd = models.end();
304         for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
305              modelResource != modelsEnd; ++modelResource)
306         {
307             nw::math::VEC3& translate = (*modelResource).GetTransform().translate;
308             translate += resourceData.position;
309 
310             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
311                 &s_DeviceAllocator,
312                 (*modelResource),
313                 false
314             );
315             NW_NULL_ASSERT(node);
316             sceneNodeArray.push_back(node);
317         }
318     }
319 
320     // モデル以外のリソースを読み込みます。
321     NW_FOREACH(const wchar_t* name, RESOURCE_FILES)
322     {
323         nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator);
324 
325         nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
326         if (result.IsFailure())
327         {
328             NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
329         }
330 
331         nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
332         nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
333         for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
334              lightResource != lightsEnd; ++lightResource)
335         {
336             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
337                 &s_DeviceAllocator,
338                 (*lightResource)
339             );
340             NW_NULL_ASSERT(node);
341             sceneNodeArray.push_back(node);
342         }
343 
344         nw::gfx::ResCameraArray cameras = resourceSet->resource.GetCameras();
345         nw::gfx::ResCameraArray::iterator camerasEnd = cameras.end();
346         for (nw::gfx::ResCameraArray::iterator cameraResource = cameras.begin();
347              cameraResource != camerasEnd; ++cameraResource)
348         {
349             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
350                 &s_DeviceAllocator,
351                 (*cameraResource)
352             );
353             NW_NULL_ASSERT(node);
354             sceneNodeArray.push_back(node);
355         }
356 
357         nw::gfx::ResFogArray fogs = resourceSet->resource.GetFogs();
358         nw::gfx::ResFogArray::iterator fogsEnd = fogs.end();
359         for (nw::gfx::ResFogArray::iterator fogResource = fogs.begin();
360              fogResource != fogsEnd; ++fogResource)
361         {
362             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
363                 &s_DeviceAllocator,
364                 (*fogResource)
365             );
366             NW_NULL_ASSERT(node);
367             sceneNodeArray.push_back(node);
368         }
369 
370         nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
371         nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
372         for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
373             settingResource != settingsEnd; ++settingResource)
374         {
375             nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
376                 .Resource(*settingResource)
377                 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
378 
379             nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
380                 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
381 
382             NW_NULL_ASSERT(sceneEnvironmentSetting);
383             s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
384         }
385     }
386 
387     // 親子付け参照関係を解決
388     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
389 
390     // モデルをシーンに追加
391     nw::gfx::SceneHelper::ForeachRootNodes(
392         sceneNodeArray.Begin(),
393         sceneNodeArray.End(),
394         nw::gfx::AttachNode(s_SceneRoot)
395     );
396 
397     // シーンツリーを巡回して初期化を行います。
398     s_SceneSystem->InitializeScene(s_SceneRoot);
399 
400     BuildCameras();
401 
402     // シーン環境の参照解決を行い設定します。
403     s_RenderSystem->SetSceneEnvironmentSettings(
404         s_SceneSystem,
405         &s_SceneEnvironmentSettings);
406 
407     s_SceneSystem->UpdateScene();
408 
409     NW_GL_ASSERT();
410 
411     //-----------------------------------------------------------------------------
412 
413     s_FrameCount = 0;
414 }
415 
416 /*!--------------------------------------------------------------------------*
417   @brief        シーン関連の後始末をします。
418  *---------------------------------------------------------------------------*/
419 void
TerminateScenes()420 TerminateScenes()
421 {
422     nw::gfx::SafeDestroyBranch(s_SceneRoot);
423     nw::demo::SafeCleanupResources(s_Resources);
424     nw::demo::SafeCleanupResources(s_LutResources);
425     nw::ut::SafeCleanup(s_ShaderResource->resource);
426     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
427 
428     NW_GL_ASSERT();
429 
430     s_Resources.clear();
431     s_LutResources.clear();
432     s_SceneEnvironmentSettings.clear();
433 }
434 
435 /*!--------------------------------------------------------------------------*
436   @brief        シーンを更新します。
437  *---------------------------------------------------------------------------*/
438 void
UpdateScene()439 UpdateScene()
440 {
441     s_SceneSystem->GetCameraController()->Update();
442 
443     s_SceneSystem->UpdateScene();
444 
445     s_BaseCamera->UpdateCameraMatrix();
446 
447     s_RenderSystem->CalcStereoCamera(
448         s_LeftCamera,
449         s_RightCamera,
450         *(s_SceneSystem->GetSceneContext()->GetCameraBegin()),
451         s_fNearPlane + 5.0f
452     );
453 
454     ++s_FrameCount;
455 }
456 
457 /*!--------------------------------------------------------------------------*
458   @brief        負荷表示やテスト機能の処理をおこないます。
459  *---------------------------------------------------------------------------*/
460 void
ReportDemo()461 ReportDemo()
462 {
463     NW_PROFILE("ReportDemo");
464 
465     // 負荷表示からはこれらの負荷は除きます。
466     s_RenderSystem->SuspendLoadMeter();
467 
468     s_GraphicsDrawing.BeginDrawingString();
469 
470     nw::demo::DebugUtility::DrawLoadMeter(
471         s_RenderSystem,
472         &s_GraphicsDrawing,
473         (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
474     );
475 
476     s_GraphicsDrawing.FlushDrawing();
477 
478     s_RenderSystem->ResumeLoadMeter();
479 }
480 
481 /*!--------------------------------------------------------------------------*
482   @brief        シーンをデモンストレーションします。
483  *---------------------------------------------------------------------------*/
484 void
DemoScene()485 DemoScene()
486 {
487     NW_ASSERT(!s_RenderTargets.empty());
488 
489     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
490 
491     InitializeScenes();
492     nw::gfx::Camera* camera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin());
493     nw::demo::Utility::SetCameraAspectRatio(camera, s_RenderTargets[0]);
494 
495     bool isContinuing = true;
496 
497     while ( isContinuing )
498     {
499         nw::demo::DebugUtility::AdvanceAutoTestFrame();
500 
501         nw::demo::PadFactory::GetPad()->Update();
502 
503         UpdateScene();
504 
505         renderContext->SetActiveCamera(s_BaseCameraIndex);
506         s_RenderSystem->SubmitView(s_SceneSystem);
507 
508         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
509         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
510 
511         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
512         ReportDemo();
513         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
514 
515         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
516 
517         renderContext->ResetState();
518 
519         if (nw::demo::Utility::IsTerminating())
520         {
521             isContinuing = false;
522         }
523     }
524 
525     TerminateScenes();
526 }
527 
528 } // namespace
529 
530 /*!--------------------------------------------------------------------------*
531   @brief        メイン関数です。
532  *---------------------------------------------------------------------------*/
533 void
nnMain()534 nnMain()
535 {
536     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
537 
538     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
539 
540     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
541     {
542         InitializeGraphics();
543 
544         DemoScene();
545 
546         TerminateGraphics();
547     }
548 
549     nw::demo::PadFactory::Finalize();
550 
551     nw::demo::FinalizeGraphicsSystem();
552 }
553