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