1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     SmModel.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 
16 #include "../include/SmModel.h"
17 
18 namespace
19 {
20 
21 //----------------------------------------
22 // コンストラクタ
SmModel()23 SmModel::SmModel()
24 : m_pParentNode( NULL ),
25   m_pSceneNode( NULL ),
26   m_Model( NULL ),
27   m_SkeletalModel( NULL ),
28   m_AnimationFrame( 0.f ),
29   m_CurrentAnimEvNo( -1 ),
30   m_CostrainId( -1 ),
31   m_Duplicated( false )
32 {
33     m_AnimEvaluatorArray.clear();
34 }
35 
36 
37 //----------------------------------------
38 //
~SmModel()39 SmModel::~SmModel()
40 {
41 
42 }
43 
44 
45 //----------------------------------------
46 // ノードをセットする
47 void
SetSceneNode(nw::gfx::SceneNode * pParentNode,nw::gfx::SceneNode * pSceneNode)48 SmModel::SetSceneNode( nw::gfx::SceneNode* pParentNode, nw::gfx::SceneNode* pSceneNode )
49 {
50     NW_NULL_ASSERT(pParentNode);
51 
52     m_pParentNode   = pParentNode;
53      if ( pSceneNode )
54     {
55         m_pSceneNode    = pSceneNode;
56     }
57 }
58 
59 
60 //----------------------------------------
61 // モデルをセットする
62 void
SetModel(nw::gfx::Model * pModel,nw::gfx::SkeletalModel * pSkelModel)63 SmModel::SetModel( nw::gfx::Model* pModel, nw::gfx::SkeletalModel* pSkelModel )
64 {
65     m_Model         = pModel;
66     m_SkeletalModel = pSkelModel;
67 }
68 
69 
70 //----------------------------------------
71 // アップデート、コンストレイン等の解決を行う
72 void
Update()73 SmModel::Update()
74 {
75     // 親子関係の解決
76     updateConstrain();
77 }
78 
79 
80 
81 //----------------------------------------
82 // 位置
83 void
SetPosition(f32 x,f32 y,f32 z)84 SmModel::SetPosition( f32 x, f32 y, f32 z )
85 {
86     nw::gfx::TransformNode* transformNode =
87         nw::ut::DynamicCast<nw::gfx::TransformNode*>(m_pSceneNode);
88     NW_NULL_ASSERT(transformNode);
89 
90     transformNode->Transform().SetTranslate( x, y, z );
91 }
92 
93 
94 //----------------------------------------
95 // 拡縮
96 void
SetScale(f32 x,f32 y,f32 z)97 SmModel::SetScale( f32 x, f32 y, f32 z )
98 {
99     nw::gfx::TransformNode* transformNode =
100         nw::ut::DynamicCast<nw::gfx::TransformNode*>(m_pSceneNode);
101     NW_NULL_ASSERT(transformNode);
102 
103     transformNode->Transform().SetScale( x, y, z );
104 }
105 
106 
107 //----------------------------------------
108 // 回転 Degree
109 void
SetRotate(f32 x,f32 y,f32 z)110 SmModel::SetRotate( f32 x, f32 y, f32 z )
111 {
112     nw::gfx::TransformNode* transformNode =
113         nw::ut::DynamicCast<nw::gfx::TransformNode*>(m_pSceneNode);
114     NW_NULL_ASSERT(transformNode);
115 
116     transformNode->Transform().SetRotateXYZ( NW_MATH_DEG_TO_RAD(x),
117                                              NW_MATH_DEG_TO_RAD(y),
118                                              NW_MATH_DEG_TO_RAD(z) );
119 }
120 
121 
122 //----------------------------------------
123 // マトリクス
124 void
SetMatrix(const nw::math::MTX34 * matrix)125 SmModel::SetMatrix( const nw::math::MTX34* matrix )
126 {
127     NW_NULL_ASSERT( matrix );
128 
129     nw::gfx::TransformNode* transformNode =
130         nw::ut::DynamicCast<nw::gfx::TransformNode*>(m_pSceneNode);
131     NW_NULL_ASSERT(transformNode);
132 
133     transformNode->Transform().SetTransformMatrix( *matrix );
134 }
135 
136 
SetWorldMatrix(const nw::math::MTX34 * matrix)137 void SmModel::SetWorldMatrix( const nw::math::MTX34* matrix )
138 {
139     NW_NULL_ASSERT( matrix );
140 
141     nw::gfx::TransformNode* transformNode =
142         nw::ut::DynamicCast<nw::gfx::TransformNode*>(m_pSceneNode);
143     NW_NULL_ASSERT(transformNode);
144 
145     transformNode->WorldMatrix() = *matrix;
146 }
147 
148 
149 
150 
151 //----------------------------------------
152 // 表示/非表示
153 void
SetVisible(bool visible)154 SmModel::SetVisible( bool visible )
155 {
156     if ( !m_SkeletalModel ) return;
157     m_SkeletalModel->SetVisible( visible );
158 
159     if ( !visible )
160     {
161         if ( m_pSceneNode->GetParent() )
162         {
163             m_pParentNode->DetachChild( m_pSceneNode );
164         }
165     }
166     else
167     {
168         if ( !m_pSceneNode->GetParent() )
169         {
170             m_pParentNode->AttachChild( m_pSceneNode );
171         }
172     }
173 }
174 
175 void
SwapVisible()176 SmModel::SwapVisible()
177 {
178     if ( !m_SkeletalModel ) return;
179 
180     if ( m_SkeletalModel->IsVisible() )
181     {
182         m_SkeletalModel->SetVisible( false );
183 
184          if ( m_pSceneNode->GetParent() )
185         {
186             m_pParentNode->DetachChild( m_pSceneNode );
187         }
188     }
189     else
190     {
191         m_SkeletalModel->SetVisible( true );
192 
193         if ( !m_pSceneNode->GetParent() )
194         {
195             m_pParentNode->AttachChild( m_pSceneNode );
196         }
197     }
198 }
199 
200 bool
IsVisible()201 SmModel::IsVisible()
202 {
203     if ( !m_SkeletalModel ) return false;
204     return m_SkeletalModel->IsVisible();
205 }
206 
207 
208 //----------------------------------------
209 // 複製する
Duplicate()210 SmModel* SmModel::Duplicate()
211 {
212     SmModel* model = new SmModel();
213 
214 #if 1
215     // スケルトン共有ナシ
216     nw::gfx::SkeletalModel* skeletalModel = nw::gfx::SkeletalModel::Builder()
217         .Create( NULL, nw::gfx::ResSceneObject( m_SkeletalModel->GetResModel() ), m_Allocator );
218 #else
219     // スケルトン共有アリ
220     nw::gfx::SkeletalModel* skeletalModel = nw::gfx::SkeletalModel::Builder()
221         .SharedSkeleton( m_SkeletalModel->GetSkeleton() )
222         .Create(NULL, nw::gfx::ResSceneObject(m_SkeletalModel->GetResModel()), m_Allocator);
223 #endif
224 
225     NW_NULL_ASSERT(skeletalModel);
226 
227     // コピー元モデルから値のコピー
228     model->m_SkeletalModel      = skeletalModel;
229     model->m_Duplicated         = true;
230     model->m_pSceneNode         = static_cast<nw::gfx::SceneNode*>(model->m_SkeletalModel);
231 
232     model->SetLayerId( this->GetLayerId() );
233 
234     // todo:パラでアニメーションさせるには、
235     //      アニメーションをコピーする必要がアリ。
236     model->m_AnimEvaluatorArray.CopyFrom( m_AnimEvaluatorArray );
237 
238     return model;
239 }
240 
241 
242 //----------------------------------------
243 // アニメーションを追加する
244 void
AddAnimEvaluator(nw::gfx::TransformAnimEvaluator * animEvaluator)245 SmModel::AddAnimEvaluator( nw::gfx::TransformAnimEvaluator* animEvaluator )
246 {
247     m_AnimEvaluatorArray.push_back( animEvaluator );
248 }
249 
250 
251 //----------------------------------------
252 // アニメーション数を取得する
253 uint
GetAnimEvaluatorNum() const254 SmModel::GetAnimEvaluatorNum() const
255 {
256     return m_AnimEvaluatorArray.size();
257 }
258 
259 
260 //----------------------------------------
261 // アニメーションを設定する
262 bool
SetAnimEvaluatorNo(uint animEvaluatorNo)263 SmModel::SetAnimEvaluatorNo( uint animEvaluatorNo )
264 {
265     if ( animEvaluatorNo >= GetAnimEvaluatorNum() ) return false;
266     if ( !m_SkeletalModel ) return false;
267 
268     nw::gfx::AnimGroup* animGroup = m_SkeletalModel->GetSkeletalAnimGroup();
269     if (animGroup == NULL){ NW_FATAL_ERROR("Dont have AnimGroup");; }
270 
271     // アニメーションをバインドします。
272     m_AnimEvaluatorArray[animEvaluatorNo]->Release();
273     bool bindResult = m_AnimEvaluatorArray[animEvaluatorNo]->Bind(animGroup);
274 
275     // アニメーションをモデルに登録します。
276     m_SkeletalModel->SetSkeletalAnimObject(m_AnimEvaluatorArray[animEvaluatorNo]);
277 
278     // 番号を保持
279     m_CurrentAnimEvNo = animEvaluatorNo;
280 
281     return true;
282 }
283 
284 
285 //----------------------------------------
286 // アニメーションフレームを設定する
287 void
SetAnimationFrame(f32 setFrame)288 SmModel::SetAnimationFrame( f32 setFrame )
289 {
290     m_AnimationFrame = setFrame;
291     if ( m_CurrentAnimEvNo == -1 ) return;
292 
293     // 非表示であればアニメーションは更新しません
294     if ( !this->IsVisible() ) return;
295 
296     // フレーム数をセット
297     m_AnimEvaluatorArray[m_CurrentAnimEvNo]->SetFrame(m_AnimationFrame);
298 }
299 
300 
301 //----------------------------------------
302 // アニメーションフレームを進める
303 // 最終フレームに到達した場合は、trueを返す
304 bool
AddAnimationFrame(f32 addFrame,bool loop)305 SmModel::AddAnimationFrame( f32 addFrame, bool loop )
306 {
307     bool ret = false;
308 
309     m_AnimationFrame += addFrame;
310     if ( m_CurrentAnimEvNo == -1 ) return ret;
311 
312     // 最終フレームで固定
313     f32 endFrame = m_AnimEvaluatorArray[m_CurrentAnimEvNo]->AnimFrameController().GetEndFrame();
314     if ( m_AnimationFrame > endFrame )
315     {
316         if ( loop )
317         {
318             m_AnimationFrame = 0.f;
319         }
320         else
321         {
322             m_AnimationFrame = endFrame;
323         }
324 
325         ret = true;
326     }
327 
328     // 非表示であればアニメーションは更新しません
329     if ( !this->IsVisible() ) return ret;
330 
331     // フレーム数をセットします
332     m_AnimEvaluatorArray[m_CurrentAnimEvNo]->SetFrame(m_AnimationFrame);
333 
334     return ret;
335 }
336 
337 
338 //----------------------------------------
339 // アニメーションフレームを取得する
340 f32
GetAnimationFrame() const341 SmModel::GetAnimationFrame() const
342 {
343     return m_AnimationFrame;
344 }
345 
346 
347 //----------------------------------------
348 // 設定されているアニメーションの最大フレームを取得する
349 f32
GetAnimationMaxFrame() const350 SmModel::GetAnimationMaxFrame() const
351 {
352     if ( m_CurrentAnimEvNo == -1 ) return 0.f;
353 
354     return m_AnimEvaluatorArray[m_CurrentAnimEvNo]->AnimFrameController().GetEndFrame();
355 }
356 
357 
358 //----------------------------------------
359 // マテリアルアニメーションを設定する
360 bool
SetMaterialAnim(nw::gfx::AnimEvaluator * animEvaluator)361 SmModel::SetMaterialAnim( nw::gfx::AnimEvaluator* animEvaluator )
362 {
363     nw::gfx::AnimGroup* animGroup = m_Model->GetMaterialAnimGroup();
364     if ( !animGroup ) return false;
365 
366     bool bindResult = animEvaluator->Bind( animGroup );
367     if ( !bindResult ) return false;
368 
369     // アニメーションをモデルに登録します。
370     m_Model->SetMaterialAnimObject( animEvaluator );
371 
372     return true;
373 }
374 
375 
376 
377 //----------------------------------------
378 // 親のノードIDを指定する
379 void
SetConstrainId(s32 boneId)380 SmModel::SetConstrainId( s32 boneId )
381 {
382     m_CostrainId = boneId;
383 
384     nw::gfx::TransformNode* transformNode =
385         nw::ut::DynamicCast<nw::gfx::TransformNode*>(m_pSceneNode);
386     NW_NULL_ASSERT(transformNode);
387 
388     // -1 でキャンセル
389     if ( m_CostrainId == -1 )
390     {
391         // FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED フラグを立てる
392         transformNode->Transform().EnableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
393 
394         transformNode->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
395 
396     }
397     else
398     {
399         // FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED フラグを下げる
400         transformNode->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
401 
402         transformNode->Transform().EnableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
403     }
404 }
405 
406 
407 //----------------------------------------
408 // 親子継承を解決
409 void
updateConstrain()410 SmModel::updateConstrain()
411 {
412      if ( m_CostrainId == -1 ) return;
413 
414     // 親が骨構造を持つか?
415     nw::gfx::SkeletalModel* pParentSkeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(m_pParentNode);
416 
417      if ( pParentSkeletalModel )
418     {
419         // Skeleton を取得
420         nw::gfx::Skeleton* pSkeleton = pParentSkeletalModel->GetSkeleton();
421         NW_NULL_ASSERT(pSkeleton);
422 
423         nw::gfx::Skeleton::TransformPose& transformPose = pSkeleton->WorldTransformPose();
424 //        nw::gfx::Skeleton::TransformPose& transformPose = pSkeleton->LocalTransformPose();
425          if ( transformPose.GetBonesCount() < m_CostrainId ) return;
426 
427         // 指定ノードのマトリクスを取得して、自分にワールドマトリクスへセットする
428         nw::gfx::Skeleton::TransformPose::Transform* transForm = transformPose.GetTransform( m_CostrainId );
429 //        this->SetWorldMatrix( &transForm->TransformMatrix() );
430         this->SetMatrix( &transForm->TransformMatrix() );
431     }
432     else
433     {
434         // 骨なしの場合は何もしない
435     }
436 }
437 
438 
439 //----------------------------------------
440 // テスト機能
441 // モデル内メッシュを0~1で表示/非表示する
442 void
SetVisibleZone(f32 term)443 SmModel::SetVisibleZone( f32 term )
444 {
445     if ( !m_SkeletalModel ) return;
446 
447     nw::gfx::ResMeshArray meshArray = m_SkeletalModel->GetResMeshes();
448 
449     s32 visibleNum = meshArray.size() * term;
450 
451     for ( int i = 0; i < meshArray.size(); i++ )
452     {
453         if ( i < visibleNum )
454         {
455             meshArray[i].SetVisible( true );
456         }
457         else
458         {
459             meshArray[i].SetVisible( false );
460         }
461     }
462 }
463 
464 
465 
466 } // namespace
467 
468 
469