1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_CalculatedTransform.h
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: 24862 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_GFX_CALCULATED_TRANSFORM_H_
17 #define NW_GFX_CALCULATED_TRANSFORM_H_
18 
19 #include <nw/ut/ut_Flag.h>
20 #include <nw/gfx/gfx_Common.h>
21 #include <nw/types.h>
22 #include <nw/assert.h>
23 #include <nw/gfx/res/gfx_ResSkeleton.h>
24 
25 namespace nw {
26 namespace gfx {
27 #define NN_MATH_USE_ANONYMOUS_STRUCT
28 
29 //---------------------------------------------------------------------------
30 //! @brief        計算済みトランスフォームを表すクラスです。
31 //---------------------------------------------------------------------------
32 class CalculatedTransform
33 {
34 public:
35     //----------------------------------------
36     //! @name 定数定義
37     //@{
38 
39     //! 変換情報についての付加情報ビットフラグの定義です。
40     enum Flag
41     {
42         // TODO: CreativeStudio側の、Graphics.Scenes.CalculatedTransform.csで定義されているフラグは、
43         //       ここで定義されているものと一致していることが期待されます。
44         //       ビットシフトがずれたりした場合は、両方とも同じように変更してください。
45 
46         //! @details :private
47         FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED_SHIFT           = 0,
48         //! @details :private
49         FLAG_IS_VALID_SHIFT                                     = 1,
50         //! @details :private
51         FLAG_IS_IGNORE_TRANSLATE_SHIFT                          = 2,
52         //! @details :private
53         FLAG_IS_IGNORE_SCALE_SHIFT                              = 3,
54         //! @details :private
55         FLAG_IS_IGNORE_ROTATE_SHIFT                             = 4,
56         //! @details :private
57         FLAG_IS_IDENTITY_SHIFT                                  = 5,
58         //! @details :private
59         FLAG_IS_ROTATE_TRANSLATE_ZERO_SHIFT                     = 6,
60         //! @details :private
61         FLAG_IS_ROTATE_ZERO_SHIFT                               = 7,
62         //! @details :private
63         FLAG_IS_TRANSLATE_ZERO_SHIFT                            = 8,
64         //! @details :private
65         FLAG_IS_SCALE_ONE_SHIFT                                 = 9,
66         //! @details :private
67         FLAG_IS_UNIFORM_SCALE_SHIFT                             = 10,
68         //! @details :private
69         FLAG_IS_DIRTY_SHIFT                                     = 11,
70         //! @details :private
71         FLAG_FORCE_VIEW_CALCULATION_ENABLED_SHIFT               = 12,
72         //! @details :private
73         FLAG_CONVERTED_FOR_BLEND_SHIFT                          = 30,
74 
75          //! ワールドマトリクスの計算処理を行うのであれば、1になります。
76         FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED             = 0x1 << FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED_SHIFT,
77         //! 有効な変換情報であれば、1になります。
78         FLAG_IS_VALID                                       = 0x1 << FLAG_IS_VALID_SHIFT,
79         //! 平行移動計算を無視できるのであれば、1になります。
80         FLAG_IS_IGNORE_TRANSLATE                            = 0x1 << FLAG_IS_IGNORE_TRANSLATE_SHIFT,
81         //! スケール計算を無視できるのであれば、1になります。
82         FLAG_IS_IGNORE_SCALE                                = 0x1 << FLAG_IS_IGNORE_SCALE_SHIFT,
83         //! 回転計算を無視できるのであれば、1になります。
84         FLAG_IS_IGNORE_ROTATE                               = 0x1 << FLAG_IS_IGNORE_ROTATE_SHIFT,
85         //! 正規化されていれば、1となります。
86         FLAG_IS_IDENTITY                                    = 0x1 << FLAG_IS_IDENTITY_SHIFT,
87         //! 回転と平行移動が0であれば、1となります。
88         FLAG_IS_ROTATE_TRANSLATE_ZERO                       = 0x1 << FLAG_IS_ROTATE_TRANSLATE_ZERO_SHIFT,
89         //! 回転が0であれば、1となります。
90         FLAG_IS_ROTATE_ZERO                                 = 0x1 << FLAG_IS_ROTATE_ZERO_SHIFT,
91         //! 平行移動が0であれば、1となります。
92         FLAG_IS_TRANSLATE_ZERO                              = 0x1 << FLAG_IS_TRANSLATE_ZERO_SHIFT,
93         //! スケール値全てが1であれば、1となります。
94         FLAG_IS_SCALE_ONE                                   = 0x1 << FLAG_IS_SCALE_ONE_SHIFT,
95         //! スケール値全てが均一であれば、1となります。
96         FLAG_IS_UNIFORM_SCALE                               = 0x1 << FLAG_IS_UNIFORM_SCALE_SHIFT,
97         //! 値が変更されれば、1となります。
98         FLAG_IS_DIRTY                                       = 0x1 << FLAG_IS_DIRTY_SHIFT,
99         //! 必ず UpdateView を計算するのであれば、1となります。
100         FLAG_FORCE_VIEW_CALCULATION_ENABLED                 = 0x1 << FLAG_FORCE_VIEW_CALCULATION_ENABLED_SHIFT,
101         //! アニメーションブレンド用の空間に変換されていれば、1になります。
102         FLAG_CONVERTED_FOR_BLEND                            = 0x1 << FLAG_CONVERTED_FOR_BLEND_SHIFT,
103 
104         //! ビットフラグの初期値です。
105         FLAG_DEFAULT = FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED | FLAG_IS_DIRTY
106     };
107 
108     //! @brief 単位行列を取得します。
Identity()109     static const CalculatedTransform& Identity()
110     {
111         static const CalculatedTransform identity(
112             FLAG_IS_WORLDMATRIX_CALCULATION_ENABLED |
113             FLAG_IS_IDENTITY |
114             FLAG_IS_ROTATE_TRANSLATE_ZERO |
115             FLAG_IS_ROTATE_ZERO |
116             FLAG_IS_TRANSLATE_ZERO |
117             FLAG_IS_SCALE_ONE |
118             FLAG_IS_UNIFORM_SCALE);
119 
120         return identity;
121     }
122 
123     //@}
124 
125 public:
126     //----------------------------------------
127     //! @name 作成
128     //@{
129 
130     //! コンストラクタです。
CalculatedTransform(bit32 flags)131     CalculatedTransform(bit32 flags)
132     : m_TransformMatrix(math::MTX34::Identity()),
133       m_Scale(1.0f, 1.0f, 1.0f),
134       m_Flags(flags)
135     {
136     }
137 
138     //! コンストラクタです。
CalculatedTransform()139     CalculatedTransform()
140     : m_TransformMatrix(math::MTX34::Identity()),
141       m_Scale(1.0f, 1.0f, 1.0f),
142       m_Flags(FLAG_DEFAULT)
143     {
144     }
145 
146     //! @brief コンストラクタです。
147     //!        内部で Setup を呼び出します。
148     //!
149     //! @param[in] resBone 初期化に用いるボーンです。
150     //!
CalculatedTransform(const ResBone bone)151     CalculatedTransform(const ResBone bone)
152     : m_Flags(FLAG_DEFAULT)
153     {
154         // m_TransformMatrix と m_Scale は Setup で設定されます。
155         Setup(bone);
156     }
157 
158     //! コピーコンストラクタです。
CalculatedTransform(const CalculatedTransform & transform)159     CalculatedTransform(const CalculatedTransform& transform)
160     : m_TransformMatrix(transform.m_TransformMatrix),
161       m_Scale(transform.m_Scale),
162       m_Flags(transform.m_Flags)
163     {
164     }
165 
166 
167     //! @brief リソースボーンから計算済みトランスフォームをセットアップします。
168     //!
169     //! @param[in] bone リソースボーンです。
170     //!
171     void Setup(const ResBone bone);
172 
173     //@}
174 
175     //----------------------------------------
176     //! @name 取得/設定
177     //@{
178 
179     //! @brief 座標変換を表す行列を取得します。
180     //!        更新をした場合、必ず Dirty フラグを設定してください。
DirectTransformMatrix()181     math::MTX34& DirectTransformMatrix() { return this->m_TransformMatrix; }
182 
183     //! @brief 座標変換を表す行列を取得します。
184     //!        自分のスケールは掛かっておらず、親のスケールは掛かっています
185     //!
186     //! @return トランスフォームのマトリクスです。
TransformMatrix()187     const math::MTX34& TransformMatrix() const { return this->m_TransformMatrix; }
188 
189     //! @brief 座標変換を表す行列を設定します。
190     //!        Dirty フラグを設定します。
SetTransformMatrix(const math::MTX34 & transformMatrix)191     void SetTransformMatrix(const math::MTX34& transformMatrix)
192     {
193         math::MTX34Copy(&this->m_TransformMatrix, transformMatrix);
194 
195         this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
196     }
197 
198     //! @brief 座標変換を表す行列を設定します。
199     //!        Dirty フラグを設定します。
SetTransformMatrix(f32 x00,f32 x01,f32 x02,f32 x03,f32 x10,f32 x11,f32 x12,f32 x13,f32 x20,f32 x21,f32 x22,f32 x23)200     void SetTransformMatrix(
201         f32 x00, f32 x01, f32 x02, f32 x03,
202         f32 x10, f32 x11, f32 x12, f32 x13,
203         f32 x20, f32 x21, f32 x22, f32 x23)
204     {
205         this->m_TransformMatrix.f._00 = x00;
206         this->m_TransformMatrix.f._10 = x10;
207         this->m_TransformMatrix.f._20 = x20;
208         this->m_TransformMatrix.f._01 = x01;
209         this->m_TransformMatrix.f._11 = x11;
210         this->m_TransformMatrix.f._21 = x21;
211         this->m_TransformMatrix.f._02 = x02;
212         this->m_TransformMatrix.f._12 = x12;
213         this->m_TransformMatrix.f._22 = x22;
214         this->m_TransformMatrix.f._03 = x03;
215         this->m_TransformMatrix.f._13 = x13;
216         this->m_TransformMatrix.f._23 = x23;
217 
218         this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
219     }
220 
221     //! @brief 回転行列を設定します。
222     //!        Dirty フラグを設定します。
223     template<typename TMatrix>
SetRotateMatrix(const TMatrix & rotateMatrix)224     void SetRotateMatrix(const TMatrix& rotateMatrix)
225     {
226         this->m_TransformMatrix.f._00 = rotateMatrix.f._00;
227         this->m_TransformMatrix.f._10 = rotateMatrix.f._10;
228         this->m_TransformMatrix.f._20 = rotateMatrix.f._20;
229         this->m_TransformMatrix.f._01 = rotateMatrix.f._01;
230         this->m_TransformMatrix.f._11 = rotateMatrix.f._11;
231         this->m_TransformMatrix.f._21 = rotateMatrix.f._21;
232         this->m_TransformMatrix.f._02 = rotateMatrix.f._02;
233         this->m_TransformMatrix.f._12 = rotateMatrix.f._12;
234         this->m_TransformMatrix.f._22 = rotateMatrix.f._22;
235 
236         this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
237     }
238 
239     //! @brief 回転行列を設定します。
240     //!        Dirty フラグを設定します。
SetRotateMatrix(f32 x00,f32 x01,f32 x02,f32 x10,f32 x11,f32 x12,f32 x20,f32 x21,f32 x22)241     void SetRotateMatrix(
242         f32 x00, f32 x01, f32 x02,
243         f32 x10, f32 x11, f32 x12,
244         f32 x20, f32 x21, f32 x22)
245     {
246         this->m_TransformMatrix.f._00 = x00;
247         this->m_TransformMatrix.f._10 = x10;
248         this->m_TransformMatrix.f._20 = x20;
249         this->m_TransformMatrix.f._01 = x01;
250         this->m_TransformMatrix.f._11 = x11;
251         this->m_TransformMatrix.f._21 = x21;
252         this->m_TransformMatrix.f._02 = x02;
253         this->m_TransformMatrix.f._12 = x12;
254         this->m_TransformMatrix.f._22 = x22;
255 
256         this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
257     }
258 
259     //! @brief スケーリング変換ベクトルを取得します。
260     //!        更新をした場合、必ず Dirty フラグを設定してください。
DirectScale()261     math::VEC3& DirectScale() { return m_Scale; }
262 
263     //! スケーリング変換ベクトルを取得します。
Scale()264     const math::VEC3& Scale() const { return m_Scale; }
265 
266     //! @brief スケーリング変換ベクトルを設定します。
267     //!        Dirty フラグを設定します。
SetScale(const math::VEC3 & scale)268     void SetScale(const math::VEC3& scale)
269     {
270         m_Scale = scale;
271 
272         this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
273     }
274 
275     //! @brief スケーリング変換ベクトルを設定します。
276     //!        Dirty フラグを設定します。
SetScale(f32 fx,f32 fy,f32 fz)277     void SetScale(f32 fx, f32 fy, f32 fz)
278     {
279         m_Scale.Set(fx, fy, fz);
280 
281         this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
282     }
283 
284     //! @brief 平行移動を設定します。
285     //!        Dirty フラグを設定します。
SetTranslate(f32 x,f32 y,f32 z)286     void SetTranslate(f32 x, f32 y, f32 z)
287     {
288         this->m_TransformMatrix.f._03 = x;
289         this->m_TransformMatrix.f._13 = y;
290         this->m_TransformMatrix.f._23 = z;
291 
292         this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
293     }
294 
295     //! @brief 平行移動を設定します。
296     //!        Dirty フラグを設定します。
SetTranslate(const math::VEC3 & translate)297     void SetTranslate(const math::VEC3& translate)
298     {
299         SetTranslate(translate.x, translate.y, translate.z);
300 
301         // SetTranslate 内で呼び出しているので不要
302         //this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
303     }
304 
305     //! @brief 平行移動を取得します。
GetTranslate(math::VEC3 * translate)306     void GetTranslate(math::VEC3* translate) const
307     {
308         NW_NULL_ASSERT(translate);
309         translate->x = this->m_TransformMatrix.f._03;
310         translate->y = this->m_TransformMatrix.f._13;
311         translate->z = this->m_TransformMatrix.f._23;
312     }
313 
314     //! @brief 平行移動を取得します。
GetTranslate()315     math::VEC3 GetTranslate() const
316     {
317         return math::VEC3(
318             this->m_TransformMatrix.f._03,
319             this->m_TransformMatrix.f._13,
320             this->m_TransformMatrix.f._23);
321     }
322 
323     //! @brief 回転を設定します。
324     //!        Dirty フラグを設定します。
SetRotateXYZ(f32 x,f32 y,f32 z)325     void SetRotateXYZ(f32 x, f32 y, f32 z)
326     {
327         math::VEC3 translate;
328         this->GetTranslate(&translate);
329         nw::math::MTX34RotXYZRad(&this->m_TransformMatrix,
330                                  x,
331                                  y,
332                                  z);
333         this->SetTranslate(translate);
334 
335         // SetTranslate 内で呼び出しているので不要
336         //this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
337     }
338 
339     //! @brief 回転と平行移動を設定します。
340     //!        回転順は XYZ となります。
341     //!        Dirty フラグを設定します。
SetRotateAndTranslate(const math::VEC3 & rotate,const math::VEC3 & translate)342     void SetRotateAndTranslate(const math::VEC3& rotate, const math::VEC3& translate)
343     {
344         nw::math::MTX34RotXYZRad(&this->m_TransformMatrix,
345                                  rotate.x,
346                                  rotate.y,
347                                  rotate.z);
348 
349         this->SetTranslate(translate);
350 
351         // SetTranslate 内で呼び出しているので不要
352         //this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
353     }
354 
355     //! @brief トランスフォームを設定します。
356     //!        Dirty フラグを設定します。
SetTransform(const math::Transform3 & transform)357     void SetTransform(const math::Transform3& transform)
358     {
359         this->m_Scale = transform.scale;
360         SetRotateAndTranslate(transform.rotate, transform.translate);
361 
362         // SetRotateAndTranslate 内で呼び出しているので不要
363         //this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
364     }
365 
366     //@}
367 
368     //----------------------------------------
369     //! @name ユーティリティ関数
370     //@{
371 
372     //! @brief 行列の回転成分を正規直交化します。
373     //!        Dirty フラグを設定します。
374     //!
375     //! @return 正しく変換できれば true を返します。
376     //!
NormalizeRotateMatrix()377     bool NormalizeRotateMatrix()
378     {
379         const float s_VecSquareLenTol = 1.0e-6f;
380 
381         if (!this->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE))
382         {
383             // 回転行列を正規直交化します。
384 
385             // 回転行列の 3 行目を外積で計算
386             math::VEC3* v0 = reinterpret_cast<math::VEC3*>(&this->m_TransformMatrix.m[0]);
387             math::VEC3* v1 = reinterpret_cast<math::VEC3*>(&this->m_TransformMatrix.m[1]);
388             math::VEC3* v2 = reinterpret_cast<math::VEC3*>(&this->m_TransformMatrix.m[2]);
389 
390             (void)math::VEC3Cross(v2, v0, v1);
391 
392             float lengthSquareV0 = v0->LengthSquare();
393             float lengthSquareV2 = v2->LengthSquare();
394 
395             if (lengthSquareV0 < s_VecSquareLenTol ||
396                 lengthSquareV2 < s_VecSquareLenTol)
397             {
398                 // 回転軸がゼロベクトル
399                 return false;
400             }
401             else
402             {
403                 *v0 *= 1.0f / nn::math::FSqrt(lengthSquareV0);
404                 *v2 *= 1.0f / nn::math::FSqrt(lengthSquareV2);
405 
406                 (void)math::VEC3Cross(v1, v2, v0);
407             }
408 
409             this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
410         }
411         return true;
412     }
413 
414     //! @brief 行列の回転成分をクォータニオンに変換します。
415     //!        行列の 00, 01, 02, 10 成分にクォータニオンの x, y, z, w が格納されます。
416     //!        Dirty フラグを設定します。
417     //!
418     //! @return 正しく変換できれば true を返します。
419     //!
RotateMatrixToQuaternion()420     bool RotateMatrixToQuaternion()
421     {
422         if (!this->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE))
423         {
424             // 行列の回転成分をクォータニオンに変換します。
425             math::QUAT q;
426             math::MTX34ToQUAT(&q, &this->m_TransformMatrix);
427             this->m_TransformMatrix.f._00 = q.x;
428             this->m_TransformMatrix.f._01 = q.y;
429             this->m_TransformMatrix.f._02 = q.z;
430             this->m_TransformMatrix.f._10 = q.w;
431 
432             this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
433         }
434         return true;
435     }
436 
437     //! @brief クォータニオンを行列の回転成分に変換します。
438     //!        行列の 00, 01, 02, 10 成分をクォータニオンの x, y, z, w とみなします。
439     //!        Dirty フラグを設定します。
440     //!
441     //! @return 正しく変換できれば true を返します。
442     //!
QuaternionToRotateMatrix()443     bool QuaternionToRotateMatrix()
444     {
445         const float s_VecSquareLenTol = 1.0e-6f;
446 
447         if (!this->IsEnabledFlags(CalculatedTransform::FLAG_IS_IGNORE_ROTATE))
448         {
449             // クォータニオンを行列の回転成分に変換します。
450             math::VEC3 t = this->m_TransformMatrix.GetColumn(3);
451             math::QUAT q(this->m_TransformMatrix.f._00, this->m_TransformMatrix.f._01, this->m_TransformMatrix.f._02, this->m_TransformMatrix.f._10);
452             math::QUATToMTX34(&this->m_TransformMatrix, &q);
453             this->m_TransformMatrix.SetColumn(3, t); // 移動成分を復元
454 
455             math::VEC3* v0 = reinterpret_cast<math::VEC3*>(&this->m_TransformMatrix.m[0]);
456             math::VEC3* v1 = reinterpret_cast<math::VEC3*>(&this->m_TransformMatrix.m[1]);
457             math::VEC3* v2 = reinterpret_cast<math::VEC3*>(&this->m_TransformMatrix.m[2]);
458             if (math::VEC3SquareLen(v0) < s_VecSquareLenTol ||
459                 math::VEC3SquareLen(v1) < s_VecSquareLenTol ||
460                 math::VEC3SquareLen(v2) < s_VecSquareLenTol)
461             {
462                 // ブレンド結果の回転軸がゼロベクトル
463                 return false;
464             }
465 
466             this->EnableFlags(CalculatedTransform::FLAG_IS_DIRTY);
467         }
468         return true;
469     }
470 
471     //@}
472 
473     //----------------------------------------
474     //! @name フラグ取得/設定
475     //@{
476 
477     //! フラグの値を直接取得します。
GetFlags()478     bit32 GetFlags() const { return m_Flags; }
479 
480     //! フラグの値を直接設定します。
SetFlags(bit32 flags)481     void SetFlags(bit32 flags) { m_Flags = flags; }
482 
483     //! 任意のフラグが有効になっているか取得します。
IsEnabledFlags(bit32 flags)484     bool IsEnabledFlags(bit32 flags) const { return ut::CheckFlag(m_Flags, flags); }
485 
486     //! 任意のフラグのいずれかが有効になっているか取得します。
IsEnabledFlagsOr(bit32 flags)487     bool IsEnabledFlagsOr(bit32 flags) const { return ut::CheckFlagOr(m_Flags, flags); }
488 
489     //! 任意のフラグを有効に設定します。
EnableFlags(bit32 flags)490     void EnableFlags(bit32 flags) { m_Flags = ut::EnableFlag(m_Flags, flags); }
491 
492     //! 任意のフラグを無効に設定します。
DisableFlags(bit32 flags)493     void DisableFlags(bit32 flags) { m_Flags = ut::DisableFlag(m_Flags, flags);  }
494 
495     //! 任意のフラグの有効/無効を設定します。
EnableFlags(bit32 flags,bool enable)496     void EnableFlags(bit32 flags, bool enable)
497     {
498         if (enable)
499         {
500             EnableFlags(flags);
501         }
502         else
503         {
504             DisableFlags(flags);
505         }
506     }
507 
508     //! 全てのフラグを無効にします。
ResetFlags()509     void ResetFlags() { m_Flags = 0x0; }
510 
511     //! 全てのトランスフォームのフラグを無効にします。
ResetTransformFlags()512     void ResetTransformFlags()
513     {
514         m_Flags &=
515             (~(FLAG_IS_IDENTITY |
516             FLAG_IS_ROTATE_TRANSLATE_ZERO |
517             FLAG_IS_ROTATE_ZERO |
518             FLAG_IS_TRANSLATE_ZERO |
519             FLAG_IS_SCALE_ONE |
520             FLAG_IS_UNIFORM_SCALE));
521     }
522 
523     //! トランスフォーム情報から全てのフラグを更新します。
524     void UpdateFlags();
525 
526     //! トランスフォーム情報からスケールのフラグのみを更新します。
UpdateScaleFlags()527     void UpdateScaleFlags()
528     {
529         if (this->IsEnabledFlags(FLAG_IS_IGNORE_SCALE))
530         {
531             return;
532         }
533 
534         this->DisableFlags(FLAG_IS_UNIFORM_SCALE | FLAG_IS_SCALE_ONE);
535 
536         const math::VEC3& scale = this->m_Scale;
537         if (scale.x == scale.y && scale.x == scale.z)
538         {
539             this->EnableFlags(FLAG_IS_UNIFORM_SCALE);
540 
541             if (scale.x == 1.0f)
542             {
543                 this->EnableFlags(FLAG_IS_SCALE_ONE);
544             }
545         }
546     }
547 
548     //! トランスフォーム情報から回転のフラグのみを更新します。
549     void UpdateRotateFlags();
550 
551     //! トランスフォーム情報から平行移動のフラグのみを更新します。
552     void UpdateTranslateFlags();
553 
554     //! 各成分のフラグから行列全体のフラグを更新します。
555     void UpdateCompositeFlags();
556 
557     //@}
558 
559 private:
560     math::MTX34 m_TransformMatrix;
561     math::VEC3  m_Scale;
562     bit32 m_Flags;
563 
564     friend class WorldMatrixUpdater;
565     friend class TransformAnimEvaluator;
566     friend class TransformAnimBlendOp;
567 };
568 
569 } // gfx
570 } // nw
571 
572 #endif // NW_GFX_CALCULATED_TRANSFORM_H_
573