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