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