1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ParticleUpdaterDemo.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: 25401 $
14  *---------------------------------------------------------------------------*/
15 /*
16 現在は、UserUpdaterをCreativeStudio上で追加することができないので、
17 中間ファイルのParticleUpdatersのリスト内に
18 
19 <ParticleUserUpdaterXml IsUpdaterEnabled="true" UserParameter="0">
20     <ParticleAnimationData />
21     <TargetStreams />
22 </ParticleUserUpdaterXml>
23 
24 を追加してください。
25 
26 ParticleUpdatersはParticleSet毎の設定です。
27 */
28 
29 
30 #define NW_DEBUG_CHECK_MEMORY_LEAK
31 
32 #include <nn/os.h>
33 #include <nn/fs.h>
34 
35 #include <nw/types.h>
36 #include <nw/demo.h>
37 #include <nw/dev.h>
38 #include <nw/gfx.h>
39 #include <nw/ut.h>
40 
41 namespace
42 {
43 
44 //----------------------------------------
45 // メモリ関係
46 
47 // デバイスメモリを確保するためのアロケータです。
48 nw::demo::DemoAllocator s_DeviceAllocator;
49 nw::demo::DemoAllocator s_ParticleAllocator;
50 
51 //----------------------------------------
52 // ファイル名の定義です。
53 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
54 const wchar_t* FONT_FILE_NAME        = NW_DEMO_FILE_PATH(L"Font.bcfnt");
55 const wchar_t* SKY_SPHERE_FILE_NAME  = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
56 
57 const wchar_t* MODEL_RESOURCE_FILES[] =
58 {
59     NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl"),
60     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
61     NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
62 };
63 
64 //----------------------------------------
65 // プロファイル関係
66 const int NW_LOAD_METER_INTERVAL = 60;
67 
68 //----------------------------------------
69 // 描画関係
70 const int RENDER_TARGET_COUNT = 1;
71 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
72 
73 RenderTargetArray s_RenderTargets;
74 nw::demo::SceneSystem*  s_SceneSystem = NULL;
75 nw::demo::RenderSystem* s_RenderSystem = NULL;
76 nw::gfx::ParticleContext* s_ParticleContext = NULL;
77 
78 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
79 
80 //----------------------------------------
81 // リソース関係
82 nw::demo::ResourceArray s_Resources;
83 
84 //----------------------------------------
85 // シーン関係
86 nw::gfx::SceneNode* s_SceneRoot = NULL;
87 s32 s_FrameCount = 0;
88 nw::gfx::Camera* s_BaseCamera = NULL;
89 nw::gfx::Camera* s_LeftCamera = NULL;
90 nw::gfx::Camera* s_RightCamera = NULL;
91 const f32 s_fNearPlane = 0.1f;
92 
93 //----------------------------------------
94 // シーン環境関係
95 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
96 
97 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
98 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
99 
100 const s32 s_BaseCameraIndex = 0;
101 
102 //----------------------------------------
103 // パーティクル関係
104 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
105 
106 nw::demo::FlushCache* s_FlushCache;
107 
108 
109 /*!--------------------------------------------------------------------------*
110   @brief        グラフィックス関連の初期化を行います。
111  *---------------------------------------------------------------------------*/
112 void
InitializeGraphics()113 InitializeGraphics()
114 {
115     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
116 
117     // renderDescriptionへステレオの設定を行います。
118     nw::demo::RenderSystem::Description renderDescription;
119 
120     renderDescription.reusableCommandBufferSize = 0x100000;
121     renderDescription.reusableCommandRequestCount      = 512;
122     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
123 
124     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
125 
126     s_GraphicsDrawing.SetScreenSize(
127         renderDescription.lowerScreenDescription.width,
128         renderDescription.lowerScreenDescription.height
129     );
130 
131     bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
132 
133     NN_ASSERTMSG(result, "Fail to load Font.");
134 
135     s_RenderTargets.push_back(
136         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
137     );
138     NW_ASSERT(!s_RenderTargets.empty());
139     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
140 
141     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
142     nw::demo::SceneSystem::Description sceneDescription;
143     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
144 
145     s_ParticleContext = nw::gfx::ParticleContext::Builder()
146         .MaxEmission(1000)
147         .Create(&s_DeviceAllocator);
148 
149     s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
150         .Create(&s_DeviceAllocator);
151 
152     // デモ用の最遠景モデルをレンダリングシステムに設定します。
153     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
154     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
155 
156     NW_GL_ASSERT();
157 }
158 
159 /*!--------------------------------------------------------------------------*
160   @brief        グラフィックス関連の後始末をします。
161  *---------------------------------------------------------------------------*/
162 void
TerminateGraphics()163 TerminateGraphics()
164 {
165     nw::gfx::SafeDestroy(s_LeftCamera);
166 
167     nw::gfx::SafeDestroy(s_RightCamera);
168 
169     nw::gfx::SafeDestroy(s_ParticleSceneUpdater);
170 
171     nw::gfx::SafeDestroy(s_ParticleContext);
172 
173     nw::gfx::SafeDestroy(s_SceneSystem);
174 
175     nw::gfx::SafeDestroyAll(s_RenderTargets);
176 
177     s_GraphicsDrawing.Finalize();
178 
179     nw::gfx::SafeDestroy(s_RenderSystem);
180 
181     NW_GL_ASSERT();
182 }
183 
184 /*!--------------------------------------------------------------------------*
185   @brief        再生ステップを設定します。
186 
187   @param[in]    再生ステップです。
188  *---------------------------------------------------------------------------*/
189 void
SetStepFrame(f32 stepFrame)190 SetStepFrame(f32 stepFrame)
191 {
192     nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
193 
194     nw::gfx::SceneNodeArray::iterator end = sceneContext->GetSceneNodesEnd();
195     for (nw::gfx::SceneNodeArray::iterator i = sceneContext->GetSceneNodesBegin(); i != end; ++i)
196     {
197         nw::gfx::ParticleEmitter* emitter = nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(*i);
198         if (emitter != NULL)
199         {
200             emitter->ParticleAnimFrameController().SetStepFrame(stepFrame);
201         }
202         else
203         {
204             nw::gfx::ParticleModel* model = nw::ut::DynamicCast<nw::gfx::ParticleModel*>(*i);
205             if (model != NULL)
206             {
207                 model->ParticleAnimFrameController().SetStepFrame(stepFrame);
208             }
209         }
210     }
211 }
212 
213 /*!--------------------------------------------------------------------------*
214   @brief        ユーザ定義のアップデータです
215  *---------------------------------------------------------------------------*/
UserUpdater(nw::gfx::ParticleContext * context,nw::gfx::ParticleSet * particleSet,const nw::gfx::ResParticleUserUpdater * userUpdater,f32 prevTime,f32 time)216 static void UserUpdater(
217         nw::gfx::ParticleContext* context,
218         nw::gfx::ParticleSet* particleSet,
219         const nw::gfx::ResParticleUserUpdater* userUpdater,
220         f32 prevTime,
221         f32 time
222 )
223 {
224     NW_UNUSED_VARIABLE(context);
225     NW_UNUSED_VARIABLE(particleSet);
226     NW_UNUSED_VARIABLE(userUpdater);
227     NW_UNUSED_VARIABLE(prevTime);
228     NW_UNUSED_VARIABLE(time);
229 
230     nw::gfx::ParticleCollection* collection = particleSet->GetParticleCollection();
231     NW_NULL_ASSERT(collection);
232 
233     // 有効なパーティクルの個数
234     const int count = collection->GetCount();
235     if (count == 0)
236     {
237         return;
238     }
239 
240     // 有効なパーティクルへのインデックス・テーブル
241     // 必ずPARTICLE_BUFFER_BACKから取得してください
242     u16* activeIndex =
243         (u16*)collection->GetStreamPtr(
244             nw::gfx::PARTICLEUSAGE_ACTIVEINDEX,
245             nw::gfx::PARTICLE_BUFFER_BACK);
246 
247     // ACTIVEINDEX以外はPARTICLE_BUFFER_FRONTから取得します。
248     nw::math::VEC3* translate =
249         (nw::math::VEC3*)collection->GetStreamPtr(
250             nw::gfx::PARTICLEUSAGE_TRANSLATE,
251             nw::gfx::PARTICLE_BUFFER_FRONT);
252     if (translate == NULL)
253     {
254         // アニメーションが元々付いていない場合などは固定値の扱いとなります
255         // 粒子毎の設定が要らない場合は、Shapeのアトリビュートを変更するほうが効率的です
256         return;
257     }
258 
259     nw::math::VEC3* velocity =
260         (nw::math::VEC3*)collection->GetStreamPtr(
261             nw::gfx::PARTICLEUSAGE_VELOCITY,
262             nw::gfx::PARTICLE_BUFFER_FRONT);
263     if (velocity == NULL)
264     {
265         return;
266     }
267 
268     const bool isAscendingOrder = particleSet->IsAscendingOrder();
269     const int startIndex = (isAscendingOrder) ? 0 : collection->GetCapacity() - 1;
270     const int incrIndex = (isAscendingOrder) ? 1 : -1;
271     activeIndex += startIndex;
272 
273     for (int i = 0; i < count; ++i)
274     {
275         int index = *activeIndex;
276         activeIndex += incrIndex;
277 
278         nw::math::VEC3 nextPosition;
279         nextPosition = translate[index] + velocity[index];
280 
281         if (nextPosition.x > 2.0f)
282         {
283 #if 1 // 反射
284             velocity[index].x *= -1.0f;
285             velocity[index].z *= -1.0f;
286 #else // 消滅
287             collection->KillParticle(index);
288 #endif
289         }
290     }
291 }
292 
293 /*!--------------------------------------------------------------------------*
294   @brief        ユーザ定義のアップデータを設定します
295 
296   @param[in]    sceneNodeArray シーンノードのアレイです。
297 
298  *---------------------------------------------------------------------------*/
299 void
SetUserUpdater(nw::ut::MoveArray<nw::gfx::SceneNode * > * sceneNodeArray)300 SetUserUpdater(
301     nw::ut::MoveArray<nw::gfx::SceneNode*> *sceneNodeArray
302 )
303 {
304     NW_NULL_ASSERT(sceneNodeArray);
305 
306     NW_FOREACH(nw::gfx::SceneNode* node, *sceneNodeArray)
307     {
308         switch (node->GetResSceneNode().ptr()->typeInfo)
309         {
310         case nw::gfx::ResParticleModel::TYPE_INFO:
311             {
312                 nw::gfx::ParticleModel* model = reinterpret_cast<nw::gfx::ParticleModel*>(node);
313 
314                 for (u32 i = 0; i < model->GetParticleSetsCount(); ++i)
315                 {
316                     nw::gfx::ParticleSet* particleSet = model->GetParticleSets(i);
317 
318                     nw::ut::MoveArray<nw::gfx::ParticleSet::Updater>* updaters =
319                         particleSet->GetUpdaters();
320 
321                     nw::ut::MoveArray<nw::gfx::ParticleSet::Updater>::iterator endIter = updaters->end();
322                     for (nw::ut::MoveArray<nw::gfx::ParticleSet::Updater>::iterator iter = updaters->begin();
323                         iter != endIter;)
324                     {
325                         nw::gfx::ParticleSet::Updater& updater = *iter++;
326 
327                         nw::gfx::ResParticleUpdater resUpdater(updater.resource);
328                         NW_ASSERT(resUpdater.IsValid());
329 
330                         if (resUpdater.GetTypeInfo() == nw::gfx::ResParticleUserUpdater::TYPE_INFO)
331                         {
332                             nw::gfx::ResParticleUserUpdater userUpdater =
333                                 nw::gfx::ResDynamicCast<nw::gfx::ResParticleUserUpdater>(resUpdater);
334 
335                             updater.work = (u32)UserUpdater;
336                         }
337                     }
338                 }
339             }
340             break;
341         }
342     }
343 }
344 
345 /*!--------------------------------------------------------------------------*
346   @brief        ルートノード関連の構築をします。
347  *---------------------------------------------------------------------------*/
348 void
BuildRootNodes()349 BuildRootNodes()
350 {
351     NW_ASSERT(s_SceneRoot == NULL);
352     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
353         .IsFixedSizeMemory(false)
354         .Create(&s_DeviceAllocator);
355     NW_NULL_ASSERT(s_SceneRoot);
356 }
357 
358 /*!--------------------------------------------------------------------------*
359   @brief        カメラ関連の構築をします。
360  *---------------------------------------------------------------------------*/
361 void
BuildCameras()362 BuildCameras()
363 {
364     nw::demo::Utility::CreateStereoCameras(
365         &s_BaseCamera,
366         &s_LeftCamera,
367         &s_RightCamera,
368         &s_DeviceAllocator,
369         nw::math::VEC3(28.0f, 22.0f, 28.0f),
370         nw::math::VEC3(0.0f, 0.0f, 0.0f),
371         s_fNearPlane
372     );
373 
374     s_SceneRoot->AttachChild(s_BaseCamera);
375     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
376 }
377 
378 /*!--------------------------------------------------------------------------*
379   @brief        リソース関連の構築をします。
380  *---------------------------------------------------------------------------*/
381 void
BuildResources(nw::demo::ResourceSet * resourceSet)382 BuildResources(nw::demo::ResourceSet* resourceSet)
383 {
384     resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
385     resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
386     resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
387 
388     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
389 
390     if (result.IsFailure())
391     {
392         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
393     }
394 
395     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
396 
397     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
398     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
399     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
400          modelResource != modelsEnd; ++modelResource)
401     {
402         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
403             &s_ParticleAllocator,
404             (*modelResource)
405         );
406         if (node != NULL)
407         {
408             sceneNodeArray.push_back(node);
409         }
410     }
411 
412     nw::gfx::ResEmitterArray emitters = resourceSet->resource.GetEmitters();
413     for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
414          emitterResource != emitters.end(); ++emitterResource)
415     {
416         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
417             &s_ParticleAllocator,
418             (*emitterResource)
419         );
420         if (node != NULL)
421         {
422             sceneNodeArray.push_back(node);
423         }
424     }
425 
426     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
427     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
428          lightResource != lights.end(); ++lightResource)
429     {
430         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
431             &s_DeviceAllocator,
432             (*lightResource)
433         );
434         NW_NULL_ASSERT(node);
435         sceneNodeArray.push_back(node);
436     }
437 
438     // 親子付け参照関係を解決
439     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
440 
441     nw::gfx::ParticleUtil::SetupParticleObject(&sceneNodeArray, s_ParticleContext);
442 
443     SetUserUpdater(&sceneNodeArray);
444 
445     // モデルとエミッタをシーンに追加
446     nw::gfx::SceneHelper::ForeachRootNodes(
447         sceneNodeArray.Begin(),
448         sceneNodeArray.End(),
449         nw::gfx::AttachNode(s_SceneRoot)
450     );
451 
452     nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
453     nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
454     for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
455         settingResource != settingsEnd; ++settingResource)
456     {
457         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
458             .Resource(*settingResource)
459             .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
460 
461         nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
462             nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
463 
464         NW_NULL_ASSERT(sceneEnvironmentSetting);
465         s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
466     }
467 }
468 /*!--------------------------------------------------------------------------*
469   @brief        シーンを初期化します。
470  *---------------------------------------------------------------------------*/
471 void
InitializeScenes()472 InitializeScenes()
473 {
474     BuildRootNodes();
475 
476     BuildCameras();
477 
478     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
479     {
480         BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
481     }
482 
483     // シーンツリーを巡回して初期化を行います。
484     s_SceneSystem->InitializeScene(s_SceneRoot);
485     s_SceneSystem->UpdateScene();
486 
487     // シーン環境の参照解決を行い設定します。
488     s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
489 
490     // カメラを設定します。
491     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
492     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
493     nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
494 
495     NW_GL_ASSERT();
496 
497     s_FrameCount = 0;
498 }
499 
500 /*!--------------------------------------------------------------------------*
501   @brief        シーン関連の後始末をします。
502  *---------------------------------------------------------------------------*/
503 void
TerminateScenes()504 TerminateScenes()
505 {
506     nw::gfx::SafeDestroyBranch(s_SceneRoot);
507     nw::demo::SafeCleanupResources(s_Resources);
508     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
509 
510     NW_GL_ASSERT();
511 
512     s_Resources.clear();
513     s_SceneEnvironmentSettings.clear();
514 }
515 
516 /*!--------------------------------------------------------------------------*
517   @brief        シーンを更新します。
518  *---------------------------------------------------------------------------*/
519 void
UpdateScene()520 UpdateScene()
521 {
522     NW_ASSERT(0 < s_RenderTargets.size());
523 
524     s_SceneSystem->GetCameraController()->Update();
525 
526     s_SceneSystem->UpdateScene();
527 
528     s_BaseCamera->UpdateCameraMatrix();
529 
530     NW_NULL_ASSERT(s_ParticleSceneUpdater);
531     s_ParticleSceneUpdater->UpdateNode(
532         s_SceneSystem->GetSceneContext(),
533         s_ParticleContext);
534 
535     s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
536 
537     s_FrameCount++;
538 
539     s_FlushCache->Execute();
540 }
541 
542 /*!--------------------------------------------------------------------------*
543   @brief        負荷表示やテスト機能の処理をおこないます。
544  *---------------------------------------------------------------------------*/
545 void
ReportDemo()546 ReportDemo()
547 {
548     NW_PROFILE("ReportDemo");
549 
550     // 負荷表示からはこれらの負荷は除きます。
551     s_RenderSystem->SuspendLoadMeter();
552 
553     s_GraphicsDrawing.BeginDrawingString();
554 
555     nw::demo::DebugUtility::DrawLoadMeter(
556         s_RenderSystem,
557         &s_GraphicsDrawing,
558         (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
559     );
560 
561     s_GraphicsDrawing.FlushDrawing();
562 
563     s_RenderSystem->ResumeLoadMeter();
564 }
565 
566 /*!--------------------------------------------------------------------------*
567   @brief        シーンをデモンストレーションします。
568  *---------------------------------------------------------------------------*/
569 void
DemoScene()570 DemoScene()
571 {
572     NW_ASSERT(!s_RenderTargets.empty());
573 
574     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
575 
576     InitializeScenes();
577 
578     bool isContinuing = true;
579 
580     while ( isContinuing )
581     {
582         nw::demo::DebugUtility::AdvanceAutoTestFrame();
583 
584         nw::demo::PadFactory::GetPad()->Update();
585 
586         SetStepFrame(1.0f);
587         UpdateScene();
588 
589         renderContext->SetActiveCamera(s_BaseCameraIndex);
590         s_RenderSystem->SubmitView(s_SceneSystem);
591 
592         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
593         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
594 
595         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
596         ReportDemo();
597         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
598 
599         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
600 
601         renderContext->ResetState();
602 
603         if (nw::demo::Utility::IsTerminating())
604         {
605             isContinuing = false;
606         }
607     }
608 
609     TerminateScenes();
610 }
611 
612 } // namespace
613 
614 /*!--------------------------------------------------------------------------*
615   @brief        メイン関数です。
616  *---------------------------------------------------------------------------*/
617 void
nnMain()618 nnMain()
619 {
620     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
621     nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
622 
623     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
624 
625     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
626     {
627         InitializeGraphics();
628 
629         s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
630 
631         DemoScene();
632 
633         nw::ut::SafeDestroy(s_FlushCache);
634 
635         TerminateGraphics();
636     }
637 
638     nw::demo::PadFactory::Finalize();
639 
640     nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
641 
642     nw::demo::FinalizeGraphicsSystem();
643 }
644