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