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