1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ResourceDemo.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: 28152 $
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
36 //----------------------------------------
37 // リソース関係
38 nw::demo::ResourceSet* s_ShaderResource;
39 nw::demo::ResourceArray s_LutResources;
40 nw::demo::ResourceArray s_Resources;
41
42 struct ResourceData
43 {
ResourceData__anon25f74af20111::ResourceData44 ResourceData(
45 wchar_t* modelName,
46 s32 lutIndex,
47 nw::math::VEC3 position)
48 : modelName(modelName),
49 lutIndex(lutIndex),
50 position(position)
51 {}
52
53 const wchar_t* modelName;
54 const s32 lutIndex;
55 const nw::math::VEC3 position;
56 };
57
58 enum LutResource
59 {
60 //! @brief 共通のLUTセットです。
61 DemoLutSet,
62
63 //! @brief マテリアルサンプルのLUTセットです。
64 MaterialSampleLutSet
65 };
66
67 static const wchar_t* LUT_RESOURCE_FILES[] =
68 {
69 NW_DEMO_FILE_PATH(L"Lutset.bclts"),
70 NW_DEMO_FILE_PATH(L"SampleLutset.bclts"),
71 };
72
73 static const ResourceData MODEL_RESOURCE_DATA[] =
74 {
75 ResourceData(NW_DEMO_FILE_PATH(L"Phong.bcmdl"), DemoLutSet, nw::math::VEC3(0.0f, 0.0f, 0.0f)),
76 ResourceData(NW_DEMO_FILE_PATH(L"Blinn.bcmdl"), DemoLutSet, nw::math::VEC3(2.5f, 0.0f, 0.0f)),
77 ResourceData(NW_DEMO_FILE_PATH(L"VertexLight.bcmdl"), DemoLutSet, nw::math::VEC3(5.0f, 0.0f, 0.0f)),
78 ResourceData(NW_DEMO_FILE_PATH(L"CarPaint.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(7.5f, 0.0f, 0.0f)),
79 ResourceData(NW_DEMO_FILE_PATH(L"Sss.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(10.0f, 0.0f, 0.0f)),
80 ResourceData(NW_DEMO_FILE_PATH(L"ThinFilm.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(12.5f, 0.0f, 0.0f)),
81 ResourceData(NW_DEMO_FILE_PATH(L"Toon.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(15.0f, 0.0f, 0.0f)),
82 };
83
84 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
85
86 static const wchar_t* RESOURCE_FILES[] =
87 {
88 NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
89 NW_DEMO_FILE_PATH(L"Camera.bcenv"),
90 NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
91 NW_DEMO_FILE_PATH(L"HemisphereLight.bcenv"),
92 NW_DEMO_FILE_PATH(L"VertexLight.bcenv"),
93 NW_DEMO_FILE_PATH(L"Fog.bcenv"),
94 };
95
96 static const wchar_t* SHADER_RESOURCE_FILE_NAME = NW_DEMO_FILE_PATH(L"nwgfx_DefaultShader.bcsdr");
97
98 //----------------------------------------
99 // 描画関係
100 const int RENDER_TARGET_COUNT = 1;
101 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
102
103 RenderTargetArray s_RenderTargets;
104 nw::demo::SceneSystem* s_SceneSystem = NULL;
105 nw::demo::RenderSystem* s_RenderSystem = NULL;
106
107 nw::demo::GraphicsDrawing s_GraphicsDrawing;
108
109 //----------------------------------------
110 // シーン関係
111 const int SCENE_NODE_COUNT = 16;
112 nw::gfx::SceneNode* s_SceneRoot = NULL;
113 s32 s_FrameCount = 0;
114 nw::gfx::Camera* s_BaseCamera = NULL;
115 nw::gfx::Camera* s_LeftCamera = NULL;
116 nw::gfx::Camera* s_RightCamera = NULL;
117 const f32 s_fNearPlane = 0.1f;
118
119 //----------------------------------------
120 // シーン環境関係
121 const int ENVIRONMENT_SETTINGS_COUNT = 1;
122
123 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
124 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
125
126 const s32 s_BaseCameraIndex = 0;
127
128 /*!--------------------------------------------------------------------------*
129 @brief グラフィックス関連の初期化を行います。
130 *---------------------------------------------------------------------------*/
131 void
InitializeGraphics()132 InitializeGraphics()
133 {
134 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
135
136 // renderDescriptionへステレオの設定を行います。
137 nw::demo::RenderSystem::Description renderDescription;
138
139 renderDescription.reusableCommandBufferSize = 0x100000;
140 renderDescription.reusableCommandRequestCount = 512;
141 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
142
143 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
144
145 s_GraphicsDrawing.SetScreenSize(
146 renderDescription.lowerScreenDescription.width,
147 renderDescription.lowerScreenDescription.height
148 );
149
150 nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
151
152 s_RenderTargets.push_back(
153 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
154 );
155 NW_ASSERT(!s_RenderTargets.empty());
156 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
157
158 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
159 nw::demo::SceneSystem::Description sceneDescription;
160 sceneDescription.isFixedSizeMemory = true;
161 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
162
163 // ファイルからシェーダリソースを読み込みます。
164 // シェーダの作り方は CreativeStudio の シェーダクリエーションパネルの説明を参照してください。
165 s_ShaderResource = s_DeviceAllocator.AllocAndConstruct<nw::demo::ResourceSet>(1);
166 s_ShaderResource->buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , SHADER_RESOURCE_FILE_NAME);
167
168 NW_NULL_ASSERT(s_ShaderResource->buffer);
169
170 s_ShaderResource->resource = nw::gfx::ResGraphicsFile(&(s_ShaderResource->buffer.front()));
171
172 // デモ用の最遠景モデルをレンダリングシステムに設定します。
173 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
174 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
175
176 NW_GL_ASSERT();
177 }
178
179 /*!--------------------------------------------------------------------------*
180 @brief グラフィックス関連の後始末をします。
181 *---------------------------------------------------------------------------*/
182 void
TerminateGraphics()183 TerminateGraphics()
184 {
185 s_DeviceAllocator.DestructAndFree(s_ShaderResource, 1);
186
187 nw::gfx::SafeDestroy(s_LeftCamera);
188
189 nw::gfx::SafeDestroy(s_RightCamera);
190
191 nw::gfx::SafeDestroy(s_SceneSystem);
192
193 nw::gfx::SafeDestroyAll(s_RenderTargets);
194
195 s_GraphicsDrawing.Finalize();
196
197 nw::gfx::SafeDestroy(s_RenderSystem);
198
199 NW_GL_ASSERT();
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 .MaxChildren(16)
211 .Create(&s_DeviceAllocator);
212 NW_NULL_ASSERT(s_SceneRoot);
213 }
214
215 /*!--------------------------------------------------------------------------*
216 @brief カメラ関連の構築をします。
217 *---------------------------------------------------------------------------*/
218 void
BuildCameras()219 BuildCameras()
220 {
221 s_LeftCamera =
222 nw::gfx::Camera::DynamicBuilder()
223 .MaxChildren(0)
224 .MaxCallbacks(0)
225 .Create(&s_DeviceAllocator);
226
227 NW_POINTER_ASSERT(s_LeftCamera);
228
229 s_RightCamera =
230 nw::gfx::Camera::DynamicBuilder()
231 .MaxChildren(0)
232 .MaxCallbacks(0)
233 .Create(&s_DeviceAllocator);
234
235 NW_POINTER_ASSERT(s_RightCamera);
236
237 s_BaseCamera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin());
238 s_SceneRoot->AttachChild(s_BaseCamera);
239 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
240 }
241
242 /*!--------------------------------------------------------------------------*
243 @brief シーンを初期化します。
244 *---------------------------------------------------------------------------*/
245 void
InitializeScenes()246 InitializeScenes()
247 {
248 BuildRootNodes();
249
250 // ファイルから LUT Set を読み込みます。
251 NW_FOREACH(const wchar_t* name, LUT_RESOURCE_FILES)
252 {
253 nw::demo::ResourceSet resourceSet;
254 resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , name);
255
256 NW_NULL_ASSERT(resourceSet.buffer);
257
258 resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front()));
259
260 s_LutResources.push_back(resourceSet);
261 }
262
263 nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
264
265 // モデルリソースを読み込みます。
266 NW_FOREACH(const ResourceData resourceData, MODEL_RESOURCE_DATA)
267 {
268 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, resourceData.modelName, &s_DeviceAllocator);
269
270 resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
271 resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
272 resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
273
274 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
275 if (result.IsFailure())
276 {
277 if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_SHADER)
278 {
279 // シェーダーが見つからなかったときは、外部ファイルを指定して再びセットアップします。
280 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_ShaderResource->resource);
281 }
282
283 if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_LUT)
284 {
285 // 参照テーブルが見つからなかったときは、外部ファイルを指定して再びセットアップします。
286 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_LutResources[resourceData.lutIndex].resource);
287 }
288
289 if (result.IsFailure())
290 {
291 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
292 }
293 }
294
295 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
296 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
297 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
298 modelResource != modelsEnd; ++modelResource)
299 {
300 nw::math::VEC3& translate = (*modelResource).GetTransform().translate;
301 translate += resourceData.position;
302
303 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
304 &s_DeviceAllocator,
305 (*modelResource),
306 false
307 );
308 NW_NULL_ASSERT(node);
309 sceneNodeArray.push_back(node);
310 }
311 }
312
313 // モデル以外のリソースを読み込みます。
314 NW_FOREACH(const wchar_t* name, RESOURCE_FILES)
315 {
316 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator);
317
318 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
319 if (result.IsFailure())
320 {
321 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
322 }
323
324 nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
325 nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
326 for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
327 lightResource != lightsEnd; ++lightResource)
328 {
329 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
330 &s_DeviceAllocator,
331 (*lightResource)
332 );
333 NW_NULL_ASSERT(node);
334 sceneNodeArray.push_back(node);
335 }
336
337 nw::gfx::ResCameraArray cameras = resourceSet->resource.GetCameras();
338 nw::gfx::ResCameraArray::iterator camerasEnd = cameras.end();
339 for (nw::gfx::ResCameraArray::iterator cameraResource = cameras.begin();
340 cameraResource != camerasEnd; ++cameraResource)
341 {
342 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
343 &s_DeviceAllocator,
344 (*cameraResource)
345 );
346 NW_NULL_ASSERT(node);
347 sceneNodeArray.push_back(node);
348 }
349
350 nw::gfx::ResFogArray fogs = resourceSet->resource.GetFogs();
351 nw::gfx::ResFogArray::iterator fogsEnd = fogs.end();
352 for (nw::gfx::ResFogArray::iterator fogResource = fogs.begin();
353 fogResource != fogsEnd; ++fogResource)
354 {
355 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
356 &s_DeviceAllocator,
357 (*fogResource)
358 );
359 NW_NULL_ASSERT(node);
360 sceneNodeArray.push_back(node);
361 }
362
363 nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
364 nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
365 for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
366 settingResource != settingsEnd; ++settingResource)
367 {
368 nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
369 .Resource(*settingResource)
370 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
371
372 nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
373 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
374
375 NW_NULL_ASSERT(sceneEnvironmentSetting);
376 s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
377 }
378 }
379
380 // 親子付け参照関係を解決
381 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
382
383 // モデルをシーンに追加
384 nw::gfx::SceneHelper::ForeachRootNodes(
385 sceneNodeArray.Begin(),
386 sceneNodeArray.End(),
387 nw::gfx::AttachNode(s_SceneRoot)
388 );
389
390 // シーンツリーを巡回して初期化を行います。
391 s_SceneSystem->InitializeScene(s_SceneRoot);
392
393 BuildCameras();
394
395 // シーン環境の参照解決を行い設定します。
396 s_RenderSystem->SetSceneEnvironmentSettings(
397 s_SceneSystem,
398 &s_SceneEnvironmentSettings);
399
400 s_SceneSystem->UpdateScene();
401
402 NW_GL_ASSERT();
403
404 //-----------------------------------------------------------------------------
405
406 s_FrameCount = 0;
407 }
408
409 /*!--------------------------------------------------------------------------*
410 @brief シーン関連の後始末をします。
411 *---------------------------------------------------------------------------*/
412 void
TerminateScenes()413 TerminateScenes()
414 {
415 nw::gfx::SafeDestroyBranch(s_SceneRoot);
416 nw::demo::SafeCleanupResources(s_Resources);
417 nw::demo::SafeCleanupResources(s_LutResources);
418 nw::ut::SafeCleanup(s_ShaderResource->resource);
419 nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
420
421 NW_GL_ASSERT();
422
423 s_Resources.clear();
424 s_LutResources.clear();
425 s_SceneEnvironmentSettings.clear();
426 }
427
428 /*!--------------------------------------------------------------------------*
429 @brief シーンを更新します。
430 *---------------------------------------------------------------------------*/
431 void
UpdateScene()432 UpdateScene()
433 {
434 s_SceneSystem->GetCameraController()->Update();
435
436 s_SceneSystem->UpdateScene();
437
438 s_BaseCamera->UpdateCameraMatrix();
439
440 s_RenderSystem->CalcStereoCamera(
441 s_LeftCamera,
442 s_RightCamera,
443 *(s_SceneSystem->GetSceneContext()->GetCameraBegin()),
444 s_fNearPlane + 5.0f
445 );
446
447 ++s_FrameCount;
448 }
449
450 /*!--------------------------------------------------------------------------*
451 @brief 負荷表示やテスト機能の処理をおこないます。
452 *---------------------------------------------------------------------------*/
453 void
ReportDemo()454 ReportDemo()
455 {
456 NW_PROFILE("ReportDemo");
457
458 // 負荷表示からはこれらの負荷は除きます。
459 s_RenderSystem->SuspendLoadMeter();
460
461 nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
462
463 s_GraphicsDrawing.BeginDrawingShape();
464
465 nw::demo::DebugUtility::DrawLoadMeter(
466 s_RenderSystem,
467 &s_GraphicsDrawing
468 );
469
470 s_GraphicsDrawing.EndDrawingShape();
471
472 s_GraphicsDrawing.BeginDrawingString();
473
474 nw::demo::DebugUtility::DrawLoadMeterText(
475 s_RenderSystem,
476 &s_GraphicsDrawing
477 );
478
479 s_GraphicsDrawing.EndDrawingString();
480
481 s_RenderSystem->ResumeLoadMeter();
482 }
483
484 /*!--------------------------------------------------------------------------*
485 @brief シーンをデモンストレーションします。
486 *---------------------------------------------------------------------------*/
487 void
DemoScene()488 DemoScene()
489 {
490 NW_ASSERT(!s_RenderTargets.empty());
491
492 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
493
494 InitializeScenes();
495
496 nw::demo::DebugUtility::PostInitializeScenes();
497 nw::gfx::Camera* camera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin());
498 nw::demo::Utility::SetCameraAspectRatio(camera, s_RenderTargets[0]);
499
500 bool isContinuing = true;
501
502 while ( isContinuing )
503 {
504 nw::demo::DebugUtility::AdvanceAutoTestFrame();
505
506 nw::demo::PadFactory::GetPad()->Update();
507
508 UpdateScene();
509
510 renderContext->SetActiveCamera(s_BaseCameraIndex);
511 s_RenderSystem->SubmitView(s_SceneSystem);
512
513 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
514 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
515
516 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
517 ReportDemo();
518 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
519
520 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
521
522 renderContext->ResetState();
523
524 if (nw::demo::Utility::IsTerminating())
525 {
526 isContinuing = false;
527 }
528 }
529
530 nw::demo::DebugUtility::PreTerminateScenes();
531
532 TerminateScenes();
533 }
534
535 } // namespace
536
537 /*!--------------------------------------------------------------------------*
538 @brief メイン関数です。
539 *---------------------------------------------------------------------------*/
540 void
nnMain()541 nnMain()
542 {
543 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
544
545 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
546
547 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
548 {
549 InitializeGraphics();
550
551 DemoScene();
552
553 TerminateGraphics();
554 }
555
556 nw::demo::PadFactory::Finalize();
557
558 nw::demo::FinalizeGraphicsSystem();
559 }
560