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