1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_TransformAnimBlendOp.cpp
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: 31311 $
16 *---------------------------------------------------------------------------*/
17
18 #include "precompiled.h"
19
20 #include <nw/gfx/gfx_TransformAnimBlendOp.h>
21
22 namespace nw
23 {
24 namespace gfx
25 {
26
27 //! トランスフォームアニメーションのブレンドオペレーションで使用する定数です。
28 const float TransformAnimBlendOp::WeightDiscard = -1.0f;
29
30 namespace {
31
32 /*!--------------------------------------------------------------------------*
33 @brief Vector3 の値をすべて Flog で変換します。
34 *---------------------------------------------------------------------------*/
35 void
FlogVector3(math::VEC3 * dst)36 FlogVector3(math::VEC3* dst)
37 {
38 dst->x = math::FLog(dst->x);
39 dst->y = math::FLog(dst->y);
40 dst->z = math::FLog(dst->z);
41 }
42
43 /*!--------------------------------------------------------------------------*
44 @brief Vector3 のブレンド処理を行います。
45
46 @param[in,out] dst ブレンド処理結果です。
47 @param[in] src ブレンド処理の入力です。
48 @param[in] weight ブレンド比率です。
49 @param[in] overrideFlag 値を上書き更新するかどうかのフラグです。
50 *---------------------------------------------------------------------------*/
51 void
BlendVector3(math::VEC3 * dst,const math::VEC3 * src,const float weight,const bool overrideFlag)52 BlendVector3(
53 math::VEC3* dst,
54 const math::VEC3* src,
55 const float weight,
56 const bool overrideFlag
57 )
58 {
59 if (overrideFlag)
60 {
61 VEC3Scale(dst, src, weight);
62 }
63 else
64 {
65 math::VEC3 tmp;
66 VEC3Scale(&tmp, src, weight);
67 VEC3Add(dst, dst, &tmp);
68 }
69 }
70
71 } // namespace
72
73 //----------------------------------------------------------
74 void
Apply(void * target,const anim::AnimResult * result) const75 TransformAnimBlendOp::Apply(void* target, const anim::AnimResult* result) const
76 {
77 *reinterpret_cast<CalculatedTransform*>(target) =
78 *reinterpret_cast<const CalculatedTransform*>(result->GetValueBuffer());
79 }
80
81 //----------------------------------------------------------
82 void
ConvertToAnimResult(anim::AnimResult * result,const void * source) const83 TransformAnimBlendOp::ConvertToAnimResult(
84 anim::AnimResult* result,
85 const void* source
86 ) const
87 {
88 *reinterpret_cast<CalculatedTransform*>(result->GetValueBuffer()) =
89 *reinterpret_cast<const CalculatedTransform*>(source);
90 }
91
92 //----------------------------------------------------------
93 void
BlendScaleStandard(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const94 TransformAnimBlendOp::BlendScaleStandard(
95 CalculatedTransform* dst,
96 const CalculatedTransform* src,
97 const float weight
98 ) const
99 {
100 if (weight != TransformAnimBlendOp::WeightDiscard)
101 {
102 // スケール値を直接ブレンド
103 BlendVector3(&dst->m_Scale, &src->Scale(),
104 weight, dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE));
105
106 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE);
107 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
108 }
109 }
110
111 //----------------------------------------------------------
112 void
BlendScaleAccurate(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const113 TransformAnimBlendOp::BlendScaleAccurate(
114 CalculatedTransform* dst,
115 const CalculatedTransform* src,
116 const float weight
117 ) const
118 {
119 if (weight != TransformAnimBlendOp::WeightDiscard)
120 {
121 // 正確なスケールブレンド
122 // s = Π(s(i)^weight) = exp(Σ(log(s(i)) * weight))
123 // exp の計算は最後に行う
124 math::VEC3 logScale = src->Scale();
125 FlogVector3(&logScale);
126 BlendVector3(&dst->m_Scale, &logScale,
127 weight, dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE));
128
129 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE);
130 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
131 }
132 }
133
134 //----------------------------------------------------------
135 bool
PostBlendAccurateScale(CalculatedTransform * transform) const136 TransformAnimBlendOp::PostBlendAccurateScale(CalculatedTransform* transform) const
137 {
138 math::VEC3& scale = transform->m_Scale;
139 scale.x = math::FExp(scale.x);
140 scale.y = math::FExp(scale.y);
141 scale.z = math::FExp(scale.z);
142 transform->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
143 return true;
144 }
145
146 //----------------------------------------------------------
147 void
BlendRotateMatrix(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const148 TransformAnimBlendOp::BlendRotateMatrix(
149 CalculatedTransform* dst,
150 const CalculatedTransform* src,
151 const float weight
152 ) const
153 {
154 if (weight != TransformAnimBlendOp::WeightDiscard)
155 {
156 math::MTX34& dstMtx = dst->m_TransformMatrix;
157 const math::MTX34& srcMtx = src->TransformMatrix();
158
159 if (dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE))
160 {
161 dstMtx.f._00 = srcMtx.f._00 * weight;
162 dstMtx.f._01 = srcMtx.f._01 * weight;
163 dstMtx.f._02 = srcMtx.f._02 * weight;
164
165 dstMtx.f._10 = srcMtx.f._10 * weight;
166 dstMtx.f._11 = srcMtx.f._11 * weight;
167 dstMtx.f._12 = srcMtx.f._12 * weight;
168
169 // ブレンド後の処理で回転行列を正規直交化するので、 2 行目の計算は不要
170 }
171 else
172 {
173 dstMtx.f._00 += srcMtx.f._00 * weight;
174 dstMtx.f._01 += srcMtx.f._01 * weight;
175 dstMtx.f._02 += srcMtx.f._02 * weight;
176
177 dstMtx.f._10 += srcMtx.f._10 * weight;
178 dstMtx.f._11 += srcMtx.f._11 * weight;
179 dstMtx.f._12 += srcMtx.f._12 * weight;
180
181 // ブレンド後の処理で回転行列を正規直交化するので、 2 行目の計算は不要
182 }
183
184 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE);
185 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
186 }
187 }
188
189 //----------------------------------------------------------
190 void
BlendRotateQuaternion(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const191 TransformAnimBlendOp::BlendRotateQuaternion(
192 CalculatedTransform* dst,
193 const CalculatedTransform* src,
194 const float weight
195 ) const
196 {
197 if (weight != TransformAnimBlendOp::WeightDiscard)
198 {
199 math::MTX34& dstMtx = dst->m_TransformMatrix;
200 const math::MTX34& srcMtx = src->TransformMatrix();
201
202 float& addedWeight = dstMtx.f._11;
203 math::QUAT srcQ;
204 if (src->IsEnabledFlags(CalculatedTransform::FLAG_CONVERTED_FOR_BLEND))
205 {
206 srcQ = math::QUAT(srcMtx.f._00, srcMtx.f._01, srcMtx.f._02, srcMtx.f._10);
207 }
208 else
209 {
210 math::MTX34ToQUAT(&srcQ, &srcMtx);
211 }
212 math::QUAT dstQ;
213 if (dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE))
214 {
215 addedWeight = weight;
216 dstQ = srcQ;
217 }
218 else
219 {
220 dstQ = math::QUAT(dstMtx.f._00, dstMtx.f._01, dstMtx.f._02, dstMtx.f._10);
221 addedWeight += weight;
222 const float t = (addedWeight != 0.0f) ? weight / addedWeight : 0.0f;
223 math::QUATSlerp(&dstQ, &dstQ, &srcQ, t);
224 }
225 dstMtx.f._00 = dstQ.x;
226 dstMtx.f._01 = dstQ.y;
227 dstMtx.f._02 = dstQ.z;
228 dstMtx.f._10 = dstQ.w;
229
230 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE);
231 dst->SetTransformMatrix(dstMtx);
232 }
233 }
234
235 //----------------------------------------------------------
236 void
BlendTranslate(CalculatedTransform * dst,const CalculatedTransform * src,const float weight) const237 TransformAnimBlendOp::BlendTranslate(
238 CalculatedTransform* dst,
239 const CalculatedTransform* src,
240 const float weight
241 ) const
242 {
243 if (weight != TransformAnimBlendOp::WeightDiscard)
244 {
245 const math::MTX34& dstMtx = dst->TransformMatrix();
246 const math::MTX34& srcMtx = src->TransformMatrix();
247
248 math::VEC3 srcT(srcMtx.f._03, srcMtx.f._13, srcMtx.f._23);
249 if (dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_TRANSLATE))
250 {
251 VEC3Scale(&srcT, &srcT, weight);
252 dst->SetTranslate(srcT);
253 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_TRANSLATE);
254 }
255 else
256 {
257 math::VEC3 dstT(dstMtx.f._03, dstMtx.f._13, dstMtx.f._23);
258 BlendVector3(&dstT, &srcT, weight, false);
259 dst->SetTranslate(dstT);
260 }
261 }
262 }
263
264 //----------------------------------------------------------
265 bool
OverrideTransform(CalculatedTransform * dst,const CalculatedTransform * src,const bit32 blendFlags) const266 TransformAnimBlendOp::OverrideTransform(
267 CalculatedTransform* dst,
268 const CalculatedTransform* src,
269 const bit32 blendFlags
270 ) const
271 {
272 const bool needToConverted =
273 dst->IsEnabledFlags(CalculatedTransform::FLAG_CONVERTED_FOR_BLEND) &&
274 !src->IsEnabledFlags(CalculatedTransform::FLAG_CONVERTED_FOR_BLEND);
275
276 math::MTX34 dstMtx = dst->TransformMatrix();
277 const math::MTX34& srcMtx = src->TransformMatrix();
278
279 if ( dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE) &&
280 !src->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE))
281 {
282 dst->SetScale(src->Scale());
283
284 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE);
285
286 if (needToConverted && (blendFlags & FLAG_ACCURATE_SCALE))
287 {
288 math::VEC3& dstScale = dst->m_Scale;
289 FlogVector3(&dstScale);
290 dst->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
291 }
292 }
293
294 if ( dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE) &&
295 !src->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE))
296 {
297 dstMtx.f._00 = srcMtx.f._00;
298 dstMtx.f._01 = srcMtx.f._01;
299 dstMtx.f._02 = srcMtx.f._02;
300
301 dstMtx.f._10 = srcMtx.f._10;
302 dstMtx.f._11 = srcMtx.f._11;
303 dstMtx.f._12 = srcMtx.f._12;
304
305 dstMtx.f._20 = srcMtx.f._20;
306 dstMtx.f._21 = srcMtx.f._21;
307 dstMtx.f._22 = srcMtx.f._22;
308
309 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE);
310
311 if (needToConverted && (blendFlags & FLAG_QUATERNION_ROTATE))
312 {
313 dst->RotateMatrixToQuaternion();
314 }
315 }
316
317 if ( dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_TRANSLATE) &&
318 !src->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_TRANSLATE))
319 {
320 dstMtx.f._03 = srcMtx.f._03;
321 dstMtx.f._13 = srcMtx.f._13;
322 dstMtx.f._23 = srcMtx.f._23;
323
324 dst->DisableFlags(CalculatedTransform::FLAG_IS_IGNORE_TRANSLATE);
325 }
326
327 dst->SetTransformMatrix(dstMtx);
328
329 return
330 !dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_SCALE) &&
331 !dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE) &&
332 !dst->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_TRANSLATE);
333 }
334
335 } // namespace gfx
336 } // namespace nw
337