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