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