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