1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: AnimationBlendDemo.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"Walk.bcskla"),
54 NW_DEMO_FILE_PATH(L"Run.bcskla")
55 };
56
57 const wchar_t* MATERIAL_ANIM_RESOURCE_FILES[] =
58 {
59 NW_DEMO_FILE_PATH(L"RedFading.bcmata"),
60 NW_DEMO_FILE_PATH(L"GreenFading.bcmata")
61 };
62
63 //----------------------------------------
64 // 描画関係
65 const int RENDER_TARGET_COUNT = 1;
66 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
67
68 RenderTargetArray s_RenderTargets;
69 nw::demo::SceneSystem* s_SceneSystem = NULL;
70 nw::demo::RenderSystem* s_RenderSystem = NULL;
71
72 nw::demo::GraphicsDrawing s_GraphicsDrawing;
73
74 //----------------------------------------
75 // リソース関係
76 nw::demo::ResourceArray s_Resources;
77
78 //----------------------------------------
79 // シーン関係
80 const int SCENE_NODE_COUNT = 4;
81 nw::gfx::SceneNode* s_SceneRoot = NULL;
82 nw::gfx::SceneNode* s_ModelRoot = NULL;
83 s32 s_FrameCount = 0;
84 nw::gfx::Camera* s_BaseCamera = NULL;
85 nw::gfx::Camera* s_LeftCamera = NULL;
86 nw::gfx::Camera* s_RightCamera = NULL;
87 const f32 s_fNearPlane = 0.1f;
88
89 //----------------------------------------
90 // シーン環境関係
91 const s32 ENVIRONMENT_SETTINGS_COUNT = 1;
92
93 typedef nw::ut::FixedSizeArray<nw::gfx::SceneEnvironmentSetting*, ENVIRONMENT_SETTINGS_COUNT> SceneEnvironmentSettingArray;
94 SceneEnvironmentSettingArray s_SceneEnvironmentSettings;
95
96 const s32 s_BaseCameraIndex = 0;
97
98 //----------------------------------------
99 // アニメーション関係
100 nw::gfx::SkeletalModel* s_AnimModel = NULL;
101 const int MAX_ANIM_OBJECTS = 6;
102 nw::ut::FixedSizeArray<nw::gfx::AnimObject*, MAX_ANIM_OBJECTS> s_AnimObjects;
103 float s_SkeletalAnimWeight0 = 0.5f;
104 float s_SkeletalAnimWeight1 = 0.5f;
105 float s_MaterialAnimWeight0 = 0.5f;
106 float s_MaterialAnimWeight1 = 0.5f;
107
108 /*!--------------------------------------------------------------------------*
109 @brief グラフィックス関連の初期化を行います。
110 *---------------------------------------------------------------------------*/
111 void
InitializeGraphics()112 InitializeGraphics()
113 {
114 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
115
116 // renderDescriptionへステレオの設定を行います。
117 nw::demo::RenderSystem::Description renderDescription;
118
119 renderDescription.reusableCommandBufferSize = 0x100000;
120 renderDescription.reusableCommandRequestCount = 512;
121 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
122
123 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
124
125 s_GraphicsDrawing.SetScreenSize(
126 renderDescription.lowerScreenDescription.width,
127 renderDescription.lowerScreenDescription.height
128 );
129
130 nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
131
132 s_RenderTargets.push_back(
133 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
134 );
135 NW_ASSERT(!s_RenderTargets.empty());
136 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
137
138 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
139 nw::demo::SceneSystem::Description sceneDescription;
140 sceneDescription.isFixedSizeMemory = true;
141 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
142
143 // デモ用の最遠景モデルをレンダリングシステムに設定します。
144 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
145 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
146
147 NW_GL_ASSERT();
148 }
149
150 /*!--------------------------------------------------------------------------*
151 @brief グラフィックス関連の後始末をします。
152 *---------------------------------------------------------------------------*/
153 void
TerminateGraphics()154 TerminateGraphics()
155 {
156 nw::gfx::SafeDestroy(s_LeftCamera);
157
158 nw::gfx::SafeDestroy(s_RightCamera);
159
160 nw::gfx::SafeDestroy(s_SceneSystem);
161
162 nw::gfx::SafeDestroyAll(s_RenderTargets);
163
164 s_GraphicsDrawing.Finalize();
165
166 nw::gfx::SafeDestroy(s_RenderSystem);
167
168 NW_GL_ASSERT();
169 }
170
171 /*!--------------------------------------------------------------------------*
172 @brief ファイルから TransformAnimEvaluator を生成します。
173
174 リソースからアニメーションを計算するための AnimEvaluator(アニメーション評価)を生成します。
175
176 @param[in] maxBones 最大メンバ数です。
177 @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。
178 @param[in] filePath トランスフォームアニメーションファイルのフルパスです。
179
180 @return トランスフォームアニメーション評価です。
181 *---------------------------------------------------------------------------*/
182 nw::gfx::TransformAnimEvaluator*
CreateTransformAnimEvaluator(const int maxMembers,const bool translateAnimEnabled,const wchar_t * filePath)183 CreateTransformAnimEvaluator(
184 const int maxMembers,
185 const bool translateAnimEnabled,
186 const wchar_t* filePath
187 )
188 {
189 // ファイルからアニメーションデータのインスタンスを生成します。
190 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator);
191 if (resourceSet->resource.GetSkeletalAnimsCount() == 0)
192 {
193 // スケルタルアニメーション用のアニメーションデータがありません。
194 return NULL;
195 }
196 nw::anim::ResAnim resAnim = resourceSet->resource.GetSkeletalAnims(0);
197
198 if (!resAnim.IsValid())
199 {
200 return NULL;
201 }
202
203 // resAnim から、AnimEvaluator::Builder を用いて AnimEvaluator を生成します。
204 // スケルタルアニメーションの場合は、TransformAnimEvaluator::Builder を使用します。
205 //
206 // アニメーションを1つのモデルにのみ適用する場合や、
207 // コマ形式データの場合は、 AllocCache を false にすると処理負荷が下がります。
208 nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
209 .AnimData(resAnim)
210 .MaxMembers(maxMembers)
211 .MaxAnimMembers(resAnim.GetMemberAnimSetCount())
212 .AllocCache(false)
213 .Create(&s_DeviceAllocator);
214
215 // 移動アニメーションの無効化フラグを設定します。
216 evaluator->SetIsTranslateDisabled(!translateAnimEnabled);
217
218 return evaluator;
219 }
220
221 /*!--------------------------------------------------------------------------*
222 @brief ファイルからマテリアルアニメーション評価を生成します。
223
224 @param[in] maxBones 最大メンバ数です。
225 @param[in] filePath マテリアルアニメーションファイルのフルパスです。
226
227 @return マテリアルアニメーション評価です。
228 *---------------------------------------------------------------------------*/
229 nw::gfx::AnimEvaluator*
CreateMaterialAnimEvaluator(const int maxMembers,const wchar_t * filePath)230 CreateMaterialAnimEvaluator(
231 const int maxMembers,
232 const wchar_t* filePath
233 )
234 {
235 //----------------------------------------
236 // アニメーションリソースを生成します。
237 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator);
238 if (resourceSet->resource.GetMaterialAnimsCount() == 0)
239 {
240 return NULL;
241 }
242
243 nw::anim::ResAnim resAnim = resourceSet->resource.GetMaterialAnims(0);
244 if (!resAnim.IsValid())
245 {
246 return NULL;
247 }
248
249 //----------------------------------------
250 // マテリアルアニメーション評価を生成します。
251 nw::gfx::AnimEvaluator* evaluator = nw::gfx::AnimEvaluator::Builder()
252 .AnimData(resAnim)
253 .MaxMembers(maxMembers)
254 .MaxAnimMembers(resAnim.GetMemberAnimSetCount())
255 .AllocCache(true)
256 .Create(&s_DeviceAllocator);
257
258 return evaluator;
259 }
260
261 /*!--------------------------------------------------------------------------*
262 @brief スケルタルアニメーションを初期化します。
263
264 アニメーション補間を生成し、2 つのアニメーション評価の結果をブレンドします。
265
266 @param[in] model スケルタルモデルです。
267 *---------------------------------------------------------------------------*/
268 void
InitializeSkeletalAnim(nw::gfx::SkeletalModel * model)269 InitializeSkeletalAnim(nw::gfx::SkeletalModel* model)
270 {
271 nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup();
272 if (animGroup == NULL) // スケルタルアニメーション用のアニメーショングループがありません。
273 {
274 return;
275 }
276
277 nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel();
278 nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
279 const int maxBones = resSkeleton.GetBonesCount();
280 const bool translateAnimEnabled =
281 nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED);
282
283 //----------------------------------------
284 // アニメーション評価を生成します。
285 nw::gfx::TransformAnimEvaluator* evaluator0 = CreateTransformAnimEvaluator(
286 maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILES[0]);
287 if (evaluator0 == NULL)
288 {
289 return;
290 }
291
292 // アニメーションをバインドします。
293 evaluator0->Bind(animGroup);
294 s_AnimObjects.PushBack(evaluator0);
295
296 //----------------------------------------
297 // 2 つめのアニメーション評価を生成します。
298 nw::gfx::TransformAnimEvaluator* evaluator1 = CreateTransformAnimEvaluator(
299 maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILES[1]);
300
301 if (evaluator1 == NULL)
302 {
303 return;
304 }
305
306 evaluator1->Bind(animGroup);
307 s_AnimObjects.PushBack(evaluator1);
308
309 // 自然な絵になるように、2つのアニメーションの再生時間を合わせます。
310 float frameSize0 = evaluator0->AnimFrameController().GetEndFrame();
311 float frameSize1 = evaluator1->AnimFrameController().GetEndFrame();
312 evaluator1->SetStepFrame(frameSize1 / frameSize0);
313
314 //----------------------------------------
315 // スケルタルアニメーション補間を生成します。
316 nw::gfx::TransformAnimInterpolator* blender = nw::gfx::TransformAnimInterpolator::Builder()
317 .MaxAnimObjects(2)
318 .Create(&s_DeviceAllocator);
319
320 blender->Bind(animGroup);
321 blender->AddAnimObject(evaluator0);
322 blender->AddAnimObject(evaluator1);
323 blender->SetWeight(0, s_SkeletalAnimWeight0);
324 blender->SetWeight(1, s_SkeletalAnimWeight1);
325
326 // 設定する重みは常に合計が 1 になり正規化は不要なので、正規化を無効にします。
327 // 合計が 1 にならないような重みを設定する場合は true を指定します。
328 blender->SetNormalizationEnabled(false);
329
330 model->SetSkeletalAnimObject(blender);
331 s_AnimObjects.PushBack(blender);
332 }
333
334 /*!--------------------------------------------------------------------------*
335 @brief マテリアルアニメーションを初期化します。
336
337 アニメーション補間を生成し、2 つのアニメーション評価の結果をブレンドします。
338
339 @param[in] model モデルです。
340 *---------------------------------------------------------------------------*/
341 void
InitializeMaterialAnim(nw::gfx::Model * model)342 InitializeMaterialAnim(nw::gfx::Model* model)
343 {
344 nw::gfx::AnimGroup* animGroup = model->GetMaterialAnimGroup();
345
346 if (animGroup == NULL) // アニメーション用のアニメーショングループがありません。
347 {
348 return;
349 }
350
351 int maxMembers = animGroup->GetMemberCount();
352
353 //----------------------------------------
354 // アニメーション評価を生成します。
355 nw::gfx::AnimEvaluator* evaluator0 = CreateMaterialAnimEvaluator(
356 maxMembers, MATERIAL_ANIM_RESOURCE_FILES[0]);
357 if (evaluator0 == NULL)
358 {
359 return;
360 }
361
362 // アニメーションをバインドします。
363 evaluator0->Bind(animGroup);
364 s_AnimObjects.PushBack(evaluator0);
365
366 //----------------------------------------
367 // 2 つめのアニメーション評価を生成します。
368 nw::gfx::AnimEvaluator* evaluator1 = CreateMaterialAnimEvaluator(
369 maxMembers, MATERIAL_ANIM_RESOURCE_FILES[1]);
370
371 if (evaluator1 == NULL)
372 {
373 return;
374 }
375
376 evaluator1->Bind(animGroup);
377 s_AnimObjects.PushBack(evaluator1);
378
379 //----------------------------------------
380 // アニメーション補間を生成します。
381 nw::gfx::AnimInterpolator* blender = nw::gfx::AnimInterpolator::Builder()
382 .MaxAnimObjects(2)
383 .Create(&s_DeviceAllocator);
384
385 blender->Bind(animGroup);
386 blender->AddAnimObject(evaluator0);
387 blender->AddAnimObject(evaluator1);
388 blender->SetWeight(0, s_MaterialAnimWeight0);
389 blender->SetWeight(1, s_MaterialAnimWeight0);
390
391 // 設定する重みは常に合計が 1 になり正規化は不要なので、正規化を無効にします。
392 // 合計が 1 にならないような重みを設定する場合は true を指定します。
393 blender->SetNormalizationEnabled(false);
394
395 model->SetMaterialAnimObject(blender);
396 s_AnimObjects.PushBack(blender);
397 }
398
399 /*!--------------------------------------------------------------------------*
400 @brief ブレンダーを更新します。
401
402 @param[in] model モデルです。
403 *---------------------------------------------------------------------------*/
404 void
UpdateBlender(nw::gfx::SkeletalModel * model)405 UpdateBlender(nw::gfx::SkeletalModel* model)
406 {
407 NW_PROFILE("UpdateBlender");
408
409 if (model == NULL)
410 {
411 return;
412 }
413
414 // ブレンドのウェイト値を設定します。
415 nw::gfx::AnimObject* skeletalAnimObject = model->GetSkeletalAnimObject();
416 nw::gfx::TransformAnimInterpolator* skeletalInterpolator =
417 nw::ut::DynamicCast<nw::gfx::TransformAnimInterpolator*>(skeletalAnimObject);
418 if (skeletalInterpolator != NULL)
419 {
420 bool weightChanged = false;
421 nw::demo::Pad* pad = nw::demo::PadFactory::GetPad();
422 if (pad->IsButtonPress(nw::demo::Pad::BUTTON_LEFT))
423 {
424 s_SkeletalAnimWeight1 -= 0.02f;
425 weightChanged = true;
426 }
427 if (pad->IsButtonPress(nw::demo::Pad::BUTTON_RIGHT))
428 {
429 s_SkeletalAnimWeight1 += 0.02f;
430 weightChanged = true;
431 }
432 if (weightChanged)
433 {
434 s_SkeletalAnimWeight1 = nw::ut::Clamp(s_SkeletalAnimWeight1, 0.0f, 1.0f);
435 s_SkeletalAnimWeight0 = 1.0f - s_SkeletalAnimWeight1;
436
437 skeletalInterpolator->SetWeight(0, s_SkeletalAnimWeight0);
438 skeletalInterpolator->SetWeight(1, s_SkeletalAnimWeight1);
439 }
440 }
441
442 nw::gfx::AnimObject* materialAnimObject = model->GetMaterialAnimObject();
443 nw::gfx::AnimInterpolator* materialInterpolator =
444 nw::ut::DynamicCast<nw::gfx::AnimInterpolator*>(materialAnimObject);
445 if (materialInterpolator != NULL)
446 {
447 bool weightChanged = false;
448 nw::demo::Pad* pad = nw::demo::PadFactory::GetPad();
449 if (pad->IsButtonPress(nw::demo::Pad::BUTTON_UP))
450 {
451 s_MaterialAnimWeight1 -= 0.02f;
452 weightChanged = true;
453 }
454 if (pad->IsButtonPress(nw::demo::Pad::BUTTON_DOWN))
455 {
456 s_MaterialAnimWeight1 += 0.02f;
457 weightChanged = true;
458 }
459 if (weightChanged)
460 {
461 s_MaterialAnimWeight1 = nw::ut::Clamp(s_MaterialAnimWeight1, 0.0f, 1.0f);
462 s_MaterialAnimWeight0 = 1.0f - s_MaterialAnimWeight1;
463
464 materialInterpolator->SetWeight(0, s_MaterialAnimWeight1);
465 materialInterpolator->SetWeight(1, s_MaterialAnimWeight0);
466 }
467 }
468 }
469
470 /*!--------------------------------------------------------------------------*
471 @brief アニメーションの後始末をします。
472 *---------------------------------------------------------------------------*/
473 void
TerminateAnim(void)474 TerminateAnim(void)
475 {
476 for (int animIdx = 0; animIdx < s_AnimObjects.Size(); ++animIdx)
477 {
478 nw::gfx::SafeDestroy(s_AnimObjects[animIdx]);
479 }
480 s_AnimObjects.clear();
481 }
482
483 /*!--------------------------------------------------------------------------*
484 @brief ルートノード関連の構築をします。
485 *---------------------------------------------------------------------------*/
486 void
BuildRootNodes()487 BuildRootNodes()
488 {
489 NW_ASSERT(s_SceneRoot == NULL);
490 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
491 .Create(&s_DeviceAllocator);
492 NW_NULL_ASSERT(s_SceneRoot);
493
494 NW_ASSERT(s_ModelRoot == NULL);
495 s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder()
496 .Create(&s_DeviceAllocator);
497 s_SceneRoot->AttachChild(s_ModelRoot);
498 NW_NULL_ASSERT(s_ModelRoot);
499 }
500
501 /*!--------------------------------------------------------------------------*
502 @brief カメラ関連の構築をします。
503 *---------------------------------------------------------------------------*/
504 void
BuildCameras()505 BuildCameras()
506 {
507 nw::demo::Utility::CreateStereoCameras(
508 &s_BaseCamera,
509 &s_LeftCamera,
510 &s_RightCamera,
511 &s_DeviceAllocator,
512 nw::math::VEC3(20.0f, 15.0f, 20.0f),
513 nw::math::VEC3(0.0f, 10.0f, 0.0f),
514 s_fNearPlane
515 );
516
517 s_SceneRoot->AttachChild(s_BaseCamera);
518 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
519 }
520
521 /*!--------------------------------------------------------------------------*
522 @brief リソース関連の構築をします。
523 *---------------------------------------------------------------------------*/
524 void
BuildResources(nw::demo::ResourceSet * resourceSet)525 BuildResources(nw::demo::ResourceSet* resourceSet)
526 {
527 resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
528 resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
529 resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
530
531 nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator);
532 if (result.IsFailure())
533 {
534 NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
535 }
536
537 nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator);
538
539 nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
540 nw::gfx::ResModelArray::iterator modelsEnd = models.end();
541 for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
542 modelResource != modelsEnd; ++modelResource)
543 {
544 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
545 &s_DeviceAllocator,
546 (*modelResource)
547 );
548 NW_NULL_ASSERT(node);
549 sceneNodeArray.push_back(node);
550 s_AnimModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(node);
551 }
552
553 nw::gfx::ResLightArray lights = resourceSet->resource.GetLights();
554 nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
555 for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
556 lightResource != lightsEnd; ++lightResource)
557 {
558 nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
559 &s_DeviceAllocator,
560 (*lightResource)
561 );
562 NW_NULL_ASSERT(node);
563 sceneNodeArray.push_back(node);
564 }
565
566 // 親子付け参照関係を解決
567 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
568
569 // モデルをシーンに追加
570 nw::gfx::SceneHelper::ForeachRootNodes(
571 sceneNodeArray.Begin(),
572 sceneNodeArray.End(),
573 nw::gfx::AttachNode(s_ModelRoot)
574 );
575
576 nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings();
577 nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
578 for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
579 settingResource != settingsEnd; ++settingResource)
580 {
581 nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
582 .Resource(*settingResource)
583 .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator);
584
585 nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
586 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
587
588 NW_NULL_ASSERT(sceneEnvironmentSetting);
589 s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting);
590 }
591 }
592
593 /*!--------------------------------------------------------------------------*
594 @brief シーンを初期化します。
595 *---------------------------------------------------------------------------*/
596 void
InitializeScenes()597 InitializeScenes()
598 {
599 s_SkeletalAnimWeight0 = 0.5f;
600 s_SkeletalAnimWeight1 = 0.5f;
601 s_MaterialAnimWeight0 = 0.5f;
602 s_MaterialAnimWeight1 = 0.5f;
603
604 BuildRootNodes();
605
606 BuildCameras();
607
608 NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES)
609 {
610 BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator));
611 }
612
613 if (s_AnimModel != NULL)
614 {
615 InitializeSkeletalAnim(s_AnimModel);
616 InitializeMaterialAnim(s_AnimModel);
617 }
618
619 // シーンツリーを巡回して初期化を行います。
620 s_SceneSystem->InitializeScene(s_SceneRoot);
621 s_SceneSystem->UpdateScene();
622
623 // シーン環境の参照解決を行い設定します。
624 s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings);
625
626 // カメラを設定します。
627 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
628 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
629 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
630
631 NW_GL_ASSERT();
632
633 s_FrameCount = 0;
634 }
635
636 /*!--------------------------------------------------------------------------*
637 @brief シーン関連の後始末をします。
638 *---------------------------------------------------------------------------*/
639 void
TerminateScenes()640 TerminateScenes()
641 {
642 nw::gfx::SafeDestroyBranch(s_SceneRoot);
643 nw::demo::SafeCleanupResources(s_Resources);
644 nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings);
645 TerminateAnim();
646
647 NW_GL_ASSERT();
648
649 s_Resources.clear();
650 s_SceneEnvironmentSettings.clear();
651 s_ModelRoot = NULL;
652 }
653
654 /*!--------------------------------------------------------------------------*
655 @brief シーンを更新します。
656 *---------------------------------------------------------------------------*/
657 void
UpdateScene()658 UpdateScene()
659 {
660 UpdateBlender(s_AnimModel);
661
662 s_SceneSystem->GetCameraController()->Update();
663
664 s_SceneSystem->UpdateScene();
665
666 s_BaseCamera->UpdateCameraMatrix();
667
668 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
669
670 ++s_FrameCount;
671 }
672
673 /*!--------------------------------------------------------------------------*
674 @brief 負荷表示やテスト機能の処理をおこないます。
675 *---------------------------------------------------------------------------*/
676 void
ReportDemo()677 ReportDemo()
678 {
679 NW_PROFILE("ReportDemo");
680
681 // 負荷表示からはこれらの負荷は除きます。
682 s_RenderSystem->SuspendLoadMeter();
683
684 nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
685
686 s_GraphicsDrawing.BeginDrawingShape();
687
688 nw::demo::DebugUtility::DrawLoadMeter(
689 s_RenderSystem,
690 &s_GraphicsDrawing
691 );
692
693 s_GraphicsDrawing.EndDrawingShape();
694
695 s_GraphicsDrawing.BeginDrawingString();
696
697 nw::demo::DebugUtility::DrawLoadMeterText(
698 s_RenderSystem,
699 &s_GraphicsDrawing
700 );
701
702 const int dumpPositionX = 10;
703 const int dumpPositionY = 10;
704 s_GraphicsDrawing.DrawString(
705 dumpPositionX,
706 dumpPositionY,
707 "weight: %0.2f %0.2f",
708 s_SkeletalAnimWeight1,
709 s_MaterialAnimWeight1
710 );
711
712 s_GraphicsDrawing.EndDrawingString();
713
714 s_RenderSystem->ResumeLoadMeter();
715 }
716
717 /*!--------------------------------------------------------------------------*
718 @brief シーンをデモンストレーションします。
719 *---------------------------------------------------------------------------*/
720 void
DemoScene()721 DemoScene()
722 {
723 NW_ASSERT(!s_RenderTargets.empty());
724
725 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
726
727 InitializeScenes();
728
729 nw::demo::DebugUtility::PostInitializeScenes();
730
731 NW_LOG("[Animation Blend Demo usage]\n");
732 NW_LOG("up/down : change material animation blender weight\n");
733 NW_LOG("left/right: change skeletal animation blender weight\n");
734
735 bool isContinuing = true;
736
737 while ( isContinuing )
738 {
739 nw::demo::DebugUtility::AdvanceAutoTestFrame();
740
741 nw::demo::PadFactory::GetPad()->Update();
742
743 UpdateScene();
744
745 renderContext->SetActiveCamera(s_BaseCameraIndex);
746 s_RenderSystem->SubmitView(s_SceneSystem);
747
748 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
749 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
750
751 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
752 ReportDemo();
753 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
754
755 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
756
757 renderContext->ResetState();
758
759 if (nw::demo::Utility::IsTerminating())
760 {
761 isContinuing = false;
762 }
763 }
764
765 nw::demo::DebugUtility::PreTerminateScenes();
766
767 TerminateScenes();
768 }
769
770 } // namespace
771
772 /*!--------------------------------------------------------------------------*
773 @brief メイン関数です。
774 *---------------------------------------------------------------------------*/
775 void
nnMain()776 nnMain()
777 {
778 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
779
780 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
781
782 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem)
783 {
784 InitializeGraphics();
785
786 DemoScene();
787
788 TerminateGraphics();
789 }
790
791 nw::demo::PadFactory::Finalize();
792
793 nw::demo::FinalizeGraphicsSystem();
794 }
795