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