1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ParticleDemo.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
23 #include <nw/types.h>
24 #include <nw/demo.h>
25 #include <nw/dev.h>
26 #include <nw/gfx.h>
27 #include <nw/ut.h>
28
29 namespace
30 {
31
32 //----------------------------------------
33 // メモリ関係
34
35 // デバイスメモリを確保するためのアロケータです。
36 nw::demo::DemoAllocator s_DeviceAllocator;
37 nw::demo::DemoAllocator s_ParticleAllocator;
38
39 //----------------------------------------
40 // ファイル名の定義です。
41 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
42
43 const wchar_t* MODEL_RESOURCE_FILES[] =
44 {
45 NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl"),
46 NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
47 NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
48 };
49
50 //----------------------------------------
51 // 描画関係
52 const int RENDER_TARGET_COUNT = 1;
53 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
54
55 RenderTargetArray s_RenderTargets;
56 nw::demo::SceneSystem* s_SceneSystem = NULL;
57 nw::demo::RenderSystem* s_RenderSystem = NULL;
58 nw::gfx::ParticleContext* s_ParticleContext = NULL;
59
60 nw::demo::GraphicsDrawing s_GraphicsDrawing;
61
62 //----------------------------------------
63 // リソース関係
64 nw::demo::ResourceArray s_Resources;
65
66 int s_ModelCount = 0;
67 int s_EmitterCount = 0;
68
69 //----------------------------------------
70 // シーン関係
71 const int SCENE_NODE_COUNT = 4;
72 nw::gfx::SceneNode* s_SceneRoot = NULL;
73 s32 s_FrameCount = 0;
74 nw::gfx::Camera* s_BaseCamera = NULL;
75 nw::gfx::Camera* s_LeftCamera = NULL;
76 nw::gfx::Camera* s_RightCamera = NULL;
77 const f32 s_fNearPlane = 0.1f;
78
79 //----------------------------------------
80 // シーン環境関係
81 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
82
83 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
84 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
85
86 const s32 s_BaseCameraIndex = 0;
87
88 //----------------------------------------
89 // パーティクル関係
90 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
91
92 nw::demo::FlushCache* s_FlushCache;
93
94 /*!--------------------------------------------------------------------------*
95 @brief グラフィックス関連の初期化を行います。
96 *---------------------------------------------------------------------------*/
97 void
InitializeGraphics()98 InitializeGraphics()
99 {
100 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
101
102 // renderDescriptionへステレオの設定を行います。
103 nw::demo::RenderSystem::Description renderDescription;
104
105 renderDescription.reusableCommandBufferSize = 0x100000;
106 renderDescription.reusableCommandRequestCount = 512;
107 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
108
109 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
110
111 s_GraphicsDrawing.SetScreenSize(
112 renderDescription.lowerScreenDescription.width,
113 renderDescription.lowerScreenDescription.height
114 );
115
116 nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
117
118 s_RenderTargets.push_back(
119 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
120 );
121 NW_ASSERT(!s_RenderTargets.empty());
122 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
123
124 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
125 nw::demo::SceneSystem::Description sceneDescription;
126 sceneDescription.isFixedSizeMemory = true;
127 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
128
129 // ParticleContextを生成します。
130 s_ParticleContext = nw::gfx::ParticleContext::Builder()
131 .MaxEmission(1000)
132 .Create(&s_DeviceAllocator);
133
134 // ParticleSceneUpdaterを生成します。
135 s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
136 .Create(&s_DeviceAllocator);
137
138 // デモ用の最遠景モデルをレンダリングシステムに設定します。
139 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
140 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
141
142 NW_GL_ASSERT();
143 }
144
145 /*!--------------------------------------------------------------------------*
146 @brief グラフィックス関連の後始末をします。
147 *---------------------------------------------------------------------------*/
148 void
TerminateGraphics()149 TerminateGraphics()
150 {
151 nw::gfx::SafeDestroy(s_LeftCamera);
152
153 nw::gfx::SafeDestroy(s_RightCamera);
154
155 nw::gfx::SafeDestroy(s_ParticleSceneUpdater);
156
157 nw::gfx::SafeDestroy(s_ParticleContext);
158
159 nw::gfx::SafeDestroy(s_SceneSystem);
160
161 nw::gfx::SafeDestroyAll(s_RenderTargets);
162
163 s_GraphicsDrawing.Finalize();
164
165 nw::gfx::SafeDestroy(s_RenderSystem);
166
167 NW_GL_ASSERT();
168 }
169
170 /*!--------------------------------------------------------------------------*
171 @brief 再生ステップを設定します。
172
173 @param[in] 再生ステップです。
174 *---------------------------------------------------------------------------*/
175 void
SetStepFrame(f32 stepFrame)176 SetStepFrame(f32 stepFrame)
177 {
178 nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
179
180 nw::gfx::SceneNodeArray::iterator end = sceneContext->GetSceneNodesEnd();
181 for (nw::gfx::SceneNodeArray::iterator i = sceneContext->GetSceneNodesBegin(); i != end; ++i)
182 {
183 nw::gfx::ParticleEmitter* emitter = nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(*i);
184 if (emitter != NULL)
185 {
186 emitter->ParticleAnimFrameController().SetStepFrame(stepFrame);
187 }
188 else
189 {
190 nw::gfx::ParticleModel* model = nw::ut::DynamicCast<nw::gfx::ParticleModel*>(*i);
191 if (model != NULL)
192 {
193 model->ParticleAnimFrameController().SetStepFrame(stepFrame);
194 }
195 }
196 }
197 }
198
199 /*!--------------------------------------------------------------------------*
200 @brief ルートノード関連の構築をします。
201 *---------------------------------------------------------------------------*/
202 void
BuildRootNodes()203 BuildRootNodes()
204 {
205 NW_ASSERT(s_SceneRoot == NULL);
206 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
207 .Create(&s_DeviceAllocator);
208 NW_NULL_ASSERT(s_SceneRoot);
209 }
210
211 /*!--------------------------------------------------------------------------*
212 @brief カメラ関連の構築をします。
213 *---------------------------------------------------------------------------*/
214 void
BuildCameras()215 BuildCameras()
216 {
217 nw::demo::Utility::CreateStereoCameras(
218 &s_BaseCamera,
219 &s_LeftCamera,
220 &s_RightCamera,
221 &s_DeviceAllocator,
222 nw::math::VEC3(28.0f, 22.0f, 28.0f),
223 nw::math::VEC3(0.0f, 0.0f, 0.0f),
224 s_fNearPlane
225 );
226
227 s_SceneRoot->AttachChild(s_BaseCamera);
228 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
229 }
230
231 /*!--------------------------------------------------------------------------*
232 @brief リソース関連の構築をします。
233 *---------------------------------------------------------------------------*/
234 void
BuildResources(nw::demo::ResourceSet * resourceSet)235 BuildResources(nw::demo::ResourceSet* resourceSet)
236 {
237 // テクスチャリソースをVRAMに配置します。
238 resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
239
240 // リソースのセットアップを行います。
241 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
242
243 if (result.IsFailure())
244 {
245 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
246 }
247
248 // 生成したノードを格納する配列です。
249 nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
250
251 // ResModelArray から ParticleModel インスタンスを生成します。
252 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
253 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
254 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
255 modelResource != modelsEnd; ++modelResource)
256 {
257 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
258 &s_ParticleAllocator,
259 (*modelResource)
260 );
261 if (node != NULL)
262 {
263 sceneNodeArray.push_back(node);
264 s_ModelCount++;
265 }
266 }
267
268 // ResEmitterArray から ParticleEmitter インスタンスを生成します。
269 nw::gfx::ResEmitterArray emitters = resourceSet->resource.GetEmitters();
270 for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
271 emitterResource != emitters.end(); ++emitterResource)
272 {
273 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
274 &s_ParticleAllocator,
275 (*emitterResource)
276 );
277 if (node != NULL)
278 {
279 sceneNodeArray.push_back(node);
280 s_EmitterCount++;
281 }
282 }
283
284 // 親子付け参照関係を解決します。
285 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
286
287 // パーティクル独自の初期設定を行います。
288 nw::gfx::ParticleUtil::SetupParticleObject(&sceneNodeArray, s_ParticleContext);
289
290 // モデルとエミッタをシーンツリーに追加します。
291 nw::gfx::SceneHelper::ForeachRootNodes(
292 sceneNodeArray.Begin(),
293 sceneNodeArray.End(),
294 nw::gfx::AttachNode(s_SceneRoot)
295 );
296 }
297
298 /*!--------------------------------------------------------------------------*
299 @brief シーンを初期化します。
300 *---------------------------------------------------------------------------*/
301 void
InitializeScenes()302 InitializeScenes()
303 {
304 BuildRootNodes();
305
306 BuildCameras();
307
308 // リソースをロードして、セットアップを行います。
309 NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
310 {
311 BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
312 }
313 NW_ASSERT(s_ModelCount > 0);
314 NW_ASSERT(s_EmitterCount > 0);
315
316 // シーンツリーを巡回して初期化を行います。
317 s_SceneSystem->InitializeScene(s_SceneRoot);
318 s_SceneSystem->UpdateScene();
319
320 // シーン環境の参照解決を行い設定します。
321 s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
322
323 // カメラを設定します。
324 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
325 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
326 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
327
328 NW_GL_ASSERT();
329
330 s_FrameCount = 0;
331 }
332
333 /*!--------------------------------------------------------------------------*
334 @brief シーン関連の後始末をします。
335 *---------------------------------------------------------------------------*/
336 void
TerminateScenes()337 TerminateScenes()
338 {
339 nw::gfx::SafeDestroyBranch(s_SceneRoot);
340 nw::demo::SafeCleanupResources(s_Resources);
341 nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
342
343 NW_GL_ASSERT();
344
345 s_Resources.clear();
346 s_SceneEnvironmentSettings.clear();
347 }
348
349 /*!--------------------------------------------------------------------------*
350 @brief シーンを更新します。
351 *---------------------------------------------------------------------------*/
352 void
UpdateScene()353 UpdateScene()
354 {
355 NW_ASSERT(0 < s_RenderTargets.size());
356
357 s_SceneSystem->GetCameraController()->Update();
358
359 s_SceneSystem->UpdateScene();
360
361 s_BaseCamera->UpdateCameraMatrix();
362
363 NW_NULL_ASSERT(s_ParticleSceneUpdater);
364 s_ParticleSceneUpdater->UpdateNode(
365 s_SceneSystem->GetSceneContext(),
366 s_ParticleContext);
367
368 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
369
370 s_FrameCount++;
371
372 s_FlushCache->Execute();
373 }
374
375 /*!--------------------------------------------------------------------------*
376 @brief 負荷表示やテスト機能の処理をおこないます。
377 *---------------------------------------------------------------------------*/
378 void
ReportDemo()379 ReportDemo()
380 {
381 NW_PROFILE("ReportDemo");
382
383 // 負荷表示からはこれらの負荷は除きます。
384 s_RenderSystem->SuspendLoadMeter();
385
386 nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
387
388 s_GraphicsDrawing.BeginDrawingShape();
389
390 nw::demo::DebugUtility::DrawLoadMeter(
391 s_RenderSystem,
392 &s_GraphicsDrawing
393 );
394
395 s_GraphicsDrawing.EndDrawingShape();
396
397 s_GraphicsDrawing.BeginDrawingString();
398
399 nw::demo::DebugUtility::DrawLoadMeterText(
400 s_RenderSystem,
401 &s_GraphicsDrawing
402 );
403
404 s_GraphicsDrawing.EndDrawingString();
405
406 s_RenderSystem->ResumeLoadMeter();
407 }
408
409 /*!--------------------------------------------------------------------------*
410 @brief シーンをデモンストレーションします。
411 *---------------------------------------------------------------------------*/
412 void
DemoScene()413 DemoScene()
414 {
415 NW_ASSERT(!s_RenderTargets.empty());
416
417 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
418
419 InitializeScenes();
420
421 nw::demo::DebugUtility::PostInitializeScenes();
422
423 bool isContinuing = true;
424
425 while ( isContinuing )
426 {
427 nw::demo::DebugUtility::AdvanceAutoTestFrame();
428
429 nw::demo::PadFactory::GetPad()->Update();
430
431 SetStepFrame(1.0f);
432 UpdateScene();
433
434 renderContext->SetActiveCamera(s_BaseCameraIndex);
435 s_RenderSystem->SubmitView(s_SceneSystem);
436
437 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
438 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
439
440 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
441 ReportDemo();
442 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
443
444 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
445
446 renderContext->ResetState();
447
448 if (nw::demo::Utility::IsTerminating())
449 {
450 isContinuing = false;
451 }
452 }
453
454 nw::demo::DebugUtility::PreTerminateScenes();
455
456 TerminateScenes();
457 }
458
459 } // namespace
460
461 /*!--------------------------------------------------------------------------*
462 @brief メイン関数です。
463 *---------------------------------------------------------------------------*/
464 void
nnMain()465 nnMain()
466 {
467 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
468 nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
469
470 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
471
472 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
473 {
474 InitializeGraphics();
475
476 // キャッシュフラッシュ用のクラスを生成(通常のアプリでは必要ありません)
477 s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
478
479 DemoScene();
480
481 // キャッシュフラッシュ用のクラスを破棄
482 nw::ut::SafeDestroy(s_FlushCache);
483
484 TerminateGraphics();
485 }
486
487 nw::demo::PadFactory::Finalize();
488
489 nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
490
491 nw::demo::FinalizeGraphicsSystem();
492 }
493