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