1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ParticleMultiEmitterDemo.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: 25401 $
14  *---------------------------------------------------------------------------*/
15 /*
16 エミッタを複数配置し、同じParticleSetに送るデモです。
17 */
18 
19 #define NW_DEBUG_CHECK_MEMORY_LEAK
20 
21 #include <nn/os.h>
22 #include <nn/fs.h>
23 
24 #include <nw/types.h>
25 #include <nw/demo.h>
26 #include <nw/dev.h>
27 #include <nw/gfx.h>
28 #include <nw/ut.h>
29 
30 namespace
31 {
32 
33 //----------------------------------------
34 // メモリ関係
35 
36 // デバイスメモリを確保するためのアロケータです。
37 nw::demo::DemoAllocator s_DeviceAllocator;
38 nw::demo::DemoAllocator s_ParticleAllocator;
39 
40 //----------------------------------------
41 // ファイル名の定義です。
42 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
43 const wchar_t* FONT_FILE_NAME        = NW_DEMO_FILE_PATH(L"Font.bcfnt");
44 const wchar_t* SKY_SPHERE_FILE_NAME  = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
45 
46 const wchar_t* MODEL_RESOURCE_FILES[] =
47 {
48     NW_DEMO_FILE_PATH(L"fire_particle_all.bcptl"),
49     NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
50     NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
51 };
52 
53 //----------------------------------------
54 // プロファイル関係
55 const int NW_LOAD_METER_INTERVAL = 60;
56 
57 //----------------------------------------
58 // 描画関係
59 const int RENDER_TARGET_COUNT = 1;
60 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
61 
62 RenderTargetArray s_RenderTargets;
63 nw::demo::SceneSystem*  s_SceneSystem = NULL;
64 nw::demo::RenderSystem* s_RenderSystem = NULL;
65 nw::gfx::ParticleContext* s_ParticleContext = NULL;
66 
67 nw::demo::GraphicsDrawing  s_GraphicsDrawing;
68 
69 //----------------------------------------
70 // リソース関係
71 nw::demo::ResourceArray s_Resources;
72 
73 //----------------------------------------
74 // シーン関係
75 nw::gfx::SceneNode* s_SceneRoot = NULL;
76 s32 s_FrameCount = 0;
77 nw::gfx::Camera* s_BaseCamera = NULL;
78 nw::gfx::Camera* s_LeftCamera = NULL;
79 nw::gfx::Camera* s_RightCamera = NULL;
80 const f32 s_fNearPlane = 0.1f;
81 
82 //----------------------------------------
83 // シーン環境関係
84 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
85 
86 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
87 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
88 
89 const s32 s_BaseCameraIndex = 0;
90 
91 //----------------------------------------
92 // パーティクル関係
93 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
94 
95 nw::demo::FlushCache* s_FlushCache;
96 
97 /*!--------------------------------------------------------------------------*
98   @brief        グラフィックス関連の初期化を行います。
99  *---------------------------------------------------------------------------*/
100 void
InitializeGraphics()101 InitializeGraphics()
102 {
103     nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
104 
105     // renderDescriptionへステレオの設定を行います。
106     nw::demo::RenderSystem::Description renderDescription;
107 
108     renderDescription.reusableCommandBufferSize = 0x100000;
109     renderDescription.reusableCommandRequestCount      = 512;
110     renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
111 
112     s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
113 
114     s_GraphicsDrawing.SetScreenSize(
115         renderDescription.lowerScreenDescription.width,
116         renderDescription.lowerScreenDescription.height
117     );
118 
119     bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
120 
121     NN_ASSERTMSG(result, "Fail to load Font.");
122 
123     s_RenderTargets.push_back(
124         nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
125     );
126     NW_ASSERT(!s_RenderTargets.empty());
127     s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
128 
129     // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
130     nw::demo::SceneSystem::Description sceneDescription;
131     s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
132 
133     s_ParticleContext = nw::gfx::ParticleContext::Builder()
134         .MaxEmission(1000)
135         .Create(&s_DeviceAllocator);
136 
137     s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
138         .Create(&s_DeviceAllocator);
139 
140     // デモ用の最遠景モデルをレンダリングシステムに設定します。
141     // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
142     s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
143 
144     NW_GL_ASSERT();
145 }
146 
147 /*!--------------------------------------------------------------------------*
148   @brief        グラフィックス関連の後始末をします。
149  *---------------------------------------------------------------------------*/
150 void
TerminateGraphics()151 TerminateGraphics()
152 {
153     nw::gfx::SafeDestroy(s_LeftCamera);
154 
155     nw::gfx::SafeDestroy(s_RightCamera);
156 
157     nw::gfx::SafeDestroy(s_ParticleSceneUpdater);
158 
159     nw::gfx::SafeDestroy(s_ParticleContext);
160 
161     nw::gfx::SafeDestroy(s_SceneSystem);
162 
163     nw::gfx::SafeDestroyAll(s_RenderTargets);
164 
165     s_GraphicsDrawing.Finalize();
166 
167     nw::gfx::SafeDestroy(s_RenderSystem);
168 
169     NW_GL_ASSERT();
170 }
171 
172 /*!--------------------------------------------------------------------------*
173   @brief        再生ステップを設定します。
174 
175   @param[in]    再生ステップです。
176  *---------------------------------------------------------------------------*/
177 void
SetStepFrame(f32 stepFrame)178 SetStepFrame(f32 stepFrame)
179 {
180     nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
181 
182     nw::gfx::SceneNodeArray::iterator end = sceneContext->GetSceneNodesEnd();
183     for (nw::gfx::SceneNodeArray::iterator i = sceneContext->GetSceneNodesBegin(); i != end; ++i)
184     {
185         nw::gfx::ParticleEmitter* emitter = nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(*i);
186         if (emitter != NULL)
187         {
188             emitter->ParticleAnimFrameController().SetStepFrame(stepFrame);
189         }
190         else
191         {
192             nw::gfx::ParticleModel* model = nw::ut::DynamicCast<nw::gfx::ParticleModel*>(*i);
193             if (model != NULL)
194             {
195                 model->ParticleAnimFrameController().SetStepFrame(stepFrame);
196             }
197         }
198     }
199 }
200 
201 /*!--------------------------------------------------------------------------*
202   @brief        ルートノード関連の構築をします。
203  *---------------------------------------------------------------------------*/
204 void
BuildRootNodes()205 BuildRootNodes()
206 {
207     NW_ASSERT(s_SceneRoot == NULL);
208     s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
209         .IsFixedSizeMemory(false)
210         .Create(&s_DeviceAllocator);
211     NW_NULL_ASSERT(s_SceneRoot);
212 }
213 
214 /*!--------------------------------------------------------------------------*
215   @brief        カメラ関連の構築をします。
216  *---------------------------------------------------------------------------*/
217 void
BuildCameras()218 BuildCameras()
219 {
220     nw::demo::Utility::CreateStereoCameras(
221         &s_BaseCamera,
222         &s_LeftCamera,
223         &s_RightCamera,
224         &s_DeviceAllocator,
225         nw::math::VEC3(28.0f, 22.0f, 28.0f),
226         nw::math::VEC3(0.0f, 0.0f, 0.0f),
227         s_fNearPlane
228     );
229 
230     s_SceneRoot->AttachChild(s_BaseCamera);
231     s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
232 }
233 
234 /*!--------------------------------------------------------------------------*
235   @brief        リソース関連の構築をします。
236  *---------------------------------------------------------------------------*/
237 void
BuildResources(nw::demo::ResourceSet * resourceSet)238 BuildResources(nw::demo::ResourceSet* resourceSet)
239 {
240     resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
241     resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
242     resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
243 
244     nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
245 
246     if (result.IsFailure())
247     {
248         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
249     }
250 
251     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(&s_DeviceAllocator);
252 
253     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
254     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
255     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
256          modelResource != modelsEnd; ++modelResource)
257     {
258         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
259             &s_ParticleAllocator,
260             (*modelResource)
261         );
262         if (node != NULL)
263         {
264             sceneNodeArray.push_back(node);
265         }
266     }
267 
268     for (int i = 0; i < 5; ++i)
269     {
270         nw::gfx::ResEmitterArray emitters = resourceSet->resource.GetEmitters();
271         for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
272             emitterResource != emitters.end(); ++emitterResource)
273         {
274             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
275                 &s_ParticleAllocator,
276                 (*emitterResource)
277                 );
278 
279             if (node)
280             {
281                 nw::gfx::ParticleEmitter* emitter = nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(node);
282                 if (emitter != NULL)
283                 {
284                     emitter->Transform().SetTranslate(5.0f * (i - 2), 0, 0);
285                 }
286                 sceneNodeArray.push_back(node);
287             }
288         }
289     }
290 
291     nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
292     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
293          lightResource != lights.end(); ++lightResource)
294     {
295         nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
296             &s_DeviceAllocator,
297             (*lightResource)
298         );
299         NW_NULL_ASSERT(node);
300         sceneNodeArray.push_back(node);
301     }
302 
303     // 親子付け参照関係を解決
304     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
305 
306     nw::gfx::ParticleUtil::SetupParticleObject(&sceneNodeArray, s_ParticleContext);
307 
308     // モデルとエミッタをシーンに追加
309     nw::gfx::SceneHelper::ForeachRootNodes(
310         sceneNodeArray.Begin(),
311         sceneNodeArray.End(),
312         nw::gfx::AttachNode(s_SceneRoot)
313     );
314 
315     nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
316     nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
317     for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
318         settingResource != settingsEnd; ++settingResource)
319     {
320         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
321             .Resource(*settingResource)
322             .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
323 
324         nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
325             nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
326 
327         NW_NULL_ASSERT(sceneEnvironmentSetting);
328         s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
329     }
330 }
331 
332 /*!--------------------------------------------------------------------------*
333   @brief        シーンを初期化します。
334  *---------------------------------------------------------------------------*/
335 void
InitializeScenes()336 InitializeScenes()
337 {
338     BuildRootNodes();
339 
340     BuildCameras();
341 
342     NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
343     {
344         BuildResources( nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator) );
345     }
346 
347     // シーンツリーを巡回して初期化を行います。
348     s_SceneSystem->InitializeScene(s_SceneRoot);
349     s_SceneSystem->UpdateScene();
350 
351     // シーン環境の参照解決を行い設定します。
352     s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
353 
354     // カメラを設定します。
355     nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
356     sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
357     nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
358 
359     NW_GL_ASSERT();
360 
361     s_FrameCount = 0;
362 }
363 
364 /*!--------------------------------------------------------------------------*
365   @brief        シーン関連の後始末をします。
366  *---------------------------------------------------------------------------*/
367 void
TerminateScenes()368 TerminateScenes()
369 {
370     nw::gfx::SafeDestroyBranch(s_SceneRoot);
371     nw::demo::SafeCleanupResources(s_Resources);
372     nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
373 
374     NW_GL_ASSERT();
375 
376     s_Resources.clear();
377     s_SceneEnvironmentSettings.clear();
378 }
379 
380 /*!--------------------------------------------------------------------------*
381   @brief        シーンを更新します。
382  *---------------------------------------------------------------------------*/
383 void
UpdateScene()384 UpdateScene()
385 {
386     NW_ASSERT(0 < s_RenderTargets.size());
387 
388     s_SceneSystem->GetCameraController()->Update();
389 
390     s_SceneSystem->UpdateScene();
391 
392     s_BaseCamera->UpdateCameraMatrix();
393 
394     NW_NULL_ASSERT(s_ParticleSceneUpdater);
395     s_ParticleSceneUpdater->UpdateNode(
396         s_SceneSystem->GetSceneContext(),
397         s_ParticleContext);
398 
399     s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
400 
401     s_FrameCount++;
402 
403     s_FlushCache->Execute();
404 }
405 
406 /*!--------------------------------------------------------------------------*
407   @brief        負荷表示やテスト機能の処理をおこないます。
408  *---------------------------------------------------------------------------*/
409 void
ReportDemo()410 ReportDemo()
411 {
412     NW_PROFILE("ReportDemo");
413 
414     // 負荷表示からはこれらの負荷は除きます。
415     s_RenderSystem->SuspendLoadMeter();
416 
417     s_GraphicsDrawing.BeginDrawingString();
418 
419     nw::demo::DebugUtility::DrawLoadMeter(
420         s_RenderSystem,
421         &s_GraphicsDrawing,
422         (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
423     );
424 
425     s_GraphicsDrawing.FlushDrawing();
426 
427     s_RenderSystem->ResumeLoadMeter();
428 }
429 
430 /*!--------------------------------------------------------------------------*
431   @brief        シーンをデモンストレーションします。
432  *---------------------------------------------------------------------------*/
433 void
DemoScene()434 DemoScene()
435 {
436     NW_ASSERT(!s_RenderTargets.empty());
437 
438     nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
439 
440     InitializeScenes();
441 
442     bool isContinuing = true;
443 
444     while ( isContinuing )
445     {
446         nw::demo::DebugUtility::AdvanceAutoTestFrame();
447 
448         nw::demo::PadFactory::GetPad()->Update();
449 
450         SetStepFrame(1.0f);
451         UpdateScene();
452 
453         renderContext->SetActiveCamera(s_BaseCameraIndex);
454         s_RenderSystem->SubmitView(s_SceneSystem);
455 
456         s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
457         s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
458 
459         s_RenderSystem->ClearBySkyModel(s_BaseCamera);
460         ReportDemo();
461         s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
462 
463         s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
464 
465         renderContext->ResetState();
466 
467         if (nw::demo::Utility::IsTerminating())
468         {
469             isContinuing = false;
470         }
471     }
472 
473     TerminateScenes();
474 }
475 
476 } // namespace
477 
478 /*!--------------------------------------------------------------------------*
479   @brief        メイン関数です。
480  *---------------------------------------------------------------------------*/
481 void
nnMain()482 nnMain()
483 {
484     nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
485     nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
486 
487     nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
488 
489     NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
490     {
491         InitializeGraphics();
492 
493         s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
494 
495         DemoScene();
496 
497         nw::ut::SafeDestroy(s_FlushCache);
498 
499         TerminateGraphics();
500     }
501 
502     nw::demo::PadFactory::Finalize();
503 
504     nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
505 
506     nw::demo::FinalizeGraphicsSystem();
507 }
508