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