1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ParticleDropFrameDemo.cpp
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: 31311 $
16 *---------------------------------------------------------------------------*/
17
18 #define NW_DEBUG_CHECK_MEMORY_LEAK
19
20 #include <nn/os.h>
21 #include <nn/fs.h>
22
23 #include <nw/types.h>
24 #include <nw/demo.h>
25 #include <nw/dev.h>
26 #include <nw/gfx.h>
27 #include <nw/ut.h>
28
29 namespace
30 {
31
32 //----------------------------------------
33 // メモリ関係
34
35 // デバイスメモリを確保するためのアロケータです。
36 nw::demo::DemoAllocator s_DeviceAllocator;
37 nw::demo::DemoAllocator s_ParticleAllocator;
38
39 //----------------------------------------
40 // ファイル名の定義です。
41 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
42
43 const wchar_t* MODEL_RESOURCE_FILES[] =
44 {
45 NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl"),
46 NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
47 NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
48 };
49
50 //----------------------------------------
51 // 描画関係
52 const int RENDER_TARGET_COUNT = 1;
53 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
54
55 RenderTargetArray s_RenderTargets;
56 nw::demo::SceneSystem* s_SceneSystem = NULL;
57 nw::demo::RenderSystem* s_RenderSystem = NULL;
58 nw::gfx::ParticleContext* s_ParticleContext = NULL;
59
60 nw::demo::GraphicsDrawing s_GraphicsDrawing;
61
62 //----------------------------------------
63 // リソース関係
64 nw::demo::ResourceArray s_Resources;
65
66 int s_ModelCount = 0;
67 int s_EmitterCount = 0;
68
69 //----------------------------------------
70 // シーン関係
71 const int SCENE_NODE_COUNT = 4;
72 nw::gfx::SceneNode* s_SceneRoot = NULL;
73 s32 s_FrameCount = 0;
74 nw::gfx::Camera* s_BaseCamera = NULL;
75 nw::gfx::Camera* s_LeftCamera = NULL;
76 nw::gfx::Camera* s_RightCamera = NULL;
77 const f32 s_fNearPlane = 0.1f;
78
79 //----------------------------------------
80 // シーン環境関係
81 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
82
83 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
84 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
85
86 const s32 s_BaseCameraIndex = 0;
87
88 //----------------------------------------
89 // パーティクル関係
90 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
91
92 nw::demo::FlushCache* s_FlushCache;
93
94 /*!--------------------------------------------------------------------------*
95 @brief グラフィックス関連の初期化を行います。
96 *---------------------------------------------------------------------------*/
97 void
InitializeGraphics()98 InitializeGraphics()
99 {
100 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
101
102 // renderDescriptionへステレオの設定を行います。
103 nw::demo::RenderSystem::Description renderDescription;
104
105 renderDescription.reusableCommandBufferSize = 0x100000;
106 renderDescription.reusableCommandRequestCount = 512;
107 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
108
109 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
110
111 s_GraphicsDrawing.SetScreenSize(
112 renderDescription.lowerScreenDescription.width,
113 renderDescription.lowerScreenDescription.height
114 );
115
116 nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
117
118 s_RenderTargets.push_back(
119 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
120 );
121 NW_ASSERT(!s_RenderTargets.empty());
122 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
123
124 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
125 nw::demo::SceneSystem::Description sceneDescription;
126 sceneDescription.isFixedSizeMemory = true;
127 sceneDescription.maxSceneNodes = 128;
128 sceneDescription.maxParticleSets = 64;
129 sceneDescription.maxParticleEmitters = 64;
130 sceneDescription.maxParticleModels = 64;
131 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
132
133 // ParticleContextを生成します。
134 s_ParticleContext = nw::gfx::ParticleContext::Builder()
135 .MaxEmission(1000)
136 .MaxStreamLength(1000)
137 .UseDoubleBuffer(true)
138 .Create(&s_DeviceAllocator);
139
140 // ParticleSceneUpdaterを生成します。
141 s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
142 .Create(&s_DeviceAllocator);
143
144 // デモ用の最遠景モデルをレンダリングシステムに設定します。
145 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
146 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
147
148 NW_GL_ASSERT();
149 }
150
151 /*!--------------------------------------------------------------------------*
152 @brief グラフィックス関連の後始末をします。
153 *---------------------------------------------------------------------------*/
154 void
TerminateGraphics()155 TerminateGraphics()
156 {
157 nw::gfx::SafeDestroy(s_LeftCamera);
158
159 nw::gfx::SafeDestroy(s_RightCamera);
160
161 nw::gfx::SafeDestroy(s_ParticleSceneUpdater);
162
163 nw::gfx::SafeDestroy(s_ParticleContext);
164
165 nw::gfx::SafeDestroy(s_SceneSystem);
166
167 nw::gfx::SafeDestroyAll(s_RenderTargets);
168
169 s_GraphicsDrawing.Finalize();
170
171 nw::gfx::SafeDestroy(s_RenderSystem);
172
173 NW_GL_ASSERT();
174 }
175
176 /*!--------------------------------------------------------------------------*
177 @brief 再生ステップを設定します。
178
179 @param[in] 再生ステップです。
180 *---------------------------------------------------------------------------*/
181 void
SetStepFrame(f32 stepFrame)182 SetStepFrame(f32 stepFrame)
183 {
184 nw::gfx::SceneContext* sceneContext = s_SceneSystem->GetSceneContext();
185
186 nw::gfx::SceneNodeArray::iterator end = sceneContext->GetSceneNodesEnd();
187 for (nw::gfx::SceneNodeArray::iterator i = sceneContext->GetSceneNodesBegin(); i != end; ++i)
188 {
189 nw::gfx::ParticleEmitter* emitter = nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(*i);
190 if (emitter != NULL)
191 {
192 emitter->ParticleAnimFrameController().SetStepFrame(stepFrame);
193 }
194 else
195 {
196 nw::gfx::ParticleModel* model = nw::ut::DynamicCast<nw::gfx::ParticleModel*>(*i);
197 if (model != NULL)
198 {
199 model->ParticleAnimFrameController().SetStepFrame(stepFrame);
200 }
201 }
202 }
203 }
204
205 /*!--------------------------------------------------------------------------*
206 @brief ルートノード関連の構築をします。
207 *---------------------------------------------------------------------------*/
208 void
BuildRootNodes()209 BuildRootNodes()
210 {
211 NW_ASSERT(s_SceneRoot == NULL);
212 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
213 .MaxChildren(128)
214 .Create(&s_DeviceAllocator);
215 NW_NULL_ASSERT(s_SceneRoot);
216 }
217
218 /*!--------------------------------------------------------------------------*
219 @brief カメラ関連の構築をします。
220 *---------------------------------------------------------------------------*/
221 void
BuildCameras()222 BuildCameras()
223 {
224 nw::demo::Utility::CreateStereoCameras(
225 &s_BaseCamera,
226 &s_LeftCamera,
227 &s_RightCamera,
228 &s_DeviceAllocator,
229 nw::math::VEC3(28.0f, 22.0f, 28.0f),
230 nw::math::VEC3(0.0f, 0.0f, 0.0f),
231 s_fNearPlane
232 );
233
234 s_SceneRoot->AttachChild(s_BaseCamera);
235 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
236 }
237
238 /*!--------------------------------------------------------------------------*
239 @brief リソース関連の構築をします。
240 *---------------------------------------------------------------------------*/
241 void
BuildResources(nw::demo::ResourceSet * resourceSet)242 BuildResources(nw::demo::ResourceSet* resourceSet)
243 {
244 // テクスチャリソースをVRAMに配置します。
245 resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
246
247 // リソースのセットアップを行います。
248 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
249
250 if (result.IsFailure())
251 {
252 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
253 }
254
255 for (int i = 0; i < 10; ++i)
256 {
257 // 生成したノードを格納する配列です。
258 nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
259
260 // ResModelArray から ParticleModel インスタンスを生成します。
261 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
262 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
263 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
264 modelResource != modelsEnd; ++modelResource)
265 {
266 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
267 &s_ParticleAllocator,
268 (*modelResource)
269 );
270 if (node != NULL)
271 {
272 sceneNodeArray.push_back(node);
273 s_ModelCount++;
274 }
275 }
276
277 // ResEmitterArray から ParticleEmitter インスタンスを生成します。
278 nw::gfx::ResEmitterArray emitters = resourceSet->resource.GetEmitters();
279 for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
280 emitterResource != emitters.end(); ++emitterResource)
281 {
282 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
283 &s_ParticleAllocator,
284 (*emitterResource)
285 );
286 if (node != NULL)
287 {
288 sceneNodeArray.push_back(node);
289 s_EmitterCount++;
290 }
291 }
292
293 // 親子付け参照関係を解決します。
294 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
295
296 // パーティクル独自の初期設定を行います。
297 nw::gfx::ParticleUtil::SetupParticleObject(&sceneNodeArray, s_ParticleContext);
298
299 // モデルとエミッタをシーンツリーに追加します。
300 nw::gfx::SceneHelper::ForeachRootNodes(
301 sceneNodeArray.Begin(),
302 sceneNodeArray.End(),
303 nw::gfx::AttachNode(s_SceneRoot)
304 );
305 }
306 }
307
308 /*!--------------------------------------------------------------------------*
309 @brief シーンを初期化します。
310 *---------------------------------------------------------------------------*/
311 void
InitializeScenes()312 InitializeScenes()
313 {
314 BuildRootNodes();
315
316 BuildCameras();
317
318 // リソースをロードして、セットアップを行います。
319 NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
320 {
321 BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
322 }
323 NW_ASSERT(s_ModelCount > 0);
324 NW_ASSERT(s_EmitterCount > 0);
325
326 // シーンツリーを巡回して初期化を行います。
327 s_SceneSystem->InitializeScene(s_SceneRoot);
328 s_SceneSystem->UpdateScene();
329
330 // シーン環境の参照解決を行い設定します。
331 s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
332
333 // カメラを設定します。
334 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
335 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
336 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
337
338 NW_GL_ASSERT();
339
340 s_FrameCount = 0;
341 }
342
343 /*!--------------------------------------------------------------------------*
344 @brief シーン関連の後始末をします。
345 *---------------------------------------------------------------------------*/
346 void
TerminateScenes()347 TerminateScenes()
348 {
349 nw::gfx::SafeDestroyBranch(s_SceneRoot);
350 nw::demo::SafeCleanupResources(s_Resources);
351 nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
352
353 NW_GL_ASSERT();
354
355 s_Resources.clear();
356 s_SceneEnvironmentSettings.clear();
357 }
358
359 /*!--------------------------------------------------------------------------*
360 @brief シーンを更新します。
361 *---------------------------------------------------------------------------*/
362 void
UpdateScene(bool particleSwapBuffer=true)363 UpdateScene(bool particleSwapBuffer = true)
364 {
365 NW_ASSERT(0 < s_RenderTargets.size());
366
367 s_SceneSystem->GetCameraController()->Update();
368
369 s_SceneSystem->UpdateScene();
370
371 s_BaseCamera->UpdateCameraMatrix();
372
373 NW_NULL_ASSERT(s_ParticleSceneUpdater);
374 s_ParticleSceneUpdater->UpdateNode(
375 s_SceneSystem->GetSceneContext(),
376 s_ParticleContext,
377 particleSwapBuffer);
378
379 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
380
381 s_FrameCount++;
382
383 s_FlushCache->Execute();
384 }
385
386 /*!--------------------------------------------------------------------------*
387 @brief 負荷表示やテスト機能の処理をおこないます。
388 *---------------------------------------------------------------------------*/
389 void
ReportDemo()390 ReportDemo()
391 {
392 NW_PROFILE("ReportDemo");
393
394 // 負荷表示からはこれらの負荷は除きます。
395 s_RenderSystem->SuspendLoadMeter();
396
397 nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
398
399 s_GraphicsDrawing.BeginDrawingShape();
400
401 nw::demo::DebugUtility::DrawLoadMeter(
402 s_RenderSystem,
403 &s_GraphicsDrawing
404 );
405
406 s_GraphicsDrawing.EndDrawingShape();
407
408 s_GraphicsDrawing.BeginDrawingString();
409
410 nw::demo::DebugUtility::DrawLoadMeterText(
411 s_RenderSystem,
412 &s_GraphicsDrawing
413 );
414
415 s_GraphicsDrawing.EndDrawingString();
416
417 s_RenderSystem->ResumeLoadMeter();
418 }
419
420 /*!--------------------------------------------------------------------------*
421 @brief シーンをデモンストレーションします。
422 *---------------------------------------------------------------------------*/
423 void
DemoScene()424 DemoScene()
425 {
426 NW_ASSERT(!s_RenderTargets.empty());
427
428 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
429
430 InitializeScenes();
431
432 nw::demo::DebugUtility::PostInitializeScenes();
433
434 bool isContinuing = true;
435 bool isFirst = true;
436 int currentVsyncCount = nngxCheckVSync(NN_GX_DISPLAY0);
437 int prevVsyncCount = currentVsyncCount - 1; // 最初の処理用に-1
438
439 while ( isContinuing )
440 {
441 const s32 screenKind = nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN;
442
443 nw::demo::DebugUtility::AdvanceAutoTestFrame();
444
445 nw::demo::PadFactory::GetPad()->Update();
446
447 // 効率的なダブルバッファの処理ではなく、
448 // サンプルとしてのわかりやすさを重視しています。
449 #if 0
450 // 再生レートを上げてまとめて処理する
451 // 利点:処理が高速
452 // 欠点:1フレーム毎の処理と結果が多少異なる
453 SetStepFrame(currentVsyncCount - prevVsyncCount);
454 UpdateScene();
455 #else
456 // コマ落ち分の処理を繰り返し行う
457 // 利点:コマ落ちでないときと結果が一致することが保証される
458 // 欠点:繰り返し分のCPU処理がかかる
459 for (int i = 0; i < currentVsyncCount - prevVsyncCount; ++i)
460 {
461 //SetStepFrame(1.0f);
462 UpdateScene(i == 0);
463 }
464 #endif
465
466 prevVsyncCount = currentVsyncCount;
467
468 renderContext->SetActiveCamera(s_BaseCameraIndex);
469 s_RenderSystem->SubmitView(s_SceneSystem);
470
471 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
472 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
473
474 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
475 ReportDemo();
476 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
477
478 //s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
479 s_RenderSystem->WaitCommandList();
480 s_RenderSystem->SwapBuffer(screenKind);
481 s_RenderSystem->WaitVSync(screenKind);
482 currentVsyncCount = nngxCheckVSync(NN_GX_DISPLAY0);
483 s_RenderSystem->RunCommandList();
484 s_RenderSystem->SwapCommandList();
485
486 renderContext->ResetState();
487
488 if (nw::demo::Utility::IsTerminating())
489 {
490 isContinuing = false;
491 }
492 }
493
494 nw::demo::DebugUtility::PreTerminateScenes();
495
496 TerminateScenes();
497 }
498
499 } // namespace
500
501 /*!--------------------------------------------------------------------------*
502 @brief メイン関数です。
503 *---------------------------------------------------------------------------*/
504 void
nnMain()505 nnMain()
506 {
507 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
508 nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
509
510 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
511
512 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
513 {
514 InitializeGraphics();
515
516 // キャッシュフラッシュ用のクラスを生成(通常のアプリでは必要ありません)
517 s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
518
519 DemoScene();
520
521 // キャッシュフラッシュ用のクラスを破棄
522 nw::ut::SafeDestroy(s_FlushCache);
523
524 TerminateGraphics();
525 }
526
527 nw::demo::PadFactory::Finalize();
528
529 nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
530
531 nw::demo::FinalizeGraphicsSystem();
532 }
533