1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ParticleScaleDemo.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: 25056 $
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(0.0f, 13.0f, 70.f),
180 nw::math::VEC3(0.0f, 13.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_PaticleNode = NULL;
288
289 // カウンタ
290 u32 s_Count = 0;
291
292 // アニメーションステート
293 enum
294 {
295 DEMO_STATE_SCALING_PARTICLE_MODEL = 0,
296 DEMO_STATE_SCALING_PARTICLE_EMITTER = 1,
297 DEMO_STATE_SCALING_PARTICLE = 2,
298 DEMO_STATE_MAX = 3
299 };
300 u32 s_AnimationState = DEMO_STATE_SCALING_PARTICLE_MODEL;
301
302 // ロードするエフェクトファイル
303 const wchar_t* EFFECT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"rain_follow_on.bcptl");
304
305 /*!--------------------------------------------------------------------------*
306 @brief ParticleScaleDemoの初期化を行います。
307 *---------------------------------------------------------------------------*/
308 void
InitializeParticleScaleDemo()309 InitializeParticleScaleDemo()
310 {
311 // このデモは、パーティクルモデル、パーティクルエミッタ、パーティクル
312 // それぞれにスケールをかけた場合の効果を確認するデモです。
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 s_ParticleEffect->Setup(resourceSet->resource, false);
322
323 // ParticleEffectにリソースをセットします。
324 s_ParticleEffect->Register(resourceSet->resource);
325 s_ParticleEffect->AddPool(1);
326
327 // パーティクルノードクラスのインスタンスをリースします。
328 s_PaticleNode = s_ParticleEffect->LeaseInstance();
329
330 // シーンに追加します。
331 s_SceneRoot->AttachChild(s_PaticleNode);
332 s_SceneSystem->InitializeScene(s_SceneRoot);
333 s_SceneSystem->UpdateScene();
334 }
335
336 /*!--------------------------------------------------------------------------*
337 @brief ParticleScaleDemoの定期処理です。
338 *---------------------------------------------------------------------------*/
339 void
UpdateParticleScaleDemo()340 UpdateParticleScaleDemo()
341 {
342 ++s_Count;
343
344 // 360フレーム単位でスケールを適用する対象を変更します。
345 if (s_Count%360 == 0)
346 {
347 s_AnimationState++;
348
349 // エミッタのスケールを戻します。
350 if (s_AnimationState == DEMO_STATE_SCALING_PARTICLE)
351 {
352 for (u32 i = 0; i < s_PaticleNode->GetParticleEmitterSize(); ++i)
353 {
354 s_PaticleNode->GetParticleEmitter(i)->Transform().SetScale(1.f, 1.f, 1.f);
355 }
356 }
357
358 if (s_AnimationState == DEMO_STATE_MAX)
359 {
360 s_AnimationState = DEMO_STATE_SCALING_PARTICLE_MODEL;
361 }
362 }
363
364 // ParticleModelに対するスケールアニメーションを適用します。
365 // エフェクト全体に対してスケールが適用されます。
366 if (s_AnimationState == DEMO_STATE_SCALING_PARTICLE_MODEL)
367 {
368 f32 fsin = 0.5f * nn::math::SinDeg(s_Count);
369
370 for (u32 i = 0; i < s_PaticleNode->GetParticleModelSize(); ++i)
371 {
372 s_PaticleNode->GetParticleModel(i)->Transform().SetScale( 1.f + fsin, 1.f + fsin, 1.f + fsin );
373 }
374 }
375
376 // ParticleEmitterに対するスケールを適用します。
377 // 各パーティクルの大きさはそのままで、発生源にスケールが適用されます。
378 if (s_AnimationState == DEMO_STATE_SCALING_PARTICLE_EMITTER)
379 {
380 // 雲がXZ平面上に広がるようにスケールをかけます。
381 for (u32 i = 0; i < s_PaticleNode->GetParticleEmitterSize(); ++i)
382 {
383 s_PaticleNode->GetParticleEmitter(i)->Transform().SetScale( 3.f, 1.f, 3.f );
384 }
385 }
386
387 // 粒に対するスケールアニメーション
388 // 各パーティクルの粒の大きさにスケールが適用されます。
389 // SetParticleScaleOffsetメソッド内では、
390 // ParticleModel が保持するParitcleSet内メソッド、SetScaleOffsetへの操作が行われます。
391 if (s_AnimationState == DEMO_STATE_SCALING_PARTICLE)
392 {
393 f32 fsin = 0.5f * nn::math::SinDeg(s_Count);
394 s_PaticleNode->SetParticleScaleOffset(1.f + fsin);
395 }
396 }
397
398 /*!--------------------------------------------------------------------------*
399 @brief ParticleScaleDemoのスクリーンデバッグ表示です。
400 *---------------------------------------------------------------------------*/
401 void
ReportParticleScaleDemo()402 ReportParticleScaleDemo()
403 {
404 if(s_AnimationState== DEMO_STATE_SCALING_PARTICLE_MODEL)
405 {
406 s_GraphicsDrawing.DrawString(10, 10, "Particle Model Scaling");
407 }
408
409 if(s_AnimationState== DEMO_STATE_SCALING_PARTICLE_EMITTER)
410 {
411 s_GraphicsDrawing.DrawString(10, 10, "Particle Emitter Scaling");
412 }
413
414 if(s_AnimationState== DEMO_STATE_SCALING_PARTICLE)
415 {
416 s_GraphicsDrawing.DrawString(10, 10, "Particle Scaling");
417 }
418 }
419
420 /*!--------------------------------------------------------------------------*
421 @brief ParticleScaleDemoの終了処理を行います。
422 *---------------------------------------------------------------------------*/
423 void
TerminateParticleScaleDemo()424 TerminateParticleScaleDemo()
425 {
426 nw::demo::ParticleNode* prevTarget = s_ParticleEffect->GetActiveEffect(0);
427 while (prevTarget != NULL)
428 {
429 s_ParticleEffect->ReleaseInstance(prevTarget);
430 prevTarget = s_ParticleEffect->GetActiveEffect(0);
431 }
432
433 s_ParticleEffect->FreePool();
434
435 nw::ut::SafeDestroy(s_ParticleEffect);
436 }
437
438
439
440
441 /*!--------------------------------------------------------------------------*
442 @brief シーンをデモンストレーションします。
443 *---------------------------------------------------------------------------*/
444 void
DemoScene()445 DemoScene()
446 {
447 NW_ASSERT(!s_RenderTargets.empty());
448
449 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
450
451 InitializeScenes();
452
453 // ParticleScaleDemoの初期化処理です。
454 InitializeParticleScaleDemo();
455
456 bool isContinuing = true;
457
458 while ( isContinuing )
459 {
460 nw::demo::DebugUtility::AdvanceAutoTestFrame();
461
462 nw::demo::PadFactory::GetPad()->Update();
463
464
465 // ParticleScaleDemoの定期処理です。
466 UpdateParticleScaleDemo();
467
468 UpdateScene();
469
470 renderContext->SetActiveCamera(s_BaseCameraIndex);
471 s_RenderSystem->SubmitView(s_SceneSystem);
472
473 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
474 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
475
476 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
477 ReportDemo();
478
479 // ParticleScaleDemoのレポートを表示します。
480 ReportParticleScaleDemo();
481
482 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
483
484 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
485
486 renderContext->ResetState();
487
488 if (nw::demo::Utility::IsTerminating())
489 {
490 isContinuing = false;
491 }
492 }
493
494 // ParticleScaleDemoの終了処理です。
495 TerminateParticleScaleDemo();
496
497 TerminateScenes();
498 }
499
500 } // namespace
501
502 /*!--------------------------------------------------------------------------*
503 @brief メイン関数です。
504 *---------------------------------------------------------------------------*/
505 void
nnMain()506 nnMain()
507 {
508 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
509 nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
510
511 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
512
513 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
514 {
515 InitializeGraphics();
516
517 s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
518
519 DemoScene();
520
521 nw::ut::SafeDestroy(s_FlushCache);
522
523 TerminateGraphics();
524 }
525
526 nw::demo::PadFactory::Finalize();
527
528 nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
529
530 nw::demo::FinalizeGraphicsSystem();
531 }
532