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