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