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