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