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: 28424 $
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->UpdateScaleFlags();
713     transform->UpdateRotateFlags();
714     transform->UpdateTranslateFlags();
715     transform->UpdateCompositeFlags();
716 }
717 
718 //----------------------------------------------------------
719 void
ApplyBakedFlags(CalculatedTransform * transform,bit32 flags) const720 TransformAnimEvaluator::ApplyBakedFlags(CalculatedTransform* transform, bit32 flags) const
721 {
722     UpdateFlagsCommon(transform);
723     // Bake済みデータで更新する
724     anim::ResBakedTransformAnim::ApplyBakedFlags(transform, flags);
725 }
726 
727 //----------------------------------------------------------
728 const anim::AnimResult*
GetResult(void * target,int memberIdx) const729 TransformAnimEvaluator::GetResult(
730     void* target,
731     int memberIdx
732 ) const
733 {
734     return GetResultCommon(target, memberIdx, true);
735 }
736 
737 //----------------------------------------------------------
ResetNoAnimMember(AnimGroup * animGroup,anim::ResAnim animData)738 void TransformAnimEvaluator::ResetNoAnimMember(AnimGroup* animGroup, anim::ResAnim animData)
739 {
740     using namespace anim;
741 
742     for (int memberIdx = 0; memberIdx < animGroup->GetMemberCount(); ++memberIdx)
743     {
744         const int animIdx = m_BindIndexTable[memberIdx];
745         if (animIdx == NotFoundIndex){ continue; }
746 
747         ResMemberAnim memberAnim = animData.GetMemberAnimSet(animIdx);
748         switch (memberAnim.GetPrimitiveType())
749         {
750         case ResMemberAnim::PRIMITIVETYPE_TRANSFORM:
751         case ResMemberAnim::PRIMITIVETYPE_BAKED_TRANSFORM:
752             {
753                 u32 rotateAndTranslateMask;
754                 u32 scaleMask;
755                 if (memberAnim.GetPrimitiveType() == ResMemberAnim::PRIMITIVETYPE_TRANSFORM)
756                 {
757                     rotateAndTranslateMask = ResTransformAnimData::FLAG_ROTATE_NOT_EXIST |
758                                              ResTransformAnimData::FLAG_TRANSLATE_NOT_EXIST;
759                     scaleMask = ResTransformAnimData::FLAG_SCALE_NOT_EXIST;
760                 }
761                 else
762                 {
763                     rotateAndTranslateMask = ResBakedTransformAnimData::FLAG_ROTATE_NOT_EXIST |
764                                              ResBakedTransformAnimData::FLAG_TRANSLATE_NOT_EXIST;
765                     scaleMask = ResBakedTransformAnimData::FLAG_SCALE_NOT_EXIST;
766                 }
767 
768                 CalculatedTransform* target =
769                     static_cast<CalculatedTransform*>(animGroup->GetTargetPtr(memberIdx));
770 
771                 const math::Transform3* originalValue =
772                     static_cast<const math::Transform3*>(animGroup->GetOriginalValue(memberIdx));
773 
774                 const u32 flags = memberAnim.GetFlags();
775                 bool modified = false;
776 
777                 if (flags & rotateAndTranslateMask)
778                 {
779                     // TODO: 回転行列の生成は重いので、originalValueをCalculatedTransform型で保存するようにする
780                     target->SetRotateAndTranslate(originalValue->rotate, originalValue->translate);
781                     modified = true;
782                 }
783 
784                 if (flags & scaleMask)
785                 {
786                     target->SetScale(originalValue->scale);
787                     modified = true;
788                 }
789 
790                 if (modified)
791                 {
792                     UpdateFlags(target);
793 
794                     if (!m_CacheTransforms.Empty())
795                     {
796                         m_CacheTransforms[animIdx] = *target;
797                     }
798                 }
799             }
800             break;
801         case ResMemberAnim::PRIMITIVETYPE_FULL_BAKED:
802             // 全てのボーンの行列に必ず書き込む仕様なので、Resetの必要はない
803             break;
804         default:
805             NW_ASSERT(false);
806         }
807     }
808 }
809 
810 //----------------------------------------------------------
811 const anim::AnimResult*
GetResultFast(void * target,int memberIdx) const812 TransformAnimEvaluator::GetResultFast(void* target, int memberIdx) const
813 {
814     return GetResultCommon(target, memberIdx, false);
815 }
816 
817 //----------------------------------------------------------
818 const anim::AnimResult*
GetResultCommon(void * target,int memberIdx,bool writeNoAnimMember) const819 TransformAnimEvaluator::GetResultCommon(void* target, int memberIdx, bool writeNoAnimMember) const
820 {
821     using namespace anim;
822 
823     //-----------------------------------------------------------------
824     // メンバに関連付けられたアニメーションが存在しない場合は
825     // target を変更せずに NULL を返す
826     if (!HasMemberAnim(memberIdx))
827     {
828         return NULL;
829     }
830 
831     //-----------------------------------------------------------------
832     CalculatedTransform* transform =
833         reinterpret_cast<CalculatedTransform*>(target);
834     if (!m_CacheTransforms.Empty() && !m_IsCacheDirty && m_AnimData.ptr() != NULL)
835     {
836         //-----------------------------------------------------------------
837         // キャッシュがあればキャッシュの値を target にコピー
838         const int animIdx = m_BindIndexTable[memberIdx];
839         *transform = m_CacheTransforms[animIdx];
840     }
841     else
842     {
843         //-----------------------------------------------------------------
844         // アニメーションカーブを評価して対象に書き込む
845         const math::Transform3* originalValue =
846             static_cast<const math::Transform3*>(m_AnimGroup->GetOriginalValue(memberIdx));
847         if (m_AnimData.ptr() != NULL)
848         {
849             const int animIdx = m_BindIndexTable[memberIdx];
850             ResMemberAnim memberAnim = m_AnimData.GetMemberAnimSet(animIdx);
851 
852             switch (memberAnim.GetPrimitiveType())
853             {
854             case ResMemberAnim::PRIMITIVETYPE_TRANSFORM:
855                 {
856                     ResTransformAnim transformAnim = static_cast<ResTransformAnim>(memberAnim);
857                     EvaluateMemberAnim(transform, transformAnim, m_AnimFrameController.GetFrame(), originalValue, writeNoAnimMember);
858                 }
859                 break;
860             case ResMemberAnim::PRIMITIVETYPE_BAKED_TRANSFORM:
861                 {
862                     ResBakedTransformAnim transformAnim = static_cast<ResBakedTransformAnim>(memberAnim);
863                     EvaluateMemberBakedAnim(transform, transformAnim, m_AnimFrameController.GetFrame(), originalValue, writeNoAnimMember);
864                 }
865                 break;
866             case ResMemberAnim::PRIMITIVETYPE_FULL_BAKED:
867                 {
868                     ResFullBakedAnim transformAnim = static_cast<ResFullBakedAnim>(memberAnim);
869                     math::MTX34* worldMatrix = reinterpret_cast<math::MTX34*>(target);
870 
871                     transformAnim.EvaluateTransform(worldMatrix, m_AnimFrameController.GetFrame());
872                 }
873                 break;
874             default:
875                 NW_ASSERT(false);
876                 break;
877             }
878         }
879         else
880         {
881             // アニメーションデータがない場合はオリジナル値をコピー
882             transform->SetTransform(*originalValue);
883             UpdateFlags(transform);
884         }
885     }
886 
887     // target を AnimResult にキャストして返す(親のブレンダで使用)
888     return reinterpret_cast<AnimResult*>(target);
889 }
890 
891 //----------------------------------------------------------
892 Result
TryBind(AnimGroup * animGroup)893 TransformAnimEvaluator::TryBind(AnimGroup* animGroup)
894 {
895     Result result;
896     NW_NULL_ASSERT(m_AnimData.ptr());
897 
898     result = BaseAnimEvaluator::TryBind(animGroup);
899     if (result.IsFailure())
900     {
901         return result;
902     }
903 
904     ResetNoAnimMember(animGroup, m_AnimData);
905     m_AnimGroup = animGroup;
906 
907     return result;
908 }
909 
910 //----------------------------------------------------------
911 const anim::AnimResult*
GetResult(void * target,int memberIdx) const912 TransformAnimInterpolator::GetResult(
913     void* target,
914     int memberIdx
915 ) const
916 {
917     //----------------------------------------------------------
918     // ブレンドオペレーションを取得
919     const anim::AnimBlendOp* blendOp = m_AnimGroup->GetBlendOperation(memberIdx);
920 
921     if (m_IsOldMethod)
922     {
923         // TODO: こちらのブロックを整理。
924 
925         //----------------------------------------------------------
926         // 有効な子アニメーションの重みの合計を SRT ごとに求める
927         float weightSums[3] = { 0.0f, 0.0f, 0.0f };
928         for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
929         {
930             if (m_AnimObjects[animIdx] == NULL)
931             {
932                 continue;
933             }
934             const float weight = m_Weights[animIdx];
935             if (!AnimWeightNearlyEqualZero(weight))
936             {
937                 const AnimObject* animObj = m_AnimObjects[animIdx];
938                 if (animObj->HasMemberAnim(memberIdx))
939                 {
940                     const TransformAnimEvaluator* evaluator =
941                         ut::DynamicCast<const TransformAnimEvaluator*>(animObj);
942                     if (evaluator != NULL)
943                     {
944                         if (!evaluator->GetIsScaleDisabled())
945                         {
946                             weightSums[0] += weight;
947                         }
948                         if (!evaluator->GetIsRotateDisabled())
949                         {
950                             weightSums[1] += weight;
951                         }
952                         if (!evaluator->GetIsTranslateDisabled())
953                         {
954                             weightSums[2] += weight;
955                         }
956                     }
957                     else
958                     {
959                         weightSums[0] += weight;
960                         weightSums[1] += weight;
961                         weightSums[2] += weight;
962                     }
963                 }
964             }
965         }
966 
967         // 有効な子アニメーションが存在しない場合は
968         // target を変更せずに NULL を返す
969         if (CheckWeightsNearyZero(weightSums))
970         {
971             return NULL;
972         }
973 
974         // 重みの合計が 1.0 でない場合は正規化スケールを計算
975         float weightNormalizeScale[3] =
976         {
977             GetAnimWeightNormalizeScale(weightSums[0]),
978             GetAnimWeightNormalizeScale(weightSums[1]),
979             GetAnimWeightNormalizeScale(weightSums[2])
980         };
981 
982         //----------------------------------------------------------
983         // 補間は操作空間があればそこで行われるべきなので
984         // target の CONVERTED フラグを退避してからオンに
985         CalculatedTransform* transform =
986             reinterpret_cast<CalculatedTransform*>(target);
987         const bit32 flagsBak = transform->GetFlags();
988         const bool convertedBak = transform->IsEnabledFlags(XFORM_CONVERTED);
989         transform->EnableFlags(XFORM_CONVERTED);
990 
991         //----------------------------------------------------------
992         // target の IGNORE フラグをオンにして未書き込み状態とする
993         transform->EnableFlags(XFORM_IGNORE_SRT);
994 
995         //----------------------------------------------------------
996         // すべての子アニメーションについてループ
997         CalculatedTransform workResult;
998         bool written = false;
999         bool firstRotateFlag = true;
1000         math::MTX34 firstRotateMtx;
1001         //for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
1002         for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1003         {
1004             const AnimObject* animObj = m_AnimObjects[animIdx];
1005             if (animObj == NULL)
1006             {
1007                 continue;
1008             }
1009 
1010             const float childWeight = m_Weights[animIdx];
1011             NW_ASSERT(childWeight >= 0.0f);
1012             float srcWeights[3] =
1013             {
1014                 childWeight * weightNormalizeScale[0],
1015                 childWeight * weightNormalizeScale[1],
1016                 childWeight * weightNormalizeScale[2]
1017             };
1018             DisableSRTWeightsIfNeeded(srcWeights, animObj);
1019 
1020             if (!CheckWeightsNearyZero(srcWeights))
1021             {
1022                 // 退避した CONVERTED フラグを work に反映
1023                 // 子が CONVERTED を扱う Blender であれば CONVERTED なままの結果が返ってくることを期待
1024                 // 子が Evaluator の場合はフラグがオフで返ってくるが blendOp 内で変換されるので問題ない
1025                 workResult.EnableFlags(XFORM_CONVERTED, convertedBak);
1026 
1027                 // 評価
1028                 const anim::AnimResult* childResult =
1029                     animObj->GetResult(&workResult, memberIdx);
1030 
1031                 if (childResult != NULL)
1032                 {
1033                     written = true;
1034                     const bool evaluatorFlag =
1035                         ut::DynamicCast<const TransformAnimEvaluator*>(animObj) != NULL;
1036 
1037                     // ブレンド結果の回転行列の行がゼロベクトルになった場合のために
1038                     // 最初のアニメーションの回転行列を保存しておく
1039                     if (evaluatorFlag && firstRotateFlag &&
1040                         !workResult.IsEnabledFlags(XFORM_IGNORE_R))
1041                     {
1042                         firstRotateFlag = false;
1043                         firstRotateMtx = workResult.TransformMatrix();
1044                     }
1045 
1046                     // ブレンド
1047                     if (!blendOp->Blend(reinterpret_cast<anim::AnimResult*>(transform),
1048                         NULL, childResult, srcWeights))
1049                     {
1050                         break;
1051                     }
1052                 }
1053             }
1054         }
1055 
1056         //----------------------------------------------------------
1057         // target の CONVERTED フラグを復元
1058         if (!convertedBak)
1059         {
1060             transform->DisableFlags(XFORM_CONVERTED);
1061         }
1062 
1063         if (!written) // 有効な子アニメーションなし
1064         {
1065             RestoreIgnoreFlags(transform, flagsBak);
1066             return NULL;
1067         }
1068 
1069         //----------------------------------------------------------
1070         // ブレンド後の処理があれば実行
1071         if (!convertedBak && blendOp->HasPostBlend())
1072         {
1073             if (!blendOp->PostBlend(reinterpret_cast<anim::AnimResult*>(transform), NULL))
1074             {
1075                 // ブレンド結果の回転行列の行がゼロベクトルなら
1076                 // 最初のアニメーションの回転行列を採用します。
1077                 // 結果が品質上問題となる場合は
1078                 // 元データを微妙にずらして回避する必要があります。
1079                 AdjustZeroRotateMatrix(transform, !firstRotateFlag, firstRotateMtx);
1080             }
1081         }
1082 #if 1
1083         // 計測したところ、こちらの方が速い。
1084         transform->UpdateScaleFlags();
1085         transform->UpdateRotateFlags();
1086         transform->UpdateTranslateFlags();
1087         transform->UpdateCompositeFlags();
1088 #else
1089         transform->UpdateFlags();
1090 #endif
1091     }
1092     else
1093     {
1094         bool isValidAnim = false;
1095         for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
1096         {
1097             if (m_AnimObjects[animIdx] && m_AnimObjects[animIdx]->HasMemberAnim(memberIdx))
1098             {
1099                 isValidAnim = true;
1100                 break;
1101             }
1102         }
1103 
1104         // 有効な子アニメーションが存在しない場合は
1105         // target を変更せずに NULL を返す
1106         if (!isValidAnim)
1107         {
1108             return NULL;
1109         }
1110 
1111         // アニメーション重みの正規化を必要なら行います。
1112         if (m_IsWeightDirty && m_IsWeightNormalizationEnabled)
1113         {
1114             NormalizeWeight();
1115         }
1116 
1117         //----------------------------------------------------------
1118         // 補間は操作空間があればそこで行われるべきなので
1119         // target の CONVERTED フラグを退避してからオンに
1120         CalculatedTransform* transform =
1121             reinterpret_cast<CalculatedTransform*>(target);
1122         const bit32 flagsBak = transform->GetFlags();
1123         const bool convertedBak = transform->IsEnabledFlags(XFORM_CONVERTED);
1124         transform->EnableFlags(XFORM_CONVERTED);
1125 
1126         //----------------------------------------------------------
1127         // target の IGNORE フラグをオンにして未書き込み状態とする
1128         transform->EnableFlags(XFORM_IGNORE_SRT);
1129 
1130         //----------------------------------------------------------
1131         // すべての子アニメーションについてループ
1132         CalculatedTransform workResult;
1133         bool firstRotateFlag = true;
1134         math::MTX34 firstRotateMtx;
1135         for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1136         {
1137             const AnimObject* animObj = m_AnimObjects[animIdx];
1138 
1139             const float childWeight = m_NormalizedWeights[animIdx];
1140             NW_ASSERT(childWeight >= 0.0f);
1141             const float srcWeights[3] =
1142             {
1143                 childWeight,
1144                 childWeight,
1145                 childWeight
1146             };
1147 
1148             if (!CheckWeightsNearyZero(srcWeights))
1149             {
1150                 // 退避した CONVERTED フラグを work に反映
1151                 // 子が CONVERTED を扱う Blender であれば CONVERTED なままの結果が返ってくることを期待
1152                 // 子が Evaluator の場合はフラグがオフで返ってくるが blendOp 内で変換されるので問題ない
1153                 workResult.EnableFlags(XFORM_CONVERTED, convertedBak);
1154 
1155                 // 評価
1156                 const anim::AnimResult* childResult = NULL;
1157                 if (animObj != NULL)
1158                 {
1159                     childResult = animObj->GetResult(&workResult, memberIdx);
1160                 }
1161 
1162                 if (childResult == NULL)
1163                 {
1164                     const math::Transform3* originalValue =
1165                         static_cast<const math::Transform3*>(GetAnimGroup()->GetOriginalValue(memberIdx));
1166                     workResult.SetTransform(*originalValue);
1167                     workResult.UpdateScaleFlags();
1168                     workResult.UpdateRotateFlags();
1169                     workResult.UpdateTranslateFlags();
1170                     workResult.UpdateCompositeFlags();
1171                     childResult = reinterpret_cast<anim::AnimResult*>(&workResult);
1172                 }
1173 
1174                 const bool evaluatorFlag =
1175                     ut::DynamicCast<const TransformAnimEvaluator*>(animObj) != NULL;
1176 
1177                 // ブレンド結果の回転行列の行がゼロベクトルになった場合のために
1178                 // 最初のアニメーションの回転行列を保存しておく
1179                 if (evaluatorFlag && firstRotateFlag &&
1180                     !workResult.IsEnabledFlags(XFORM_IGNORE_R))
1181                 {
1182                     firstRotateFlag = false;
1183                     firstRotateMtx = workResult.TransformMatrix();
1184                 }
1185 
1186                 // ブレンド
1187                 if (!blendOp->Blend(reinterpret_cast<anim::AnimResult*>(transform),
1188                     NULL, childResult, srcWeights))
1189                 {
1190                     break;
1191                 }
1192             }
1193         }
1194 
1195         //----------------------------------------------------------
1196         // target の CONVERTED フラグを復元
1197         if (!convertedBak)
1198         {
1199             transform->DisableFlags(XFORM_CONVERTED);
1200         }
1201 
1202         //----------------------------------------------------------
1203         // ブレンド後の処理があれば実行
1204         if (!convertedBak && blendOp->HasPostBlend())
1205         {
1206             if (!blendOp->PostBlend(reinterpret_cast<anim::AnimResult*>(transform), NULL))
1207             {
1208                 // ブレンド結果の回転行列の行がゼロベクトルなら
1209                 // 最初のアニメーションの回転行列を採用します。
1210                 // 結果が品質上問題となる場合は
1211                 // 元データを微妙にずらして回避する必要があります。
1212                 AdjustZeroRotateMatrix(transform, !firstRotateFlag, firstRotateMtx);
1213             }
1214         }
1215 #if 0
1216         transform->UpdateScaleFlags();
1217         transform->UpdateRotateFlagsUnsafe();
1218         transform->UpdateTranslateFlags();
1219         transform->UpdateCompositeFlags();
1220 #else
1221         // 計測したところ、こちらの方が速い。
1222         transform->UpdateFlags();
1223 #endif
1224     }
1225 
1226     // target を AnimResult にキャストして返す(親のブレンダで使用)
1227     return reinterpret_cast<anim::AnimResult*>(target);
1228 }
1229 
1230 //----------------------------------------------------------
1231 const anim::AnimResult*
GetResult(void * target,int memberIdx) const1232 TransformAnimAdder::GetResult(
1233     void* target,
1234     int memberIdx
1235 ) const
1236 {
1237     //----------------------------------------------------------
1238     // ブレンドオペレーションを取得
1239     const anim::AnimBlendOp* blendOp = m_AnimGroup->GetBlendOperation(memberIdx);
1240 
1241     //----------------------------------------------------------
1242     // 補間は操作空間があればそこで行われるべきなので
1243     // target の CONVERTED フラグを退避してからオンに
1244     CalculatedTransform* transform =
1245         reinterpret_cast<CalculatedTransform*>(target);
1246     const bit32 flagsBak = transform->GetFlags();
1247     const bool convertedBak = transform->IsEnabledFlags(XFORM_CONVERTED);
1248     transform->EnableFlags(XFORM_CONVERTED);
1249 
1250     //----------------------------------------------------------
1251     // target の IGNORE フラグをオンにして未書き込み状態とする
1252     transform->EnableFlags(XFORM_IGNORE_SRT);
1253 
1254     //----------------------------------------------------------
1255     // すべての子アニメーションについてループ
1256     CalculatedTransform workResult;
1257     bool written = false;
1258     bool firstRotateFlag = true;
1259     math::MTX34 firstRotateMtx;
1260     //for (int animIdx = 0; animIdx < m_AnimObjects.Size(); ++animIdx)
1261     for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1262     {
1263         const AnimObject* animObj = m_AnimObjects[animIdx];
1264         if (animObj == NULL)
1265         {
1266             continue;
1267         }
1268 
1269         const float childWeight = m_Weights[animIdx];
1270         float srcWeights[3] = { childWeight, childWeight, childWeight };
1271         DisableSRTWeightsIfNeeded(srcWeights, animObj);
1272 
1273         if (!CheckWeightsNearyZero(srcWeights))
1274         {
1275             // 退避した CONVERTED フラグを work に反映
1276             // 子が CONVERTED を扱う Blender であれば CONVERTED なままの結果が返ってくることを期待
1277             // 子が Evaluator の場合はフラグがオフで返ってくるが blendOp 内で変換されるので問題ない
1278             workResult.EnableFlags(XFORM_CONVERTED, convertedBak);
1279 
1280             // 評価
1281             const anim::AnimResult* childResult =
1282                 animObj->GetResult(&workResult, memberIdx);
1283             if (childResult != NULL)
1284             {
1285                 written = true;
1286                 const bool evaluatorFlag =
1287                     ut::DynamicCast<const TransformAnimEvaluator*>(animObj) != NULL;
1288 
1289                 // ブレンド結果の回転行列の行がゼロベクトルになった場合のために
1290                 // 最初のアニメーションの回転行列を保存しておく
1291                 if (evaluatorFlag && firstRotateFlag &&
1292                     !workResult.IsEnabledFlags(XFORM_IGNORE_R))
1293                 {
1294                     firstRotateFlag = false;
1295                     firstRotateMtx = workResult.TransformMatrix();
1296                 }
1297 
1298                 // ブレンド
1299                 if (!blendOp->Blend(reinterpret_cast<anim::AnimResult*>(transform),
1300                     NULL, childResult, srcWeights))
1301                 {
1302                     break;
1303                 }
1304             }
1305         }
1306     }
1307 
1308     //----------------------------------------------------------
1309     // target の CONVERTED フラグを復元
1310     if (!convertedBak)
1311     {
1312         transform->DisableFlags(XFORM_CONVERTED);
1313     }
1314 
1315     if (!written) // 有効な子アニメーションなし
1316     {
1317         RestoreIgnoreFlags(transform, flagsBak);
1318         return NULL;
1319     }
1320 
1321     //----------------------------------------------------------
1322     // ブレンド後の処理があれば実行
1323     if (!convertedBak && blendOp->HasPostBlend())
1324     {
1325         if (!blendOp->PostBlend(reinterpret_cast<anim::AnimResult*>(transform), NULL))
1326         {
1327             // ブレンド結果の回転行列の行がゼロベクトルなら
1328             // 最初のアニメーションの回転行列を採用します。
1329             // 結果が品質上問題となる場合は
1330             // 元データを微妙にずらして回避する必要があります。
1331             AdjustZeroRotateMatrix(transform, !firstRotateFlag, firstRotateMtx);
1332         }
1333     }
1334     transform->UpdateScaleFlags();
1335     transform->UpdateRotateFlags();
1336     transform->UpdateTranslateFlags();
1337     transform->UpdateCompositeFlags();
1338 
1339     // target を AnimResult にキャストして返す(親のブレンダで使用)
1340     return reinterpret_cast<anim::AnimResult*>(target);
1341 }
1342 
1343 //----------------------------------------------------------
1344 const anim::AnimResult*
GetResult(void * target,int memberIdx) const1345 TransformAnimOverrider::GetResult(
1346     void* target,
1347     int memberIdx
1348 ) const
1349 {
1350     //----------------------------------------------------------
1351     // ブレンドオペレーションを取得
1352     const anim::AnimBlendOp* blendOp = m_AnimGroup->GetBlendOperation(memberIdx);
1353 
1354     //----------------------------------------------------------
1355     // target の IGNORE フラグをオンにして未書き込み状態とする
1356     CalculatedTransform* transform =
1357         reinterpret_cast<CalculatedTransform*>(target);
1358     const bit32 flagsBak = transform->GetFlags();
1359     transform->EnableFlags(XFORM_IGNORE_SRT);
1360 
1361     //----------------------------------------------------------
1362     // すべての子アニメーションについてループ
1363     CalculatedTransform workResult;
1364     bool written = false;
1365     for (int animIdx = m_AnimObjects.Size() - 1; animIdx >= 0; --animIdx)
1366     {
1367         const AnimObject* animObj = m_AnimObjects[animIdx];
1368         if (animObj == NULL)
1369         {
1370             continue;
1371         }
1372 
1373         float srcWeights[3] = { 1.0f, 1.0f, 1.0f };
1374         DisableSRTWeightsIfNeeded(srcWeights, animObj);
1375 
1376         if (!CheckWeightsNearyZero(srcWeights))
1377         {
1378             // 評価
1379             const anim::AnimResult* childResult =
1380                 animObj->GetResult(&workResult, memberIdx);
1381             if (childResult != NULL)
1382             {
1383                 written = true;
1384                 if (blendOp->Override(reinterpret_cast<anim::AnimResult*>(transform),
1385                     childResult)) // 全成分を上書きしたら true が返る
1386                 {
1387                     break;
1388                 }
1389             }
1390         }
1391     }
1392 
1393     if (!written) // 有効な子アニメーションなし
1394     {
1395         RestoreIgnoreFlags(transform, flagsBak);
1396         return NULL;
1397     }
1398 
1399     transform->UpdateScaleFlags();
1400     transform->UpdateRotateFlags();
1401     transform->UpdateTranslateFlags();
1402     transform->UpdateCompositeFlags();
1403 
1404     // target を AnimResult にキャストして返す(親のブレンダで使用)
1405     return reinterpret_cast<anim::AnimResult*>(target);
1406 }
1407 
1408 } // namespace gfx
1409 } // namespace nw
1410