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