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     // 親が居る居ないでシーンツーリーに登録されているか判断する。
160     if ( !visible )
161     {
162         if ( m_pSceneNode->GetParent() )
163         {
164             m_pParentNode->DetachChild( m_pSceneNode );
165         }
166     }
167     else
168     {
169         if ( !m_pSceneNode->GetParent() )
170         {
171             m_pParentNode->AttachChild( m_pSceneNode );
172         }
173     }
174 }
175 
176 void
SwapVisible()177 SmModel::SwapVisible()
178 {
179     if ( !m_SkeletalModel ) return;
180 
181     // 親が居る居ないでシーンツーリーに登録されているか判断する。
182     if ( m_SkeletalModel->IsVisible() )
183     {
184         m_SkeletalModel->SetVisible( false );
185 
186         if ( m_pSceneNode->GetParent() )
187         {
188             m_pParentNode->DetachChild( m_pSceneNode );
189         }
190     }
191     else
192     {
193         m_SkeletalModel->SetVisible( true );
194 
195         if ( !m_pSceneNode->GetParent() )
196         {
197             m_pParentNode->AttachChild( m_pSceneNode );
198         }
199     }
200 }
201 
202 bool
IsVisible()203 SmModel::IsVisible()
204 {
205     if ( !m_SkeletalModel ) return false;
206     return m_SkeletalModel->IsVisible();
207 }
208 
209 
210 //----------------------------------------
211 // 複製する
Duplicate()212 SmModel* SmModel::Duplicate()
213 {
214     SmModel* model = new SmModel();
215 
216 #if 1
217     // スケルトン共有ナシ
218     nw::gfx::SkeletalModel* skeletalModel = nw::gfx::SkeletalModel::Builder()
219         .Create( NULL, nw::gfx::ResSceneObject( m_SkeletalModel->GetResModel() ), m_Allocator );
220 #else
221     // スケルトン共有アリ
222     nw::gfx::SkeletalModel* skeletalModel = nw::gfx::SkeletalModel::Builder()
223         .SharedSkeleton( m_SkeletalModel->GetSkeleton() )
224         .Create(NULL, nw::gfx::ResSceneObject(m_SkeletalModel->GetResModel()), m_Allocator);
225 #endif
226 
227     NW_NULL_ASSERT(skeletalModel);
228 
229     // コピー元モデルから値のコピー
230     model->m_SkeletalModel      = skeletalModel;
231     model->m_Duplicated         = true;
232     model->m_pSceneNode         = static_cast<nw::gfx::SceneNode*>(model->m_SkeletalModel);
233 
234     model->SetLayerId( this->GetLayerId() );
235 
236     // todo:パラでアニメーションさせるには、
237     //      アニメーションをコピーする必要がアリ。
238     model->m_AnimEvaluatorArray.CopyFrom( m_AnimEvaluatorArray );
239 
240     return model;
241 }
242 
243 
244 //----------------------------------------
245 // アニメーションを追加する
246 void
AddAnimEvaluator(nw::gfx::TransformAnimEvaluator * animEvaluator)247 SmModel::AddAnimEvaluator( nw::gfx::TransformAnimEvaluator* animEvaluator )
248 {
249     m_AnimEvaluatorArray.push_back( animEvaluator );
250 }
251 
252 
253 //----------------------------------------
254 // アニメーション数を取得する
255 uint
GetAnimEvaluatorNum() const256 SmModel::GetAnimEvaluatorNum() const
257 {
258     return m_AnimEvaluatorArray.size();
259 }
260 
261 
262 //----------------------------------------
263 // アニメーションを設定する
264 bool
SetAnimEvaluatorNo(uint animEvaluatorNo)265 SmModel::SetAnimEvaluatorNo( uint animEvaluatorNo )
266 {
267     if ( animEvaluatorNo >= GetAnimEvaluatorNum() ) return false;
268     if ( !m_SkeletalModel ) return false;
269 
270     nw::gfx::AnimGroup* animGroup = m_SkeletalModel->GetSkeletalAnimGroup();
271     if (animGroup == NULL){ NW_FATAL_ERROR("Dont have AnimGroup");; }
272 
273     // アニメーションをバインドします。
274     m_AnimEvaluatorArray[animEvaluatorNo]->Release();
275     bool bindResult = m_AnimEvaluatorArray[animEvaluatorNo]->Bind(animGroup);
276 
277     // アニメーションをモデルに登録します。
278     m_SkeletalModel->SetSkeletalAnimObject(m_AnimEvaluatorArray[animEvaluatorNo]);
279 
280     // 番号を保持
281     m_CurrentAnimEvNo = animEvaluatorNo;
282 
283     return true;
284 }
285 
286 
287 //----------------------------------------
288 // アニメーションフレームを設定する
289 void
SetAnimationFrame(f32 setFrame)290 SmModel::SetAnimationFrame( f32 setFrame )
291 {
292     m_AnimationFrame = setFrame;
293     if ( m_CurrentAnimEvNo == -1 ) return;
294 
295     // 非表示であればアニメーションは更新しません
296     if ( !this->IsVisible() ) return;
297 
298     // フレーム数をセット
299     m_AnimEvaluatorArray[m_CurrentAnimEvNo]->SetFrame(m_AnimationFrame);
300 }
301 
302 
303 //----------------------------------------
304 // アニメーションフレームを進める
305 // 最終フレームに到達した場合は、trueを返す
306 bool
AddAnimationFrame(f32 addFrame,bool loop)307 SmModel::AddAnimationFrame( f32 addFrame, bool loop )
308 {
309     bool ret = false;
310 
311     m_AnimationFrame += addFrame;
312     if ( m_CurrentAnimEvNo == -1 ) return ret;
313 
314     // 最終フレームで固定
315     f32 endFrame = m_AnimEvaluatorArray[m_CurrentAnimEvNo]->AnimFrameController().GetEndFrame();
316     if ( m_AnimationFrame > endFrame )
317     {
318         if ( loop )
319         {
320             m_AnimationFrame = 0.f;
321         }
322         else
323         {
324             m_AnimationFrame = endFrame;
325         }
326 
327         ret = true;
328     }
329 
330     // 非表示であればアニメーションは更新しません
331     if ( !this->IsVisible() ) return ret;
332 
333     // フレーム数をセットします
334     m_AnimEvaluatorArray[m_CurrentAnimEvNo]->SetFrame(m_AnimationFrame);
335 
336     return ret;
337 }
338 
339 
340 //----------------------------------------
341 // アニメーションフレームを取得する
342 f32
GetAnimationFrame() const343 SmModel::GetAnimationFrame() const
344 {
345     return m_AnimationFrame;
346 }
347 
348 
349 //----------------------------------------
350 // 設定されているアニメーションの最大フレームを取得する
351 f32
GetAnimationMaxFrame() const352 SmModel::GetAnimationMaxFrame() const
353 {
354     if ( m_CurrentAnimEvNo == -1 ) return 0.f;
355 
356     return m_AnimEvaluatorArray[m_CurrentAnimEvNo]->AnimFrameController().GetEndFrame();
357 }
358 
359 
360 //----------------------------------------
361 // マテリアルアニメーションを設定する
362 bool
SetMaterialAnim(nw::gfx::AnimEvaluator * animEvaluator)363 SmModel::SetMaterialAnim( nw::gfx::AnimEvaluator* animEvaluator )
364 {
365     nw::gfx::AnimGroup* animGroup = m_Model->GetMaterialAnimGroup();
366     if ( !animGroup ) return false;
367 
368     bool bindResult = animEvaluator->Bind( animGroup );
369     if ( !bindResult ) return false;
370 
371     // アニメーションをモデルに登録します。
372     m_Model->SetMaterialAnimObject( animEvaluator );
373 
374     return true;
375 }
376 
377 
378 
379 //----------------------------------------
380 // 親のノードIDを指定する
381 void
SetConstrainId(s32 boneId)382 SmModel::SetConstrainId( s32 boneId )
383 {
384     m_CostrainId = boneId;
385 
386     nw::gfx::TransformNode* transformNode =
387         nw::ut::DynamicCast<nw::gfx::TransformNode*>(m_pSceneNode);
388     NW_NULL_ASSERT(transformNode);
389 
390     // -1 でキャンセル
391     if ( m_CostrainId == -1 )
392     {
393         // FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED フラグを立てる
394         transformNode->Transform().EnableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
395 
396         transformNode->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
397 
398     }
399     else
400     {
401         // FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED フラグを下げる
402         transformNode->Transform().DisableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
403 
404         transformNode->Transform().EnableFlags(nw::gfx::CalculatedTransform::FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED);
405     }
406 }
407 
408 
409 //----------------------------------------
410 // 親子継承を解決
411 void
updateConstrain()412 SmModel::updateConstrain()
413 {
414      if ( m_CostrainId == -1 ) return;
415 
416     // 親が骨構造を持つか?
417     nw::gfx::SkeletalModel* pParentSkeletalModel = nw::ut::DynamicCast<nw::gfx::SkeletalModel*>(m_pParentNode);
418 
419      if ( pParentSkeletalModel )
420     {
421         // Skeleton を取得
422         nw::gfx::Skeleton* pSkeleton = pParentSkeletalModel->GetSkeleton();
423         NW_NULL_ASSERT(pSkeleton);
424 
425         nw::gfx::Skeleton::TransformPose& transformPose = pSkeleton->WorldTransformPose();
426 //        nw::gfx::Skeleton::TransformPose& transformPose = pSkeleton->LocalTransformPose();
427          if ( transformPose.GetBonesCount() < m_CostrainId ) return;
428 
429         // 指定ノードのマトリクスを取得して、自分にワールドマトリクスへセットする
430         nw::gfx::Skeleton::TransformPose::Transform* transForm = transformPose.GetTransform( m_CostrainId );
431 //        this->SetWorldMatrix( &transForm->TransformMatrix() );
432         this->SetMatrix( &transForm->TransformMatrix() );
433     }
434     else
435     {
436         // 骨なしの場合は何もしない
437     }
438 }
439 
440 
441 //----------------------------------------
442 // テスト機能
443 // モデル内メッシュを0~1で表示/非表示する
444 void
SetVisibleZone(f32 term)445 SmModel::SetVisibleZone( f32 term )
446 {
447     if ( !m_SkeletalModel ) return;
448 
449     nw::gfx::ResMeshArray meshArray = m_SkeletalModel->GetResMeshes();
450 
451     s32 visibleNum = meshArray.size() * term;
452 
453     for ( int i = 0; i < meshArray.size(); i++ )
454     {
455         if ( i < visibleNum )
456         {
457             meshArray[i].SetVisible( true );
458         }
459         else
460         {
461             meshArray[i].SetVisible( false );
462         }
463     }
464 }
465 
466 
467 
468 } // namespace
469 
470 
471