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