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: 28211 $
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     s_GraphicsMemoryAllocator.Finalize();
276 
277     NW_GL_ASSERT();
278 }
279 
280 /*!--------------------------------------------------------------------------*
281   @brief        グラフィックスリソースをロードします。
282 
283   @param[in]    resourcePath ファイルのパス名
284 
285   @return       ロードしたグラフィックス情報を返します。
286  *---------------------------------------------------------------------------*/
287 ResourceSet*
LoadResources(const wchar_t * resourcePath)288 LoadResources(const wchar_t* resourcePath)
289 {
290     ResourceSet resourceSet;
291     // 現在、デバイスメモリ上に読み込む方式にのみ対応しています。
292     // テクスチャをロードするには128byteアライメントを行う必要があります。
293     static const int resourceAlignment = 128;
294     resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , resourcePath, resourceAlignment);
295 
296     if (!resourceSet.buffer)
297     {
298         return NULL;
299     }
300 
301     resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
302 
303     bool isPushed = s_Resources.push_back(resourceSet);
304 
305     NW_ASSERT(isPushed);
306 
307     return &(s_Resources.back());
308 }
309 
310 /*!--------------------------------------------------------------------------*
311   @brief        シーンノードを生成します。
312 
313   @param[in]    resource シーンノードのリソースです。
314 
315   @return       生成したシーンノードです。。
316  *---------------------------------------------------------------------------*/
317 nw::gfx::SceneNode*
CreateSceneNode(nw::gfx::ResSceneObject resource)318 CreateSceneNode(nw::gfx::ResSceneObject resource)
319 {
320     nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
321         .Resource(resource)
322         .MaxChildren(0)
323         .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
324 
325     return nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
326 }
327 
328 /*!--------------------------------------------------------------------------*
329   @brief        リソース関連の構築をします。
330 *---------------------------------------------------------------------------*/
331 void
BuildResources(ResourceSet * resourceSet)332 BuildResources(ResourceSet* resourceSet)
333 {
334     resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
335     resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
336     resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
337 
338     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
339     if (result.IsFailure())
340     {
341         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
342     }
343 
344     /*
345     リソースでの階層組みは無視します。
346     */
347     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
348 
349     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
350     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
351     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
352         modelResource != modelsEnd; ++modelResource)
353     {
354         nw::gfx::SceneNode* node = CreateSceneNode(*modelResource);
355         NW_NULL_ASSERT(node);
356 
357         sceneNodeArray.push_back(node);
358 
359         if (nw::ut::IsTypeOf<nw::gfx::ParticleModel>(node))
360         {
361             s_ParticleModels.push_back(static_cast<nw::gfx::ParticleModel*>(node));
362 
363             nw::gfx::ParticleModel* particleModel =
364                 static_cast<nw::gfx::ParticleModel*>(node);
365             for (int i = 0; i < particleModel->GetParticleSetsCount(); ++i)
366             {
367                 s_ParticleSets.push_back(particleModel->GetParticleSets(i));
368             }
369         }
370     }
371 
372     nw::gfx::ResEmitterArray emitters = resourceSet->resource.GetEmitters();
373     nw::gfx::ResEmitterArray::iterator emittersEnd = emitters.end();
374     for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
375         emitterResource != emittersEnd; ++emitterResource)
376     {
377         nw::gfx::SceneNode* node = CreateSceneNode(*emitterResource);
378         NW_NULL_ASSERT(node);
379 
380         sceneNodeArray.push_back(node);
381 
382         if (nw::ut::IsTypeOf<nw::gfx::ParticleEmitter>(node))
383         {
384             s_ParticleEmitters.push_back(static_cast<nw::gfx::ParticleEmitter*>(node));
385         }
386     }
387 
388     // 親子付け参照関係を解決
389     //nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
390 
391     nw::gfx::ParticleUtil::SetupParticleObject(&sceneNodeArray, s_ParticleContext);
392 }
393 
394 /*!--------------------------------------------------------------------------*
395   @brief        カメラの構築をします。
396 *---------------------------------------------------------------------------*/
397 void
BuildCameras()398 BuildCameras()
399 {
400     nw::gfx::LookAtTargetViewUpdater* viewUpdater
401         = nw::gfx::LookAtTargetViewUpdater::Create(&s_DeviceAllocator);
402 
403     nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
404         nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(
405             viewUpdater->GetResource());
406     resViewUpdater.SetTargetPosition(0.0f,0.0f,0.0f);
407     resViewUpdater.SetUpwardVector(0.0f,1.0f,0.0f);
408 
409     nw::gfx::PerspectiveProjectionUpdater* projectionUpdater
410         = nw::gfx::PerspectiveProjectionUpdater::Create(&s_DeviceAllocator);
411 
412     nw::gfx::ResPerspectiveProjectionUpdater resProjectionUpdater =
413         nw::gfx::ResStaticCast<nw::gfx::ResPerspectiveProjectionUpdater>(
414             projectionUpdater->GetResource());
415     resProjectionUpdater.SetNear(s_NearPlane);
416     resProjectionUpdater.SetFar(1000.0f);
417     resProjectionUpdater.SetFovy(NW_MATH_DEG_TO_RAD(37.8f));
418 
419     resProjectionUpdater.SetAspectRatio(
420         static_cast<f32>(s_RenderTarget->GetDescription().height) /
421             static_cast<f32>(s_RenderTarget->GetDescription().width));
422 
423     s_BaseCamera =
424         nw::gfx::Camera::DynamicBuilder()
425         .MaxChildren(0)
426         .MaxCallbacks(0)
427         .ViewUpdater(viewUpdater)
428         .ProjectionUpdater(projectionUpdater)
429         .Create(&s_DeviceAllocator);
430     NW_POINTER_ASSERT(s_BaseCamera);
431     s_BaseCamera->Transform().SetTranslate(nw::math::VEC3(28.0f, 22.0f, 28.0f));
432 
433     s_LeftCamera =
434         nw::gfx::Camera::DynamicBuilder()
435         .MaxChildren(0)
436         .MaxCallbacks(0)
437         .Create(&s_DeviceAllocator);
438     NW_POINTER_ASSERT(s_LeftCamera);
439 
440     s_RightCamera =
441         nw::gfx::Camera::DynamicBuilder()
442         .MaxChildren(0)
443         .MaxCallbacks(0)
444         .Create(&s_DeviceAllocator);
445     NW_POINTER_ASSERT(s_RightCamera);
446 
447     s_CameraController =
448         nw::demo::CameraController::Builder()
449         .MaxCameraCount(1)
450         .Create(&s_DeviceAllocator);
451     s_CameraController->Register(s_BaseCamera);
452 }
453 
454 /*!--------------------------------------------------------------------------*
455   @brief        シーンを初期化します。
456 *---------------------------------------------------------------------------*/
457 void
InitializeScenes()458 InitializeScenes()
459 {
460     BuildCameras();
461 
462     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
463     {
464         BuildResources(LoadResources(name));
465     }
466 
467     NW_GL_ASSERT();
468 
469     s_FrameCount = 0;
470 }
471 
472 /*!--------------------------------------------------------------------------*
473   @brief        シーン関連の後始末をします。
474 *---------------------------------------------------------------------------*/
475 void
TerminateScenes()476 TerminateScenes()
477 {
478     nw::gfx::SafeDestroyBranchAll(s_ParticleModels);
479     nw::gfx::SafeDestroyAll(s_ParticleEmitters);
480     s_ParticleSets.clear();
481     nw::demo::SafeCleanupResources(s_Resources);
482     nw::gfx::SafeDestroy(s_BaseCamera);
483     nw::gfx::SafeDestroy(s_LeftCamera);
484     nw::gfx::SafeDestroy(s_RightCamera);
485     nw::gfx::SafeDestroy(s_CameraController);
486 
487     NW_GL_ASSERT();
488 
489     s_Resources.clear();
490 }
491 
492 /*!--------------------------------------------------------------------------*
493   @brief        ノードを更新します。
494  *---------------------------------------------------------------------------*/
495 void
UpdateNode(nw::gfx::TransformNode * node)496 UpdateNode(nw::gfx::TransformNode* node)
497 {
498     // 一度計算したら計算処理をスキップする。
499     // ただし、ツリー構造は正しく解釈されない。
500     if (node->Transform().IsEnabledFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY))
501     {
502         s_WorldMatrixUpdater->UpdateBasic(
503             &node->WorldMatrix(),
504             &node->WorldTransform(),
505             node->Transform(),
506             nw::gfx::CalculatedTransform::Identity(),
507             nw::gfx::CalculatedTransform::Identity());
508 
509         node->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_DIRTY);
510     }
511 }
512 
513 /*!--------------------------------------------------------------------------*
514   @brief        カメラを更新します。
515  *---------------------------------------------------------------------------*/
UpdateCamera()516 void UpdateCamera()
517 {
518     s_CameraController->Update();
519     UpdateNode(s_BaseCamera);
520     s_BaseCamera->UpdateCameraMatrix();
521 
522     // ステレオカメラの計算
523     NW_NULL_ASSERT(s_LeftCamera);
524     NW_NULL_ASSERT(s_RightCamera);
525     NW_NULL_ASSERT(s_BaseCamera);
526     nn::math::MTX44& projOriginal = s_BaseCamera->ProjectionMatrix();
527     nn::math::MTX34& viewOriginal = s_BaseCamera->ViewMatrix();
528     nn::math::MTX44& projL = s_LeftCamera->ProjectionMatrix();
529     nn::math::MTX34& viewL = s_LeftCamera->ViewMatrix();
530     nn::math::MTX44& projR = s_RightCamera->ProjectionMatrix();
531     nn::math::MTX34& viewR = s_RightCamera->ViewMatrix();
532 
533     // Ortho カメラでは別の処理を行う必要があります。
534     // 例として demo::RenderSystem::CalcStereoCamera() を参照してください。
535     const f32 DEPTH_LEVEL = 5.0f + s_NearPlane;
536     const f32 DEPTH_RANGE = 1.0f;
537     s_StereoCamera->CalculateMatrices(
538         &projL,
539         &viewL,
540         &projR,
541         &viewR,
542         &projOriginal,
543         &viewOriginal,
544         DEPTH_LEVEL,
545         DEPTH_RANGE,
546         false);
547 }
548 
549 /*!--------------------------------------------------------------------------*
550   @brief        生成されたノードを更新します。
551  *---------------------------------------------------------------------------*/
UpdateNodes()552 void UpdateNodes()
553 {
554     // モデル更新
555     ParticleModelArray::iterator particleModelEnd = s_ParticleModels.end();
556     for (ParticleModelArray::iterator node = s_ParticleModels.begin(); node != particleModelEnd; ++node)
557     {
558         UpdateNode(*node);
559         (*node)->UpdateParticleFrame();
560     }
561 
562     EmitterArray::iterator particleEmitterEnd = s_ParticleEmitters.end();
563     for (EmitterArray::iterator node = s_ParticleEmitters.begin(); node != particleEmitterEnd; ++node)
564     {
565         UpdateNode(*node);
566         (*node)->UpdateParticleFrame();
567         (*node)->Emission(s_ParticleContext);
568     }
569 
570     ParticleSetArray::iterator particleSetEnd = s_ParticleSets.end();
571     for (ParticleSetArray::iterator node = s_ParticleSets.begin(); node != particleSetEnd; ++node)
572     {
573         (*node)->UpdateParticles(s_ParticleContext);
574     }
575 }
576 
577 /*!--------------------------------------------------------------------------*
578   @brief        カメラ、ライト、フォグなどのシーン環境を設定します。
579  *---------------------------------------------------------------------------*/
580 void
SetEnvironment()581 SetEnvironment()
582 {
583     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderContext->GetSceneEnvironment();
584     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
585 }
586 
587 /*!--------------------------------------------------------------------------*
588   @brief        シーンを更新します。
589  *---------------------------------------------------------------------------*/
590 void
UpdateScene()591 UpdateScene()
592 {
593     UpdateNodes();
594 
595     UpdateCamera();
596 
597     ++s_FrameCount;
598 
599     // デモでは少量のメモリしか扱わないので明示的にフラッシュする必要がある
600     s_FlushCache->Execute();
601 }
602 
603 /*!--------------------------------------------------------------------------*
604   @brief        ビューに関連する更新処理を行います。
605  *---------------------------------------------------------------------------*/
606 void
SubmitView()607 SubmitView()
608 {
609     ParticleModelArray::iterator particleModelEnd = s_ParticleModels.end();
610     for (ParticleModelArray::iterator node = s_ParticleModels.begin(); node != particleModelEnd; ++node)
611     {
612         nw::gfx::ResModel resModel = (*node)->GetResModel();
613         NW_ASSERT(resModel.IsValid());
614         if (!resModel.IsVisible()) {
615             continue;
616         }
617 
618         (*node)->UpdateModelViewMatrixAndNormalMatrix(s_BaseCamera->ViewMatrix(), false);
619     }
620 }
621 
622 /*!--------------------------------------------------------------------------*
623   @brief        シーンを描画します。
624  *---------------------------------------------------------------------------*/
625 void
RenderScene()626 RenderScene()
627 {
628     s_RenderContext->SetRenderTarget(s_RenderTarget);
629     s_RenderContext->SetActiveCamera(0);
630 
631     // 描画コマンドを生成します。
632     s_CommandListSwapper->StartCommandSave();
633     NW_GL_ASSERT();
634 
635     s_RenderContext->ClearBuffer(
636         GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
637         nw::ut::FloatColor(0.5f, 0.5f, 0.5f, 1.0f),
638         1.0f);
639 
640     ParticleModelArray::iterator modelEnd = s_ParticleModels.end();
641     for (ParticleModelArray::iterator model = s_ParticleModels.begin(); model != modelEnd; ++model)
642     {
643         if ((*model)->IsVisible())
644         {
645             nw::gfx::ResMeshArray resMeshes = (*model)->GetResMeshes();
646 
647             nw::gfx::ResMeshArray::iterator meshEnd = resMeshes.end();
648             for(nw::gfx::ResMeshArray::iterator mesh = resMeshes.begin();
649                 mesh != meshEnd;
650                 ++mesh)
651             {
652                 if ((*model)->IsMeshVisible(*mesh))
653                 {
654                     s_MeshRenderer->RenderMesh(*mesh, *model);
655                 }
656             }
657         }
658     }
659     NW_GL_ASSERT();
660 
661     s_CommandListSwapper->EndCommandSave();
662 
663     // 左目の描画を行います。
664     s_RenderContext->SetCameraMatrix(s_LeftCamera);
665     s_CommandListSwapper->ReuseCommand(false);
666     s_UpperSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
667 
668     // 右目の描画を行います。
669     s_RenderContext->SetCameraMatrix(s_RightCamera);
670     s_CommandListSwapper->ReuseCommand(false);
671     s_ExtensionSwapper->MakeTransferBufferCommand(s_RenderTarget, false);
672 
673     s_CommandListSwapper->WaitDone();
674     s_CommandListSwapper->RunAsync();
675 }
676 
677 /*!--------------------------------------------------------------------------*
678   @brief        ディスプレイバッファをスワップして表示します。
679  *---------------------------------------------------------------------------*/
680 void
PresentBuffer()681 PresentBuffer()
682 {
683     s_UpperSwapper->ActivateBuffer();
684     s_ExtensionSwapper->ActivateBuffer();
685 
686     nngxSwapBuffers(NN_GX_DISPLAY0);
687 
688     glBindFramebuffer(GL_FRAMEBUFFER, 0);
689 
690     NW_GL_ASSERT();
691 
692     nngxWaitVSync(NN_GX_DISPLAY0);
693 }
694 
695 /*!--------------------------------------------------------------------------*
696   @brief        シーンをデモンストレーションします。
697  *---------------------------------------------------------------------------*/
698 void
DemoScene()699 DemoScene()
700 {
701     NW_NULL_ASSERT(s_RenderTarget);
702 
703     InitializeScenes();
704 
705     nw::demo::DebugUtility::PostInitializeScenes();
706 
707     s_CommandListSwapper->RunAsync();
708 
709     bool isContinuing = true;
710 
711     while ( isContinuing )
712     {
713         nw::demo::DebugUtility::AdvanceAutoTestFrame();
714 
715         nw::demo::PadFactory::GetPad()->Update();
716 
717         UpdateScene();
718 
719         SetEnvironment();
720 
721         s_RenderContext->SetActiveCamera(s_BaseCameraIndex);
722 
723         SubmitView();
724 
725         RenderScene();
726 
727         s_RenderContext->ResetState();
728 
729         PresentBuffer();
730 
731         if (nw::demo::Utility::IsTerminating())
732         {
733             isContinuing = false;
734         }
735     }
736 
737     nw::demo::DebugUtility::PreTerminateScenes();
738 
739     TerminateScenes();
740 }
741 
742 } // namespace
743 
744 /*!--------------------------------------------------------------------------*
745   @brief        メイン関数です。
746  *---------------------------------------------------------------------------*/
747 void
nnMain()748 nnMain()
749 {
750     InitializeGraphicsSystem();
751 
752     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
753 
754     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_DeviceAllocator, NULL)
755     {
756         InitializeGraphics();
757 
758         s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
759 
760         DemoScene();
761 
762         // キャッシュフラッシュ用のクラスを破棄
763         nw::ut::SafeDestroy(s_FlushCache);
764 
765         TerminateGraphics();
766     }
767 
768     nw::demo::PadFactory::Finalize();
769 
770     FinalizeGraphicsSystem();
771 }
772