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