1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     MultiAnimationDemo.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: 19751 $
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 
23 #include <nw/demo.h>
24 #include <nw/dev.h>
25 #include <nw/gfx.h>
26 #include <nw/ut.h>
27 #include <nw/anim.h>
28 
29 namespace
30 {
31 
32 //----------------------------------------
33 // メモリ関係
34 
35 // デバイスメモリを確保するためのアロケータです。
36 nw::demo::DemoAllocator s_DeviceAllocator;
37 
38 //----------------------------------------
39 // ファイル名の定義です。
40 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
41 const wchar_t* FONT_FILE_NAME        = NW_DEMO_FILE_PATH(L"Font.bcfnt");
42 const wchar_t* SKY_SPHERE_FILE_NAME  = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
43 
44 const wchar_t* RESOURCE_FILES[] =
45 {
46     NW_DEMO_FILE_PATH(L"MultiAnimation.bcmdl"),
47     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
48     NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
49     NW_DEMO_FILE_PATH(L"Walk.bcskla"),
50     NW_DEMO_FILE_PATH(L"MatAnim.bcmata"),
51     NW_DEMO_FILE_PATH(L"VisibilityAnim.bcmdla"),
52     NW_DEMO_FILE_PATH(L"CameraAnim.bccam"),
53     NW_DEMO_FILE_PATH(L"LightAnim.bclgt"),
54     NW_DEMO_FILE_PATH(L"LightAnim.bcenv")
55 };
56 
57 const wchar_t* LUT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"LightAnim.bcres");
58 
59 //----------------------------------------
60 // プロファイル関係
61 const int NW_LOAD_METER_INTERVAL = 60;
62 
63 //----------------------------------------
64 // 描画関係
65 const int RENDER_TARGET_COUNT = 1;
66 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
67 
68 RenderTargetArray s_RenderTargets;
69 nw::demo::SceneSystem*  s_SceneSystem = NULL;
70 nw::demo::RenderSystem* s_RenderSystem = NULL;
71 
72 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
73 
74 //----------------------------------------
75 // リソース関係
76 nw::demo::ResourceArray s_Resources;
77 nw::demo::ResourceSet* s_LutResource;
78 
79 //----------------------------------------
80 // シーン関係
81 const int SCENE_NODE_COUNT = 4;
82 nw::gfx::SceneNode* s_SceneRoot = NULL;
83 s32 s_FrameCount = 0;
84 nw::gfx::Camera* s_BaseCamera = NULL;
85 nw::gfx::Camera* s_LeftCamera = NULL;
86 nw::gfx::Camera* s_RightCamera = NULL;
87 nw::gfx::Camera* s_AnimCamera = NULL;
88 nw::gfx::Camera* s_ActiveCamera = NULL;
89 
90 const f32 s_fNearPlane = 0.1f;
91 
92 nw::gfx::SceneNode* s_SceneRootInvisible = NULL;
93 nw::gfx::SceneNode* s_SkeletalRoot = NULL;
94 nw::gfx::SceneNode* s_MaterialRoot = NULL;
95 nw::gfx::SceneNode* s_VisibilityRoot = NULL;
96 nw::gfx::SceneNode* s_CameraRoot = NULL;
97 nw::gfx::SceneNode* s_LightRoot = NULL;
98 
99 //----------------------------------------
100 // シーン環境関係
101 const s32 ENVIRONMENT_SETTINGS_COUNT = 2;
102 
103 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
104 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
105 
106 const s32 s_BaseCameraIndex = 0;
107 const s32 s_AnimCameraIndex = 1;
108 
109 //----------------------------------------
110 // アニメーション関係
111 const int MAX_ANIM_OBJECTS = 8;
112 nw::ut::FixedSizeArray<nw::gfx::AnimObject*, MAX_ANIM_OBJECTS> s_AnimObjects;
113 float s_AnimWeight0 = 0.5f;
114 float s_AnimWeight1 = 0.5f;
115 
116 s32 s_ActiveCameraIndex = s_BaseCameraIndex;
117 const int ANIMATION_RESOURCES_COUNT = 9;
118 const int ANIMATION_TARGETS_COUNT = 15;
119 
120 nw::ut::FixedSizeArray<nw::gfx::ResGraphicsFile, ANIMATION_RESOURCES_COUNT> s_ResAnims;
121 nw::ut::FixedSizeArray<nw::gfx::SceneObject*, ANIMATION_TARGETS_COUNT> s_AnimTargets;
122 
123 struct AnimBindingTable
124 {
125     const char* targetName;
126     const char* animName;
127     nw::demo::Utility::AnimationType animType;
128 };
129 
130 const AnimBindingTable ANIM_BINDING_TABLE[] =
131 {
132     { "Male", "Walk", nw::demo::Utility::SKELETAL_ANIMATION },
133     { "MatAnim", "MatAnim", nw::demo::Utility::MATERIAL_ANIMATION },
134     { "VisibilityAnim", "VisibilityAnim", nw::demo::Utility::VISIBILITY_ANIMATION },
135     { "AnimCamera", "CameraAnim", nw::demo::Utility::CAMERA_ANIMATION },
136     { "pointLight1", "pointLight1", nw::demo::Utility::LIGHT_ANIMATION },
137     { "pointLight2", "pointLight2", nw::demo::Utility::LIGHT_ANIMATION },
138     { "pointLight3", "pointLight3", nw::demo::Utility::LIGHT_ANIMATION }
139 };
140 
141 //----------------------------------------
142 // 操作関係
143 int s_AnimMode = 0;
144 
145 /*!--------------------------------------------------------------------------*
146   @brief        グラフィックス関連の初期化を行います。
147  *---------------------------------------------------------------------------*/
148 void
InitializeGraphics()149 InitializeGraphics()
150 {
151     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
152 
153     // renderDescriptionへステレオの設定を行います。
154     nw::demo::RenderSystem::Description renderDescription;
155 
156     renderDescription.reusableCommandBufferSize = 0x100000;
157     renderDescription.reusableCommandRequestCount      = 512;
158     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
159 
160     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
161 
162     s_GraphicsDrawing.SetScreenSize(
163         renderDescription.lowerScreenDescription.width,
164         renderDescription.lowerScreenDescription.height
165     );
166 
167     bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
168 
169     NN_ASSERTMSG(result, "Fail to load Font.");
170 
171     s_RenderTargets.push_back(
172         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
173     );
174     NW_ASSERT(!s_RenderTargets.empty());
175     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
176 
177     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
178     nw::demo::SceneSystem::Description sceneDescription;
179     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
180 
181     // デモ用の最遠景モデルをレンダリングシステムに設定します。
182     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
183     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
184 
185     NW_GL_ASSERT();
186 }
187 
188 /*!--------------------------------------------------------------------------*
189   @brief        グラフィックス関連の後始末をします。
190  *---------------------------------------------------------------------------*/
191 void
TerminateGraphics()192 TerminateGraphics()
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
TerminateAnim(void)213 TerminateAnim(void)
214 {
215     for (int animIdx = 0; animIdx < s_AnimObjects.Size(); ++animIdx)
216     {
217         nw::gfx::SafeDestroy(s_AnimObjects[animIdx]);
218     }
219     s_AnimObjects.clear();
220 }
221 
222 /*!--------------------------------------------------------------------------*
223   @brief        カメラを切り替えます。
224  *---------------------------------------------------------------------------*/
225 void
ChangeCamera(s32 cameraIndex)226 ChangeCamera(s32 cameraIndex)
227 {
228     s_RenderSystem->GetRenderContext()->SetActiveCamera(cameraIndex);
229 
230     s_ActiveCamera = s_RenderSystem->GetRenderContext()->GetActiveCamera();
231     s_ActiveCameraIndex = cameraIndex;
232 
233     nw::demo::Utility::SetCameraAspectRatio(s_ActiveCamera, s_RenderTargets[0]);
234 }
235 
236 /*!--------------------------------------------------------------------------*
237   @brief        ルートノード関連の構築をします。
238  *---------------------------------------------------------------------------*/
239 void
BuildRootNodes()240 BuildRootNodes()
241 {
242     NW_ASSERT(s_SceneRoot == NULL);
243     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
244         .IsFixedSizeMemory(false)
245         .Create(&s_DeviceAllocator);
246     NW_NULL_ASSERT(s_SceneRoot);
247 
248     NW_ASSERT(s_SceneRootInvisible == NULL);
249     s_SceneRootInvisible = nw::gfx::TransformNode::DynamicBuilder()
250         .IsFixedSizeMemory(false)
251         .Create(&s_DeviceAllocator);
252 
253     // 各アニメーション毎にルートノードを作成します。
254     NW_ASSERT(s_SkeletalRoot == NULL);
255     s_SkeletalRoot = nw::gfx::TransformNode::DynamicBuilder()
256         .IsFixedSizeMemory(false)
257         .Create(&s_DeviceAllocator);
258     s_SceneRootInvisible->AttachChild(s_SkeletalRoot);
259     NW_NULL_ASSERT(s_SkeletalRoot);
260 
261     NW_ASSERT(s_MaterialRoot == NULL);
262     s_MaterialRoot = nw::gfx::TransformNode::DynamicBuilder()
263         .IsFixedSizeMemory(false)
264         .Create(&s_DeviceAllocator);
265     s_SceneRootInvisible->AttachChild(s_MaterialRoot);
266     NW_NULL_ASSERT(s_MaterialRoot);
267 
268     NW_ASSERT(s_VisibilityRoot == NULL);
269     s_VisibilityRoot = nw::gfx::TransformNode::DynamicBuilder()
270         .IsFixedSizeMemory(false)
271         .Create(&s_DeviceAllocator);
272     s_SceneRootInvisible->AttachChild(s_VisibilityRoot);
273     NW_NULL_ASSERT(s_VisibilityRoot);
274 
275     NW_ASSERT(s_CameraRoot == NULL);
276     s_CameraRoot = nw::gfx::TransformNode::DynamicBuilder()
277         .IsFixedSizeMemory(false)
278         .Create(&s_DeviceAllocator);
279     s_SceneRootInvisible->AttachChild(s_CameraRoot);
280     NW_NULL_ASSERT(s_CameraRoot);
281 
282     NW_ASSERT(s_LightRoot == NULL);
283     s_LightRoot = nw::gfx::TransformNode::DynamicBuilder()
284         .IsFixedSizeMemory(false)
285         .Create(&s_DeviceAllocator);
286     s_SceneRootInvisible->AttachChild(s_LightRoot);
287     NW_NULL_ASSERT(s_LightRoot);
288 }
289 
290 /*!--------------------------------------------------------------------------*
291   @brief        カメラ関連の構築をします。
292  *---------------------------------------------------------------------------*/
293 void
BuildCameras()294 BuildCameras()
295 {
296     nw::demo::Utility::CreateStereoCameras(
297         &s_BaseCamera,
298         &s_LeftCamera,
299         &s_RightCamera,
300         &s_DeviceAllocator,
301         nw::math::VEC3(20.0f, 15.0f, 20.0f),
302         nw::math::VEC3(0.0f, 0.0f, 0.0f),
303         s_fNearPlane
304     );
305 
306     s_SceneRoot->AttachChild(s_BaseCamera);
307     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
308 }
309 
310 /*!--------------------------------------------------------------------------*
311   @brief        リソース関連の構築をします。
312  *---------------------------------------------------------------------------*/
313 void
BuildResources(nw::demo::ResourceSet * resourceSet)314 BuildResources(nw::demo::ResourceSet* resourceSet)
315 {
316     resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
317     resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
318     resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
319 
320     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
321     if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_LUT)
322     {
323         result = resourceSet->resource.Setup(&s_DeviceAllocator, s_LutResource->resource);
324     }
325     if (result.IsFailure())
326     {
327         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
328     }
329 
330     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
331 
332     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
333     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
334     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
335          modelResource != modelsEnd; ++modelResource)
336     {
337         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
338             &s_DeviceAllocator,
339             (*modelResource)
340         );
341         NW_NULL_ASSERT(node);
342         sceneNodeArray.push_back(node);
343 
344         s_AnimTargets.push_back(node);
345     }
346 
347     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
348     nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
349     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
350          lightResource != lightsEnd; ++lightResource)
351     {
352         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
353             &s_DeviceAllocator,
354             (*lightResource)
355         );
356         NW_NULL_ASSERT(node);
357         sceneNodeArray.push_back(node);
358 
359         s_AnimTargets.push_back(node);
360     }
361 
362     nw::gfx::ResCameraArray cameras = resourceSet->resource.GetCameras();
363     nw::gfx::ResCameraArray::iterator camerasEnd = cameras.end();
364     for (nw::gfx::ResCameraArray::iterator cameraResource = cameras.begin();
365          cameraResource != camerasEnd; ++cameraResource)
366     {
367         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
368             &s_DeviceAllocator,
369             (*cameraResource)
370         );
371         NW_NULL_ASSERT(node);
372         sceneNodeArray.push_back(node);
373 
374         s_AnimTargets.push_back(node);
375     }
376 
377     // 親子付け参照関係を解決
378     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
379 
380     // モデルをシーンに追加
381     nw::gfx::SceneHelper::ForeachRootNodes(
382         sceneNodeArray.Begin(),
383         sceneNodeArray.End(),
384         nw::gfx::AttachNode(s_SceneRoot)
385     );
386 
387     nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
388     nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
389     for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
390         settingResource != settingsEnd; ++settingResource)
391     {
392         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
393             .Resource(*settingResource)
394             .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
395 
396         nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
397             nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
398 
399         NW_NULL_ASSERT(sceneEnvironmentSetting);
400         s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
401     }
402 }
403 
404 /*!--------------------------------------------------------------------------*
405   @brief        アニメーション関連の構築をします。
406  *---------------------------------------------------------------------------*/
407 void
BuildAnimations()408 BuildAnimations()
409 {
410     s_AnimCamera = NULL;
411 
412     NW_FOREACH(AnimBindingTable animBindingTable, ANIM_BINDING_TABLE)
413     {
414         s_AnimObjects.PushBack(
415             nw::demo::Utility::BindAnimationByName(
416                 &s_DeviceAllocator,
417                 s_AnimTargets,
418                 s_ResAnims,
419                 animBindingTable.targetName,
420                 animBindingTable.animName,
421                 animBindingTable.animType,
422                 false)
423             );
424 
425         if (animBindingTable.animType == nw::demo::Utility::CAMERA_ANIMATION)
426         {
427             s_AnimCamera = nw::ut::DynamicCast<nw::gfx::Camera*>
428                 (nw::demo::Utility::FindObjectByName(s_AnimTargets, animBindingTable.targetName));
429         }
430     }
431 
432     NW_NULL_ASSERT(s_AnimCamera);
433 }
434 
435 /*!--------------------------------------------------------------------------*
436   @brief        指定した名前のオブジェクトを指定したシーンルートに再配置します。
437  *---------------------------------------------------------------------------*/
438 void
ReattachObjectByName(const char * name,nw::gfx::SceneNode * root)439 ReattachObjectByName(const char* name, nw::gfx::SceneNode* root)
440 {
441     nw::gfx::SceneNode* node = nw::ut::DynamicCast<nw::gfx::SceneNode*>
442         (nw::demo::Utility::FindObjectByName(s_AnimTargets, name));
443 
444     NW_NULL_ASSERT(node);
445 
446     node->GetParent()->DetachChild( node );
447     root->AttachChild( node );
448 }
449 
450 /*!--------------------------------------------------------------------------*
451   @brief        指定した名前のオブジェクトを移動します。
452  *---------------------------------------------------------------------------*/
453 void
MoveObjectByName(const char * name,f32 x,f32 y,f32 z)454 MoveObjectByName(const char* name, f32 x, f32 y, f32 z)
455 {
456     nw::gfx::TransformNode* node = nw::ut::DynamicCast<nw::gfx::TransformNode*>
457         (nw::demo::Utility::FindObjectByName(s_AnimTargets, name));
458 
459     NW_NULL_ASSERT(node);
460 
461     node->Transform().SetTranslate(x,y,z);
462 }
463 
464 /*!--------------------------------------------------------------------------*
465   @brief        オブジェクトを各シーンルートに再配置します。
466  *---------------------------------------------------------------------------*/
467 void
ReattachObjects()468 ReattachObjects()
469 {
470     // スケルタルアニメーション
471     ReattachObjectByName("Male", s_SkeletalRoot);
472     MoveObjectByName("Male", 0.0f, -8.0f, 0.0f);
473 
474     // マテリアルアニメーション
475     ReattachObjectByName("MatAnim", s_MaterialRoot);
476 
477     // ビジビリティアニメーション
478     ReattachObjectByName("VisibilityAnim", s_VisibilityRoot);
479     MoveObjectByName("VisibilityAnim", 0.0f, -8.0f, 0.0f);
480 
481     // カメラアニメーション
482     ReattachObjectByName("CameraAnim", s_CameraRoot);
483 
484     // ライトアニメーション
485     ReattachObjectByName("LightAnim", s_LightRoot);
486 }
487 
488 /*!--------------------------------------------------------------------------*
489   @brief        アニメーションを切り替えます。
490  *---------------------------------------------------------------------------*/
491 void
ToggleAnimationMode(bool isIncremental)492 ToggleAnimationMode(bool isIncremental)
493 {
494     // s_SceneRoot から取り外したシーンノードは描画されなくなります。
495     // 不可視にするためには取り外すだけで十分なのですが、
496     // 破棄などの処理を行いやすくするために、描画しないシーンノードは
497     // s_SceneRootInvisible という別のシーンルートに取り付けておきます。
498 
499     switch (s_AnimMode)
500     {
501     case 0:
502         s_SceneRoot->DetachChild(s_SkeletalRoot);
503         s_SceneRootInvisible->AttachChild(s_SkeletalRoot);
504         break;
505     case 1:
506         s_SceneRoot->DetachChild(s_MaterialRoot);
507         s_SceneRootInvisible->AttachChild(s_MaterialRoot);
508         break;
509     case 2:
510         s_SceneRoot->DetachChild(s_VisibilityRoot);
511         s_SceneRootInvisible->AttachChild(s_VisibilityRoot);
512         break;
513     case 3:
514         ChangeCamera(s_BaseCameraIndex);
515         s_SceneRoot->DetachChild(s_CameraRoot);
516         s_SceneRootInvisible->AttachChild(s_CameraRoot);
517         break;
518     case 4:
519         s_SceneRoot->DetachChild(s_LightRoot);
520         s_SceneRootInvisible->AttachChild(s_LightRoot);
521         break;
522     default:
523         NW_ASSERT(false);
524     }
525 
526     if (isIncremental)
527     {
528         s_AnimMode++;
529         if (s_AnimMode > 4)
530         {
531             s_AnimMode = 0;
532         }
533     }
534     else
535     {
536         s_AnimMode--;
537         if (s_AnimMode < 0)
538         {
539             s_AnimMode = 4;
540         }
541     }
542 
543     switch (s_AnimMode)
544     {
545     case 0:
546         s_SceneRootInvisible->DetachChild(s_SkeletalRoot);
547         s_SceneRoot->AttachChild(s_SkeletalRoot);
548         break;
549     case 1:
550         s_SceneRootInvisible->DetachChild(s_MaterialRoot);
551         s_SceneRoot->AttachChild(s_MaterialRoot);
552         break;
553     case 2:
554         s_SceneRootInvisible->DetachChild(s_VisibilityRoot);
555         s_SceneRoot->AttachChild(s_VisibilityRoot);
556         break;
557     case 3:
558         s_SceneRootInvisible->DetachChild(s_CameraRoot);
559         s_SceneRoot->AttachChild(s_CameraRoot);
560         ChangeCamera(s_AnimCameraIndex);
561         break;
562     case 4:
563         s_SceneRootInvisible->DetachChild(s_LightRoot);
564         s_SceneRoot->AttachChild(s_LightRoot);
565         break;
566     default:
567         NW_ASSERT(false);
568     }
569 
570     // シーン構造が変化したので、シーンの初期化を行います。
571     s_SceneSystem->InitializeScene(s_SceneRoot);
572 }
573 /*!--------------------------------------------------------------------------*
574   @brief        シーンを初期化します。
575  *---------------------------------------------------------------------------*/
576 void
InitializeScenes()577 InitializeScenes()
578 {
579     BuildRootNodes();
580 
581     BuildCameras();
582 
583     // LUT を持ったリソースを読み込みます。
584     s_LutResource = nw::demo::Utility::LoadResources(s_Resources, LUT_RESOURCE_FILE, &s_DeviceAllocator);
585     BuildResources(s_LutResource);
586 
587     // モデルやそれ以外のリソースを読み込みます。
588     NW_FOREACH(const wchar_t* name, RESOURCE_FILES)
589     {
590         nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator);
591         BuildResources(resourceSet);
592         s_ResAnims.push_back(resourceSet->resource);
593     }
594 
595     BuildAnimations();
596     ReattachObjects();
597 
598     // ライトアニメーションを表示します
599     s_SceneRootInvisible->DetachChild(s_LightRoot);
600     s_SceneRoot->AttachChild(s_LightRoot);
601     s_AnimMode = 4;
602 
603     // シーンツリーを巡回して初期化を行います。
604     s_SceneSystem->InitializeScene(s_SceneRoot);
605     s_SceneSystem->UpdateScene();
606 
607     // シーン環境の参照解決を行い設定します。
608     s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
609     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
610     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
611     sceneEnvironment.SetCamera(s_AnimCameraIndex, s_AnimCamera);
612     ChangeCamera(s_BaseCameraIndex);
613 
614     NW_GL_ASSERT();
615 
616     s_FrameCount = 0;
617 }
618 
619 /*!--------------------------------------------------------------------------*
620   @brief        シーン関連の後始末をします。
621  *---------------------------------------------------------------------------*/
622 void
TerminateScenes()623 TerminateScenes()
624 {
625     // 表示されていないシーンオブジェクトも破棄するために s_SceneRootInvisible に対して SafeDestroyBranch を実行します。
626     nw::gfx::SafeDestroyBranch(s_SceneRoot);
627     nw::gfx::SafeDestroyBranch(s_SceneRootInvisible);
628     nw::demo::SafeCleanupResources(s_Resources);
629     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
630 
631     TerminateAnim();
632 
633     NW_GL_ASSERT();
634 
635     s_Resources.clear();
636     s_SceneEnvironmentSettings.clear();
637 
638     s_SceneRoot = NULL;
639     s_SkeletalRoot = NULL;
640     s_MaterialRoot = NULL;
641     s_VisibilityRoot = NULL;
642     s_CameraRoot = NULL;
643     s_LightRoot = NULL;
644 }
645 
646 /*!--------------------------------------------------------------------------*
647   @brief        シーンを更新します。
648  *---------------------------------------------------------------------------*/
649 void
UpdateScene()650 UpdateScene()
651 {
652     s_SceneSystem->GetCameraController()->Update();
653 
654     s_SceneSystem->UpdateScene();
655 
656     s_ActiveCamera->UpdateCameraMatrix();
657 
658     f32 near = s_ActiveCamera->GetNear();
659 
660     s_RenderSystem->CalcStereoCamera(
661         s_LeftCamera,
662         s_RightCamera,
663         s_ActiveCamera,
664         near + 5.0f);
665 
666     ++s_FrameCount;
667 }
668 
669 /*!--------------------------------------------------------------------------*
670   @brief        負荷表示やテスト機能の処理をおこないます。
671  *---------------------------------------------------------------------------*/
672 void
ReportDemo()673 ReportDemo()
674 {
675     NW_PROFILE("ReportDemo");
676 
677     // 負荷表示からはこれらの負荷は除きます。
678     s_RenderSystem->SuspendLoadMeter();
679 
680     s_GraphicsDrawing.BeginDrawingString();
681 
682     nw::demo::DebugUtility::DrawLoadMeter(
683         s_RenderSystem,
684         &s_GraphicsDrawing,
685         (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
686     );
687 
688     const int dumpPositionX = 10;
689     const int dumpPositionY = 10;
690     const char* mode;
691     switch (s_AnimMode)
692     {
693     case 0:
694         mode = "Skeletal";
695         break;
696     case 1:
697         mode = "Material";
698         break;
699     case 2:
700         mode = "Visibility";
701         break;
702     case 3:
703         mode = "Camera";
704         break;
705     case 4:
706         mode = "Light";
707         break;
708     default:
709         mode = "";
710         break;
711     }
712     s_GraphicsDrawing.DrawString(
713         dumpPositionX,
714         dumpPositionY,
715         "%s",
716         mode
717     );
718 
719     s_GraphicsDrawing.FlushDrawing();
720 
721     s_RenderSystem->ResumeLoadMeter();
722 }
723 
724 /*!--------------------------------------------------------------------------*
725   @brief        シーンをデモンストレーションします。
726  *---------------------------------------------------------------------------*/
727 void
DemoScene()728 DemoScene()
729 {
730     NW_ASSERT(!s_RenderTargets.empty());
731 
732     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
733 
734     InitializeScenes();
735 
736     bool isContinuing = true;
737 
738     while ( isContinuing )
739     {
740         nw::demo::DebugUtility::AdvanceAutoTestFrame();
741 
742         nw::demo::PadFactory::GetPad()->Update();
743 
744         if (nw::demo::PadFactory::GetPad()->IsButtonDown( nw::demo::Pad::BUTTON_L ))
745         {
746             ToggleAnimationMode(true);
747         }
748         if (nw::demo::PadFactory::GetPad()->IsButtonDown( nw::demo::Pad::BUTTON_R ))
749         {
750             ToggleAnimationMode(false);
751         }
752         UpdateScene();
753 
754         renderContext->SetActiveCamera(s_ActiveCameraIndex);
755         s_RenderSystem->SubmitView(s_SceneSystem);
756 
757         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
758         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
759 
760         s_RenderSystem->ClearBySkyModel(renderContext->GetActiveCamera());
761         ReportDemo();
762         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
763 
764         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
765 
766         renderContext->ResetState();
767 
768         if (nw::demo::Utility::IsTerminating())
769         {
770             isContinuing = false;
771         }
772     }
773 
774     TerminateScenes();
775 }
776 
777 } // namespace
778 
779 /*!--------------------------------------------------------------------------*
780   @brief        メイン関数です。
781  *---------------------------------------------------------------------------*/
782 void
nnMain()783 nnMain()
784 {
785     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
786 
787     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
788 
789     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
790     {
791         InitializeGraphics();
792 
793         DemoScene();
794 
795         TerminateGraphics();
796     }
797 
798     nw::demo::PadFactory::Finalize();
799 
800     nw::demo::FinalizeGraphicsSystem();
801 }
802