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