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