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