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