1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ParticleLowLayerDemo.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: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #define NW_DEBUG_CHECK_MEMORY_LEAK
19 
20 #include <nn/os.h>
21 #include <nn/fs.h>
22 #include <nn/gx.h>
23 
24 #include <nw/types.h>
25 #include <nw/demo.h>
26 #include <nw/dev.h>
27 #include <nw/gfx.h>
28 #include <nw/ut.h>
29 
30 namespace
31 {
32 
33 //----------------------------------------
34 // メモリ関係
35 // デモではデバイスメモリから全てのメモリを確保するようになっています。
36 
37 // デモで使用するメモリサイズです。
38 const size_t DEMO_MEMORY_SIZE = 0x1000000;
39 
40 // デバイスメモリを確保するためのアロケータです。
41 nw::demo::DemoAllocator s_DeviceAllocator;
42 
43 nw::demo::GraphicsMemoryAllocator s_GraphicsMemoryAllocator;
44 
45 const int MAX_FILE = 256;
46 const int MAX_DIRECTORY = 16;
47 
48 // メモリのフラッシュコード
49 nw::demo::FlushCache* s_FlushCache;
50 
51 //----------------------------------------
52 // ファイル名の定義です。
53 static const wchar_t* MODEL_RESOURCE_FILES[] =
54 {
55     NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl"),
56     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
57 };
58 
59 //----------------------------------------
60 // 描画関係
61 nw::gfx::IRenderTarget* s_RenderTarget = NULL;
62 
63 nw::gfx::ParticleContext* s_ParticleContext = NULL;
64 
65 nw::gfx::RenderContext* s_RenderContext = NULL;
66 nw::gfx::MeshRenderer* s_MeshRenderer = NULL;
67 nw::demo::DisplayBufferSwapper* s_UpperSwapper = NULL;
68 nw::demo::DisplayBufferSwapper* s_ExtensionSwapper = NULL;
69 
70 const size_t COMMAND_BUFFER_SIZE = 0x100000;
71 const size_t REQUEST_COUNT = 512;
72 nw::demo::CommandListSwapper* s_CommandListSwapper = NULL;
73 
74 //----------------------------------------
75 // リソース関係
76 const int RESOURCES_COUNT = 3;
77 struct ResourceSet
78 {
79     nw::ut::MoveArray<u8> buffer;
80     nw::gfx::ResGraphicsFile resource;
81 };
82 typedef nw::ut::FixedSizeArray<ResourceSet, RESOURCES_COUNT> ResourceArray;
83 
84 ResourceArray s_Resources;
85 
86 //----------------------------------------
87 // シーン関係
88 s32 s_FrameCount = 0;
89 nw::gfx::WorldMatrixUpdater* s_WorldMatrixUpdater = NULL;
90 
91 const s32 s_BaseCameraIndex = 0;
92 nw::gfx::Camera* s_BaseCamera = NULL;
93 nw::gfx::Camera* s_LeftCamera = NULL;
94 nw::gfx::Camera* s_RightCamera = NULL;
95 const f32 s_NearPlane = 0.1f;
96 
97 nw::demo::CameraController* s_CameraController = NULL;
98 
99 nn::ulcd::CTR::StereoCamera* s_StereoCamera;
100 
101 const int MODEL_COUNT = 2;
102 const int EMITTER_COUNT = 1;
103 const int PARTICLESET_COUNT = 2;
104 
105 typedef nw::ut::FixedSizeArray<nw::gfx::ParticleModel*, MODEL_COUNT> ParticleModelArray;
106 typedef nw::ut::FixedSizeArray<nw::gfx::ParticleEmitter*, EMITTER_COUNT> EmitterArray;
107 typedef nw::ut::FixedSizeArray<nw::gfx::ParticleSet*, PARTICLESET_COUNT> ParticleSetArray;
108 
109 ParticleModelArray s_ParticleModels;
110 EmitterArray s_ParticleEmitters;
111 ParticleSetArray s_ParticleSets;
112 
113 void UpdateNode(nw::gfx::TransformNode* node);
114 
115 /*!--------------------------------------------------------------------------*
116   @brief        グラフィックスメモリのアロケータです。
117 
118                 関数ポインタが nngxInitialize の引数として使用されます。
119  *---------------------------------------------------------------------------*/
AllocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,GLsizei size)120 void* AllocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, GLsizei size)
121 {
122     void* buffer = s_GraphicsMemoryAllocator.Allocate(area, aim, id, size);
123     return buffer;
124 }
125 
126 /*!--------------------------------------------------------------------------*
127   @brief        グラフィックスメモリのデアロケータです。
128 
129                 関数ポインタが nngxInitialize の引数として使用されます。
130 *---------------------------------------------------------------------------*/
DeallocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,void * addr)131 void DeallocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, void* addr)
132 {
133     s_GraphicsMemoryAllocator.Deallocate(area, aim, id, addr);
134 }
135 
136 /*!--------------------------------------------------------------------------*
137   @brief        グラフィックスシステムに必要なメモリなどの初期化を行います。
138 *---------------------------------------------------------------------------*/
139 void
InitializeGraphicsSystem()140 InitializeGraphicsSystem()
141 {
142     nn::os::Initialize();
143     nn::fs::Initialize();
144 
145     nw::demo::InitializeDemoMemory();
146 
147     nw::demo::InitializeDemoAllocator(&s_DeviceAllocator, DEMO_MEMORY_SIZE, nn::os::ALLOCATE_OPTION_LINEAR);
148 
149     // デバイスメモリを用いるグラフィックスメモリアロケータを初期化します。
150     s_GraphicsMemoryAllocator.Initialize(&s_DeviceAllocator);
151 
152     s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(MAX_FILE, MAX_DIRECTORY);
153     void* workingMemory = nw::demo::Alloc(workingMemorySize);
154     nn::Result result = nn::fs::MountRom(MAX_FILE, MAX_DIRECTORY, workingMemory, workingMemorySize);
155 
156     NW_ASSERT(result.IsSuccess());
157 }
158 
159 /*!--------------------------------------------------------------------------*
160   @brief        グラフィックスシステムに必要なメモリなどの終了処理を行います。
161 *---------------------------------------------------------------------------*/
162 void
FinalizeGraphicsSystem()163 FinalizeGraphicsSystem()
164 {
165     s_GraphicsMemoryAllocator.Finalize();
166 
167     nw::demo::FinalizeDemoAllocator(&s_DeviceAllocator);
168 }
169 
170 /*!--------------------------------------------------------------------------*
171   @brief        グラフィックス関連の初期化を行います。
172 *---------------------------------------------------------------------------*/
173 void
InitializeGraphics()174 InitializeGraphics()
175 {
176     s_ParticleContext = nw::gfx::ParticleContext::Builder()
177         .MaxEmission(1000)
178         .Create(&s_DeviceAllocator);
179 
180     if (nngxInitialize(AllocateGraphicsMemory, DeallocateGraphicsMemory) == GL_FALSE)
181     {
182         NW_FATAL_ERROR("nngxInitialize failed.\n");
183     }
184 
185     //-----------------------------
186     nw::demo::DisplayBufferSwapper::Description upperScreenDescription;
187     upperScreenDescription.screenKind = nw::demo::UPPER_SCREEN;
188     upperScreenDescription.width  = 400;
189     upperScreenDescription.height = 240;
190     upperScreenDescription.bufferCount = 2;
191 
192     nw::demo::DisplayBufferSwapper::Description extensionScreenDescription;
193     extensionScreenDescription.screenKind = nw::demo::EXTENSION_SCREEN;
194     extensionScreenDescription.width  = upperScreenDescription.width;
195     extensionScreenDescription.height = upperScreenDescription.height;
196     extensionScreenDescription.bufferCount = upperScreenDescription.bufferCount;
197 
198     s_UpperSwapper = nw::demo::DisplayBufferSwapper::Builder()
199         .BufferDescription(upperScreenDescription)
200         .Create(&s_DeviceAllocator);
201 
202     s_ExtensionSwapper = nw::demo::DisplayBufferSwapper::Builder()
203         .BufferDescription(extensionScreenDescription)
204         .Create(&s_DeviceAllocator);
205 
206     //-----------------------------
207     nw::demo::CommandListSwapper::Description commandListSwapperDescription;
208     commandListSwapperDescription.commandListCount = 1;
209     commandListSwapperDescription.bufferSize = COMMAND_BUFFER_SIZE;
210     commandListSwapperDescription.requestCount = REQUEST_COUNT;
211     commandListSwapperDescription.reusableBufferSize = COMMAND_BUFFER_SIZE;
212     commandListSwapperDescription.reusableRequestCount = REQUEST_COUNT;
213     commandListSwapperDescription.maxGpuProfilingEntryCount = 0;
214     s_CommandListSwapper =
215         nw::demo::CommandListSwapper::Create(&s_DeviceAllocator, commandListSwapperDescription);
216     s_CommandListSwapper->Bind();
217 
218     //-----------------------------
219     nngxSetDisplayMode(nw::demo::UPPER_SCREEN_MODE_STEREO);
220 
221     //-----------------------------
222     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
223 
224     //-----------------------------
225     s_RenderContext = nw::gfx::RenderContext::Builder()
226         .Create(&s_DeviceAllocator);
227 
228     //-----------------------------
229     void* cameraMemory = s_DeviceAllocator.Alloc(sizeof(nn::ulcd::CTR::StereoCamera));
230     s_StereoCamera = new(cameraMemory) nn::ulcd::CTR::StereoCamera();
231     s_StereoCamera->Initialize();
232 
233     //-----------------------------
234     s_MeshRenderer = nw::gfx::MeshRenderer::Create(&s_DeviceAllocator);
235     s_MeshRenderer->SetRenderContext(s_RenderContext);
236 
237     //-----------------------------
238     nw::gfx::RenderColorFormat renderColorFormat = nw::gfx::RENDER_COLOR_FORMAT_RGBA8;
239     s_RenderTarget =
240         nw::gfx::IRenderTarget::Builder()
241         .BufferSize(upperScreenDescription.height, upperScreenDescription.width)
242         .ColorFormat(renderColorFormat)
243         .Create(&s_DeviceAllocator);
244     NW_NULL_ASSERT(s_RenderTarget);
245 
246     //-----------------------------
247     s_WorldMatrixUpdater = nw::gfx::WorldMatrixUpdater::Builder()
248         .Create(&s_DeviceAllocator);
249 
250     //-----------------------------
251     nngxStartLcdDisplay();
252 
253     NW_GL_ASSERT();
254 }
255 /*!--------------------------------------------------------------------------*
256   @brief        グラフィックス関連の後始末をします。
257 *---------------------------------------------------------------------------*/
258 void
TerminateGraphics()259 TerminateGraphics()
260 {
261     s_StereoCamera->Finalize();
262     s_DeviceAllocator.Free(s_StereoCamera);
263 
264     nw::gfx::SafeDestroy(s_ParticleContext);
265 
266     nw::gfx::SafeDestroy(s_WorldMatrixUpdater);
267 
268     nw::gfx::SafeDestroy(s_RenderTarget);
269 
270     nw::gfx::SafeDestroy(s_MeshRenderer);
271     nw::gfx::SafeDestroy(s_CommandListSwapper);
272     nw::gfx::SafeDestroy(s_UpperSwapper);
273     nw::gfx::SafeDestroy(s_ExtensionSwapper);
274     nw::gfx::SafeDestroy(s_RenderContext);
275 
276     nngxFinalize();
277     s_GraphicsMemoryAllocator.Finalize();
278 
279     NW_GL_ASSERT();
280 }
281 
282 /*!--------------------------------------------------------------------------*
283   @brief        グラフィックスリソースをロードします。
284 
285   @param[in]    resourcePath ファイルのパス名
286 
287   @return       ロードしたグラフィックス情報を返します。
288  *---------------------------------------------------------------------------*/
289 ResourceSet*
LoadResources(const wchar_t * resourcePath)290 LoadResources(const wchar_t* resourcePath)
291 {
292     ResourceSet resourceSet;
293     // 現在、デバイスメモリ上に読み込む方式にのみ対応しています。
294     // テクスチャをロードするには128byteアライメントを行う必要があります。
295     static const int resourceAlignment = 128;
296     resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , resourcePath, resourceAlignment);
297 
298     if (!resourceSet.buffer)
299     {
300         return NULL;
301     }
302 
303     resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
304 
305     bool isPushed = s_Resources.push_back(resourceSet);
306 
307     NW_ASSERT(isPushed);
308 
309     return &(s_Resources.back());
310 }
311 
312 /*!--------------------------------------------------------------------------*
313   @brief        シーンノードを生成します。
314 
315   @param[in]    resource シーンノードのリソースです。
316 
317   @return       生成したシーンノードです。。
318  *---------------------------------------------------------------------------*/
319 nw::gfx::SceneNode*
CreateSceneNode(nw::gfx::ResSceneObject resource)320 CreateSceneNode(nw::gfx::ResSceneObject resource)
321 {
322     nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
323         .Resource(resource)
324         .MaxChildren(0)
325         .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
326 
327     return nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
328 }
329 
330 /*!--------------------------------------------------------------------------*
331   @brief        リソース関連の構築をします。
332 *---------------------------------------------------------------------------*/
333 void
BuildResources(ResourceSet * resourceSet)334 BuildResources(ResourceSet* resourceSet)
335 {
336     resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
337     resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
338     resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
339 
340     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
341     if (result.IsFailure())
342     {
343         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
344     }
345 
346     /*
347     リソースでの階層組みは無視します。
348     */
349     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
350 
351     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
352     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
353     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
354         modelResource != modelsEnd; ++modelResource)
355     {
356         nw::gfx::SceneNode* node = CreateSceneNode(*modelResource);
357         NW_NULL_ASSERT(node);
358 
359         sceneNodeArray.push_back(node);
360 
361         if (nw::ut::IsTypeOf<nw::gfx::ParticleModel>(node))
362         {
363             s_ParticleModels.push_back(static_cast<nw::gfx::ParticleModel*>(node));
364 
365             nw::gfx::ParticleModel* particleModel =
366                 static_cast<nw::gfx::ParticleModel*>(node);
367             for (int i = 0; i < particleModel->GetParticleSetsCount(); ++i)
368             {
369                 s_ParticleSets.push_back(particleModel->GetParticleSets(i));
370             }
371         }
372     }
373 
374     nw::gfx::ResEmitterArray emitters = resourceSet->resource.GetEmitters();
375     nw::gfx::ResEmitterArray::iterator emittersEnd = emitters.end();
376     for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
377         emitterResource != emittersEnd; ++emitterResource)
378     {
379         nw::gfx::SceneNode* node = CreateSceneNode(*emitterResource);
380         NW_NULL_ASSERT(node);
381 
382         sceneNodeArray.push_back(node);
383 
384         if (nw::ut::IsTypeOf<nw::gfx::ParticleEmitter>(node))
385         {
386             s_ParticleEmitters.push_back(static_cast<nw::gfx::ParticleEmitter*>(node));
387         }
388     }
389 
390     // 親子付け参照関係を解決
391     //nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
392 
393     nw::gfx::ParticleUtil::SetupParticleObject(&sceneNodeArray, s_ParticleContext);
394 }
395 
396 /*!--------------------------------------------------------------------------*
397   @brief        カメラの構築をします。
398 *---------------------------------------------------------------------------*/
399 void
BuildCameras()400 BuildCameras()
401 {
402     nw::gfx::LookAtTargetViewUpdater* viewUpdater
403         = nw::gfx::LookAtTargetViewUpdater::Create(&s_DeviceAllocator);
404 
405     nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
406         nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(
407             viewUpdater->GetResource());
408     resViewUpdater.SetTargetPosition(0.0f,0.0f,0.0f);
409     resViewUpdater.SetUpwardVector(0.0f,1.0f,0.0f);
410 
411     nw::gfx::PerspectiveProjectionUpdater* projectionUpdater
412         = nw::gfx::PerspectiveProjectionUpdater::Create(&s_DeviceAllocator);
413 
414     nw::gfx::ResPerspectiveProjectionUpdater resProjectionUpdater =
415         nw::gfx::ResStaticCast<nw::gfx::ResPerspectiveProjectionUpdater>(
416             projectionUpdater->GetResource());
417     resProjectionUpdater.SetNear(s_NearPlane);
418     resProjectionUpdater.SetFar(1000.0f);
419     resProjectionUpdater.SetFovy(NW_MATH_DEG_TO_RAD(37.8f));
420 
421     resProjectionUpdater.SetAspectRatio(
422         static_cast<f32>(s_RenderTarget->GetDescription().height) /
423             static_cast<f32>(s_RenderTarget->GetDescription().width));
424 
425     s_BaseCamera =
426         nw::gfx::Camera::DynamicBuilder()
427         .MaxChildren(0)
428         .MaxCallbacks(0)
429         .ViewUpdater(viewUpdater)
430         .ProjectionUpdater(projectionUpdater)
431         .Create(&s_DeviceAllocator);
432     NW_POINTER_ASSERT(s_BaseCamera);
433     s_BaseCamera->Transform().SetTranslate(nw::math::VEC3(28.0f, 22.0f, 28.0f));
434 
435     s_LeftCamera =
436         nw::gfx::Camera::DynamicBuilder()
437         .MaxChildren(0)
438         .MaxCallbacks(0)
439         .Create(&s_DeviceAllocator);
440     NW_POINTER_ASSERT(s_LeftCamera);
441 
442     s_RightCamera =
443         nw::gfx::Camera::DynamicBuilder()
444         .MaxChildren(0)
445         .MaxCallbacks(0)
446         .Create(&s_DeviceAllocator);
447     NW_POINTER_ASSERT(s_RightCamera);
448 
449     s_CameraController =
450         nw::demo::CameraController::Builder()
451         .MaxCameraCount(1)
452         .Create(&s_DeviceAllocator);
453     s_CameraController->Register(s_BaseCamera);
454 }
455 
456 /*!--------------------------------------------------------------------------*
457   @brief        シーンを初期化します。
458 *---------------------------------------------------------------------------*/
459 void
InitializeScenes()460 InitializeScenes()
461 {
462     BuildCameras();
463 
464     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
465     {
466         BuildResources(LoadResources(name));
467     }
468 
469     NW_GL_ASSERT();
470 
471     s_FrameCount = 0;
472 }
473 
474 /*!--------------------------------------------------------------------------*
475   @brief        シーン関連の後始末をします。
476 *---------------------------------------------------------------------------*/
477 void
TerminateScenes()478 TerminateScenes()
479 {
480     nw::gfx::SafeDestroyBranchAll(s_ParticleModels);
481     nw::gfx::SafeDestroyAll(s_ParticleEmitters);
482     s_ParticleSets.clear();
483     nw::demo::SafeCleanupResources(s_Resources);
484     nw::gfx::SafeDestroy(s_BaseCamera);
485     nw::gfx::SafeDestroy(s_LeftCamera);
486     nw::gfx::SafeDestroy(s_RightCamera);
487     nw::gfx::SafeDestroy(s_CameraController);
488 
489     NW_GL_ASSERT();
490 
491     s_Resources.clear();
492 }
493 
494 /*!--------------------------------------------------------------------------*
495   @brief        ノードを更新します。
496  *---------------------------------------------------------------------------*/
497 void
UpdateNode(nw::gfx::TransformNode * node)498 UpdateNode(nw::gfx::TransformNode* node)
499 {
500     // 一度計算したら計算処理をスキップする。
501     // ただし、ツリー構造は正しく解釈されない。
502     if (node->Transform().IsEnabledFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY))
503     {
504         s_WorldMatrixUpdater->UpdateBasic(
505             &node->WorldMatrix(),
506             &node->WorldTransform(),
507             node->Transform(),
508             nw::gfx::CalculatedTransform::Identity(),
509             nw::gfx::CalculatedTransform::Identity());
510 
511         node->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY);
512     }
513 }
514 
515 /*!--------------------------------------------------------------------------*
516   @brief        カメラを更新します。
517  *---------------------------------------------------------------------------*/
UpdateCamera()518 void UpdateCamera()
519 {
520     s_CameraController->Update();
521     UpdateNode(s_BaseCamera);
522     s_BaseCamera->UpdateCameraMatrix();
523 
524     // ステレオカメラの計算
525     NW_NULL_ASSERT(s_LeftCamera);
526     NW_NULL_ASSERT(s_RightCamera);
527     NW_NULL_ASSERT(s_BaseCamera);
528     nn::math::MTX44& projOriginal = s_BaseCamera->ProjectionMatrix();
529     nn::math::MTX34& viewOriginal = s_BaseCamera->ViewMatrix();
530     nn::math::MTX44& projL = s_LeftCamera->ProjectionMatrix();
531     nn::math::MTX34& viewL = s_LeftCamera->ViewMatrix();
532     nn::math::MTX44& projR = s_RightCamera->ProjectionMatrix();
533     nn::math::MTX34& viewR = s_RightCamera->ViewMatrix();
534 
535     // Ortho カメラでは別の処理を行う必要があります。
536     // 例として demo::RenderSystem::CalcStereoCamera() を参照してください。
537     const f32 DEPTH_LEVEL = 5.0f + s_NearPlane;
538     const f32 DEPTH_RANGE = 1.0f;
539     s_StereoCamera->CalculateMatrices(
540         &projL,
541         &viewL,
542         &projR,
543         &viewR,
544         &projOriginal,
545         &viewOriginal,
546         DEPTH_LEVEL,
547         DEPTH_RANGE,
548         false);
549 }
550 
551 /*!--------------------------------------------------------------------------*
552   @brief        生成されたノードを更新します。
553  *---------------------------------------------------------------------------*/
UpdateNodes()554 void UpdateNodes()
555 {
556     // モデル更新
557     ParticleModelArray::iterator particleModelEnd = s_ParticleModels.end();
558     for (ParticleModelArray::iterator node = s_ParticleModels.begin(); node != particleModelEnd; ++node)
559     {
560         UpdateNode(*node);
561         (*node)->UpdateParticleFrame();
562     }
563 
564     EmitterArray::iterator particleEmitterEnd = s_ParticleEmitters.end();
565     for (EmitterArray::iterator node = s_ParticleEmitters.begin(); node != particleEmitterEnd; ++node)
566     {
567         UpdateNode(*node);
568         (*node)->UpdateParticleFrame();
569         (*node)->Emission(s_ParticleContext);
570     }
571 
572     ParticleSetArray::iterator particleSetEnd = s_ParticleSets.end();
573     for (ParticleSetArray::iterator node = s_ParticleSets.begin(); node != particleSetEnd; ++node)
574     {
575         (*node)->UpdateParticles(s_ParticleContext);
576     }
577 }
578 
579 /*!--------------------------------------------------------------------------*
580   @brief        カメラ、ライト、フォグなどのシーン環境を設定します。
581  *---------------------------------------------------------------------------*/
582 void
SetEnvironment()583 SetEnvironment()
584 {
585     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderContext->GetSceneEnvironment();
586     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
587 }
588 
589 /*!--------------------------------------------------------------------------*
590   @brief        シーンを更新します。
591  *---------------------------------------------------------------------------*/
592 void
UpdateScene()593 UpdateScene()
594 {
595     UpdateNodes();
596 
597     UpdateCamera();
598 
599     ++s_FrameCount;
600 
601     // デモでは少量のメモリしか扱わないので明示的にフラッシュする必要がある
602     s_FlushCache->Execute();
603 }
604 
605 /*!--------------------------------------------------------------------------*
606   @brief        ビューに関連する更新処理を行います。
607  *---------------------------------------------------------------------------*/
608 void
SubmitView()609 SubmitView()
610 {
611     ParticleModelArray::iterator particleModelEnd = s_ParticleModels.end();
612     for (ParticleModelArray::iterator node = s_ParticleModels.begin(); node != particleModelEnd; ++node)
613     {
614         nw::gfx::ResModel resModel = (*node)->GetResModel();
615         NW_ASSERT(resModel.IsValid());
616         if (!resModel.IsVisible()) {
617             continue;
618         }
619 
620         (*node)->UpdateModelViewMatrixAndNormalMatrix(s_BaseCamera->ViewMatrix(), false);
621     }
622 }
623 
624 /*!--------------------------------------------------------------------------*
625   @brief        シーンを描画します。
626  *---------------------------------------------------------------------------*/
627 void
RenderScene()628 RenderScene()
629 {
630     s_RenderContext->SetRenderTarget(s_RenderTarget);
631     s_RenderContext->SetActiveCamera(0);
632 
633     // 描画コマンドを生成します。
634     s_CommandListSwapper->StartCommandSave();
635     NW_GL_ASSERT();
636 
637     s_RenderContext->ClearBuffer(
638         GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
639         nw::ut::FloatColor(0.5f, 0.5f, 0.5f, 1.0f),
640         1.0f);
641 
642     ParticleModelArray::iterator modelEnd = s_ParticleModels.end();
643     for (ParticleModelArray::iterator model = s_ParticleModels.begin(); model != modelEnd; ++model)
644     {
645         if ((*model)->IsVisible())
646         {
647             nw::gfx::ResMeshArray resMeshes = (*model)->GetResMeshes();
648 
649             nw::gfx::ResMeshArray::iterator meshEnd = resMeshes.end();
650             for(nw::gfx::ResMeshArray::iterator mesh = resMeshes.begin();
651                 mesh != meshEnd;
652                 ++mesh)
653             {
654                 if ((*model)->IsMeshVisible(*mesh))
655                 {
656                     s_MeshRenderer->RenderMesh(*mesh, *model);
657                 }
658             }
659         }
660     }
661     NW_GL_ASSERT();
662 
663     s_CommandListSwapper->EndCommandSave();
664 
665     // 左目の描画を行います。
666     s_RenderContext->SetCameraMatrix(s_LeftCamera);
667     s_CommandListSwapper->ReuseCommand(false);
668     s_UpperSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
669 
670     // 右目の描画を行います。
671     s_RenderContext->SetCameraMatrix(s_RightCamera);
672     s_CommandListSwapper->ReuseCommand(false);
673     s_ExtensionSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
674 
675     s_CommandListSwapper->WaitDone();
676     s_CommandListSwapper->RunAsync();
677 }
678 
679 /*!--------------------------------------------------------------------------*
680   @brief        ディスプレイバッファをスワップして表示します。
681  *---------------------------------------------------------------------------*/
682 void
PresentBuffer()683 PresentBuffer()
684 {
685     s_UpperSwapper->ActivateBuffer();
686     s_ExtensionSwapper->ActivateBuffer();
687 
688     nngxSwapBuffers(NN_GX_DISPLAY0);
689 
690     glBindFramebuffer(GL_FRAMEBUFFER, 0);
691 
692     NW_GL_ASSERT();
693 
694     nngxWaitVSync(NN_GX_DISPLAY0);
695 }
696 
697 /*!--------------------------------------------------------------------------*
698   @brief        シーンをデモンストレーションします。
699  *---------------------------------------------------------------------------*/
700 void
DemoScene()701 DemoScene()
702 {
703     NW_NULL_ASSERT(s_RenderTarget);
704 
705     InitializeScenes();
706 
707     nw::demo::DebugUtility::PostInitializeScenes();
708 
709     s_CommandListSwapper->RunAsync();
710 
711     bool isContinuing = true;
712 
713     while ( isContinuing )
714     {
715         nw::demo::DebugUtility::AdvanceAutoTestFrame();
716 
717         nw::demo::PadFactory::GetPad()->Update();
718 
719         UpdateScene();
720 
721         SetEnvironment();
722 
723         s_RenderContext->SetActiveCamera(s_BaseCameraIndex);
724 
725         SubmitView();
726 
727         RenderScene();
728 
729         s_RenderContext->ResetState();
730 
731         PresentBuffer();
732 
733         if (nw::demo::Utility::IsTerminating())
734         {
735             isContinuing = false;
736         }
737     }
738 
739     nw::demo::DebugUtility::PreTerminateScenes();
740 
741     TerminateScenes();
742 }
743 
744 } // namespace
745 
746 /*!--------------------------------------------------------------------------*
747   @brief        メイン関数です。
748  *---------------------------------------------------------------------------*/
749 void
nnMain()750 nnMain()
751 {
752     InitializeGraphicsSystem();
753 
754     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
755 
756     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_DeviceAllocator, NULL)
757     {
758         InitializeGraphics();
759 
760         s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
761 
762         DemoScene();
763 
764         // キャッシュフラッシュ用のクラスを破棄
765         nw::ut::SafeDestroy(s_FlushCache);
766 
767         TerminateGraphics();
768     }
769 
770     nw::demo::PadFactory::Finalize();
771 
772     FinalizeGraphicsSystem();
773 }
774