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