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