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