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