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