1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     AnimationChangeDemo.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* MODEL_RESOURCE_FILES[] =
45 {
46     NW_DEMO_FILE_PATH(L"Male.bcmdl"),
47     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
48     NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
49 };
50 
51 const wchar_t* SKELETAL_ANIM_RESOURCE_FILES[] =
52 {
53     NW_DEMO_FILE_PATH(L"Walk.bcskla"),
54     NW_DEMO_FILE_PATH(L"Run.bcskla")
55 };
56 
57 //----------------------------------------
58 // 描画関係
59 const int RENDER_TARGET_COUNT = 1;
60 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
61 
62 RenderTargetArray s_RenderTargets;
63 nw::demo::SceneSystem*  s_SceneSystem = NULL;
64 nw::demo::RenderSystem* s_RenderSystem = NULL;
65 
66 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
67 
68 //----------------------------------------
69 // リソース関係
70 nw::demo::ResourceArray s_Resources;
71 
72 //----------------------------------------
73 // シーン関係
74 const int SCENE_NODE_COUNT = 4;
75 nw::gfx::SceneNode* s_SceneRoot = NULL;
76 nw::gfx::SceneNode* s_ModelRoot = NULL;
77 s32 s_FrameCount = 0;
78 nw::gfx::Camera* s_BaseCamera = NULL;
79 nw::gfx::Camera* s_LeftCamera = NULL;
80 nw::gfx::Camera* s_RightCamera = NULL;
81 const f32 s_fNearPlane = 0.1f;
82 
83 //----------------------------------------
84 // シーン環境関係
85 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
86 
87 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
88 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
89 
90 const s32 s_BaseCameraIndex = 0;
91 
92 //----------------------------------------
93 // アニメーション関係
94 nw::gfx::SkeletalModel* s_AnimModel = NULL;
95 nw::gfx::TransformAnimEvaluator* s_AnimEvaluator;
96 nw::anim::res::ResAnim s_ResAnim0;
97 nw::anim::res::ResAnim s_ResAnim1;
98 nw::anim::res::ResAnim s_ResAnimEmpty;
99 
100 /*!--------------------------------------------------------------------------*
101   @brief        グラフィックス関連の初期化を行います。
102  *---------------------------------------------------------------------------*/
103 void
InitializeGraphics()104 InitializeGraphics()
105 {
106     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
107 
108     // renderDescriptionへステレオの設定を行います。
109     nw::demo::RenderSystem::Description renderDescription;
110 
111     renderDescription.reusableCommandBufferSize = 0x100000;
112     renderDescription.reusableCommandRequestCount      = 512;
113     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
114 
115     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
116 
117     s_GraphicsDrawing.SetScreenSize(
118         renderDescription.lowerScreenDescription.width,
119         renderDescription.lowerScreenDescription.height
120     );
121 
122     nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
123 
124     s_RenderTargets.push_back(
125         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
126     );
127     NW_ASSERT(!s_RenderTargets.empty());
128     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
129 
130     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
131     nw::demo::SceneSystem::Description sceneDescription;
132     sceneDescription.isFixedSizeMemory = true;
133     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
134 
135     // デモ用の最遠景モデルをレンダリングシステムに設定します。
136     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
137     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
138 
139     NW_GL_ASSERT();
140 }
141 
142 /*!--------------------------------------------------------------------------*
143   @brief        グラフィックス関連の後始末をします。
144  *---------------------------------------------------------------------------*/
145 void
TerminateGraphics()146 TerminateGraphics()
147 {
148     nw::gfx::SafeDestroy(s_LeftCamera);
149 
150     nw::gfx::SafeDestroy(s_RightCamera);
151 
152     nw::gfx::SafeDestroy(s_SceneSystem);
153 
154     nw::gfx::SafeDestroyAll(s_RenderTargets);
155 
156     s_GraphicsDrawing.Finalize();
157 
158     nw::gfx::SafeDestroy(s_RenderSystem);
159 
160     NW_GL_ASSERT();
161 }
162 
163 /*!--------------------------------------------------------------------------*
164   @brief ファイルからトランスフォームアニメーションリソースを読み込みます。
165 
166   @param[in] filePath トランスフォームアニメーションファイルのフルパスです。
167 
168   @return トランスフォームアニメーションリソースです。
169  *---------------------------------------------------------------------------*/
170 nw::anim::res::ResAnim
BuildTransformAnimResource(const wchar_t * filePath)171 BuildTransformAnimResource(const wchar_t* filePath)
172 {
173     //----------------------------------------
174     // アニメーションリソースを生成します。
175     nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator);
176     if (resourceSet->resource.GetSkeletalAnimsCount() == 0)
177     {
178         return nw::anim::res::ResAnim(NULL);
179     }
180     return resourceSet->resource.GetSkeletalAnims(0);
181 }
182 
183 /*!--------------------------------------------------------------------------*
184   @brief ファイルからトランスフォームアニメーション評価を生成します。
185 
186   他のデモと違い、アニメーションリソースの読み込みを行いません。
187 
188   @param[in] maxBones 最大メンバ数です。
189   @param[in] maxAnimMembers 最大アニメーションメンバ数です。
190   @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。
191   @param[in] resAnim アニメーションリソースです。
192 
193   @return トランスフォームアニメーション評価です。
194  *---------------------------------------------------------------------------*/
195 nw::gfx::TransformAnimEvaluator*
CreateTransformAnimEvaluator(const int maxMembers,const int maxAnimMembers,const bool translateAnimEnabled,nw::anim::res::ResAnim resAnim)196 CreateTransformAnimEvaluator(
197     const int maxMembers,
198     const int maxAnimMembers,
199     const bool translateAnimEnabled,
200     nw::anim::res::ResAnim resAnim
201 )
202 {
203     nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
204         .AnimData(resAnim)
205         .MaxMembers(maxMembers)
206         .MaxAnimMembers(maxAnimMembers)
207         .AllocCache(false)
208         .Create(&s_DeviceAllocator);
209 
210     // 移動アニメーションの無効化フラグを設定します。
211     evaluator->SetIsTranslateDisabled(!translateAnimEnabled);
212 
213     return evaluator;
214 }
215 
216 /*!--------------------------------------------------------------------------*
217   @brief        スケルタルアニメーションを初期化します。
218 
219   後で切り替えるために、複数のアニメーションリソースを読み込んでおきます。
220   また、空のアニメーションリソースも生成しておき、これに切り替えられるようにします。
221 
222   @param[in]    model スケルタルモデルです。
223 
224   @return       トランスフォームアニメーション評価です。
225  *---------------------------------------------------------------------------*/
226 nw::gfx::TransformAnimEvaluator*
InitializeSkeletalAnim(nw::gfx::SkeletalModel * model)227 InitializeSkeletalAnim(nw::gfx::SkeletalModel* model)
228 {
229     nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup();
230     if (animGroup == NULL)
231     {
232         return NULL;
233     }
234 
235     nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel();
236     nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
237     const int maxBones = resSkeleton.GetBonesCount();
238     const bool translateAnimEnabled =
239         nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED);
240 
241     // アニメーションリソースを読み込みます。
242     s_ResAnim0 = BuildTransformAnimResource(SKELETAL_ANIM_RESOURCE_FILES[0]);
243     s_ResAnim1 = BuildTransformAnimResource(SKELETAL_ANIM_RESOURCE_FILES[1]);
244     NW_ASSERT(s_ResAnim0.IsValid());
245     NW_ASSERT(s_ResAnim1.IsValid());
246 
247     // 空のアニメーションリソースを生成します。
248     s_ResAnimEmpty = nw::anim::res::ResAnim::CreateEmptySkeletalAnim(&s_DeviceAllocator);
249 
250     // 最大アニメーションメンバ数を所得します。
251     const int maxAnimMembers =
252         nw::ut::Max(s_ResAnim0.GetMemberAnimSetCount(), s_ResAnim1.GetMemberAnimSetCount());
253 
254     nw::gfx::TransformAnimEvaluator* evaluator0 = CreateTransformAnimEvaluator(
255         maxBones, maxAnimMembers, translateAnimEnabled, s_ResAnim0);
256     if (evaluator0 == NULL)
257     {
258         return NULL;
259     }
260 
261     bool bindResult = evaluator0->Bind(animGroup);
262     model->SetSkeletalAnimObject(evaluator0);
263 
264     return evaluator0;
265 }
266 
267 /*!--------------------------------------------------------------------------*
268   @brief        アニメーション評価のアニメーションリソースを変更します。
269 
270   @param[in]    model モデルです。
271  *---------------------------------------------------------------------------*/
272 void
ChangeAnimation(nw::gfx::SkeletalModel * model)273 ChangeAnimation(nw::gfx::SkeletalModel* model)
274 {
275     NW_NULL_ASSERT(model);
276 
277     nw::gfx::AnimObject* animObject = model->GetSkeletalAnimObject();
278     nw::gfx::TransformAnimEvaluator* evaluator =
279         nw::ut::DynamicCast<nw::gfx::TransformAnimEvaluator*>(animObject);
280     if (evaluator != NULL)
281     {
282         nw::demo::Pad* pad = nw::demo::PadFactory::GetPad();
283 
284         // 十字キーの左右でアニメーションを切り替えます。
285         if (pad->IsButtonDown(nw::demo::Pad::BUTTON_LEFT))
286         {
287             evaluator->ChangeAnim(s_ResAnim0);
288         }
289         if (pad->IsButtonDown(nw::demo::Pad::BUTTON_RIGHT))
290         {
291             evaluator->ChangeAnim(s_ResAnim1);
292         }
293 
294         // L キーで空アニメーションに切り替えます。
295         if (pad->IsButtonDown(nw::demo::Pad::BUTTON_L))
296         {
297             evaluator->ChangeAnim(s_ResAnimEmpty);
298         }
299 
300         // R キーでバインドポーズに戻します。
301         if (pad->IsButtonDown(nw::demo::Pad::BUTTON_R))
302         {
303             evaluator->Reset();
304         }
305     }
306 }
307 
308 /*!--------------------------------------------------------------------------*
309   @brief        ルートノード関連の構築をします。
310  *---------------------------------------------------------------------------*/
311 void
BuildRootNodes()312 BuildRootNodes()
313 {
314     NW_ASSERT(s_SceneRoot == NULL);
315     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
316         .Create(&s_DeviceAllocator);
317     NW_NULL_ASSERT(s_SceneRoot);
318 
319     NW_ASSERT(s_ModelRoot == NULL);
320     s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
321         .Create(&s_DeviceAllocator);
322     s_SceneRoot->AttachChild(s_ModelRoot);
323     NW_NULL_ASSERT(s_ModelRoot);
324 }
325 
326 /*!--------------------------------------------------------------------------*
327   @brief        カメラ関連の構築をします。
328  *---------------------------------------------------------------------------*/
329 void
BuildCameras()330 BuildCameras()
331 {
332     nw::demo::Utility::CreateStereoCameras(
333         &s_BaseCamera,
334         &s_LeftCamera,
335         &s_RightCamera,
336         &s_DeviceAllocator,
337         nw::math::VEC3(20.0f, 15.0f, 20.0f),
338         nw::math::VEC3(0.0f, 10.0f, 0.0f),
339         s_fNearPlane
340     );
341 
342     s_SceneRoot->AttachChild(s_BaseCamera);
343     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
344 }
345 
346 /*!--------------------------------------------------------------------------*
347   @brief        リソース関連の構築をします。
348  *---------------------------------------------------------------------------*/
349 void
BuildResources(nw::demo::ResourceSet * resourceSet)350 BuildResources(nw::demo::ResourceSet* resourceSet)
351 {
352     resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
353     resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
354     resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
355 
356     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
357     if (result.IsFailure())
358     {
359         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
360     }
361 
362     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
363 
364     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
365     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
366     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
367          modelResource != modelsEnd; ++modelResource)
368     {
369         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
370             &s_DeviceAllocator,
371             (*modelResource)
372         );
373         NW_NULL_ASSERT(node);
374         sceneNodeArray.push_back(node);
375         s_AnimModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(node);
376     }
377 
378     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
379     nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
380     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
381          lightResource != lightsEnd; ++lightResource)
382     {
383         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
384             &s_DeviceAllocator,
385             (*lightResource)
386         );
387         NW_NULL_ASSERT(node);
388         sceneNodeArray.push_back(node);
389     }
390 
391     // 親子付け参照関係を解決
392     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
393 
394     // モデルをシーンに追加
395     nw::gfx::SceneHelper::ForeachRootNodes(
396         sceneNodeArray.Begin(),
397         sceneNodeArray.End(),
398         nw::gfx::AttachNode(s_ModelRoot)
399     );
400 
401     nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
402     nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
403     for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
404         settingResource != settingsEnd; ++settingResource)
405     {
406         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
407             .Resource(*settingResource)
408             .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
409 
410         nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
411             nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
412 
413         NW_NULL_ASSERT(sceneEnvironmentSetting);
414         s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
415     }
416 }
417 
418 /*!--------------------------------------------------------------------------*
419   @brief        シーンを初期化します。
420  *---------------------------------------------------------------------------*/
421 void
InitializeScenes()422 InitializeScenes()
423 {
424     BuildRootNodes();
425 
426     BuildCameras();
427 
428     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
429     {
430         BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
431     }
432 
433     s_AnimEvaluator = InitializeSkeletalAnim(s_AnimModel);
434     NW_NULL_ASSERT(s_AnimEvaluator);
435 
436     // シーンツリーを巡回して初期化を行います。
437     s_SceneSystem->InitializeScene(s_SceneRoot);
438     s_SceneSystem->UpdateScene();
439 
440     // シーン環境の参照解決を行い設定します。
441     s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
442 
443     // カメラを設定します。
444     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
445     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
446     nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
447 
448     NW_GL_ASSERT();
449 
450     s_FrameCount = 0;
451 }
452 
453 /*!--------------------------------------------------------------------------*
454   @brief        シーン関連の後始末をします。
455  *---------------------------------------------------------------------------*/
456 void
TerminateScenes()457 TerminateScenes()
458 {
459     nw::gfx::SafeDestroyBranch(s_SceneRoot);
460     nw::demo::SafeCleanupResources(s_Resources);
461     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
462 
463     // 空のアニメーションリソースを破棄します。
464     s_DeviceAllocator.Free(s_ResAnimEmpty.ptr());
465     s_ResAnimEmpty = nw::anim::res::ResAnim(NULL);
466 
467     nw::ut::SafeDestroy(s_AnimEvaluator);
468 
469     NW_GL_ASSERT();
470 
471     s_Resources.clear();
472     s_SceneEnvironmentSettings.clear();
473     s_ModelRoot = NULL;
474 }
475 
476 /*!--------------------------------------------------------------------------*
477   @brief        シーンを更新します。
478  *---------------------------------------------------------------------------*/
479 void
UpdateScene()480 UpdateScene()
481 {
482     ChangeAnimation(s_AnimModel);
483 
484     s_SceneSystem->GetCameraController()->Update();
485 
486     s_SceneSystem->UpdateScene();
487 
488     s_BaseCamera->UpdateCameraMatrix();
489 
490     s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
491 
492     ++s_FrameCount;
493 }
494 
495 /*!--------------------------------------------------------------------------*
496   @brief        負荷表示やテスト機能の処理をおこないます。
497  *---------------------------------------------------------------------------*/
498 void
ReportDemo()499 ReportDemo()
500 {
501     NW_PROFILE("ReportDemo");
502 
503     // 負荷表示からはこれらの負荷は除きます。
504     s_RenderSystem->SuspendLoadMeter();
505 
506     nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
507 
508     s_GraphicsDrawing.BeginDrawingShape();
509 
510     nw::demo::DebugUtility::DrawLoadMeter(
511         s_RenderSystem,
512         &s_GraphicsDrawing
513     );
514 
515     s_GraphicsDrawing.EndDrawingShape();
516 
517     s_GraphicsDrawing.BeginDrawingString();
518 
519     nw::demo::DebugUtility::DrawLoadMeterText(
520         s_RenderSystem,
521         &s_GraphicsDrawing
522     );
523 
524     s_GraphicsDrawing.EndDrawingString();
525 
526     s_RenderSystem->ResumeLoadMeter();
527 }
528 
529 /*!--------------------------------------------------------------------------*
530   @brief        シーンをデモンストレーションします。
531  *---------------------------------------------------------------------------*/
532 void
DemoScene()533 DemoScene()
534 {
535     NW_ASSERT(!s_RenderTargets.empty());
536 
537     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
538 
539     InitializeScenes();
540 
541     nw::demo::DebugUtility::PostInitializeScenes();
542 
543     NW_LOG("[Animation Change Demo usage]\n");
544     NW_LOG("left/right: change animation\n");
545     NW_LOG("l         : change to empty animation\n");
546     NW_LOG("r         : reset\n");
547 
548     bool isContinuing = true;
549 
550     while ( isContinuing )
551     {
552         nw::demo::DebugUtility::AdvanceAutoTestFrame();
553 
554         nw::demo::PadFactory::GetPad()->Update();
555 
556         UpdateScene();
557 
558         renderContext->SetActiveCamera(s_BaseCameraIndex);
559         s_RenderSystem->SubmitView(s_SceneSystem);
560 
561         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
562         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
563 
564         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
565         ReportDemo();
566         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
567 
568         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
569 
570         renderContext->ResetState();
571 
572         if (nw::demo::Utility::IsTerminating())
573         {
574             isContinuing = false;
575         }
576     }
577 
578     nw::demo::DebugUtility::PreTerminateScenes();
579 
580     TerminateScenes();
581 }
582 
583 } // namespace
584 
585 /*!--------------------------------------------------------------------------*
586   @brief        メイン関数です。
587  *---------------------------------------------------------------------------*/
588 void
nnMain()589 nnMain()
590 {
591     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
592 
593     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
594 
595     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
596     {
597         InitializeGraphics();
598 
599         DemoScene();
600 
601         TerminateGraphics();
602     }
603 
604     nw::demo::PadFactory::Finalize();
605 
606     nw::demo::FinalizeGraphicsSystem();
607 }
608