1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ParticleChokeDemo.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: 25967 $
14 *---------------------------------------------------------------------------*/
15 /*
16 エミッタからの放出を停止し、全てのパーティクルの終了を待つデモです。
17 */
18
19 #define NW_DEBUG_CHECK_MEMORY_LEAK
20
21 #include <nn/os.h>
22 #include <nn/fs.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 nw::demo::DemoAllocator s_DeviceAllocator;
38 nw::demo::DemoAllocator s_ParticleAllocator;
39
40 //----------------------------------------
41 // ファイル名の定義です。
42 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
43 const wchar_t* FONT_FILE_NAME = NW_DEMO_FILE_PATH(L"Font.bcfnt");
44 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
45
46 const wchar_t* MODEL_RESOURCE_FILES[] =
47 {
48 NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl"),
49 NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
50 NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
51 };
52
53 //----------------------------------------
54 // プロファイル関係
55 const int NW_LOAD_METER_INTERVAL = 60;
56
57 //----------------------------------------
58 // 描画関係
59 const int RENDER_TARGET_COUNT = 1;
60 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
61
62 RenderTargetArray s_RenderTargets;
63 nw::demo::SceneSystem* s_SceneSystem = NULL;
64 nw::demo::RenderSystem* s_RenderSystem = NULL;
65 nw::gfx::ParticleContext* s_ParticleContext = NULL;
66
67 nw::demo::GraphicsDrawing s_GraphicsDrawing;
68
69 //----------------------------------------
70 // リソース関係
71 nw::demo::ResourceArray s_Resources;
72
73 //----------------------------------------
74 // シーン関係
75 nw::gfx::SceneNode* s_SceneRoot = NULL;
76 s32 s_FrameCount = 0;
77 nw::gfx::Camera* s_BaseCamera = NULL;
78 nw::gfx::Camera* s_LeftCamera = NULL;
79 nw::gfx::Camera* s_RightCamera = NULL;
80 const f32 s_fNearPlane = 0.1f;
81
82 const s32 s_BaseCameraIndex = 0;
83
84 //----------------------------------------
85 // パーティクル関係
86 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
87
88 nw::demo::FlushCache* s_FlushCache;
89
90
91 /*!--------------------------------------------------------------------------*
92 @brief グラフィックス関連の初期化を行います。
93 *---------------------------------------------------------------------------*/
94 void
InitializeGraphics()95 InitializeGraphics()
96 {
97 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
98
99 // renderDescriptionへステレオの設定を行います。
100 nw::demo::RenderSystem::Description renderDescription;
101
102 renderDescription.reusableCommandBufferSize = 0x100000;
103 renderDescription.reusableCommandRequestCount = 512;
104 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
105
106 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
107
108 s_GraphicsDrawing.SetScreenSize(
109 renderDescription.lowerScreenDescription.width,
110 renderDescription.lowerScreenDescription.height
111 );
112 bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
113
114 NN_ASSERTMSG(result, "Fail to load Font.");
115
116 s_RenderTargets.push_back(
117 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
118 );
119 NW_ASSERT(!s_RenderTargets.empty());
120 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
121
122 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
123 nw::demo::SceneSystem::Description sceneDescription;
124 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
125
126 s_ParticleContext = nw::gfx::ParticleContext::Builder()
127 .Create(&s_DeviceAllocator);
128
129 s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
130 .Create(&s_DeviceAllocator);
131
132 // デモ用の最遠景モデルをレンダリングシステムに設定します。
133 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
134 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
135
136 NW_GL_ASSERT();
137 }
138
139 /*!--------------------------------------------------------------------------*
140 @brief グラフィックス関連の後始末をします。
141 *---------------------------------------------------------------------------*/
142 void
TerminateGraphics()143 TerminateGraphics()
144 {
145 nw::gfx::SafeDestroy(s_LeftCamera);
146
147 nw::gfx::SafeDestroy(s_RightCamera);
148
149 nw::gfx::SafeDestroy(s_ParticleSceneUpdater);
150
151 nw::gfx::SafeDestroy(s_ParticleContext);
152
153 nw::gfx::SafeDestroy(s_SceneSystem);
154
155 nw::gfx::SafeDestroyAll(s_RenderTargets);
156
157 s_GraphicsDrawing.Finalize();
158
159 nw::gfx::SafeDestroy(s_RenderSystem);
160
161 NW_GL_ASSERT();
162 }
163
164
165 /*!--------------------------------------------------------------------------*
166 @brief ルートノード関連の構築をします。
167 *---------------------------------------------------------------------------*/
168 void
BuildRootNodes()169 BuildRootNodes()
170 {
171 NW_ASSERT(s_SceneRoot == NULL);
172 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
173 .IsFixedSizeMemory(false)
174 .Create(&s_DeviceAllocator);
175 NW_NULL_ASSERT(s_SceneRoot);
176 }
177
178 /*!--------------------------------------------------------------------------*
179 @brief カメラ関連の構築をします。
180 *---------------------------------------------------------------------------*/
181 void
BuildCameras()182 BuildCameras()
183 {
184 nw::demo::Utility::CreateStereoCameras(
185 &s_BaseCamera,
186 &s_LeftCamera,
187 &s_RightCamera,
188 &s_DeviceAllocator,
189 nw::math::VEC3(28.0f, 22.0f, 28.0f),
190 nw::math::VEC3(0.0f, 0.0f, 0.0f),
191 s_fNearPlane
192 );
193
194 s_SceneRoot->AttachChild(s_BaseCamera);
195 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
196 }
197
198
199 /*!--------------------------------------------------------------------------*
200 @brief シーンを初期化します。
201 *---------------------------------------------------------------------------*/
202 void
InitializeScenes()203 InitializeScenes()
204 {
205 BuildRootNodes();
206
207 BuildCameras();
208
209 // シーンツリーを巡回して初期化を行います。
210 s_SceneSystem->InitializeScene(s_SceneRoot);
211 s_SceneSystem->UpdateScene();
212
213 // カメラを設定します。
214 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
215 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
216 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
217
218 NW_GL_ASSERT();
219
220 //-----------------------------------------------------------------------------
221 s_FrameCount = 0;
222 }
223
224 /*!--------------------------------------------------------------------------*
225 @brief シーン関連の後始末をします。
226 *---------------------------------------------------------------------------*/
227 void
TerminateScenes()228 TerminateScenes()
229 {
230 nw::gfx::SafeDestroyBranch(s_SceneRoot);
231 nw::demo::SafeCleanupResources(s_Resources);
232
233 NW_GL_ASSERT();
234
235 s_Resources.clear();
236 }
237
238 /*!--------------------------------------------------------------------------*
239 @brief シーンを更新します。
240 *---------------------------------------------------------------------------*/
241 void
UpdateScene()242 UpdateScene()
243 {
244 NW_ASSERT(0 < s_RenderTargets.size());
245
246 s_SceneSystem->GetCameraController()->Update();
247
248 s_SceneSystem->UpdateScene();
249
250 s_BaseCamera->UpdateCameraMatrix();
251
252 NW_NULL_ASSERT(s_ParticleSceneUpdater);
253 s_ParticleSceneUpdater->UpdateNode(
254 s_SceneSystem->GetSceneContext(),
255 s_ParticleContext);
256
257 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
258
259 s_FrameCount++;
260
261 s_FlushCache->Execute();
262 }
263
264 /*!--------------------------------------------------------------------------*
265 @brief 負荷表示やテスト機能の処理をおこないます。
266 *---------------------------------------------------------------------------*/
267 void
ReportDemo()268 ReportDemo()
269 {
270 NW_PROFILE("ReportDemo");
271
272 // 負荷表示からはこれらの負荷は除きます。
273 s_RenderSystem->SuspendLoadMeter();
274
275 s_GraphicsDrawing.BeginDrawingString();
276
277 nw::demo::DebugUtility::DrawLoadMeter(
278 s_RenderSystem,
279 &s_GraphicsDrawing,
280 (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
281 );
282
283 s_GraphicsDrawing.FlushDrawing();
284
285 s_RenderSystem->ResumeLoadMeter();
286 }
287
288
289
290
291 //----------------------------------------
292 // デモ固有の変数
293
294 // パーティクルエフェクトクラス
295 nw::demo::ParticleEffect* s_ParticleEffect = NULL;
296
297 // パーティクルノードクラス
298 nw::demo::ParticleNode* s_particleNode = NULL;
299
300 // 親ノード
301 nw::gfx::SceneNode* s_ParentNode = NULL;
302
303 // 再生が終了しているか?
304 bool s_IsDone = false;
305
306 // ロードするエフェクトファイル名
307 const wchar_t* EFFECT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"light_particle.bcptl");
308
309
310 /*!--------------------------------------------------------------------------*
311 @brief ParticleChokeDemoの初期化を行います。
312 *---------------------------------------------------------------------------*/
313 void
InitializeParticleChokeDemo()314 InitializeParticleChokeDemo()
315 {
316 // このデモは、パーティクルの終了を検知、パーティクルの再利用を行っています。
317
318 // パーティクルエフェクトクラスを生成します。
319 s_ParticleEffect = nw::demo::ParticleEffect::Create(&s_DeviceAllocator, &s_DeviceAllocator, false, s_ParticleContext);
320
321 // エフェクトデータをロードしてセットアップします。
322 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, EFFECT_RESOURCE_FILE, &s_DeviceAllocator);
323
324 // リソースをセットアップを行います。
325 s_ParticleEffect->Setup(resourceSet->resource, true);
326
327 // ParticleEffectにリソースをセットします。
328 s_ParticleEffect->Register(resourceSet->resource);
329
330 // ParticleEffect内にインスタンスを1つだけ準備します。
331 s_ParticleEffect->AddPool(1);
332
333 // ParticleEffect内に準備されたインスタンスを借りてきます。
334 s_particleNode = s_ParticleEffect->LeaseInstance();
335
336 // インスタンスをシーンに追加し、シーンの更新を行います。
337 s_SceneRoot->AttachChild(s_particleNode);
338 s_SceneSystem->InitializeScene(s_SceneRoot);
339 s_SceneSystem->UpdateScene();
340
341 // このデモでは、親ノードへAttach,Detachを行うので、親ノードを保持します。
342 s_ParentNode = s_particleNode->GetParent();
343
344 // 操作説明をログ出力します。
345 NW_DEV_LOG("[ParticleChokeDemo]\n");
346 NW_DEV_LOG("Button R : Restart Partcile\n");
347 }
348
349 /*!--------------------------------------------------------------------------*
350 @brief ParticleChokeDemoの定期処理です。
351 *---------------------------------------------------------------------------*/
352 void
UpdateParticleChokeDemo()353 UpdateParticleChokeDemo()
354 {
355 // 再生が終了しているかチェックします。
356 // IsDoneメソッド内では、ParticleModelが保持するパーティクル数と、
357 // ParticleEmitterの放出完了かどうかをチェックします。
358 if ( !s_IsDone && s_particleNode->IsDone() )
359 {
360 // 再生が終了しているのであれば、Detachを行います。
361 // 再生終了したエフェクトのDetachを行うことで、
362 // 余計なシーングラフのコストを省きます。
363 s_ParentNode->DetachChild(s_particleNode);
364 s_SceneSystem->InitializeScene(s_SceneRoot);
365 s_IsDone = true;
366 }
367
368 // 終了状態、且つ、Rボタンでリセットします。
369 if (s_IsDone && nw::demo::PadFactory::GetPad()->IsButtonDown(nw::demo::Pad::BUTTON_R))
370 {
371 // Resetメソッド内では、ParticleEmitterのリセット処理、
372 // ParticleModel内、アニメーションフレームの0初期化、
373 // 及び、ParticleCollectionのClear処理が行われています。
374 // また、コマンド2重化時には、ResetメソッドをGPU処理中にコールすることができません。
375 // Detachした後、GPU処理が終了の後、コールしてください。
376 s_particleNode->Reset();
377
378 // リセット処理ののち、シーングラフ再度Attachを行います。
379 s_ParentNode->AttachChild(s_particleNode);
380 s_SceneSystem->InitializeScene(s_SceneRoot);
381 s_IsDone = false;
382 }
383 }
384
385 /*!--------------------------------------------------------------------------*
386 @brief ParticleChokeDemoのスクリーンデバッグ表示です。
387 *---------------------------------------------------------------------------*/
388 void
ReportParticleChokeDemo()389 ReportParticleChokeDemo()
390 {
391 s_GraphicsDrawing.DrawString(10, 10, "Particle Num :%d\n", s_particleNode->GetParticleSize() );
392
393 if (s_IsDone)
394 {
395 s_GraphicsDrawing.DrawString(10, 22, "Done:Push R Restart!\n" );
396 }
397 else
398 {
399 s_GraphicsDrawing.DrawString(10, 22, "Playing\n" );
400 }
401 }
402
403
404 /*!--------------------------------------------------------------------------*
405 @brief ParticleChokeDemoの終了処理を行います。
406 *---------------------------------------------------------------------------*/
407 void
TerminateParticleChokeDemo()408 TerminateParticleChokeDemo()
409 {
410 nw::demo::ParticleNode* prevTarget = s_ParticleEffect->GetActiveEffect(0);
411 while (prevTarget != NULL)
412 {
413 s_ParticleEffect->ReleaseInstance(prevTarget);
414 prevTarget = s_ParticleEffect->GetActiveEffect(0);
415 }
416
417 s_ParticleEffect->FreePool();
418
419 nw::gfx::SafeDestroy(s_ParticleEffect);
420 }
421
422
423
424
425 /*!--------------------------------------------------------------------------*
426 @brief シーンをデモンストレーションします。
427 *---------------------------------------------------------------------------*/
428 void
DemoScene()429 DemoScene()
430 {
431 NW_ASSERT(!s_RenderTargets.empty());
432
433 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
434
435 InitializeScenes();
436
437 // ParticleChokeDemoの初期化処理です。
438 InitializeParticleChokeDemo();
439
440 int count = 0;
441 bool isContinuing = true;
442
443 while ( isContinuing )
444 {
445 nw::demo::DebugUtility::AdvanceAutoTestFrame();
446
447 nw::demo::PadFactory::GetPad()->Update();
448
449 ++count;
450
451 // ParticleChokeDemoの定期処理です。
452 UpdateParticleChokeDemo();
453
454 UpdateScene();
455
456 renderContext->SetActiveCamera(s_BaseCameraIndex);
457 s_RenderSystem->SubmitView(s_SceneSystem);
458
459 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
460 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
461
462 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
463 ReportDemo();
464
465 // ParticleCtrlEmissionDemoのレポートを表示します。
466 ReportParticleChokeDemo();
467
468 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
469
470 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
471
472 renderContext->ResetState();
473
474 if (nw::demo::Utility::IsTerminating())
475 {
476 isContinuing = false;
477 }
478 }
479
480 // ParticleChokeDemoの終了処理です。
481 TerminateParticleChokeDemo();
482
483 TerminateScenes();
484 }
485
486 } // namespace
487
488 /*!--------------------------------------------------------------------------*
489 @brief メイン関数です。
490 *---------------------------------------------------------------------------*/
491 void
nnMain()492 nnMain()
493 {
494 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
495 nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
496
497 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
498
499 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
500 {
501 InitializeGraphics();
502
503 s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
504
505 DemoScene();
506
507 nw::ut::SafeDestroy(s_FlushCache);
508
509 TerminateGraphics();
510 }
511
512 nw::demo::PadFactory::Finalize();
513
514 nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
515
516 nw::demo::FinalizeGraphicsSystem();
517 }
518