1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     GfxCtrl.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: 1 $
14  *---------------------------------------------------------------------------*/
15 #include <nn/os.h>
16 #include <nn/fs.h>
17 
18 #include <nw/types.h>
19 #include <nw/demo/demo_Utility.h>
20 #include <nw/dev.h>
21 #include <nw/gfx.h>
22 #include <nw/ut.h>
23 
24 #include "../include/SmDef.h"
25 #include "../include/GfxCtrl.h"
26 
27 namespace
28 {
29 
30 /*---------------------------------------------------------------------------*
31   @brief 指定ファイルのロードを行います。
32  *---------------------------------------------------------------------------*/
33 bool
LoadResources(GfxCtrl::GfxResourceSet * resourceSet,const wchar_t * resourcePath,nw::os::IAllocator * allocator,nw::os::IAllocator * deviceAllocator,GfxCtrl::GfxVramType vramType=GfxCtrl::GFX_CTRL_VRAM_NONE)34 LoadResources( GfxCtrl::GfxResourceSet* resourceSet, const wchar_t* resourcePath,
35               nw::os::IAllocator* allocator, nw::os::IAllocator* deviceAllocator, GfxCtrl::GfxVramType vramType = GfxCtrl::GFX_CTRL_VRAM_NONE )
36 {
37     static const int RESOURCE_ALIGNMENT = 128;
38 
39     resourceSet->buffer = nw::demo::Utility::LoadFile( deviceAllocator , resourcePath, RESOURCE_ALIGNMENT );
40     if (!resourceSet->buffer)
41     {
42         NW_FATAL_ERROR("can not open gfx archive.\n");
43     }
44     resourceSet->resource = nw::gfx::ResGraphicsFile(&(resourceSet->buffer.front()));
45 
46     if (vramType != GfxCtrl::GFX_CTRL_VRAM_NONE)
47     {
48         // 配置するVRAMを引数で切り替えます。
49         resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(vramType | GL_NO_COPY_FCRAM_DMP));
50         resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(vramType | GL_NO_COPY_FCRAM_DMP));
51         resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(vramType | GL_NO_COPY_FCRAM_DMP));
52     }
53 
54     // ロードしたリソースのセットアップを行い、エラーがあれば出力します。
55     nw::gfx::Result result = resourceSet->resource.Setup(allocator);
56     if (result.IsFailure())
57     {
58         NW_WARNING(false ,"Fail to set up model. A result code is 0x%x", result.GetCode());
59     }
60 
61     return true;
62 }
63 
64 
65 
66 /*---------------------------------------------------------------------------*
67   @brief コンストラクタです。
68  *---------------------------------------------------------------------------*/
GfxCtrl(SmSceneCtrl * sceneCtrl)69 GfxCtrl::GfxCtrl( SmSceneCtrl* sceneCtrl )
70 : m_GfxSceneCtrl(sceneCtrl),
71   m_SceneRoot(NULL),
72   m_Camera(NULL),
73   m_ResCamera(NULL),
74   m_SmCamera(NULL),
75   m_SmParticle(NULL),
76   m_ParticleContext(NULL),
77   m_ParticleSceneUpdater(NULL),
78   m_SceneEnvSetting(NULL),
79   m_LightAnimation(NULL)
80 {
81     m_ResourcesArray.clear();
82     m_AnimationArray.clear();
83     m_SmModelInstArray.clear();
84 
85     // ルートノードを生成します。
86     m_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
87         .IsFixedSizeMemory(false)
88         .Create(m_Allocator);
89     NW_NULL_ASSERT(m_SceneRoot);
90 
91     // SmCamera 生成します。
92     m_SmCamera = new SmCamera( m_SceneRoot, NULL );
93 
94     // パーティクルコンテキスト生成します。
95     m_ParticleContext = nw::gfx::ParticleContext::Builder()
96         .MaxEmission(1000)
97         .Create( m_Allocator );
98 
99     // パーティクルシーンアップデータ生成します。
100     m_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
101         .Create( m_Allocator );
102 }
103 
104 
105 /*---------------------------------------------------------------------------*
106   @brief デストラクタです。
107  *---------------------------------------------------------------------------*/
~GfxCtrl()108 GfxCtrl::~GfxCtrl()
109 {
110     // アニメーションの破棄
111     for (int animIdx = 0; animIdx < m_AnimationArray.Size(); ++animIdx)
112     {
113         nw::gfx::SafeDestroy(m_AnimationArray[animIdx]);
114     }
115     m_AnimationArray.clear();
116 
117     // SmModelインスタンスの破棄
118     for (int modelIdx = 0; modelIdx < m_SmModelInstArray.Size(); ++modelIdx)
119     {
120         SM_SAFE_DELETE(m_SmModelInstArray[modelIdx]);
121     }
122     m_SmModelInstArray.clear();
123 
124     // パーティクル関連の破棄を行います。
125     nw::gfx::SafeDestroy(m_ParticleSceneUpdater);
126     nw::gfx::SafeDestroy(m_ParticleContext);
127 
128     // シーンノードをトップノードから破棄を行います。
129     nw::gfx::SafeDestroyBranch(m_SceneRoot);
130 
131     // リソースを破棄を行います。
132     nw::demo::SafeCleanupResources(m_ResourcesArray);
133     nw::ut::SafeDestroy(m_SceneEnvSetting);
134 
135     SM_SAFE_DELETE(m_SmCamera);
136     SM_SAFE_DELETE(m_SmParticle);
137 
138     m_ResourcesArray.clear();
139 }
140 
141 
142 /*---------------------------------------------------------------------------*
143   @brief シーンの初期化を行います。
144  *---------------------------------------------------------------------------*/
145 void
InitializeScene()146 GfxCtrl::InitializeScene()
147 {
148 
149 }
150 
151 
152 /*---------------------------------------------------------------------------*
153   @brief シーンのトラバースを行います。
154  *---------------------------------------------------------------------------*/
155 void
TraverseScene()156 GfxCtrl::TraverseScene()
157 {
158     m_GfxSceneCtrl->TraverseScene(m_SceneRoot);
159 }
160 
161 
162 /*---------------------------------------------------------------------------*
163   @brief シーンの更新を行います。
164  *---------------------------------------------------------------------------*/
165 void
Update()166 GfxCtrl::Update()
167 {
168     uint i = 0;
169 
170     // パーティクルアップデートを行います。
171     m_ParticleSceneUpdater->UpdateNode( m_GfxSceneCtrl->GetSceneContext(), m_ParticleContext );
172 
173     // SmModelのアップデートを行います。
174     // コンストレインの解決を行います。
175     for ( i = 0; i < m_SmModelInstArray.size(); i++ )
176     {
177         m_SmModelInstArray[i]->Update();
178     }
179 
180     // カメラの更新を行います。
181     m_SmCamera->UpdateMatrix();
182 }
183 
184 
185 /*---------------------------------------------------------------------------*
186   @brief SmModelクラスのインスタンスを生成します。
187  *---------------------------------------------------------------------------*/
188 SmModel*
CreateModel(SmModel * parentModel,const wchar_t * resourcePath,GfxVramType vramType)189 GfxCtrl::CreateModel( SmModel* parentModel, const wchar_t* resourcePath, GfxVramType vramType )
190 {
191     NW_NULL_ASSERT( resourcePath );
192 
193     bool isPushed;
194     NW_UNUSED_VARIABLE(isPushed);
195     GfxCtrl::GfxResourceSet resSet;
196 
197     // リソースのロード、セットアップを行います。
198     LoadResources( &resSet, resourcePath, m_Allocator, m_DeviceAllocator, vramType );
199 
200     // SmModel を生成して、必要なデータを設定していきます。
201     SmModel* pModel = new SmModel();
202     NW_NULL_ASSERT( pModel );
203 
204     //------------------------------------------------------------------
205     // モデルのセットアップを行います。(モデルは1リソース1つのみ対応)
206     nw::gfx::ResModelArray models = resSet.resource.GetModels();
207      if ( models.size() != 1 ) { NW_FATAL_ERROR("1 Resource is 1 Model"); }
208 
209     // ノード生成します。
210     nw::gfx::SceneNode* pAddNode = nw::demo::Utility::CreateSceneNode(
211             m_DeviceAllocator,
212             nw::gfx::ResSceneObject((*models.begin())));
213 
214     // 親子付け参照関係を解決します。
215     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(m_Allocator);
216     sceneNodeArray.push_back( pAddNode );
217     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
218 
219     // モデルをシーンに追加します。
220      if ( parentModel )
221     {
222         // 指定された親ノードに追加します。
223         parentModel->GetSceneNode()->AttachChild( pAddNode );
224         pModel->SetSceneNode( parentModel->GetSceneNode(), pAddNode );
225     }
226     else
227     {
228         // ルートノードに追加します。
229         m_SceneRoot->AttachChild( pAddNode );
230         pModel->SetSceneNode( m_SceneRoot, pAddNode );
231     }
232 
233     // モデル/スケルタルモデルをセットします。
234     nw::gfx::Model*         pGfxModel  = nw::ut::DynamicCast<nw::gfx::Model*>(pAddNode);
235     nw::gfx::SkeletalModel* pSkelModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(pAddNode);
236     pModel->SetModel( pGfxModel, pSkelModel );
237      if ( !pSkelModel ) goto _anim_end;
238 
239 
240     //------------------------------------------------------------------
241     // アニメーションのセットアップを行います。
242     {
243         nw::gfx::ResSkeletalModel resModel = pSkelModel->GetResSkeletalModel();
244         nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton();
245         int maxBones = resSkeleton.GetBonesCount();
246 
247         uint resAnimNum = resSet.resource.GetSkeletalAnimsCount();
248 
249         for ( uint i = 0; i < resAnimNum; i++ )
250         {
251             nw::anim::ResAnim resAnim = resSet.resource.GetSkeletalAnims(i);
252             if (!resAnim.IsValid()){ NW_FATAL_ERROR("Animation is Valid"); }
253 
254             // トランスフォームアニメーション評価を生成します。
255             nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder()
256                 .AnimData(resAnim)
257                 .MaxMembers(maxBones)
258                 .AllocCache(true)
259                 .Create(m_Allocator);
260 
261             if (!evaluator){ NW_FATAL_ERROR("Animation Evaluator is Valid"); }
262 
263             // SmModel にセットします。
264             pModel->AddAnimEvaluator( evaluator );
265 
266             // アニメーションを保持
267             isPushed = m_AnimationArray.push_back( evaluator );
268             NW_ASSERT(isPushed);
269         }
270     }
271 
272 _anim_end:
273 
274     //------------------------------------------------------------------
275     // マテリアルアニメーション
276     {
277         int materialAnimCount = resSet.resource.GetMaterialAnimsCount();
278         if ( materialAnimCount == 1 )
279         {
280             nw::anim::ResAnim resAnim = resSet.resource.GetMaterialAnims(0);
281 
282             nw::gfx::AnimGroup* animGroup = pGfxModel->GetMaterialAnimGroup();
283             if ( !animGroup ) goto _setup_end;
284             int maxMembers = animGroup->GetMemberCount();
285 
286             nw::gfx::AnimEvaluator* matAnimEvaluator = nw::gfx::AnimEvaluator::Builder()
287                 .AnimData(resAnim)
288                 .MaxMembers(maxMembers)
289                 .AllocCache(true)
290                 .Create(m_Allocator);
291 
292             // アニメーションをバインドします。
293             bool bindResult = matAnimEvaluator->Bind( animGroup );
294 
295             // アニメーションをモデルに登録します。
296             if ( bindResult )
297             {
298                 pGfxModel->SetMaterialAnimObject( matAnimEvaluator );
299             }
300 
301             // アニメーションを保持します。
302             isPushed = m_AnimationArray.push_back( matAnimEvaluator );
303             NW_ASSERT(isPushed);
304         }
305     }
306 
307 _setup_end:
308 
309     // 読み込んだリソースを保持します。
310     isPushed = m_ResourcesArray.push_back( resSet );
311     NW_ASSERT(isPushed);
312 
313     // SmModel のインスタンスを保持します。
314     isPushed = m_SmModelInstArray.push_back( pModel );
315     NW_ASSERT(isPushed);
316 
317     return pModel;
318 }
319 
320 
321 /*---------------------------------------------------------------------------*
322   @brief SmModelをシーンに追加します。
323  *---------------------------------------------------------------------------*/
AddModel(SmModel * model)324 bool GfxCtrl::AddModel( SmModel* model )
325 {
326     // ルートノードに追加します。
327     m_SceneRoot->AttachChild( model->GetSceneNode() );
328     model->SetSceneNode( m_SceneRoot );
329 
330     return true;
331 }
332 
333 
334 
335 /*---------------------------------------------------------------------------*
336   @brief パーティクルを生成します。
337  *---------------------------------------------------------------------------*/
338 SmParticle*
CreateParticle(const wchar_t * resourcePath)339 GfxCtrl::CreateParticle( const wchar_t* resourcePath )
340 {
341     NW_ASSERT( !m_SmParticle );
342 
343     NW_NULL_ASSERT( resourcePath );
344 
345     bool isPushed;
346     NW_UNUSED_VARIABLE(isPushed);
347 
348     GfxCtrl::GfxResourceSet resSet;
349     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(m_Allocator);
350 
351     // リソースのロードを行います。
352     LoadResources( &resSet, resourcePath, m_Allocator, m_DeviceAllocator );
353 
354     // SmParticle を生成して、必要なデータを設定していきます。
355     m_SmParticle = new SmParticle( m_SceneRoot );
356     NW_NULL_ASSERT( m_SmParticle );
357 
358     // ノード生成します。
359     nw::gfx::ResModelArray models = resSet.resource.GetModels();
360     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
361     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
362          modelResource != modelsEnd; ++modelResource)
363     {
364         nw::gfx::SceneNode* pAddNode = nw::demo::Utility::CreateSceneNode(
365                 m_DeviceAllocator,
366                 nw::gfx::ResSceneObject((*modelResource).ptr()));
367 
368 
369         // todo:レイヤIDをここで更新します。
370         {
371             nw::gfx::ParticleModel* pParticleModel  = nw::ut::DynamicCast<nw::gfx::ParticleModel*>(pAddNode);
372             pParticleModel->SetLayerId( 6 );
373         }
374 
375         sceneNodeArray.push_back( pAddNode );
376 
377         // SmParticleにParticleModelを追加します。
378         nw::gfx::ParticleModel* pParticleModel  = nw::ut::DynamicCast<nw::gfx::ParticleModel*>(pAddNode);
379         NW_NULL_ASSERT( pParticleModel );
380         m_SmParticle->AddParticleModel( pParticleModel );
381     }
382 
383     // エミッタを生成します。
384     nw::gfx::ResEmitterArray emitters = resSet.resource.GetEmitters();
385     nw::gfx::ResEmitterArray::iterator emittersEnd = emitters.end();
386     for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
387          emitterResource != emittersEnd; ++emitterResource)
388     {
389         nw::gfx::SceneNode* pAddEmitNode = nw::demo::Utility::CreateSceneNode(
390                 m_DeviceAllocator,
391                 nw::gfx::ResSceneObject((*emitterResource).ptr()));
392 
393         sceneNodeArray.push_back( pAddEmitNode );
394 
395         // SmParticleにParticleModelを追加します。
396         nw::gfx::ParticleEmitter* pParticleEmitter  = nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(pAddEmitNode);
397         NW_NULL_ASSERT( pParticleEmitter );
398         m_SmParticle->AddParticleEmitter( pParticleEmitter );
399     }
400 /*
401     // マテリアルアニメーション
402     {
403         int materialAnimCount = resSet.resource.GetMaterialAnimsCount();
404 
405         nw::anim::ResAnim resAnim = resSet.resource.GetMaterialAnims(0);
406 
407         nw::gfx::AnimGroup* animGroup = pGfxModel->GetMaterialAnimGroup();
408         if ( !animGroup ) goto _setup_end;
409         int maxMembers = animGroup->GetMemberCount();
410 
411         nw::gfx::AnimEvaluator* matAnimEvaluator = nw::gfx::AnimEvaluator::Builder()
412             .AnimData(resAnim)
413             .MaxMembers(maxMembers)
414             .AllocCache(true)
415             .Create(m_Allocator);
416 
417         // アニメーションをバインドします。
418         bool bindResult = matAnimEvaluator->Bind( animGroup );
419 
420         // アニメーションをモデルに登録します。
421         if ( bindResult )
422         {
423             pGfxModel->SetMaterialAnimObject( matAnimEvaluator );
424         }
425 
426         // アニメーションを保持します。
427         isPushed = m_AnimationArray.push_back( matAnimEvaluator );
428         NW_ASSERT(isPushed);
429     }
430 */
431     // パーティクルのオブジェクトの参照解決と初期設定を行います。
432     nw::gfx::ParticleUtil::SetupParticleObject( &sceneNodeArray, m_ParticleContext );
433 
434     // 親子付け参照関係を解決します。
435     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
436 
437     // モデルとエミッタをシーンに追加します。
438     nw::gfx::SceneHelper::ForeachRootNodes(
439         sceneNodeArray.Begin(),
440         sceneNodeArray.End(),
441         nw::gfx::AttachNode( m_SceneRoot )
442     );
443 
444     // 読み込んだリソースを保持します。
445     isPushed = m_ResourcesArray.push_back( resSet );
446     NW_ASSERT(isPushed);
447 
448     return m_SmParticle;
449 }
450 
451 
452 /*---------------------------------------------------------------------------*
453   @brief ライト/フォグ/シーン環境を設定します。
454  *---------------------------------------------------------------------------*/
455 void
CreateSceneEnvironment(const wchar_t * resourcePath)456 GfxCtrl::CreateSceneEnvironment( const wchar_t* resourcePath )
457 {
458     bool isPushed = false;
459     NW_UNUSED_VARIABLE(isPushed);
460     GfxCtrl::GfxResourceSet resSet;
461 
462     nw::gfx::SceneNode* firstLightNode = NULL;
463 
464     // リソースのロードを行います。
465     LoadResources( &resSet, resourcePath, m_Allocator, m_DeviceAllocator );
466 
467     // ライトオブジェクトを生成します。
468     nw::gfx::ResLightArray lights = resSet.resource.GetLights();
469     nw::gfx::ResLightArray::iterator lightsEnd = lights.end();
470     for (nw::gfx::ResLightArray::iterator lightResource = lights.begin();
471          lightResource != lightsEnd; ++lightResource)
472     {
473         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
474             .Resource( nw::gfx::ResSceneObject((*lightResource).ptr()) )
475             .CreateObject(m_Allocator, m_DeviceAllocator);
476 
477         nw::gfx::SceneNode* node = nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
478 
479         // 1つ目のライトを保持して、アニメーションをバインドする。
480         if ( !firstLightNode )
481         {
482             firstLightNode = node;
483         }
484 
485         m_SceneRoot->AttachChild(node);
486     }
487 
488     // ライトアニメーションのセットアップを行います。
489     int lightAnimCount = resSet.resource.GetLightAnimsCount();
490     if ( lightAnimCount == 1 && firstLightNode )
491     {
492         nw::anim::ResAnim resAnim = resSet.resource.GetLightAnims(0);
493 
494         nw::gfx::Light* light =
495                         nw::ut::DynamicCast<nw::gfx::Light*>(firstLightNode);
496 
497         nw::gfx::AnimGroup* animGroup = light->GetAnimGroup();
498         if (animGroup)
499         {
500             int maxMembers = animGroup->GetMemberCount();
501 
502             nw::gfx::AnimEvaluator* lightAnimEvaluator = nw::gfx::AnimEvaluator::Builder()
503                 .AnimData(resAnim)
504                 .MaxMembers(maxMembers)
505                 .AllocCache(true)
506                 .Create(m_Allocator);
507 
508             // アニメーションをバインドします。
509             bool bindResult = lightAnimEvaluator->Bind( animGroup );
510 
511             // アニメーションをモデルに登録します。
512             if ( bindResult )
513             {
514                 light->SetAnimObject( lightAnimEvaluator );
515             }
516 
517             // アニメーションを保持します。
518             isPushed = m_AnimationArray.push_back( lightAnimEvaluator );
519             NW_ASSERT(isPushed);
520 
521             if( !m_LightAnimation )
522             {
523                 m_LightAnimation = lightAnimEvaluator;
524             }
525         }
526     }
527 
528 
529     // フォグのセットアップを行います。
530     {
531         nw::gfx::ResFogArray fogs = resSet.resource.GetFogs();
532         nw::gfx::ResFogArray::iterator fogsEnd = fogs.end();
533         for (nw::gfx::ResFogArray::iterator fogResource = fogs.begin();
534              fogResource != fogsEnd; ++fogResource)
535         {
536             nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
537                 m_DeviceAllocator,
538                 nw::gfx::ResSceneObject(*fogResource)
539             );
540             NW_NULL_ASSERT(node);
541 
542             m_SceneRoot->AttachChild(node);
543         }
544     }
545 
546     // シーン環境設定のインスタンスを生成します。
547     if (!m_SceneEnvSetting)
548     {
549         nw::gfx::ResSceneEnvironmentSettingArray settings = resSet.resource.GetSceneEnvironmentSettings();
550         nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end();
551         for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin();
552             settingResource != settingsEnd; ++settingResource)
553         {
554             nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
555                 .Resource(*settingResource)
556                 .CreateObject(m_Allocator, m_DeviceAllocator);
557 
558             nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting =
559                 nw::ut::DynamicCast<nw::gfx::SceneEnvironmentSetting*>(sceneObject);
560 
561             NW_NULL_ASSERT(sceneEnvironmentSetting);
562             m_SceneEnvSetting = sceneEnvironmentSetting;;
563         }
564     }
565 
566 
567     // 読み込んだリソースを保持します。
568     isPushed = m_ResourcesArray.push_back( resSet );
569     NW_ASSERT(isPushed);
570 }
571 
572 
573 /*---------------------------------------------------------------------------*
574   @brief カメラを生成します。
575  *---------------------------------------------------------------------------*/
576 void
CreateCamera(const wchar_t * resourcePath)577 GfxCtrl::CreateCamera( const wchar_t* resourcePath )
578 {
579     NW_ASSERT( !m_ResCamera );
580 
581     GfxCtrl::GfxResourceSet resSet;
582 
583     // リソースのロードを行います。
584     LoadResources( &resSet, resourcePath, m_Allocator, m_DeviceAllocator );
585 
586     // カメラは1リソース1つのみ対応
587     nw::gfx::ResCameraArray cameras = resSet.resource.GetCameras();
588     if ( cameras.size() != 1 ) { NW_FATAL_ERROR("1 Resource is 1 Camera"); }
589 
590     {
591         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
592             .Resource( nw::gfx::ResSceneObject( *cameras.begin() ) )
593             .CreateObject(m_Allocator, m_DeviceAllocator);
594 
595         nw::gfx::SceneNode* node = nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
596 
597         // gfxCameraへキャスト
598         m_ResCamera = nw::ut::DynamicCast<nw::gfx::Camera*>(node);
599         NW_ASSERT(m_ResCamera);
600 
601         // SmCameraのカメラへ設定
602         m_SmCamera->SetGxCamera( m_ResCamera );
603     }
604 
605     // 読み込んだリソースを保持します。
606     bool isPushed = m_ResourcesArray.push_back( resSet );
607     NW_UNUSED_VARIABLE(isPushed);
608     NW_ASSERT(isPushed);
609 
610     // カメラアニメーションの生成
611     {
612         nw::gfx::AnimGroup* animGroup = m_ResCamera->GetAnimGroup();
613         if (animGroup == NULL) // アニメーション用のアニメーショングループがありません。
614         {
615             return;
616         }
617 
618         int maxMembers = animGroup->GetMemberCount();
619 
620         int cameraAnimCount = resSet.resource.GetCameraAnimsCount();
621         for (int i = 0; i < cameraAnimCount; ++i)
622         {
623             nw::anim::ResAnim resAnim = resSet.resource.GetCameraAnims(i);
624 
625             // トランスフォームアニメーション評価を生成します。
626             nw::gfx::AnimEvaluator* evaluator = nw::gfx::AnimEvaluator::Builder()
627                 .AnimData(resAnim)
628                 .MaxMembers(maxMembers)
629                 .AllocCache(true)
630                 .Create(m_Allocator);
631 
632             if (!evaluator){ NW_FATAL_ERROR("Animation Evaluator is Valid"); }
633 
634             // SmCamera に追加
635             m_SmCamera->AddAnimEvaluator( evaluator );
636 
637             // アニメーションを保持
638             isPushed = m_AnimationArray.push_back( evaluator );
639             NW_ASSERT(isPushed);
640         }
641     }
642 }
643 
644 
645 } // namespace
646 
647 
648