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