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