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