1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: PartialAnimationDemo.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: 22362 $
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
23 #include <nw/demo.h>
24 #include <nw/dev.h>
25 #include <nw/gfx.h>
26 #include <nw/ut.h>
27 #include <nw/anim.h>
28
29 namespace
30 {
31
32 //----------------------------------------
33 // メモリ関係
34
35 // デバイスメモリを確保するためのアロケータです。
36 nw::demo::DemoAllocator s_DeviceAllocator;
37
38 //----------------------------------------
39 // ファイル名の定義です。
40 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin");
41 const wchar_t* FONT_FILE_NAME = NW_DEMO_FILE_PATH(L"Font.bcfnt");
42 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
43
44 const wchar_t* MODEL_RESOURCE_FILES[] =
45 {
46 NW_DEMO_FILE_PATH(L"Male.bcmdl"),
47 NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"),
48 NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"),
49 };
50
51 const wchar_t* SKELETAL_ANIM_RESOURCE_FILES[] =
52 {
53 NW_DEMO_FILE_PATH(L"WalkLower.bcskla"),
54 NW_DEMO_FILE_PATH(L"RunUpper.bcskla")
55 };
56
57 //----------------------------------------
58 // プロファイル関係
59 const int NW_LOAD_METER_INTERVAL = 60;
60
61 //----------------------------------------
62 // 描画関係
63 const int RENDER_TARGET_COUNT = 1;
64 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
65
66 RenderTargetArray s_RenderTargets;
67 nw::demo::SceneSystem* s_SceneSystem = NULL;
68 nw::demo::RenderSystem* s_RenderSystem = NULL;
69
70 nw::demo::GraphicsDrawing s_GraphicsDrawing;
71
72 //----------------------------------------
73 // リソース関係
74 nw::demo::ResourceArray s_Resources;
75
76 //----------------------------------------
77 // シーン関係
78 const int SCENE_NODE_COUNT = 4;
79 nw::gfx::SceneNode* s_SceneRoot = NULL;
80 nw::gfx::SceneNode* s_ModelRoot = NULL;
81 s32 s_FrameCount = 0;
82 nw::gfx::Camera* s_BaseCamera = NULL;
83 nw::gfx::Camera* s_LeftCamera = NULL;
84 nw::gfx::Camera* s_RightCamera = NULL;
85 const f32 s_fNearPlane = 0.1f;
86
87 //----------------------------------------
88 // シーン環境関係
89 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
90
91 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
92 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
93
94 const s32 s_BaseCameraIndex = 0;
95
96 //----------------------------------------
97 // アニメーション関係
98 nw::gfx::SkeletalModel* s_AnimModel = NULL;
99 const int MAX_ANIM_OBJECTS = 6;
100 nw::ut::FixedSizeArray<nw::gfx::AnimObject*, MAX_ANIM_OBJECTS> s_AnimObjects;
101 const int MAX_ANIM_OBJECTS_PER_MODEL = 2;
102
103 /*!--------------------------------------------------------------------------*
104 @brief グラフィックス関連の初期化を行います。
105 *---------------------------------------------------------------------------*/
106 void
InitializeGraphics()107 InitializeGraphics()
108 {
109 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
110
111 // renderDescriptionへステレオの設定を行います。
112 nw::demo::RenderSystem::Description renderDescription;
113
114 renderDescription.reusableCommandBufferSize = 0x100000;
115 renderDescription.reusableCommandRequestCount = 512;
116 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
117
118 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
119
120 s_GraphicsDrawing.SetScreenSize(
121 renderDescription.lowerScreenDescription.width,
122 renderDescription.lowerScreenDescription.height
123 );
124
125 bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME);
126
127 NN_ASSERTMSG(result, "Fail to load Font.");
128
129 s_RenderTargets.push_back(
130 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
131 );
132 NW_ASSERT(!s_RenderTargets.empty());
133 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
134
135 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
136 nw::demo::SceneSystem::Description sceneDescription;
137 sceneDescription.isFixedSizeMemory = true;
138 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
139
140 // デモ用の最遠景モデルをレンダリングシステムに設定します。
141 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
142 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
143
144 NW_GL_ASSERT();
145 }
146
147 /*!--------------------------------------------------------------------------*
148 @brief グラフィックス関連の後始末をします。
149 *---------------------------------------------------------------------------*/
150 void
TerminateGraphics()151 TerminateGraphics()
152 {
153 nw::gfx::SafeDestroy(s_LeftCamera);
154
155 nw::gfx::SafeDestroy(s_RightCamera);
156
157 nw::gfx::SafeDestroy(s_SceneSystem);
158
159 nw::gfx::SafeDestroyAll(s_RenderTargets);
160
161 s_GraphicsDrawing.Finalize();
162
163 nw::gfx::SafeDestroy(s_RenderSystem);
164
165 NW_GL_ASSERT();
166 }
167
168 /*!--------------------------------------------------------------------------*
169 @brief ファイルからトランスフォームアニメーション評価を生成します。
170
171 @param[in] maxBones 最大メンバ数です。
172 @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。
173 @param[in] filePath トランスフォームアニメーションファイルのフルパスです。
174
175 @return トランスフォームアニメーション評価です。
176 *---------------------------------------------------------------------------*/
177 nw::gfx::TransformAnimEvaluator*
CreateTransformAnimEvaluator(const int maxMembers,const bool translateAnimEnabled,const wchar_t * filePath)178 CreateTransformAnimEvaluator(
179 const int maxMembers,
180 const bool translateAnimEnabled,
181 const wchar_t* filePath
182 )
183 {
184 //----------------------------------------
185 // アニメーションリソースを生成します。
186 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator);
187 if (resourceSet->resource.GetSkeletalAnimsCount() == 0)
188 {
189 return NULL;
190 }
191 nw::anim::ResAnim resAnim = resourceSet->resource.GetSkeletalAnims(0);
192
193 if (!resAnim.IsValid())
194 {
195 return NULL;
196 }
197
198 //----------------------------------------
199 // トランスフォームアニメーション評価を生成します。
200 //
201 // アニメーションを1つのモデルにのみ適用する場合や、
202 // コマ形式データの場合は、 AllocCache を false にすると処理負荷が下がります。
203 nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
204 .AnimData(resAnim)
205 .MaxMembers(maxMembers)
206 .MaxAnimMembers(resAnim.GetMemberAnimSetCount())
207 .AllocCache(false)
208 .Create(&s_DeviceAllocator);
209
210 // 移動アニメーションの無効化フラグを設定します。
211 evaluator->SetIsTranslateDisabled(!translateAnimEnabled);
212
213 return evaluator;
214 }
215
216 /*!--------------------------------------------------------------------------*
217 @brief スケルタルアニメーションを初期化します。
218
219 1 つのモデルに複数の部分アニメのアニメーション評価をバインドします。
220
221 @param[in] model スケルタルモデルです。
222 *---------------------------------------------------------------------------*/
223 void
InitializeSkeletalAnim(nw::gfx::SkeletalModel * model)224 InitializeSkeletalAnim(nw::gfx::SkeletalModel* model)
225 {
226 nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup();
227 if (animGroup == NULL) // スケルタルアニメーション用のアニメーショングループがありません。
228 {
229 return;
230 }
231
232 nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel();
233 nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
234 const int maxBones = resSkeleton.GetBonesCount();
235 const bool translateAnimEnabled =
236 nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED);
237
238 //----------------------------------------
239 // アニメーション評価を生成します。
240 nw::gfx::TransformAnimEvaluator* evaluator0 = CreateTransformAnimEvaluator(
241 maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILES[0]);
242 if (evaluator0 == NULL)
243 {
244 return;
245 }
246
247 // アニメーションをバインドします。
248 evaluator0->Bind(animGroup);
249 s_AnimObjects.PushBack(evaluator0);
250
251 //----------------------------------------
252 // 2 つめのアニメーション評価を生成します。
253 nw::gfx::TransformAnimEvaluator* evaluator1 = CreateTransformAnimEvaluator(
254 maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILES[1]);
255
256 if (evaluator1 == NULL)
257 {
258 return;
259 }
260
261 // アニメーションを 1 つ目と同じアニメーショングループにバインドします。
262 evaluator1->Bind(animGroup);
263 s_AnimObjects.PushBack(evaluator1);
264
265 //----------------------------------------
266 // モデルに 2 つのアニメーション評価を設定します。
267 model->SetSkeletalAnimObject(evaluator0, 0);
268 model->SetSkeletalAnimObject(evaluator1, 1);
269 }
270
271 /*!--------------------------------------------------------------------------*
272 @brief アニメーションの後始末をします。
273 *---------------------------------------------------------------------------*/
274 void
TerminateAnim(void)275 TerminateAnim(void)
276 {
277 for (int animIdx = 0; animIdx < s_AnimObjects.Size(); ++animIdx)
278 {
279 nw::gfx::SafeDestroy(s_AnimObjects[animIdx]);
280 }
281 s_AnimObjects.clear();
282 }
283
284 /*!--------------------------------------------------------------------------*
285 @brief ルートノード関連の構築をします。
286 *---------------------------------------------------------------------------*/
287 void
BuildRootNodes()288 BuildRootNodes()
289 {
290 NW_ASSERT(s_SceneRoot == NULL);
291 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
292 .Create(&s_DeviceAllocator);
293 NW_NULL_ASSERT(s_SceneRoot);
294
295 NW_ASSERT(s_ModelRoot == NULL);
296 s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
297 .Create(&s_DeviceAllocator);
298 s_SceneRoot->AttachChild(s_ModelRoot);
299 NW_NULL_ASSERT(s_ModelRoot);
300 }
301
302 /*!--------------------------------------------------------------------------*
303 @brief カメラ関連の構築をします。
304 *---------------------------------------------------------------------------*/
305 void
BuildCameras()306 BuildCameras()
307 {
308 nw::demo::Utility::CreateStereoCameras(
309 &s_BaseCamera,
310 &s_LeftCamera,
311 &s_RightCamera,
312 &s_DeviceAllocator,
313 nw::math::VEC3(20.0f, 15.0f, 20.0f),
314 nw::math::VEC3(0.0f, 10.0f, 0.0f),
315 s_fNearPlane
316 );
317
318 s_SceneRoot->AttachChild(s_BaseCamera);
319 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
320 }
321
322 /*!--------------------------------------------------------------------------*
323 @brief リソース関連の構築をします。
324 *---------------------------------------------------------------------------*/
325 void
BuildResources(nw::demo::ResourceSet * resourceSet)326 BuildResources(nw::demo::ResourceSet* resourceSet)
327 {
328 resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
329 resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
330 resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
331
332 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
333 if (result.IsFailure())
334 {
335 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
336 }
337
338 nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
339
340 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
341 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
342 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
343 modelResource != modelsEnd; ++modelResource)
344 {
345 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
346 &s_DeviceAllocator,
347 (*modelResource),
348 true,
349 nw::gfx::Model::FLAG_BUFFER_NOT_USE,
350 MAX_ANIM_OBJECTS_PER_MODEL // 複数のアニメーションオブジェクトをバインドできるようにします。
351 );
352 NW_NULL_ASSERT(node);
353 sceneNodeArray.push_back(node);
354
355 s_AnimModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(node);
356 }
357
358 nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
359 nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
360 for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
361 lightResource != lightsEnd; ++lightResource)
362 {
363 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
364 &s_DeviceAllocator,
365 (*lightResource)
366 );
367 NW_NULL_ASSERT(node);
368 sceneNodeArray.push_back(node);
369 }
370
371 // 親子付け参照関係を解決
372 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
373
374 // モデルをシーンに追加
375 nw::gfx::SceneHelper::ForeachRootNodes(
376 sceneNodeArray.Begin(),
377 sceneNodeArray.End(),
378 nw::gfx::AttachNode(s_ModelRoot)
379 );
380
381 nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
382 nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
383 for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
384 settingResource != settingsEnd; ++settingResource)
385 {
386 nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
387 .Resource(*settingResource)
388 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
389
390 nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
391 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
392
393 NW_NULL_ASSERT(sceneEnvironmentSetting);
394 s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
395 }
396 }
397
398 /*!--------------------------------------------------------------------------*
399 @brief シーンを初期化します。
400 *---------------------------------------------------------------------------*/
401 void
InitializeScenes()402 InitializeScenes()
403 {
404 BuildRootNodes();
405
406 BuildCameras();
407
408 NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
409 {
410 BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
411 }
412
413 if (s_AnimModel != NULL)
414 {
415 InitializeSkeletalAnim(s_AnimModel);
416 }
417
418 // シーンツリーを巡回して初期化を行います。
419 s_SceneSystem->InitializeScene(s_SceneRoot);
420 s_SceneSystem->UpdateScene();
421
422 // シーン環境の参照解決を行い設定します。
423 s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
424
425 // カメラを設定します。
426 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
427 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
428 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
429
430 NW_GL_ASSERT();
431
432 s_FrameCount = 0;
433 }
434
435 /*!--------------------------------------------------------------------------*
436 @brief シーン関連の後始末をします。
437 *---------------------------------------------------------------------------*/
438 void
TerminateScenes()439 TerminateScenes()
440 {
441 nw::gfx::SafeDestroyBranch(s_SceneRoot);
442 nw::demo::SafeCleanupResources(s_Resources);
443 nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
444 TerminateAnim();
445
446 NW_GL_ASSERT();
447
448 s_Resources.clear();
449 s_SceneEnvironmentSettings.clear();
450
451 s_ModelRoot = NULL;
452 }
453
454 /*!--------------------------------------------------------------------------*
455 @brief シーンを更新します。
456 *---------------------------------------------------------------------------*/
457 void
UpdateScene()458 UpdateScene()
459 {
460 s_SceneSystem->GetCameraController()->Update();
461
462 s_SceneSystem->UpdateScene();
463
464 s_BaseCamera->UpdateCameraMatrix();
465
466 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
467
468 ++s_FrameCount;
469 }
470
471 /*!--------------------------------------------------------------------------*
472 @brief 負荷表示やテスト機能の処理をおこないます。
473 *---------------------------------------------------------------------------*/
474 void
ReportDemo()475 ReportDemo()
476 {
477 NW_PROFILE("ReportDemo");
478
479 // 負荷表示からはこれらの負荷は除きます。
480 s_RenderSystem->SuspendLoadMeter();
481
482 s_GraphicsDrawing.BeginDrawingString();
483
484 nw::demo::DebugUtility::DrawLoadMeter(
485 s_RenderSystem,
486 &s_GraphicsDrawing,
487 (s_FrameCount % NW_LOAD_METER_INTERVAL == 0)
488 );
489
490 s_GraphicsDrawing.FlushDrawing();
491
492 s_RenderSystem->ResumeLoadMeter();
493 }
494
495 /*!--------------------------------------------------------------------------*
496 @brief シーンをデモンストレーションします。
497 *---------------------------------------------------------------------------*/
498 void
DemoScene()499 DemoScene()
500 {
501 NW_ASSERT(!s_RenderTargets.empty());
502
503 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
504
505 InitializeScenes();
506
507 bool isContinuing = true;
508
509 while ( isContinuing )
510 {
511 nw::demo::DebugUtility::AdvanceAutoTestFrame();
512
513 nw::demo::PadFactory::GetPad()->Update();
514
515 UpdateScene();
516
517 renderContext->SetActiveCamera(s_BaseCameraIndex);
518 s_RenderSystem->SubmitView(s_SceneSystem);
519
520 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
521 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
522
523 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
524 ReportDemo();
525 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
526
527 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
528
529 renderContext->ResetState();
530
531 if (nw::demo::Utility::IsTerminating())
532 {
533 isContinuing = false;
534 }
535 }
536
537 TerminateScenes();
538 }
539
540 } // namespace
541
542 /*!--------------------------------------------------------------------------*
543 @brief メイン関数です。
544 *---------------------------------------------------------------------------*/
545 void
nnMain()546 nnMain()
547 {
548 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
549
550 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
551
552 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
553 {
554 InitializeGraphics();
555
556 DemoScene();
557
558 TerminateGraphics();
559 }
560
561 nw::demo::PadFactory::Finalize();
562
563 nw::demo::FinalizeGraphicsSystem();
564 }
565