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