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