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