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