1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_TransformAnim.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: 25777 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/gfx/gfx_TransformAnim.h>
19
20 namespace nw
21 {
22 namespace gfx
23 {
24
25 NW_UT_RUNTIME_TYPEINFO_DEFINITION(TransformAnimEvaluator , BaseAnimEvaluator);
26 NW_UT_RUNTIME_TYPEINFO_DEFINITION(TransformAnimInterpolator, AnimInterpolator);
27 NW_UT_RUNTIME_TYPEINFO_DEFINITION(TransformAnimAdder , AnimAdder);
28 NW_UT_RUNTIME_TYPEINFO_DEFINITION(TransformAnimOverrider , AnimOverrider);
29
30 //! トランスフォームアニメーションのブレンドオペレーションで使用する定数です。
31 const float TransformAnimBlendOp::WeightDiscard = -1.0f;
32
33 namespace {
34
35 const float s_VecSquareLenTol = 1.0e-6f;
36
37 const bit32 XFORM_CONVERTED = CalculatedTransform::FLAG_CONVERTED_FOR_BLEND;
38 const bit32 XFORM_IGNORE_S = CalculatedTransform::FLAG_IS_IGNORE_SCALE;
39 const bit32 XFORM_IGNORE_R = CalculatedTransform::FLAG_IS_IGNORE_ROTATE;
40 const bit32 XFORM_IGNORE_T = CalculatedTransform::FLAG_IS_IGNORE_TRANSLATE;
41 const bit32 XFORM_IGNORE_SRT = XFORM_IGNORE_S | XFORM_IGNORE_R | XFORM_IGNORE_T;
42
43 const float WEIGHT_DISCARD = TransformAnimBlendOp::WeightDiscard;
44
45 /*!--------------------------------------------------------------------------*
46 @brief SRT ごとの重みがすべてゼロかどうか判定します。
47
48 @param[in] weights SRT ごとの重みです。
49
50 @return 重みがすべてゼロなら true を返します。
51 *---------------------------------------------------------------------------*/
52 bool
CheckWeightsNearyZero(const float * weights)53 CheckWeightsNearyZero(const float* weights)
54 {
55 return
56 AnimWeightNearlyEqualZero(weights[0]) &&
57 AnimWeightNearlyEqualZero(weights[1]) &&
58 AnimWeightNearlyEqualZero(weights[2]);
59 }
60
61 /*!--------------------------------------------------------------------------*
62 @brief 必要があれば SRT ごとの重みを無効化します。
63
64 @param[in] weights SRT ごとの重みです。
65 @param[in] animObj アニメーションオブジェクトです。
66 *---------------------------------------------------------------------------*/
67 void
DisableSRTWeightsIfNeeded(float * weights,const AnimObject * animObj)68 DisableSRTWeightsIfNeeded(float* weights, const AnimObject* animObj)
69 {
70 const TransformAnimEvaluator* evaluator =
71 ut::DynamicCast<const TransformAnimEvaluator*>(animObj);
72 if (evaluator != NULL)
73 {
74 if (evaluator->GetIsScaleDisabled())
75 {
76 weights[0] = WEIGHT_DISCARD;
77 }
78 if (evaluator->GetIsRotateDisabled())
79 {
80 weights[1] = WEIGHT_DISCARD;
81 }
82 if (evaluator->GetIsTranslateDisabled())
83 {
84 weights[2] = WEIGHT_DISCARD;
85 }
86 }
87 }
88
89 /*!--------------------------------------------------------------------------*
90 @brief CalculatedTransform の IGNORE フラグを元に戻します。
91 *---------------------------------------------------------------------------*/
92 void
RestoreIgnoreFlags(CalculatedTransform * transform,const bit32 flagsBak)93 RestoreIgnoreFlags(CalculatedTransform* transform, const bit32 flagsBak)
94 {
95 transform->EnableFlags(XFORM_IGNORE_S, (flagsBak & XFORM_IGNORE_S) != 0);
96 transform->EnableFlags(XFORM_IGNORE_R, (flagsBak & XFORM_IGNORE_R) != 0);
97 transform->EnableFlags(XFORM_IGNORE_T, (flagsBak & XFORM_IGNORE_T) != 0);
98 }
99
100 /*!--------------------------------------------------------------------------*
101 @brief Vector3 の値をすべて Flog で変換します。
102 *---------------------------------------------------------------------------*/
103 void
FlogVector3(math::VEC3 * dst)104 FlogVector3(math::VEC3* dst)
105 {
106 dst->x = math::FLog(dst->x);
107 dst->y = math::FLog(dst->y);
108 dst->z = math::FLog(dst->z);
109 }
110
111 /*!--------------------------------------------------------------------------*
112 @brief Vector3 のブレンド処理を行います。
113
114 @param[in,out] dst ブレンド処理結果です。
115 @param[in] src ブレンド処理の入力です。
116 @param[in] weight ブレンド比率です。
117 @param[in] overrideFlag 値を上書き更新するかどうかのフラグです。
118 *---------------------------------------------------------------------------*/
119 void
BlendVector3(math::VEC3 * dst,const math::VEC3 * src,const float weight,const bool overrideFlag)120 BlendVector3(
121 math::VEC3* dst,
122 const math::VEC3* src,
123 const float weight,
124 const bool overrideFlag
125 )
126 {
127 if (overrideFlag)
128 {
129 VEC3Scale(dst, src, weight);
130 }
131 else
132 {
133 math::VEC3 tmp;
134 VEC3Scale(&tmp, src, weight);
135 VEC3Add(dst, dst, &tmp);
136 }
137 }
138
139 /*!--------------------------------------------------------------------------*
140 @brief 行列の回転成分にゼロベクトルがあれば補正します。
141
142 @param[in,out] transform 対象となるトランスフォームです。
143 @param[in] useDefaultMtx デフォルトの行列を使用するかどうかです。
144 false なら回転成分を単位行列にします。
145 @param[in] defaultMtx デフォルトの行列です。
146 *---------------------------------------------------------------------------*/
147 void
AdjustZeroRotateMatrix(CalculatedTransform * transform,const bool useDefaultMtx,const math::MTX34 & defaultMtx)148 AdjustZeroRotateMatrix(
149 CalculatedTransform* transform,
150 const bool useDefaultMtx,
151 const math::MTX34& defaultMtx)
152 {
153 if (!transform->IsEnabledFlags(XFORM_IGNORE_R))
154 {
155 const math::MTX34& m = transform->TransformMatrix();
156 const math::VEC3* v0 = reinterpret_cast<const math::VEC3*>(&m.m[0]);
157 const math::VEC3* v1 = reinterpret_cast<const math::VEC3*>(&m.m[1]);
158 const math::VEC3* v2 = reinterpret_cast<const math::VEC3*>(&m.m[2]);
159
160 if (math::VEC3SquareLen(v0) < s_VecSquareLenTol ||
161 math::VEC3SquareLen(v1) < s_VecSquareLenTol ||
162 math::VEC3SquareLen(v2) < s_VecSquareLenTol)
163 {
164 if (useDefaultMtx)
165 {
166 transform->SetRotateMatrix(defaultMtx);
167 }
168 else
169 {
170 transform->SetRotateMatrix(
171 1.0f, 0.0f, 0.0f,
172 0.0f, 1.0f, 0.0f,
173 0.0f, 0.0f, 1.0f);
174 }
175 }
176 }
177 }
178
179 } // namespace
180
181 //----------------------------------------------------------
182 void
Apply(void * target,const anim::AnimResult * result) const183 TransformAnimBlendOp::Apply(void* target, const anim::AnimResult* result) const
184 {
185 *reinterpret_cast<CalculatedTransform*>(target) =
186 *reinterpret_cast<const CalculatedTransform*>(result->GetValueBuffer());
187 }
188
189 //----------------------------------------------------------
190 void
ConvertToAnimResult(anim::AnimResult * result,const void * source) const191 TransformAnimBlendOp::ConvertToAnimResult(
192 anim::AnimResult* result,
193 const void* source
194 ) const
195 {
196 *reinterpret_cast<CalculatedTransform*>(result->GetValueBuffer()) =
197 *reinterpret_cast<const CalculatedTransform*>(source);
198 }
199
200 //----------------------------------------------------------
201 void
BlendScaleStandard(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const202 TransformAnimBlendOp::BlendScaleStandard(
203 CalculatedTransform* dst,
204 const CalculatedTransform* src,
205 const float weight
206 ) const
207 {
208 if (weight != WEIGHT_DISCARD)
209 {
210 // スケール値を直接ブレンド
211 BlendVector3(&dst->m_Scale, &src->Scale(),
212 weight, dst->IsEnabledFlags(XFORM_IGNORE_S));
213
214 dst->DisableFlags(XFORM_IGNORE_S);
215 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
216 }
217 }
218
219 //----------------------------------------------------------
220 void
BlendScaleAccurate(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const221 TransformAnimBlendOp::BlendScaleAccurate(
222 CalculatedTransform* dst,
223 const CalculatedTransform* src,
224 const float weight
225 ) const
226 {
227 if (weight != WEIGHT_DISCARD)
228 {
229 // 正確なスケールブレンド
230 // s = Π(s(i)^weight) = exp(Σ(log(s(i)) * weight))
231 // exp の計算は最後に行う
232 math::VEC3 logScale = src->Scale();
233 FlogVector3(&logScale);
234 BlendVector3(&dst->m_Scale, &logScale,
235 weight, dst->IsEnabledFlags(XFORM_IGNORE_S));
236
237 dst->DisableFlags(XFORM_IGNORE_S);
238 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
239 }
240 }
241
242 //----------------------------------------------------------
243 bool
PostBlendAccurateScale(CalculatedTransform * transform) const244 TransformAnimBlendOp::PostBlendAccurateScale(CalculatedTransform* transform) const
245 {
246 math::VEC3& scale = transform->m_Scale;
247 scale.x = math::FExp(scale.x);
248 scale.y = math::FExp(scale.y);
249 scale.z = math::FExp(scale.z);
250 transform->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
251 return true;
252 }
253
254 //----------------------------------------------------------
255 void
BlendRotateMatrix(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const256 TransformAnimBlendOp::BlendRotateMatrix(
257 CalculatedTransform* dst,
258 const CalculatedTransform* src,
259 const float weight
260 ) const
261 {
262 if (weight != WEIGHT_DISCARD)
263 {
264 math::MTX34& dstMtx = dst->m_TransformMatrix;
265 const math::MTX34& srcMtx = src->TransformMatrix();
266
267 if (dst->IsEnabledFlags(XFORM_IGNORE_R))
268 {
269 dstMtx.f._00 = srcMtx.f._00 * weight;
270 dstMtx.f._01 = srcMtx.f._01 * weight;
271 dstMtx.f._02 = srcMtx.f._02 * weight;
272
273 dstMtx.f._10 = srcMtx.f._10 * weight;
274 dstMtx.f._11 = srcMtx.f._11 * weight;
275 dstMtx.f._12 = srcMtx.f._12 * weight;
276
277 // ブレンド後の処理で回転行列を正規直交化するので、 2 行目の計算は不要
278 }
279 else
280 {
281 dstMtx.f._00 += srcMtx.f._00 * weight;
282 dstMtx.f._01 += srcMtx.f._01 * weight;
283 dstMtx.f._02 += srcMtx.f._02 * weight;
284
285 dstMtx.f._10 += srcMtx.f._10 * weight;
286 dstMtx.f._11 += srcMtx.f._11 * weight;
287 dstMtx.f._12 += srcMtx.f._12 * weight;
288
289 // ブレンド後の処理で回転行列を正規直交化するので、 2 行目の計算は不要
290 }
291
292 dst->DisableFlags(XFORM_IGNORE_R);
293 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
294 }
295 }
296
297 //----------------------------------------------------------
298 void
BlendRotateQuaternion(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const299 TransformAnimBlendOp::BlendRotateQuaternion(
300 CalculatedTransform* dst,
301 const CalculatedTransform* src,
302 const float weight
303 ) const
304 {
305 if (weight != WEIGHT_DISCARD)
306 {
307 math::MTX34& dstMtx = dst->m_TransformMatrix;
308 const math::MTX34& srcMtx = src->TransformMatrix();
309
310 float& addedWeight = dstMtx.f._11;
311 math::QUAT srcQ;
312 if (src->IsEnabledFlags(XFORM_CONVERTED))
313 {
314 srcQ = math::QUAT(srcMtx.f._00, srcMtx.f._01, srcMtx.f._02, srcMtx.f._10);
315 }
316 else
317 {
318 math::MTX34ToQUAT(&srcQ, &srcMtx);
319 }
320 math::QUAT dstQ;
321 if (dst->IsEnabledFlags(XFORM_IGNORE_R))
322 {
323 addedWeight = weight;
324 dstQ = srcQ;
325 }
326 else
327 {
328 dstQ = math::QUAT(dstMtx.f._00, dstMtx.f._01, dstMtx.f._02, dstMtx.f._10);
329 addedWeight += weight;
330 const float t = (addedWeight != 0.0f) ? weight / addedWeight : 0.0f;
331 math::QUATSlerp(&dstQ, &dstQ, &srcQ, t);
332 }
333 dstMtx.f._00 = dstQ.x;
334 dstMtx.f._01 = dstQ.y;
335 dstMtx.f._02 = dstQ.z;
336 dstMtx.f._10 = dstQ.w;
337
338 dst->DisableFlags(XFORM_IGNORE_R);
339 dst->SetTransformMatrix(dstMtx);
340 }
341 }
342
343 //----------------------------------------------------------
344 void
BlendTranslate(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const345 TransformAnimBlendOp::BlendTranslate(
346 CalculatedTransform* dst,
347 const CalculatedTransform* src,
348 const float weight
349 ) const
350 {
351 if (weight != WEIGHT_DISCARD)
352 {
353 const math::MTX34& dstMtx = dst->TransformMatrix();
354 const math::MTX34& srcMtx = src->TransformMatrix();
355
356 math::VEC3 srcT(srcMtx.f._03, srcMtx.f._13, srcMtx.f._23);
357 if (dst->IsEnabledFlags(XFORM_IGNORE_T))
358 {
359 VEC3Scale(&srcT, &srcT, weight);
360 dst->SetTranslate(srcT);
361 dst->DisableFlags(XFORM_IGNORE_T);
362 }
363 else
364 {
365 math::VEC3 dstT(dstMtx.f._03, dstMtx.f._13, dstMtx.f._23);
366 BlendVector3(&dstT, &srcT, weight, false);
367 dst->SetTranslate(dstT);
368 }
369 }
370 }
371
372 //----------------------------------------------------------
373 bool
OverrideTransform(CalculatedTransform * dst,const CalculatedTransform * src,const bit32 blendFlags) const374 TransformAnimBlendOp::OverrideTransform(
375 CalculatedTransform* dst,
376 const CalculatedTransform* src,
377 const bit32 blendFlags
378 ) const
379 {
380 const bool needToConverted =
381 dst->IsEnabledFlags(XFORM_CONVERTED) &&
382 !src->IsEnabledFlags(XFORM_CONVERTED);
383
384 math::MTX34 dstMtx = dst->TransformMatrix();
385 const math::MTX34& srcMtx = src->TransformMatrix();
386
387 if ( dst->IsEnabledFlags(XFORM_IGNORE_S) &&
388 !src->IsEnabledFlags(XFORM_IGNORE_S))
389 {
390 dst->SetScale(src->Scale());
391
392 dst->DisableFlags(XFORM_IGNORE_S);
393
394 if (needToConverted && (blendFlags & FLAG_ACCURATE_SCALE))
395 {
396 math::VEC3& dstScale = dst->m_Scale;
397 FlogVector3(&dstScale);
398 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
399 }
400 }
401
402 if ( dst->IsEnabledFlags(XFORM_IGNORE_R) &&
403 !src->IsEnabledFlags(XFORM_IGNORE_R))
404 {
405 dstMtx.f._00 = srcMtx.f._00;
406 dstMtx.f._01 = srcMtx.f._01;
407 dstMtx.f._02 = srcMtx.f._02;
408
409 dstMtx.f._10 = srcMtx.f._10;
410 dstMtx.f._11 = srcMtx.f._11;
411 dstMtx.f._12 = srcMtx.f._12;
412
413 dstMtx.f._20 = srcMtx.f._20;
414 dstMtx.f._21 = srcMtx.f._21;
415 dstMtx.f._22 = srcMtx.f._22;
416
417 dst->DisableFlags(XFORM_IGNORE_R);
418
419 if (needToConverted && (blendFlags & FLAG_QUATERNION_ROTATE))
420 {
421 dst->RotateMatrixToQuaternion();
422 }
423 }
424
425 if ( dst->IsEnabledFlags(XFORM_IGNORE_T) &&
426 !src->IsEnabledFlags(XFORM_IGNORE_T))
427 {
428 dstMtx.f._03 = srcMtx.f._03;
429 dstMtx.f._13 = srcMtx.f._13;
430 dstMtx.f._23 = srcMtx.f._23;
431
432 dst->DisableFlags(XFORM_IGNORE_T);
433 }
434
435 dst->SetTransformMatrix(dstMtx);
436
437 return
438 !dst->IsEnabledFlags(XFORM_IGNORE_S) &&
439 !dst->IsEnabledFlags(XFORM_IGNORE_R) &&
440 !dst->IsEnabledFlags(XFORM_IGNORE_T);
441 }
442
443 //----------------------------------------------------------
444 void
EvaluateMemberAnim(CalculatedTransform * result,anim::ResTransformAnim transformAnim,float frame,const math::Transform3 * originalTransform,bool writeNoAnimMember) const445 TransformAnimEvaluator::EvaluateMemberAnim(
446 CalculatedTransform* result,
447 anim::ResTransformAnim transformAnim,
448 float frame,
449 const math::Transform3* originalTransform,
450 bool writeNoAnimMember
451 ) const
452 {
453 const u32 flags = transformAnim.GetFlags();
454
455 const u32 FLAG_TRANSLATE_NOT_EXIST =
456 anim::ResTransformAnimData::FLAG_TRANSLATE_NOT_EXIST;
457 const u32 FLAG_ROTATE_NOT_EXIST =
458 anim::ResTransformAnimData::FLAG_ROTATE_NOT_EXIST;
459 const u32 FLAG_SCALE_NOT_EXIST =
460 anim::ResTransformAnimData::FLAG_SCALE_NOT_EXIST;
461
462 if (writeNoAnimMember)
463 {
464 math::Transform3 transform;
465
466 if (m_IsScaleDisabled)
467 {
468 transform.scale = originalTransform->scale;
469 }
470 else
471 {
472 transform.scale.x = (flags & anim::ResTransformAnimData::FLAG_SCALE_X_NOT_EXIST) ?
473 originalTransform->scale.x : transformAnim.EvaluateScaleX(frame);
474 transform.scale.y = (flags & anim::ResTransformAnimData::FLAG_SCALE_Y_NOT_EXIST) ?
475 originalTransform->scale.y : transformAnim.EvaluateScaleY(frame);
476 transform.scale.z = (flags & anim::ResTransformAnimData::FLAG_SCALE_Z_NOT_EXIST) ?
477 originalTransform->scale.z : transformAnim.EvaluateScaleZ(frame);
478 }
479
480 if (m_IsRotateDisabled)
481 {
482 transform.rotate = originalTransform->rotate;
483 }
484 else
485 {
486 transform.rotate.x = (flags & anim::ResTransformAnimData::FLAG_ROTATE_X_NOT_EXIST) ?
487 originalTransform->rotate.x : transformAnim.EvaluateRotateX(frame);
488 transform.rotate.y = (flags & anim::ResTransformAnimData::FLAG_ROTATE_Y_NOT_EXIST) ?
489 originalTransform->rotate.y : transformAnim.EvaluateRotateY(frame);
490 transform.rotate.z = (flags & anim::ResTransformAnimData::FLAG_ROTATE_Z_NOT_EXIST) ?
491 originalTransform->rotate.z : transformAnim.EvaluateRotateZ(frame);
492 }
493
494 if (m_IsTranslateDisabled)
495 {
496 transform.translate = originalTransform->translate;
497 }
498 else
499 {
500 transform.translate.x = (flags & anim::ResTransformAnimData::FLAG_TRANSLATE_X_NOT_EXIST) ?
501 originalTransform->translate.x : transformAnim.EvaluateTranslateX(frame);
502 transform.translate.y = (flags & anim::ResTransformAnimData::FLAG_TRANSLATE_Y_NOT_EXIST) ?
503 originalTransform->translate.y : transformAnim.EvaluateTranslateY(frame);
504 transform.translate.z = (flags & anim::ResTransformAnimData::FLAG_TRANSLATE_Z_NOT_EXIST) ?
505 originalTransform->translate.z : transformAnim.EvaluateTranslateZ(frame);
506 }
507
508 result->SetTransform(transform);
509 }
510 else
511 {
512 if (!m_IsScaleDisabled)
513 {
514 if (!(flags & anim::ResTransformAnimData::FLAG_SCALE_X_NOT_EXIST))
515 {
516 result->DirectScale().x = transformAnim.EvaluateScaleX(frame);
517 }
518 if (!(flags & anim::ResTransformAnimData::FLAG_SCALE_Y_NOT_EXIST))
519 {
520 result->DirectScale().y = transformAnim.EvaluateScaleY(frame);
521 }
522 if (!(flags & anim::ResTransformAnimData::FLAG_SCALE_Z_NOT_EXIST))
523 {
524 result->DirectScale().z = transformAnim.EvaluateScaleZ(frame);
525 }
526 }
527
528 if (!m_IsRotateDisabled)
529 {
530
531 if ((flags & FLAG_ROTATE_NOT_EXIST) != FLAG_ROTATE_NOT_EXIST)
532 {
533 const f32 rotX = (flags & anim::ResTransformAnimData::FLAG_ROTATE_X_NOT_EXIST) ?
534 originalTransform->rotate.x : transformAnim.EvaluateRotateX(frame);
535 const f32 rotY = (flags & anim::ResTransformAnimData::FLAG_ROTATE_Y_NOT_EXIST) ?
536 originalTransform->rotate.y : transformAnim.EvaluateRotateY(frame);
537 const f32 rotZ = (flags & anim::ResTransformAnimData::FLAG_ROTATE_Z_NOT_EXIST) ?
538 originalTransform->rotate.z : transformAnim.EvaluateRotateZ(frame);
539 result->SetRotateXYZ(rotX, rotY, rotZ);
540 }
541 }
542
543 if (!m_IsTranslateDisabled)
544 {
545 if (!(flags & anim::ResTransformAnimData::FLAG_TRANSLATE_X_NOT_EXIST))
546 {
547 result->DirectTransformMatrix().f._03 = transformAnim.EvaluateTranslateX(frame);
548 }
549 if (!(flags & anim::ResTransformAnimData::FLAG_TRANSLATE_Y_NOT_EXIST))
550 {
551 result->DirectTransformMatrix().f._13 = transformAnim.EvaluateTranslateY(frame);
552 }
553 if (!(flags & anim::ResTransformAnimData::FLAG_TRANSLATE_Z_NOT_EXIST))
554 {
555 result->DirectTransformMatrix().f._23 = transformAnim.EvaluateTranslateZ(frame);
556 }
557 }
558
559 result->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
560 }
561 UpdateFlagsCommon(result);
562
563 // 回転アニメーションが存在するならば、FLAG_IS_ROTATE_ZERO は無効にする。
564 if ((flags & FLAG_ROTATE_NOT_EXIST) != FLAG_ROTATE_NOT_EXIST)
565 {
566 result->DisableFlags(CalculatedTransform::FLAG_IS_ROTATE_ZERO);
567 }
568 // 同様に平行移動が存在するならば、FLAG_IS_TRANSLATE_ZERO は無効にする。
569 if ((flags & FLAG_TRANSLATE_NOT_EXIST) != FLAG_TRANSLATE_NOT_EXIST)
570 {
571 result->DisableFlags(CalculatedTransform::FLAG_IS_TRANSLATE_ZERO);
572 }
573 // 同様にスケールが存在するならば、FLAG_IS_SCALE_ONE は無効にする。
574 if ((flags & FLAG_SCALE_NOT_EXIST) != FLAG_SCALE_NOT_EXIST)
575 {
576 result->DisableFlags(CalculatedTransform::FLAG_IS_SCALE_ONE);
577 }
578 result->UpdateCompositeFlags();
579 }
580
581 //----------------------------------------------------------
582 void
EvaluateMemberBakedAnim(CalculatedTransform * result,anim::ResBakedTransformAnim transformAnim,float frame,const math::Transform3 * originalTransform,bool writeNoAnimMember) const583 TransformAnimEvaluator::EvaluateMemberBakedAnim(
584 CalculatedTransform* result,
585 anim::ResBakedTransformAnim transformAnim,
586 float frame,
587 const math::Transform3* originalTransform,
588 bool writeNoAnimMember
589 ) const
590 {
591 const u32 flags = transformAnim.GetFlags();
592 bit32 frameFlags = 0;
593
594 if (!writeNoAnimMember)
595 {
596 // OriginalValueが書き込み済みの場合は、
597 // アニメのない要素のフラグを再利用する
598 frameFlags = result->GetFlags();
599 }
600
601 if (!(flags & anim::ResBakedTransformAnimData::FLAG_ROTATE_NOT_EXIST))
602 {
603 frameFlags = ut::DisableFlag(frameFlags,
604 gfx::CalculatedTransform::FLAG_IS_ROTATE_ZERO);
605
606 transformAnim.EvaluateRotate(&result->m_TransformMatrix, &frameFlags, frame);
607 result->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
608 }
609
610 if (!(flags & anim::ResBakedTransformAnimData::FLAG_TRANSLATE_NOT_EXIST))
611 {
612 frameFlags = ut::DisableFlag(frameFlags,
613 gfx::CalculatedTransform::FLAG_IS_TRANSLATE_ZERO);
614
615 transformAnim.EvaluateTranslate(&result->m_TransformMatrix, &frameFlags, frame);
616 result->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
617 }
618
619 if (!(flags & anim::ResBakedTransformAnimData::FLAG_SCALE_NOT_EXIST))
620 {
621 frameFlags = ut::DisableFlag(frameFlags,
622 gfx::CalculatedTransform::FLAG_IS_UNIFORM_SCALE |
623 gfx::CalculatedTransform::FLAG_IS_SCALE_ONE);
624
625 transformAnim.EvaluateScale(&result->m_Scale, &frameFlags, frame);
626 result->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
627 }
628
629 if (writeNoAnimMember)
630 {
631 if (flags & anim::ResBakedTransformAnimData::FLAG_ROTATE_NOT_EXIST)
632 {
633 // TODO: 回転行列の生成は重いので、originalValueをCalculatedTransform型で保存するようにする
634 result->SetRotateXYZ(
635 originalTransform->rotate.x,
636 originalTransform->rotate.y,
637 originalTransform->rotate.z);
638
639 if (originalTransform->rotate.IsZero())
640 {
641 frameFlags |= gfx::CalculatedTransform::FLAG_IS_ROTATE_ZERO;
642 }
643 }
644
645 if (flags & anim::ResBakedTransformAnimData::FLAG_TRANSLATE_NOT_EXIST)
646 {
647 result->SetTranslate(originalTransform->translate);
648
649 if (originalTransform->translate.IsZero())
650 {
651 frameFlags |= gfx::CalculatedTransform::FLAG_IS_TRANSLATE_ZERO;
652 }
653 }
654
655 if (flags & anim::ResBakedTransformAnimData::FLAG_SCALE_NOT_EXIST)
656 {
657 result->SetScale(originalTransform->scale);
658
659 const math::Vector3& scale = originalTransform->scale;
660 if (scale.x == scale.y && scale.x == scale.z)
661 {
662 frameFlags |= gfx::CalculatedTransform::FLAG_IS_UNIFORM_SCALE;
663
664 if (scale.x == 1.f)
665 {
666 frameFlags |= gfx::CalculatedTransform::FLAG_IS_SCALE_ONE;
667 }
668 }
669 }
670 }
671
672 ApplyBakedFlags(result, frameFlags);
673 }
674
675 //----------------------------------------------------------
676 void
UpdateFlagsCommon(CalculatedTransform * transform) const677 TransformAnimEvaluator::UpdateFlagsCommon(CalculatedTransform* transform) const
678 {
679 transform->DisableFlags(XFORM_CONVERTED);
680
681 if (m_IsScaleDisabled)
682 {
683 transform->EnableFlags(XFORM_IGNORE_S);
684 }
685 else
686 {
687 transform->DisableFlags(XFORM_IGNORE_S);
688 }
689 if (m_IsRotateDisabled)
690 {
691 transform->EnableFlags(XFORM_IGNORE_R);
692 }
693 else
694 {
695 transform->DisableFlags(XFORM_IGNORE_R);
696 }
697 if (m_IsTranslateDisabled)
698 {
699 transform->EnableFlags(XFORM_IGNORE_T);
700 }
701 else
702 {
703 transform->DisableFlags(XFORM_IGNORE_T);
704 }
705 }
706
707 //----------------------------------------------------------
708 void
UpdateFlags(CalculatedTransform * transform) const709 TransformAnimEvaluator::UpdateFlags(CalculatedTransform* transform) const
710 {
711 UpdateFlagsCommon(transform);
712 transform->UpdateFlags();
713 }
714
715 //----------------------------------------------------------
716 void
ApplyBakedFlags(CalculatedTransform * transform,bit32 flags) const717 TransformAnimEvaluator::ApplyBakedFlags(CalculatedTransform* transform, bit32 flags) const
718 {
719 UpdateFlagsCommon(transform);
720 // Bake済みデータで更新する
721 anim::ResBakedTransformAnim::ApplyBakedFlags(transform, flags);
722 }
723
724 //----------------------------------------------------------
725 const anim::AnimResult*
GetResult(void * target,int memberIdx) const726 TransformAnimEvaluator::GetResult(
727 void* target,
728 int memberIdx
729 ) const
730 {
731 return GetResultCommon(target, memberIdx, true);
732 }
733
734 //----------------------------------------------------------
ResetNoAnimMember(AnimGroup * animGroup,anim::ResAnim animData)735 void TransformAnimEvaluator::ResetNoAnimMember(AnimGroup* animGroup, anim::ResAnim animData)
736 {
737 using namespace anim;
738
739 for (int memberIdx = 0; memberIdx < animGroup->GetMemberCount(); ++memberIdx)
740 {
741 const int animIdx = m_BindIndexTable[memberIdx];
742 if (animIdx == NotFoundIndex){ continue; }
743
744 ResMemberAnim memberAnim = animData.GetMemberAnimSet(animIdx);
745 switch (memberAnim.GetPrimitiveType())
746 {
747 case ResMemberAnim::PRIMITIVETYPE_TRANSFORM:
748 case ResMemberAnim::PRIMITIVETYPE_BAKED_TRANSFORM:
749 {
750 u32 rotateAndTranslateMask;
751 u32 scaleMask;
752 if (memberAnim.GetPrimitiveType() == ResMemberAnim::PRIMITIVETYPE_TRANSFORM)
753 {
754 rotateAndTranslateMask = ResTransformAnimData::FLAG_ROTATE_NOT_EXIST |
755 ResTransformAnimData::FLAG_TRANSLATE_NOT_EXIST;
756 scaleMask = ResTransformAnimData::FLAG_SCALE_NOT_EXIST;
757 }
758 else
759 {
760 rotateAndTranslateMask = ResBakedTransformAnimData::FLAG_ROTATE_NOT_EXIST |
761 ResBakedTransformAnimData::FLAG_TRANSLATE_NOT_EXIST;
762 scaleMask = ResBakedTransformAnimData::FLAG_SCALE_NOT_EXIST;
763 }
764
765 CalculatedTransform* target =
766 static_cast<CalculatedTransform*>(animGroup->GetTargetPtr(memberIdx));
767
768 const math::Transform3* originalValue =
769 static_cast<const math::Transform3*>(animGroup->GetOriginalValue(memberIdx));
770
771 const u32 flags = memberAnim.GetFlags();
772 bool modified = false;
773
774 if (flags & rotateAndTranslateMask)
775 {
776 // TODO: 回転行列の生成は重いので、originalValueをCalculatedTransform型で保存するようにする
777 target->SetRotateAndTranslate(originalValue->rotate, originalValue->translate);
778 modified = true;
779 }
780
781 if (flags & scaleMask)
782 {
783 target->SetScale(originalValue->scale);
784 modified = true;
785 }
786
787 if (modified)
788 {
789 UpdateFlags(target);
790
791 if (!m_CacheTransforms.Empty())
792 {
793 m_CacheTransforms[animIdx] = *target;
794 }
795 }
796 }
797 break;
798 default:
799 NW_ASSERT(false);
800 }
801 }
802 }
803
804 //----------------------------------------------------------
805 const anim::AnimResult*
GetResultFast(void * target,int memberIdx) const806 TransformAnimEvaluator::GetResultFast(void* target, int memberIdx) const
807 {
808 return GetResultCommon(target, memberIdx, false);
809 }
810
811 //----------------------------------------------------------
812 const anim::AnimResult*
GetResultCommon(void * target,int memberIdx,bool writeNoAnimMember) const813 TransformAnimEvaluator::GetResultCommon(void* target, int memberIdx, bool writeNoAnimMember) const
814 {
815 using namespace anim;
816
817 //-----------------------------------------------------------------
818 // メンバに関連付けられたアニメーションが存在しない場合は
819 // target を変更せずに NULL を返す
820 if (!HasMemberAnim(memberIdx))
821 {
822 return NULL;
823 }
824
825 //-----------------------------------------------------------------
826 CalculatedTransform* transform =
827 reinterpret_cast<CalculatedTransform*>(target);
828 if (!m_CacheTransforms.Empty() && !m_IsCacheDirty && m_AnimData.ptr() != NULL)
829 {
830 //-----------------------------------------------------------------
831 // キャッシュがあればキャッシュの値を target にコピー
832 const int animIdx = m_BindIndexTable[memberIdx];
833 *transform = m_CacheTransforms[animIdx];
834 }
835 else
836 {
837 //-----------------------------------------------------------------
838 // アニメーションカーブを評価して対象に書き込む
839 const math::Transform3* originalValue =
840 static_cast<const math::Transform3*>(m_AnimGroup->GetOriginalValue(memberIdx));
841 if (m_AnimData.ptr() != NULL)
842 {
843 const int animIdx = m_BindIndexTable[memberIdx];
844 ResMemberAnim memberAnim = m_AnimData.GetMemberAnimSet(animIdx);
845
846 switch (memberAnim.GetPrimitiveType())
847 {
848 case ResMemberAnim::PRIMITIVETYPE_TRANSFORM:
849 {
850 ResTransformAnim transformAnim = static_cast<ResTransformAnim>(memberAnim);
851 EvaluateMemberAnim(transform, transformAnim, m_AnimFrameController.GetFrame(), originalValue, writeNoAnimMember);
852 }
853 break;
854 case ResMemberAnim::PRIMITIVETYPE_BAKED_TRANSFORM:
855 {
856 ResBakedTransformAnim transformAnim = static_cast<ResBakedTransformAnim>(memberAnim);
857 EvaluateMemberBakedAnim(transform, transformAnim, m_AnimFrameController.GetFrame(), originalValue, writeNoAnimMember);
858 }
859 break;
860 default:
861 NW_ASSERT(false);
862 break;
863 }
864 }
865 else
866 {
867 // アニメーションデータがない場合はオリジナル値をコピー
868 transform->SetTransform(*originalValue);
869 UpdateFlags(transform);
870 }
871 }
872
873 // target を AnimResult にキャストして返す(親のブレンダで使用)
874 return reinterpret_cast<AnimResult*>(target);
875 }
876
877 //----------------------------------------------------------
878 Result
TryBind(AnimGroup * animGroup)879 TransformAnimEvaluator::TryBind(AnimGroup* animGroup)
880 {
881 Result result;
882 NW_NULL_ASSERT(m_AnimData.ptr());
883
884 result = BaseAnimEvaluator::TryBind(animGroup);
885 if (result.IsFailure())
886 {
887 return result;
888 }
889
890 ResetNoAnimMember(animGroup, m_AnimData);
891 m_AnimGroup = animGroup;
892
893 return result;
894 }
895
896 //----------------------------------------------------------
897 void
UpdateCache()898 TransformAnimEvaluator::UpdateCache()
899 {
900 if (!m_CacheTransforms.Empty() && m_IsCacheDirty)
901 {
902 if (m_AnimData.ptr() != NULL)
903 {
904 for (int memberIdx = 0; memberIdx < m_AnimGroup->GetMemberCount(); ++memberIdx)
905 {
906 const int animIdx = m_BindIndexTable[memberIdx];
907 if (animIdx != NotFoundIndex)
908 {
909 GetResult(&m_CacheTransforms[animIdx], memberIdx);
910 }
911 }
912 }
913 m_IsCacheDirty = false;
914 }
915 }
916
917 //----------------------------------------------------------
918 const anim::AnimResult*
GetResult(void * target,int memberIdx) const919 TransformAnimInterpolator::GetResult(
920 void* target,
921 int memberIdx
922 ) const
923 {
924 //----------------------------------------------------------
925 // ブレンドオペレーションを取得
926 const anim::AnimBlendOp* blendOp = m_AnimGroup->GetBlendOperation(memberIdx);
927
928 if (m_IsOldMethod)
929 {
930 // TODO: こちらのブロックを整理。
931
932 //----------------------------------------------------------
933 // 有効な子アニメーションの重みの合計を SRT ごとに求める
934 float weightSums[3] = { 0.0f, 0.0f, 0.0f };
935 for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
936 {
937 if (m_AnimObjects[animIdx] == NULL)
938 {
939 continue;
940 }
941 const float weight = m_Weights[animIdx];
942 if (!AnimWeightNearlyEqualZero(weight))
943 {
944 const AnimObject* animObj = m_AnimObjects[animIdx];
945 if (animObj->HasMemberAnim(memberIdx))
946 {
947 const TransformAnimEvaluator* evaluator =
948 ut::DynamicCast<const TransformAnimEvaluator*>(animObj);
949 if (evaluator != NULL)
950 {
951 if (!evaluator->GetIsScaleDisabled())
952 {
953 weightSums[0] += weight;
954 }
955 if (!evaluator->GetIsRotateDisabled())
956 {
957 weightSums[1] += weight;
958 }
959 if (!evaluator->GetIsTranslateDisabled())
960 {
961 weightSums[2] += weight;
962 }
963 }
964 else
965 {
966 weightSums[0] += weight;
967 weightSums[1] += weight;
968 weightSums[2] += weight;
969 }
970 }
971 }
972 }
973
974 // 有効な子アニメーションが存在しない場合は
975 // target を変更せずに NULL を返す
976 if (CheckWeightsNearyZero(weightSums))
977 {
978 return NULL;
979 }
980
981 // 重みの合計が 1.0 でない場合は正規化スケールを計算
982 float weightNormalizeScale[3] =
983 {
984 GetAnimWeightNormalizeScale(weightSums[0]),
985 GetAnimWeightNormalizeScale(weightSums[1]),
986 GetAnimWeightNormalizeScale(weightSums[2])
987 };
988
989 //----------------------------------------------------------
990 // 補間は操作空間があればそこで行われるべきなので
991 // target の CONVERTED フラグを退避してからオンに
992 CalculatedTransform* transform =
993 reinterpret_cast<CalculatedTransform*>(target);
994 const bit32 flagsBak = transform->GetFlags();
995 const bool convertedBak = transform->IsEnabledFlags(XFORM_CONVERTED);
996 transform->EnableFlags(XFORM_CONVERTED);
997
998 //----------------------------------------------------------
999 // target の IGNORE フラグをオンにして未書き込み状態とする
1000 transform->EnableFlags(XFORM_IGNORE_SRT);
1001
1002 //----------------------------------------------------------
1003 // すべての子アニメーションについてループ
1004 CalculatedTransform workResult;
1005 bool written = false;
1006 bool firstRotateFlag = true;
1007 math::MTX34 firstRotateMtx;
1008 //for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
1009 for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1010 {
1011 const AnimObject* animObj = m_AnimObjects[animIdx];
1012 if (animObj == NULL)
1013 {
1014 continue;
1015 }
1016
1017 const float childWeight = m_Weights[animIdx];
1018 NW_ASSERT(childWeight >= 0.0f);
1019 float srcWeights[3] =
1020 {
1021 childWeight * weightNormalizeScale[0],
1022 childWeight * weightNormalizeScale[1],
1023 childWeight * weightNormalizeScale[2]
1024 };
1025 DisableSRTWeightsIfNeeded(srcWeights, animObj);
1026
1027 if (!CheckWeightsNearyZero(srcWeights))
1028 {
1029 // 退避した CONVERTED フラグを work に反映
1030 // 子が CONVERTED を扱う Blender であれば CONVERTED なままの結果が返ってくることを期待
1031 // 子が Evaluator の場合はフラグがオフで返ってくるが blendOp 内で変換されるので問題ない
1032 workResult.EnableFlags(XFORM_CONVERTED, convertedBak);
1033
1034 // 評価
1035 const anim::AnimResult* childResult =
1036 animObj->GetResult(&workResult, memberIdx);
1037
1038 if (childResult != NULL)
1039 {
1040 written = true;
1041 const bool evaluatorFlag =
1042 ut::DynamicCast<const TransformAnimEvaluator*>(animObj) != NULL;
1043
1044 // ブレンド結果の回転行列の行がゼロベクトルになった場合のために
1045 // 最初のアニメーションの回転行列を保存しておく
1046 if (evaluatorFlag && firstRotateFlag &&
1047 !workResult.IsEnabledFlags(XFORM_IGNORE_R))
1048 {
1049 firstRotateFlag = false;
1050 firstRotateMtx = workResult.TransformMatrix();
1051 }
1052
1053 // ブレンド
1054 if (!blendOp->Blend(reinterpret_cast<anim::AnimResult*>(transform),
1055 NULL, childResult, srcWeights))
1056 {
1057 break;
1058 }
1059 }
1060 }
1061 }
1062
1063 //----------------------------------------------------------
1064 // target の CONVERTED フラグを復元
1065 if (!convertedBak)
1066 {
1067 transform->DisableFlags(XFORM_CONVERTED);
1068 }
1069
1070 if (!written) // 有効な子アニメーションなし
1071 {
1072 RestoreIgnoreFlags(transform, flagsBak);
1073 return NULL;
1074 }
1075
1076 //----------------------------------------------------------
1077 // ブレンド後の処理があれば実行
1078 if (!convertedBak && blendOp->HasPostBlend())
1079 {
1080 if (!blendOp->PostBlend(reinterpret_cast<anim::AnimResult*>(transform), NULL))
1081 {
1082 // ブレンド結果の回転行列の行がゼロベクトルなら
1083 // 最初のアニメーションの回転行列を採用します。
1084 // 結果が品質上問題となる場合は
1085 // 元データを微妙にずらして回避する必要があります。
1086 AdjustZeroRotateMatrix(transform, !firstRotateFlag, firstRotateMtx);
1087 }
1088 }
1089 transform->UpdateFlags();
1090 }
1091 else
1092 {
1093 bool isValidAnim = false;
1094 for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
1095 {
1096 if (m_AnimObjects[animIdx] && m_AnimObjects[animIdx]->HasMemberAnim(memberIdx))
1097 {
1098 isValidAnim = true;
1099 break;
1100 }
1101 }
1102
1103 // 有効な子アニメーションが存在しない場合は
1104 // target を変更せずに NULL を返す
1105 if (!isValidAnim)
1106 {
1107 return NULL;
1108 }
1109
1110 // アニメーション重みの正規化を必要なら行います。
1111 if (m_IsWeightDirty && m_IsWeightNormalizationEnabled)
1112 {
1113 NormalizeWeight();
1114 }
1115
1116 //----------------------------------------------------------
1117 // 補間は操作空間があればそこで行われるべきなので
1118 // target の CONVERTED フラグを退避してからオンに
1119 CalculatedTransform* transform =
1120 reinterpret_cast<CalculatedTransform*>(target);
1121 const bit32 flagsBak = transform->GetFlags();
1122 const bool convertedBak = transform->IsEnabledFlags(XFORM_CONVERTED);
1123 transform->EnableFlags(XFORM_CONVERTED);
1124
1125 //----------------------------------------------------------
1126 // target の IGNORE フラグをオンにして未書き込み状態とする
1127 transform->EnableFlags(XFORM_IGNORE_SRT);
1128
1129 //----------------------------------------------------------
1130 // すべての子アニメーションについてループ
1131 CalculatedTransform workResult;
1132 bool firstRotateFlag = true;
1133 math::MTX34 firstRotateMtx;
1134 for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1135 {
1136 const AnimObject* animObj = m_AnimObjects[animIdx];
1137
1138 const float childWeight = m_NormalizedWeights[animIdx];
1139 NW_ASSERT(childWeight >= 0.0f);
1140 const float srcWeights[3] =
1141 {
1142 childWeight,
1143 childWeight,
1144 childWeight
1145 };
1146
1147 if (!CheckWeightsNearyZero(srcWeights))
1148 {
1149 // 退避した CONVERTED フラグを work に反映
1150 // 子が CONVERTED を扱う Blender であれば CONVERTED なままの結果が返ってくることを期待
1151 // 子が Evaluator の場合はフラグがオフで返ってくるが blendOp 内で変換されるので問題ない
1152 workResult.EnableFlags(XFORM_CONVERTED, convertedBak);
1153
1154 // 評価
1155 const anim::AnimResult* childResult = NULL;
1156 if (animObj != NULL)
1157 {
1158 childResult = animObj->GetResult(&workResult, memberIdx);
1159 }
1160
1161 if (childResult == NULL)
1162 {
1163 const math::Transform3* originalValue =
1164 static_cast<const math::Transform3*>(GetAnimGroup()->GetOriginalValue(memberIdx));
1165 workResult.SetTransform(*originalValue);
1166 workResult.UpdateFlags();
1167 childResult = reinterpret_cast<anim::AnimResult*>(&workResult);
1168 }
1169
1170 const bool evaluatorFlag =
1171 ut::DynamicCast<const TransformAnimEvaluator*>(animObj) != NULL;
1172
1173 // ブレンド結果の回転行列の行がゼロベクトルになった場合のために
1174 // 最初のアニメーションの回転行列を保存しておく
1175 if (evaluatorFlag && firstRotateFlag &&
1176 !workResult.IsEnabledFlags(XFORM_IGNORE_R))
1177 {
1178 firstRotateFlag = false;
1179 firstRotateMtx = workResult.TransformMatrix();
1180 }
1181
1182 // ブレンド
1183 if (!blendOp->Blend(reinterpret_cast<anim::AnimResult*>(transform),
1184 NULL, childResult, srcWeights))
1185 {
1186 break;
1187 }
1188 }
1189 }
1190
1191 //----------------------------------------------------------
1192 // target の CONVERTED フラグを復元
1193 if (!convertedBak)
1194 {
1195 transform->DisableFlags(XFORM_CONVERTED);
1196 }
1197
1198 //----------------------------------------------------------
1199 // ブレンド後の処理があれば実行
1200 if (!convertedBak && blendOp->HasPostBlend())
1201 {
1202 if (!blendOp->PostBlend(reinterpret_cast<anim::AnimResult*>(transform), NULL))
1203 {
1204 // ブレンド結果の回転行列の行がゼロベクトルなら
1205 // 最初のアニメーションの回転行列を採用します。
1206 // 結果が品質上問題となる場合は
1207 // 元データを微妙にずらして回避する必要があります。
1208 AdjustZeroRotateMatrix(transform, !firstRotateFlag, firstRotateMtx);
1209 }
1210 }
1211 transform->UpdateFlags();
1212 }
1213
1214 // target を AnimResult にキャストして返す(親のブレンダで使用)
1215 return reinterpret_cast<anim::AnimResult*>(target);
1216 }
1217
1218 //----------------------------------------------------------
1219 const anim::AnimResult*
GetResult(void * target,int memberIdx) const1220 TransformAnimAdder::GetResult(
1221 void* target,
1222 int memberIdx
1223 ) const
1224 {
1225 //----------------------------------------------------------
1226 // ブレンドオペレーションを取得
1227 const anim::AnimBlendOp* blendOp = m_AnimGroup->GetBlendOperation(memberIdx);
1228
1229 //----------------------------------------------------------
1230 // 補間は操作空間があればそこで行われるべきなので
1231 // target の CONVERTED フラグを退避してからオンに
1232 CalculatedTransform* transform =
1233 reinterpret_cast<CalculatedTransform*>(target);
1234 const bit32 flagsBak = transform->GetFlags();
1235 const bool convertedBak = transform->IsEnabledFlags(XFORM_CONVERTED);
1236 transform->EnableFlags(XFORM_CONVERTED);
1237
1238 //----------------------------------------------------------
1239 // target の IGNORE フラグをオンにして未書き込み状態とする
1240 transform->EnableFlags(XFORM_IGNORE_SRT);
1241
1242 //----------------------------------------------------------
1243 // すべての子アニメーションについてループ
1244 CalculatedTransform workResult;
1245 bool written = false;
1246 bool firstRotateFlag = true;
1247 math::MTX34 firstRotateMtx;
1248 //for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
1249 for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1250 {
1251 const AnimObject* animObj = m_AnimObjects[animIdx];
1252 if (animObj == NULL)
1253 {
1254 continue;
1255 }
1256
1257 const float childWeight = m_Weights[animIdx];
1258 float srcWeights[3] = { childWeight, childWeight, childWeight };
1259 DisableSRTWeightsIfNeeded(srcWeights, animObj);
1260
1261 if (!CheckWeightsNearyZero(srcWeights))
1262 {
1263 // 退避した CONVERTED フラグを work に反映
1264 // 子が CONVERTED を扱う Blender であれば CONVERTED なままの結果が返ってくることを期待
1265 // 子が Evaluator の場合はフラグがオフで返ってくるが blendOp 内で変換されるので問題ない
1266 workResult.EnableFlags(XFORM_CONVERTED, convertedBak);
1267
1268 // 評価
1269 const anim::AnimResult* childResult =
1270 animObj->GetResult(&workResult, memberIdx);
1271 if (childResult != NULL)
1272 {
1273 written = true;
1274 const bool evaluatorFlag =
1275 ut::DynamicCast<const TransformAnimEvaluator*>(animObj) != NULL;
1276
1277 // ブレンド結果の回転行列の行がゼロベクトルになった場合のために
1278 // 最初のアニメーションの回転行列を保存しておく
1279 if (evaluatorFlag && firstRotateFlag &&
1280 !workResult.IsEnabledFlags(XFORM_IGNORE_R))
1281 {
1282 firstRotateFlag = false;
1283 firstRotateMtx = workResult.TransformMatrix();
1284 }
1285
1286 // ブレンド
1287 if (!blendOp->Blend(reinterpret_cast<anim::AnimResult*>(transform),
1288 NULL, childResult, srcWeights))
1289 {
1290 break;
1291 }
1292 }
1293 }
1294 }
1295
1296 //----------------------------------------------------------
1297 // target の CONVERTED フラグを復元
1298 if (!convertedBak)
1299 {
1300 transform->DisableFlags(XFORM_CONVERTED);
1301 }
1302
1303 if (!written) // 有効な子アニメーションなし
1304 {
1305 RestoreIgnoreFlags(transform, flagsBak);
1306 return NULL;
1307 }
1308
1309 //----------------------------------------------------------
1310 // ブレンド後の処理があれば実行
1311 if (!convertedBak && blendOp->HasPostBlend())
1312 {
1313 if (!blendOp->PostBlend(reinterpret_cast<anim::AnimResult*>(transform), NULL))
1314 {
1315 // ブレンド結果の回転行列の行がゼロベクトルなら
1316 // 最初のアニメーションの回転行列を採用します。
1317 // 結果が品質上問題となる場合は
1318 // 元データを微妙にずらして回避する必要があります。
1319 AdjustZeroRotateMatrix(transform, !firstRotateFlag, firstRotateMtx);
1320 }
1321 }
1322 transform->UpdateFlags();
1323
1324 // target を AnimResult にキャストして返す(親のブレンダで使用)
1325 return reinterpret_cast<anim::AnimResult*>(target);
1326 }
1327
1328 //----------------------------------------------------------
1329 const anim::AnimResult*
GetResult(void * target,int memberIdx) const1330 TransformAnimOverrider::GetResult(
1331 void* target,
1332 int memberIdx
1333 ) const
1334 {
1335 //----------------------------------------------------------
1336 // ブレンドオペレーションを取得
1337 const anim::AnimBlendOp* blendOp = m_AnimGroup->GetBlendOperation(memberIdx);
1338
1339 //----------------------------------------------------------
1340 // target の IGNORE フラグをオンにして未書き込み状態とする
1341 CalculatedTransform* transform =
1342 reinterpret_cast<CalculatedTransform*>(target);
1343 const bit32 flagsBak = transform->GetFlags();
1344 transform->EnableFlags(XFORM_IGNORE_SRT);
1345
1346 //----------------------------------------------------------
1347 // すべての子アニメーションについてループ
1348 CalculatedTransform workResult;
1349 bool written = false;
1350 for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1351 {
1352 const AnimObject* animObj = m_AnimObjects[animIdx];
1353 if (animObj == NULL)
1354 {
1355 continue;
1356 }
1357
1358 float srcWeights[3] = { 1.0f, 1.0f, 1.0f };
1359 DisableSRTWeightsIfNeeded(srcWeights, animObj);
1360
1361 if (!CheckWeightsNearyZero(srcWeights))
1362 {
1363 // 評価
1364 const anim::AnimResult* childResult =
1365 animObj->GetResult(&workResult, memberIdx);
1366 if (childResult != NULL)
1367 {
1368 written = true;
1369 if (blendOp->Override(reinterpret_cast<anim::AnimResult*>(transform),
1370 childResult)) // 全成分を上書きしたら true が返る
1371 {
1372 break;
1373 }
1374 }
1375 }
1376 }
1377
1378 if (!written) // 有効な子アニメーションなし
1379 {
1380 RestoreIgnoreFlags(transform, flagsBak);
1381 return NULL;
1382 }
1383
1384 transform->UpdateFlags();
1385
1386 // target を AnimResult にキャストして返す(親のブレンダで使用)
1387 return reinterpret_cast<anim::AnimResult*>(target);
1388 }
1389
1390 } // namespace gfx
1391 } // namespace nw
1392