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