1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ParticleCtrlEmissionDemo.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 #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* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
42 const wchar_t* FONT_FILE_NAME = NW_DEMO_FILE_PATH(L"Font.bcfnt");
43 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
44
45 //----------------------------------------
46 // プロファイル関係
47 const int NW_LOAD_METER_INTERVAL = 60;
48
49 //----------------------------------------
50 // 描画関係
51 const int RENDER_TARGET_COUNT = 1;
52 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
53
54 RenderTargetArray s_RenderTargets;
55 nw::demo::SceneSystem* s_SceneSystem = NULL;
56 nw::demo::RenderSystem* s_RenderSystem = NULL;
57 nw::gfx::ParticleContext* s_ParticleContext = NULL;
58
59 nw::demo::GraphicsDrawing s_GraphicsDrawing;
60
61 //----------------------------------------
62 // リソース関係
63 nw::demo::ResourceArray s_Resources;
64
65 //----------------------------------------
66 // シーン関係
67 nw::gfx::SceneNode* s_SceneRoot = NULL;
68 s32 s_FrameCount = 0;
69 nw::gfx::Camera* s_BaseCamera = NULL;
70 nw::gfx::Camera* s_LeftCamera = NULL;
71 nw::gfx::Camera* s_RightCamera = NULL;
72 const f32 s_fNearPlane = 0.1f;
73
74 const s32 s_BaseCameraIndex = 0;
75
76
77 //----------------------------------------
78 // パーティクル関係
79 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
80
81 nw::demo::FlushCache* s_FlushCache;
82
83 /*!--------------------------------------------------------------------------*
84 @brief グラフィックス関連の初期化を行います。
85 *---------------------------------------------------------------------------*/
86 void
InitializeGraphics()87 InitializeGraphics()
88 {
89 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
90
91 // renderDescriptionへステレオの設定を行います。
92 nw::demo::RenderSystem::Description renderDescription;
93
94 renderDescription.reusableCommandBufferSize = 0x100000;
95 renderDescription.reusableCommandRequestCount = 512;
96 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
97
98 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
99
100 s_GraphicsDrawing.SetScreenSize(
101 renderDescription.lowerScreenDescription.width,
102 renderDescription.lowerScreenDescription.height
103 );
104
105 bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
106
107 NN_ASSERTMSG(result, "Fail to load Font.");
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 @brief ルートノード関連の構築をします。
159 *---------------------------------------------------------------------------*/
160 void
BuildRootNodes()161 BuildRootNodes()
162 {
163 NW_ASSERT(s_SceneRoot == NULL);
164 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
165 .IsFixedSizeMemory(false)
166 .Create(&s_DeviceAllocator);
167 NW_NULL_ASSERT(s_SceneRoot);
168 }
169
170 /*!--------------------------------------------------------------------------*
171 @brief カメラ関連の構築をします。
172 *---------------------------------------------------------------------------*/
173 void
BuildCameras()174 BuildCameras()
175 {
176 nw::demo::Utility::CreateStereoCameras(
177 &s_BaseCamera,
178 &s_LeftCamera,
179 &s_RightCamera,
180 &s_DeviceAllocator,
181 nw::math::VEC3(28.0f, 22.0f, 28.0f),
182 nw::math::VEC3(0.0f, 0.0f, 0.0f),
183 s_fNearPlane
184 );
185
186 s_SceneRoot->AttachChild(s_BaseCamera);
187 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
188 }
189
190 /*!--------------------------------------------------------------------------*
191 @brief シーンを初期化します。
192 *---------------------------------------------------------------------------*/
193 void
InitializeScenes()194 InitializeScenes()
195 {
196 BuildRootNodes();
197
198 BuildCameras();
199
200 // シーンツリーを巡回して初期化を行います。
201 s_SceneSystem->InitializeScene(s_SceneRoot);
202 s_SceneSystem->UpdateScene();
203
204 // カメラを設定します。
205 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
206 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
207 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
208
209 NW_GL_ASSERT();
210
211 s_FrameCount = 0;
212 }
213
214 /*!--------------------------------------------------------------------------*
215 @brief シーン関連の後始末をします。
216 *---------------------------------------------------------------------------*/
217 void
TerminateScenes()218 TerminateScenes()
219 {
220 nw::gfx::SafeDestroyBranch(s_SceneRoot);
221 nw::demo::SafeCleanupResources(s_Resources);
222
223 NW_GL_ASSERT();
224
225 s_Resources.clear();
226 }
227
228 /*!--------------------------------------------------------------------------*
229 @brief シーンを更新します。
230 *---------------------------------------------------------------------------*/
231 void
UpdateScene()232 UpdateScene()
233 {
234 NW_ASSERT(0 < s_RenderTargets.size());
235
236 s_SceneSystem->GetCameraController()->Update();
237
238 s_SceneSystem->UpdateScene();
239
240 s_BaseCamera->UpdateCameraMatrix();
241
242 NW_NULL_ASSERT(s_ParticleSceneUpdater);
243 s_ParticleSceneUpdater->UpdateNode(
244 s_SceneSystem->GetSceneContext(),
245 s_ParticleContext);
246
247 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
248
249 s_FrameCount++;
250
251 s_FlushCache->Execute();
252 }
253
254 /*!--------------------------------------------------------------------------*
255 @brief 負荷表示やテスト機能の処理をおこないます。
256 *---------------------------------------------------------------------------*/
257 void
ReportDemo()258 ReportDemo()
259 {
260 NW_PROFILE("ReportDemo");
261
262 // 負荷表示からはこれらの負荷は除きます。
263 s_RenderSystem->SuspendLoadMeter();
264
265 s_GraphicsDrawing.BeginDrawingString();
266
267 nw::demo::DebugUtility::DrawLoadMeter(
268 s_RenderSystem,
269 &s_GraphicsDrawing,
270 (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
271 );
272
273 s_GraphicsDrawing.FlushDrawing();
274
275 s_RenderSystem->ResumeLoadMeter();
276 }
277
278
279
280
281 //----------------------------------------
282 // デモ固有の変数
283
284 // パーティクルエフェクトクラス
285 nw::demo::ParticleEffect* s_ParticleEffect = NULL;
286
287 // パーティクルノードクラス
288 nw::demo::ParticleNode* s_particleNode = NULL;
289
290 // 放出量
291 f32 s_EmissionRatio = 1.0f;
292
293 // ロードするエフェクトファイル名
294 const wchar_t* EFFECT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl");
295
296
297 /*!--------------------------------------------------------------------------*
298 @brief ParticleCtrlEmissionDemoの初期化を行います。
299 *---------------------------------------------------------------------------*/
300 void
InitializeParticleCtrlEmissionDemo()301 InitializeParticleCtrlEmissionDemo()
302 {
303 // このデモは、パッドのLRを用いて、
304 // パーティクルの放出量の調整を行うデモです。
305 // 放出量の調整は、ParticleNode::SetEmissionRatioメソッドを用いて行います。
306
307 // パーティクルエフェクトクラスを生成します。
308 s_ParticleEffect = nw::demo::ParticleEffect::Create(&s_DeviceAllocator, &s_DeviceAllocator, false, s_ParticleContext);
309
310 // エフェクトデータをロードしてセットアップします。
311 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, EFFECT_RESOURCE_FILE, &s_DeviceAllocator);
312
313 // リソースをセットアップを行います。
314 // fountain_particle_allはコンスタントカラーを使用しているので、ParticleMaterialは使用できません。
315 s_ParticleEffect->Setup(resourceSet->resource, false);
316
317 // ParticleEffectにリソースをセットします。
318 s_ParticleEffect->Register(resourceSet->resource);
319 s_ParticleEffect->AddPool(1);
320
321 // パーティクルノードクラスのインスタンスをリースします。
322 s_particleNode = s_ParticleEffect->LeaseInstance();
323
324 // シーンに追加します。
325 s_SceneRoot->AttachChild(s_particleNode);
326 s_SceneSystem->InitializeScene(s_SceneRoot);
327 s_SceneSystem->UpdateScene();
328
329 // 操作説明をログ出力します。
330 NW_DEV_LOG("[ParticleCtrlEmissionDemo Ctrl]\n");
331 NW_DEV_LOG("l : Decrement Emission Ratio\n");
332 NW_DEV_LOG("r : Additive Emission Ratio\n");
333 }
334
335 /*!--------------------------------------------------------------------------*
336 @brief ParticleCtrlEmissionDemoの定期処理です。
337 *---------------------------------------------------------------------------*/
338 void
UpdateParticleCtrlEmissionDemo()339 UpdateParticleCtrlEmissionDemo()
340 {
341 bool isEmissionRatioUpdate = false;
342
343 // パッドで放出量を操作します。
344 if (nw::demo::PadFactory::GetPad()->IsButtonDown(nw::demo::Pad::BUTTON_L))
345 {
346 s_EmissionRatio -= 0.1f;
347 if (s_EmissionRatio < 0.f)
348 {
349 s_EmissionRatio = 0.f;
350 }
351
352 isEmissionRatioUpdate = true;
353 }
354
355 if (nw::demo::PadFactory::GetPad()->IsButtonDown(nw::demo::Pad::BUTTON_R))
356 {
357 s_EmissionRatio += 0.1f;
358 if (s_EmissionRatio > 2.f)
359 {
360 s_EmissionRatio = 2.f;
361 }
362
363 isEmissionRatioUpdate = true;
364 }
365
366 // 放出量を設定します。
367 if (isEmissionRatioUpdate)
368 {
369 // SetEmissionRatioメソッド内では、
370 // ResParticleEmitterParameter内、SetEmissionRatioメソッドを操作しています。
371 // ResParticleEmitterParameter自体は、
372 // ParticleEmitter::GetResParticleEmitterParameterCopy()にて取得できます。
373 s_particleNode->SetEmissionRatio(s_EmissionRatio);
374 }
375 }
376
377 /*!--------------------------------------------------------------------------*
378 @brief ParticleCtrlEmissionDemoのスクリーンデバッグ表示です。
379 *---------------------------------------------------------------------------*/
380 void
ReportParticleCtrlEmissionDemo()381 ReportParticleCtrlEmissionDemo()
382 {
383 s_GraphicsDrawing.DrawString(10, 10, "Particle Num :%d\n", s_particleNode->GetParticleSize() );
384 s_GraphicsDrawing.DrawString(10, 22, "Emission Ratio:%2.1f/2.0\n", s_EmissionRatio );
385 }
386
387
388 /*!--------------------------------------------------------------------------*
389 @brief ParticleCtrlEmissionDemoの終了処理を行います。
390 *---------------------------------------------------------------------------*/
391 void
TerminateParticleCtrlEmissionDemo()392 TerminateParticleCtrlEmissionDemo()
393 {
394 nw::demo::ParticleNode* prevTarget = s_ParticleEffect->GetActiveEffect(0);
395 while (prevTarget != NULL)
396 {
397 s_ParticleEffect->ReleaseInstance(prevTarget);
398 prevTarget = s_ParticleEffect->GetActiveEffect(0);
399 }
400
401 s_ParticleEffect->FreePool();
402
403 nw::gfx::SafeDestroy(s_ParticleEffect);
404 }
405
406
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 // ParticleCtrlEmissionDemoの初期化処理です。
422 InitializeParticleCtrlEmissionDemo();
423
424 bool isContinuing = true;
425
426 while ( isContinuing )
427 {
428 nw::demo::DebugUtility::AdvanceAutoTestFrame();
429
430 nw::demo::PadFactory::GetPad()->Update();
431
432 // ParticleCtrlEmissionDemoの定期処理です。
433 UpdateParticleCtrlEmissionDemo();
434
435 UpdateScene();
436
437 renderContext->SetActiveCamera(s_BaseCameraIndex);
438 s_RenderSystem->SubmitView(s_SceneSystem);
439
440 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
441 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
442
443 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
444 ReportDemo();
445
446 // ParticleCtrlEmissionDemoのレポートを表示します。
447 ReportParticleCtrlEmissionDemo();
448
449 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
450
451 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
452
453 renderContext->ResetState();
454
455 if (nw::demo::Utility::IsTerminating())
456 {
457 isContinuing = false;
458 }
459 }
460
461 // ParticleCtrlEmissionDemoの終了処理です。
462 TerminateParticleCtrlEmissionDemo();
463
464 TerminateScenes();
465 }
466
467 } // namespace
468
469 /*!--------------------------------------------------------------------------*
470 @brief メイン関数です。
471 *---------------------------------------------------------------------------*/
472 void
nnMain()473 nnMain()
474 {
475 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
476 nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
477
478 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
479
480 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
481 {
482 InitializeGraphics();
483
484 s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
485
486 DemoScene();
487
488 nw::ut::SafeDestroy(s_FlushCache);
489
490 TerminateGraphics();
491 }
492
493 nw::demo::PadFactory::Finalize();
494
495 nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
496
497 nw::demo::FinalizeGraphicsSystem();
498 }
499