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