1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ParticleRecycleDemo.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 #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 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
73 
74 nw::demo::FlushCache* s_FlushCache;
75 
76 /*!--------------------------------------------------------------------------*
77   @brief        グラフィックス関連の初期化を行います。
78  *---------------------------------------------------------------------------*/
79 void
InitializeGraphics()80 InitializeGraphics()
81 {
82     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
83 
84     // renderDescriptionへステレオの設定を行います。
85     nw::demo::RenderSystem::Description renderDescription;
86 
87     renderDescription.reusableCommandBufferSize = 0x100000;
88     renderDescription.reusableCommandRequestCount      = 512;
89     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
90 
91     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
92 
93     s_GraphicsDrawing.SetScreenSize(
94         renderDescription.lowerScreenDescription.width,
95         renderDescription.lowerScreenDescription.height
96     );
97 
98     nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
99 
100     s_RenderTargets.push_back(
101         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
102     );
103     NW_ASSERT(!s_RenderTargets.empty());
104     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
105 
106     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
107     nw::demo::SceneSystem::Description sceneDescription;
108     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
109 
110     s_ParticleContext = nw::gfx::ParticleContext::Builder()
111         .Create(&s_DeviceAllocator);
112 
113     s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
114         .Create(&s_DeviceAllocator);
115 
116     // デモ用の最遠景モデルをレンダリングシステムに設定します。
117     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
118     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
119 
120     NW_GL_ASSERT();
121 }
122 
123 /*!--------------------------------------------------------------------------*
124   @brief        グラフィックス関連の後始末をします。
125  *---------------------------------------------------------------------------*/
126 void
TerminateGraphics()127 TerminateGraphics()
128 {
129     nw::gfx::SafeDestroy(s_LeftCamera);
130 
131     nw::gfx::SafeDestroy(s_RightCamera);
132 
133     nw::gfx::SafeDestroy(s_ParticleSceneUpdater);
134 
135     nw::gfx::SafeDestroy(s_ParticleContext);
136 
137     nw::gfx::SafeDestroy(s_SceneSystem);
138 
139     nw::gfx::SafeDestroyAll(s_RenderTargets);
140 
141     s_GraphicsDrawing.Finalize();
142 
143     nw::gfx::SafeDestroy(s_RenderSystem);
144 
145     NW_GL_ASSERT();
146 }
147 
148 /*!--------------------------------------------------------------------------*
149   @brief        ルートノード関連の構築をします。
150  *---------------------------------------------------------------------------*/
151 void
BuildRootNodes()152 BuildRootNodes()
153 {
154     NW_ASSERT(s_SceneRoot == NULL);
155     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
156         .IsFixedSizeMemory(false)
157         .Create(&s_DeviceAllocator);
158     NW_NULL_ASSERT(s_SceneRoot);
159 }
160 
161 /*!--------------------------------------------------------------------------*
162   @brief        カメラ関連の構築をします。
163  *---------------------------------------------------------------------------*/
164 void
BuildCameras()165 BuildCameras()
166 {
167     nw::demo::Utility::CreateStereoCameras(
168         &s_BaseCamera,
169         &s_LeftCamera,
170         &s_RightCamera,
171         &s_DeviceAllocator,
172         nw::math::VEC3(28.0f, 22.0f, 28.0f),
173         nw::math::VEC3(0.0f, 0.0f, 0.0f),
174         s_fNearPlane
175     );
176 
177     s_SceneRoot->AttachChild(s_BaseCamera);
178     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
179 }
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 nw::gfx::SceneNode* s_ParentNode = NULL;
294 
295 // カウンタ
296 u32 s_Count = 0;
297 
298 // ロードするエフェクトファイル名
299 const wchar_t* EFFECT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl");
300 
301 // ロードするエフェクトシェーダファイル
302 const wchar_t* SHADER_RESOURCE_FILE_NAME = NW_DEMO_FILE_PATH(L"nwgfx_ParticleDefaultShader.bcsdr");
303 
304 
305 /*!--------------------------------------------------------------------------*
306   @brief        ParticleRecycleDemoの初期化を行います。
307  *---------------------------------------------------------------------------*/
308 void
InitializeParticleRecycleDemo()309 InitializeParticleRecycleDemo()
310 {
311     // シェーダバイナリをロードします。
312     nw::demo::ParticleEffect::InitializeShaderBinary(SHADER_RESOURCE_FILE_NAME, &s_DeviceAllocator);
313 
314     // パーティクルエフェクトクラスを生成します。
315     s_ParticleEffect = nw::demo::ParticleEffect::Create(&s_DeviceAllocator, &s_DeviceAllocator, false, s_ParticleContext);
316 
317     // エフェクトデータをロードしてセットアップします。
318     nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, EFFECT_RESOURCE_FILE, &s_DeviceAllocator);
319 
320     // リソースのセットアップを行います。
321     // fountain_particle_allはコンスタントカラーを使用しているので、ParticleMaterialは使用できません。
322     s_ParticleEffect->Setup(resourceSet->resource, false);
323 
324     // ParticleEffectにリソースをセットします。
325     s_ParticleEffect->Register(resourceSet->resource);
326     s_ParticleEffect->AddPool(1);
327 
328     // パーティクルノードクラスのインスタンスをリースします。
329     s_particleNode = s_ParticleEffect->LeaseInstance();
330 
331     // シーンに追加します。
332     s_SceneRoot->AttachChild(s_particleNode);
333     s_SceneSystem->InitializeScene(s_SceneRoot);
334     s_SceneSystem->UpdateScene();
335 
336     // このデモでは、親ノードへAttach,Detachを行うので、親ノードを保持します。
337     s_ParentNode = s_particleNode->GetParent();
338 }
339 
340 /*!--------------------------------------------------------------------------*
341   @brief        ParticleRecycleDemoの定期処理です。
342  *---------------------------------------------------------------------------*/
343 void
UpdateParticleRecycleDemo()344 UpdateParticleRecycleDemo()
345 {
346     ++s_Count;
347 
348     if (s_Count % 180 == 120)
349     {
350         // シーンツリーからパーティクルを取り外します。
351         s_ParentNode->DetachChild(s_particleNode);
352         s_SceneSystem->InitializeScene(s_SceneRoot);
353     }
354 
355     if (s_Count % 180 == 179)
356     {
357         // パーティクルを初期状態に戻し再利用します。
358         // Resetメソッド内では、ParticleEmitterのリセット処理、
359         // ParticleModel内、アニメーションフレームの0初期化、
360         // 及び、ParticleCollectionのClear処理が行われています。
361         // また、コマンド2重化時には、ResetメソッドをGPU処理中にコールすることができません。
362         // Detachした後、GPU処理が終了の後、コールしてください。
363         s_particleNode->Reset();
364 
365         //  シーンツリーに初期化したパーティクルを取り付けます。
366         s_ParentNode->AttachChild(s_particleNode);
367         s_SceneSystem->InitializeScene(s_SceneRoot);
368     }
369 }
370 
371 /*!--------------------------------------------------------------------------*
372   @brief        ParticleRecycleDemoの終了処理を行います。
373  *---------------------------------------------------------------------------*/
374 void
TerminateParticleRecycleDemo()375 TerminateParticleRecycleDemo()
376 {
377     nw::demo::ParticleNode* prevTarget = s_ParticleEffect->GetActiveEffect(0);
378     while (prevTarget != NULL)
379     {
380         s_ParticleEffect->ReleaseInstance(prevTarget);
381         prevTarget = s_ParticleEffect->GetActiveEffect(0);
382     }
383 
384     s_ParticleEffect->FreePool();
385 
386     nw::gfx::SafeDestroy(s_ParticleEffect);
387 
388     // ロードしたパーティクルシェーダを破棄します。
389     nw::demo::ParticleEffect::FinalizeShaderBinary();
390 }
391 
392 
393 
394 
395 /*!--------------------------------------------------------------------------*
396   @brief        シーンをデモンストレーションします。
397  *---------------------------------------------------------------------------*/
398 void
DemoScene()399 DemoScene()
400 {
401     NW_ASSERT(!s_RenderTargets.empty());
402 
403     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
404 
405     InitializeScenes();
406 
407     // ParticleRecycleDemoの初期化処理です。
408     InitializeParticleRecycleDemo();
409 
410     nw::demo::DebugUtility::PostInitializeScenes();
411 
412     bool isContinuing = true;
413 
414     while ( isContinuing )
415     {
416         nw::demo::DebugUtility::AdvanceAutoTestFrame();
417 
418         nw::demo::PadFactory::GetPad()->Update();
419 
420 
421         // ParticleRecycleDemoの定期処理です。
422         UpdateParticleRecycleDemo();
423 
424         UpdateScene();
425 
426         renderContext->SetActiveCamera(s_BaseCameraIndex);
427         s_RenderSystem->SubmitView(s_SceneSystem);
428 
429         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
430         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
431 
432         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
433         ReportDemo();
434         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
435 
436         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
437 
438         renderContext->ResetState();
439 
440         if (nw::demo::Utility::IsTerminating())
441         {
442             isContinuing = false;
443         }
444     }
445 
446     nw::demo::DebugUtility::PreTerminateScenes();
447 
448     // ParticleRecycleDemoの終了処理です。
449     TerminateParticleRecycleDemo();
450 
451     TerminateScenes();
452 }
453 
454 } // namespace
455 
456 /*!--------------------------------------------------------------------------*
457   @brief        メイン関数です。
458  *---------------------------------------------------------------------------*/
459 void
nnMain()460 nnMain()
461 {
462     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
463     nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
464 
465     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
466 
467     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
468     {
469         InitializeGraphics();
470 
471         s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
472 
473         DemoScene();
474 
475         nw::ut::SafeDestroy(s_FlushCache);
476 
477         TerminateGraphics();
478     }
479 
480     nw::demo::PadFactory::Finalize();
481 
482     nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
483 
484     nw::demo::FinalizeGraphicsSystem();
485 }
486