1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: gfx_TransformAnim.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: 28677 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NW_GFX_TRANSFORMANIM_H_ 17 #define NW_GFX_TRANSFORMANIM_H_ 18 19 #include <nw/gfx/gfx_AnimObject.h> 20 #include <nw/gfx/gfx_CalculatedTransform.h> 21 22 namespace nw { 23 namespace gfx { 24 25 //--------------------------------------------------------------------------- 26 //! @brief トランスフォームアニメーションのブレンドオペレーションの基底クラスです。 27 //--------------------------------------------------------------------------- 28 class TransformAnimBlendOp : public anim::AnimBlendOp 29 { 30 public: 31 //! 無効な重み値です。 32 //! 33 //! :private 34 static const float WeightDiscard; 35 36 //---------------------------------------- 37 //! @name コンストラクタ/デストラクタ 38 //@{ 39 40 //! @brief コンストラクタです。 41 //! 42 //! @param[in] hasBlend ブレンド処理があるかどうかです。 43 //! @param[in] hasPostBlend ブレンド後の処理があるかどうかです。 44 //! TransformAnimBlendOp(bool hasBlend,bool hasPostBlend)45 TransformAnimBlendOp(bool hasBlend, bool hasPostBlend) 46 : AnimBlendOp(hasBlend, hasPostBlend) {} 47 48 //! デストラクタです。 ~TransformAnimBlendOp()49 virtual ~TransformAnimBlendOp() {} 50 51 //@} 52 53 54 //---------------------------------------- 55 //! @name 適用 56 //@{ 57 58 //! @brief ブレンド処理結果を対象に適用します。 59 //! 60 //! @param[out] target ブレンド処理結果を適用する対象です。 61 //! @param[in] result ブレンド処理結果です。 62 //! 63 virtual void Apply(void* target, const anim::AnimResult* result) const; 64 65 //! @brief 対象を AnimResult に変換します。 66 //! 67 //! @param[out] result 出力の AnimResult です。 68 //! @param[in] source 変換元へのポインタです。 69 //! 70 //! :private 71 virtual void ConvertToAnimResult(anim::AnimResult* result, const void* source) const; 72 73 //@} 74 75 protected: 76 //---------------------------------------- 77 //! @name 基本ブレンド処理 78 //@{ 79 80 //! @details :private 81 enum BasicBlendFlags 82 { 83 FLAG_ACCURATE_SCALE_SHIFT = 0, 84 FLAG_QUATERNION_ROTATE_SHIFT = 1, 85 86 // 正確なスケールブレンドをするかどうかです。 87 FLAG_ACCURATE_SCALE = 0x1 << FLAG_ACCURATE_SCALE_SHIFT, 88 89 // クォータニオンで回転をブレンドするかどうかです。オフなら行列の回転成分をブレンドします。 90 FLAG_QUATERNION_ROTATE = 0x1 << FLAG_QUATERNION_ROTATE_SHIFT 91 }; 92 93 //! @brief 標準的なスケールのブレンド処理を行います。 94 //! 95 //! @param[in,out] dst ブレンド処理結果です。 96 //! @param[in] src ブレンド処理の入力です。 97 //! @param[in] weight ブレンド処理の入力の重みです。 98 //! 99 //! :private 100 void BlendScaleStandard( 101 CalculatedTransform* dst, 102 const CalculatedTransform* src, 103 const float weight) const; 104 105 //! @brief 正確なスケールのブレンド処理を行います。 106 //! 107 //! @param[in,out] dst ブレンド処理結果です。 108 //! @param[in] src ブレンド処理の入力です。 109 //! @param[in] weight ブレンド処理の入力の重みです。 110 //! 111 //! :private 112 void BlendScaleAccurate( 113 CalculatedTransform* dst, 114 const CalculatedTransform* src, 115 const float weight) const; 116 117 //! @brief 正確なスケールブレンドのブレンド後の処理を行います。 118 //! 119 //! :private 120 //! 121 //! @param[in,out] transform トランスフォームです。 122 //! 123 //! @return 正しく処理できれば true を返します。 124 bool PostBlendAccurateScale(CalculatedTransform* transform) const; 125 126 //! @brief 行列の回転のブレンド処理を行います。 127 //! 128 //! @param[in,out] dst ブレンド処理結果です。 129 //! @param[in] src ブレンド処理の入力です。 130 //! @param[in] weight ブレンド処理の入力の重みです。 131 //! 132 //! :private 133 void BlendRotateMatrix( 134 CalculatedTransform* dst, 135 const CalculatedTransform* src, 136 const float weight) const; 137 138 //! @brief クォータニオンの回転のブレンド処理を行います。 139 //! 140 //! @param[in,out] dst ブレンド処理結果です。 141 //! @param[in] src ブレンド処理の入力です。 142 //! @param[in] weight ブレンド処理の入力の重みです。 143 //! 144 //! :private 145 void BlendRotateQuaternion( 146 CalculatedTransform* dst, 147 const CalculatedTransform* src, 148 const float weight) const; 149 150 //! @brief 移動のブレンド処理を行います。 151 //! 152 //! @param[in,out] dst ブレンド処理結果です。 153 //! @param[in] src ブレンド処理の入力です。 154 //! @param[in] weight ブレンド処理の入力の重みです。 155 //! 156 //! :private 157 void BlendTranslate( 158 CalculatedTransform* dst, 159 const CalculatedTransform* src, 160 const float weight) const; 161 162 //! @brief トランスフォームの上書き処理を行います。 163 //! 164 //! :private 165 //! 166 //! @param[in,out] dst ブレンド処理結果です。 167 //! @param[in] src ブレンド処理の入力です。 168 //! @param[in] blendFlags ブレンド処理のフラグです。 169 //! 170 //! @return すべての成分が上書きされたら true を返します。 171 bool OverrideTransform( 172 CalculatedTransform* dst, 173 const CalculatedTransform* src, 174 const bit32 blendFlags 175 ) const; 176 177 //@} 178 }; 179 180 //--------------------------------------------------------------------------- 181 //! @brief トランスフォームアニメーションの標準的なブレンドオペレーションのクラスです。 182 //! 回転行列の各成分をブレンドした後に、正規直交化します。 183 //--------------------------------------------------------------------------- 184 class TransformAnimBlendOpStandard : public TransformAnimBlendOp 185 { 186 public: 187 //---------------------------------------- 188 //! @name コンストラクタ/デストラクタ 189 //@{ 190 191 //! コンストラクタです。 TransformAnimBlendOpStandard()192 TransformAnimBlendOpStandard() 193 : TransformAnimBlendOp(true, true) 194 {} 195 196 //! デストラクタです。 ~TransformAnimBlendOpStandard()197 virtual ~TransformAnimBlendOpStandard() {} 198 199 //@} 200 201 //---------------------------------------- 202 //! @name ブレンド 203 //@{ 204 205 //! @brief ブレンド処理を行います。 206 //! 207 //! @param[in,out] dst ブレンド処理結果です。 208 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 209 //! このブレンドオペレーションでは使用しません。 210 //! @param[in] src ブレンド処理の入力です。 211 //! @param[in] srcWeights ブレンド処理の入力の重みです。 212 //! 213 //! @return ブレンド処理のループを継続するなら true を返します。 214 //! Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)215 virtual bool Blend( 216 anim::AnimResult* dst, 217 float* dstWeights, 218 const anim::AnimResult* src, 219 const float* srcWeights) const 220 { 221 (void)dstWeights; 222 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 223 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 224 BlendScaleStandard(dstX, srcX, srcWeights[0]); 225 BlendRotateMatrix (dstX, srcX, srcWeights[1]); 226 BlendTranslate (dstX, srcX, srcWeights[2]); 227 return true; 228 } 229 230 //! @brief ブレンド後の処理を行います。 231 //! 232 //! @param[in,out] result ブレンド処理結果です。 233 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 234 //! このブレンドオペレーションでは使用しません。 235 //! 236 //! @return 成功すれば true を返します。 237 //! PostBlend(anim::AnimResult * result,const float * weights)238 virtual bool PostBlend(anim::AnimResult* result, const float* weights) const 239 { 240 (void)weights; 241 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result); 242 return dstX->NormalizeRotateMatrix(); 243 } 244 245 //! @brief 上書き処理を行います。 246 //! 247 //! @param[in,out] dst ブレンド処理結果です。 248 //! @param[in] src ブレンド処理の入力です。 249 //! 250 //! @return すべての成分が上書きされたら true を返します。 251 //! Override(anim::AnimResult * dst,const anim::AnimResult * src)252 virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const 253 { 254 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 255 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 256 return OverrideTransform(dstX, srcX, 0); 257 } 258 259 //@} 260 }; 261 262 //--------------------------------------------------------------------------- 263 //! @brief トランスフォームアニメーションの正確なスケールブレンドに対応したブレンドオペレーションのクラスです。 264 //--------------------------------------------------------------------------- 265 class TransformAnimBlendOpAccScale : public TransformAnimBlendOp 266 { 267 public: 268 //---------------------------------------- 269 //! @name コンストラクタ/デストラクタ 270 //@{ 271 272 //! コンストラクタです。 TransformAnimBlendOpAccScale()273 TransformAnimBlendOpAccScale() 274 : TransformAnimBlendOp(true, true) 275 {} 276 277 //! デストラクタです。 ~TransformAnimBlendOpAccScale()278 virtual ~TransformAnimBlendOpAccScale() {} 279 280 //@} 281 282 //---------------------------------------- 283 //! @name ブレンド 284 //@{ 285 286 //! @brief ブレンド処理を行います。 287 //! 288 //! @param[in,out] dst ブレンド処理結果です。 289 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 290 //! このブレンドオペレーションでは使用しません。 291 //! @param[in] src ブレンド処理の入力です。 292 //! @param[in] srcWeights ブレンド処理の入力の重みです。 293 //! 294 //! @return ブレンド処理のループを継続するなら true を返します。 295 //! Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)296 virtual bool Blend( 297 anim::AnimResult* dst, 298 float* dstWeights, 299 const anim::AnimResult* src, 300 const float* srcWeights) const 301 { 302 (void)dstWeights; 303 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 304 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 305 BlendScaleAccurate(dstX, srcX, srcWeights[0]); 306 BlendRotateMatrix (dstX, srcX, srcWeights[1]); 307 BlendTranslate (dstX, srcX, srcWeights[2]); 308 return true; 309 } 310 311 //! @brief ブレンド後の処理を行います。 312 //! 313 //! @param[in,out] result ブレンド処理結果です。 314 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 315 //! このブレンドオペレーションでは使用しません。 316 //! 317 //! @return 成功すれば true を返します。 318 //! PostBlend(anim::AnimResult * result,const float * weights)319 virtual bool PostBlend(anim::AnimResult* result, const float* weights) const 320 { 321 (void)weights; 322 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result); 323 const bool scaleRet = PostBlendAccurateScale(dstX); 324 return dstX->NormalizeRotateMatrix() && scaleRet; 325 } 326 327 //! @brief 上書き処理を行います。 328 //! 329 //! @param[in,out] dst ブレンド処理結果です。 330 //! @param[in] src ブレンド処理の入力です。 331 //! 332 //! @return すべての成分が上書きされたら true を返します。 333 //! Override(anim::AnimResult * dst,const anim::AnimResult * src)334 virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const 335 { 336 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 337 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 338 return OverrideTransform(dstX, srcX, FLAG_ACCURATE_SCALE); 339 } 340 341 //@} 342 }; 343 344 //--------------------------------------------------------------------------- 345 //! @brief トランスフォームアニメーションのクォータニオンによる回転ブレンドに対応したブレンドオペレーションのクラスです。 346 //--------------------------------------------------------------------------- 347 class TransformAnimBlendOpQuat : public TransformAnimBlendOp 348 { 349 public: 350 //---------------------------------------- 351 //! @name コンストラクタ/デストラクタ 352 //@{ 353 354 //! コンストラクタです。 TransformAnimBlendOpQuat()355 TransformAnimBlendOpQuat() 356 : TransformAnimBlendOp(true, true) 357 {} 358 359 //! デストラクタです。 ~TransformAnimBlendOpQuat()360 virtual ~TransformAnimBlendOpQuat() {} 361 362 //@} 363 364 //---------------------------------------- 365 //! @name ブレンド 366 //@{ 367 368 //! @brief ブレンド処理を行います。 369 //! 370 //! @param[in,out] dst ブレンド処理結果です。 371 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 372 //! このブレンドオペレーションでは使用しません。 373 //! @param[in] src ブレンド処理の入力です。 374 //! @param[in] srcWeights ブレンド処理の入力の重みです。 375 //! 376 //! @return ブレンド処理のループを継続するなら true を返します。 377 //! Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)378 virtual bool Blend( 379 anim::AnimResult* dst, 380 float* dstWeights, 381 const anim::AnimResult* src, 382 const float* srcWeights) const 383 { 384 (void)dstWeights; 385 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 386 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 387 BlendScaleStandard (dstX, srcX, srcWeights[0]); 388 BlendRotateQuaternion(dstX, srcX, srcWeights[1]); 389 BlendTranslate (dstX, srcX, srcWeights[2]); 390 return true; 391 } 392 393 //! @brief ブレンド後の処理を行います。 394 //! 395 //! @param[in,out] result ブレンド処理結果です。 396 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 397 //! このブレンドオペレーションでは使用しません。 398 //! 399 //! @return 成功すれば true を返します。 400 //! PostBlend(anim::AnimResult * result,const float * weights)401 virtual bool PostBlend(anim::AnimResult* result, const float* weights) const 402 { 403 (void)weights; 404 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result); 405 return dstX->QuaternionToRotateMatrix(); 406 } 407 408 //! @brief 上書き処理を行います。 409 //! 410 //! @param[in,out] dst ブレンド処理結果です。 411 //! @param[in] src ブレンド処理の入力です。 412 //! 413 //! @return すべての成分が上書きされたら true を返します。 414 //! Override(anim::AnimResult * dst,const anim::AnimResult * src)415 virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const 416 { 417 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 418 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 419 return OverrideTransform(dstX, srcX, FLAG_QUATERNION_ROTATE); 420 } 421 422 //@} 423 }; 424 425 //--------------------------------------------------------------------------- 426 //! @brief トランスフォームアニメーションの正確なスケールブレンドとクォータニオンによる回転ブレンドに対応したブレンドオペレーションのクラスです。 427 //--------------------------------------------------------------------------- 428 class TransformAnimBlendOpAccScaleQuat : public TransformAnimBlendOp 429 { 430 public: 431 //---------------------------------------- 432 //! @name コンストラクタ/デストラクタ 433 //@{ 434 435 //! コンストラクタです。 TransformAnimBlendOpAccScaleQuat()436 TransformAnimBlendOpAccScaleQuat() 437 : TransformAnimBlendOp(true, true) 438 {} 439 440 //! デストラクタです。 ~TransformAnimBlendOpAccScaleQuat()441 virtual ~TransformAnimBlendOpAccScaleQuat() {} 442 443 //@} 444 445 //---------------------------------------- 446 //! @name ブレンド 447 //@{ 448 449 //! @brief ブレンド処理を行います。 450 //! 451 //! @param[in,out] dst ブレンド処理結果です。 452 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 453 //! このブレンドオペレーションでは使用しません。 454 //! @param[in] src ブレンド処理の入力です。 455 //! @param[in] srcWeights ブレンド処理の入力の重みです。 456 //! 457 //! @return ブレンド処理のループを継続するなら true を返します。 458 //! Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)459 virtual bool Blend( 460 anim::AnimResult* dst, 461 float* dstWeights, 462 const anim::AnimResult* src, 463 const float* srcWeights) const 464 { 465 (void)dstWeights; 466 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 467 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 468 BlendScaleAccurate (dstX, srcX, srcWeights[0]); 469 BlendRotateQuaternion(dstX, srcX, srcWeights[1]); 470 BlendTranslate (dstX, srcX, srcWeights[2]); 471 return true; 472 } 473 474 //! @brief ブレンド後の処理を行います。 475 //! 476 //! @param[in,out] result ブレンド処理結果です。 477 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 478 //! このブレンドオペレーションでは使用しません。 479 //! 480 //! @return 成功すれば true を返します。 481 //! PostBlend(anim::AnimResult * result,const float * weights)482 virtual bool PostBlend(anim::AnimResult* result, const float* weights) const 483 { 484 (void)weights; 485 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result); 486 const bool scaleRet = PostBlendAccurateScale(dstX); 487 return dstX->QuaternionToRotateMatrix() && scaleRet; 488 } 489 490 //! @brief 上書き処理を行います。 491 //! 492 //! @param[in,out] dst ブレンド処理結果です。 493 //! @param[in] src ブレンド処理の入力です。 494 //! 495 //! @return すべての成分が上書きされたら true を返します。 496 //! Override(anim::AnimResult * dst,const anim::AnimResult * src)497 virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const 498 { 499 CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst); 500 const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src); 501 return OverrideTransform(dstX, srcX, FLAG_ACCURATE_SCALE | FLAG_QUATERNION_ROTATE); 502 } 503 504 //@} 505 }; 506 507 //--------------------------------------------------------------------------- 508 //! @brief トランスフォームアニメーションを評価するクラスです。 509 //! 510 //! アニメーションデータを保持し、ファンクションカーブの評価を行います。 511 //--------------------------------------------------------------------------- 512 class TransformAnimEvaluator : public BaseAnimEvaluator 513 { 514 public: 515 NW_UT_RUNTIME_TYPEINFO; 516 517 //---------------------------------------- 518 //! @name 作成 519 //@{ 520 521 //! トランスフォームアニメーション評価を構築するクラスです。 522 class Builder 523 { 524 public: 525 //! コンストラクタです。 Builder()526 Builder() 527 : m_AnimData(NULL), 528 m_MaxMembers(64), 529 m_MaxAnimMembers(64), 530 m_AllocCache(false) {} 531 532 //! アニメーションデータを設定します。 AnimData(const anim::ResAnim & animData)533 Builder& AnimData(const anim::ResAnim& animData) { m_AnimData = animData; return *this; } 534 535 //! @brief アニメーション対象メンバの最大数を設定します。 536 //! 537 //! TransformAnimEvaluator::Bind に渡す AnimGroup の AnimGroup::GetMemberCount の値を設定してください。 538 //! 複数の AnimGroup に Bind する場合は、最大値を設定してください。 MaxMembers(int maxMembers)539 Builder& MaxMembers(int maxMembers) 540 { 541 NW_ASSERT(maxMembers > 0); 542 m_MaxMembers = maxMembers; 543 return *this; 544 } 545 546 //! @brief 実際にアニメーションするメンバの最大数を設定します。 547 //! 548 //! AnimData() に渡す anim::res::ResAnim の anim::res::ResAnim::GetMemberAnimSetCount の値を設定してください。 549 //! TransformAnimEvaluator::ChangeAnim で複数の ResAnim を切り替える場合は、最大値を設定してください。 MaxAnimMembers(int maxAnimMembers)550 Builder& MaxAnimMembers(int maxAnimMembers) 551 { 552 NW_ASSERT(maxAnimMembers > 0); 553 m_MaxAnimMembers = maxAnimMembers; 554 return *this; 555 } 556 557 //! キャッシュバッファを確保してキャッシュを有効にするかどうかを設定します。 AllocCache(bool allocCache)558 Builder& AllocCache(bool allocCache) { m_AllocCache = allocCache; return *this; } 559 560 //! @brief 生成時に必要なメモリサイズを取得します。 561 //! 562 //! メモリサイズは Builder の設定によって変化します。 563 //! すべての設定が終わった後にこの関数を呼び出してください。 564 //! 565 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 566 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 567 { 568 os::MemorySizeCalculator size(alignment); 569 570 GetMemorySizeInternal(&size); 571 572 return size.GetSizeWithPadding(alignment); 573 } 574 575 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)576 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 577 { 578 os::MemorySizeCalculator& size = *pSize; 579 580 size += sizeof(TransformAnimEvaluator); 581 BaseAnimEvaluator::GetMemorySizeForInitialize(pSize, m_MaxMembers, m_MaxAnimMembers); 582 583 if (m_AllocCache) 584 { 585 size += sizeof(CalculatedTransform) * m_MaxAnimMembers; 586 } 587 } 588 589 //! @brief トランスフォームアニメーション評価を生成します。 590 //! 591 //! @param[in] allocator アロケータです。 592 //! 593 //! @return 生成されたトランスフォームアニメーション評価です。 594 //! Create(os::IAllocator * allocator)595 TransformAnimEvaluator* Create(os::IAllocator* allocator) 596 { 597 void* buf = allocator->Alloc(sizeof(TransformAnimEvaluator)); 598 599 if (buf == NULL) 600 { 601 return NULL; 602 } 603 604 TransformAnimEvaluator* evaluator = new(buf) TransformAnimEvaluator(allocator); 605 606 Result result = evaluator->Initialize(m_AnimData, m_MaxMembers, m_MaxAnimMembers, m_AllocCache); 607 NW_ASSERT(result.IsSuccess()); 608 609 return evaluator; 610 } 611 612 private: 613 anim::ResAnim m_AnimData; 614 int m_MaxMembers; 615 int m_MaxAnimMembers; 616 bool m_AllocCache; 617 }; 618 619 //@} 620 621 //---------------------------------------- 622 //! @name 基本操作 623 //@{ 624 625 //! @brief アニメーションを関連付けます。 626 //! 627 //! Bind() よりも詳細なバインド結果を得ることができます。 628 //! 629 //! アニメーションデータがあるボーンの、アニメーションカーブがないSRT要素に、 630 //! この時点でバインドポーズをコピーします。 631 //! そのため、この関数を呼び出した後からアニメーション評価を行うまでの間は 632 //! スケルトンの姿勢が正しくない状態になりますのでご注意ください。 633 //! 634 //! @param[in] animGroup アニメーショングループです。 635 //! 636 //! @return バインドの結果を返します。 637 //! 638 //! @sa Bind 639 //! @sa BindResult 640 virtual Result TryBind(AnimGroup* animGroup); 641 642 //! @brief アニメーションを変更します。 643 //! 644 //! 内部で Bind() を呼び出すため、スケルトンの姿勢が変化します。 645 //! 646 //! GetCacheBufferSizeNeeded() の値が変化しますので、 647 //! SetCacheBuffer() している場合はバッファの再設定が必要です。 648 //! 649 //! 内部で確保したキャッシュバッファは、自動的にサイズ変更されます。 650 //! 651 //! @sa Bind 652 //! @sa BaseAnimEvaluator::ChangeAnim 653 //! @param animData アニメーションデータです。 ChangeAnim(const nw::anim::ResAnim animData)654 virtual void ChangeAnim(const nw::anim::ResAnim animData) 655 { 656 // BaseAnimEvaluator::ChangeAnim()内でBind()が呼ばれ、 657 // そこでキャッシュを書き換えるので、キャッシュのResizeを先に行う 658 if (!m_IsCacheExternal && !m_CacheTransforms.Empty()) 659 { 660 m_CacheTransforms.Resize(animData.GetMemberAnimSetCount()); 661 } 662 663 BaseAnimEvaluator::ChangeAnim(animData); 664 } 665 666 //@} 667 668 //---------------------------------------- 669 //! @name 評価 670 //@{ 671 672 //! @brief メンバ単位でアニメーション結果を取得します。 673 //! 674 //! @param[out] target アニメーション結果を書き込む対象です。 675 //! @param[in] memberIdx メンバインデックスです。 676 //! 677 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 678 //! 679 virtual const anim::AnimResult* GetResult( 680 void* target, 681 int memberIdx) const; 682 683 //@} 684 685 //---------------------------------------- 686 //! @name 取得/設定 687 //@{ 688 689 //! スケールアニメを無効化しているかを取得します。 GetIsScaleDisabled()690 bool GetIsScaleDisabled() const { return m_IsScaleDisabled; } 691 692 //! スケールアニメを無効化しているかを設定します。 SetIsScaleDisabled(bool isDisabled)693 void SetIsScaleDisabled(bool isDisabled) { m_IsScaleDisabled = isDisabled; } 694 695 //! 回転アニメを無効化しているかを取得します。 GetIsRotateDisabled()696 bool GetIsRotateDisabled() const { return m_IsRotateDisabled; } 697 698 //! 回転アニメを無効化しているかを設定します。 SetIsRotateDisabled(bool isDisabled)699 void SetIsRotateDisabled(bool isDisabled) { m_IsRotateDisabled = isDisabled; } 700 701 //! 移動アニメを無効化しているかを取得します。 GetIsTranslateDisabled()702 bool GetIsTranslateDisabled() const { return m_IsTranslateDisabled; } 703 704 //! 移動アニメを無効化しているかを設定します。 SetIsTranslateDisabled(bool isDisabled)705 void SetIsTranslateDisabled(bool isDisabled) { m_IsTranslateDisabled = isDisabled; } 706 707 //! @brief メンバに関連付けられたアニメーションが存在するかどうかを取得します。 708 //! 709 //! @param[in] memberIdx メンバインデックスです。 710 //! 711 //! @return アニメーションが存在すれば true を返します。 712 //! HasMemberAnim(int memberIdx)713 virtual bool HasMemberAnim(int memberIdx) const 714 { 715 NW_MINMAXLT_ASSERT(memberIdx, 0, m_BindIndexTable.Size()); 716 if (m_AnimData.ptr() == NULL) 717 { 718 return (0 <= memberIdx && memberIdx < m_AnimGroup->GetMemberCount()); 719 } 720 else 721 { 722 return m_BindIndexTable[memberIdx] != NotFoundIndex; 723 } 724 } 725 726 //@} 727 728 //---------------------------------------- 729 //! @name キャッシュ 730 //@{ 731 732 //---------------------------------------------------------- 733 //! :private UpdateCacheNonVirtual()734 void UpdateCacheNonVirtual() 735 { 736 if (!m_CacheTransforms.Empty() && m_IsCacheDirty) 737 { 738 if (m_AnimData.ptr() != NULL) 739 { 740 for (int memberIdx = 0; memberIdx < m_AnimGroup->GetMemberCount(); ++memberIdx) 741 { 742 const int animIdx = m_BindIndexTable[memberIdx]; 743 if (animIdx != NotFoundIndex) 744 { 745 GetResult(&m_CacheTransforms[animIdx], memberIdx); 746 } 747 } 748 } 749 m_IsCacheDirty = false; 750 } 751 } 752 753 //! アニメーション評価結果の内部キャッシュが古ければ更新します。 UpdateCache()754 virtual void UpdateCache() { this->UpdateCacheNonVirtual(); } 755 756 //! キャッシュバッファに必要なサイズ(バイト数)を取得します。 GetCacheBufferSizeNeeded()757 virtual int GetCacheBufferSizeNeeded() const 758 { 759 return m_AnimData.GetMemberAnimSetCount() * sizeof(CalculatedTransform); 760 } 761 762 //! キャッシュバッファを取得します。 GetCacheBuffer()763 virtual const void* GetCacheBuffer() const { return m_CacheTransforms.Elements(); } 764 765 //! @brief キャッシュバッファを設定します。 766 //! この関数で指定したキャッシュバッファはデストラクタで開放されません。 767 //! 768 //! @param[in] buf キャッシュバッファ用のメモリの先頭アドレスです。 769 //! NULL の場合、キャッシュが無効になります。 770 //! @param[in] size キャッシュバッファのサイズ(バイト数)です。 771 //! SetCacheBuffer(void * buf,int size)772 virtual void SetCacheBuffer(void* buf, int size) 773 { 774 if (buf != NULL) 775 { 776 NW_ASSERT(size >= GetCacheBufferSizeNeeded()); 777 const int maxCalculatedTransforms = size / sizeof(CalculatedTransform); 778 m_CacheTransforms = ut::MoveArray<CalculatedTransform>(buf, maxCalculatedTransforms); 779 m_CacheTransforms.Resize(maxCalculatedTransforms); 780 m_IsCacheDirty = true; 781 m_IsCacheExternal = true; 782 } 783 else 784 { 785 m_CacheTransforms = ut::MoveArray<CalculatedTransform>(); 786 } 787 } 788 789 //@} 790 791 protected: 792 //---------------------------------------- 793 //! @name コンストラクタ/デストラクタ 794 //@{ 795 796 //! コンストラクタです。 797 //! 798 //! :private TransformAnimEvaluator(os::IAllocator * allocator)799 TransformAnimEvaluator( 800 os::IAllocator* allocator) 801 : BaseAnimEvaluator(allocator, ANIMTYPE_TRANSFORM_SIMPLE), 802 m_IsScaleDisabled(false), 803 m_IsRotateDisabled(false), 804 m_IsTranslateDisabled(false) 805 { 806 } 807 808 //! デストラクタです。 809 //! 810 //! :private ~TransformAnimEvaluator()811 virtual ~TransformAnimEvaluator() {} 812 813 //@} 814 815 //! @details :private Initialize(const anim::ResAnim & animData,const int maxMembers,const int maxAnimMembers,bool allocCache)816 virtual Result Initialize( 817 const anim::ResAnim& animData, 818 const int maxMembers, 819 const int maxAnimMembers, 820 bool allocCache) 821 { 822 Result result = BaseAnimEvaluator::Initialize(animData, maxMembers, maxAnimMembers); 823 NW_ENSURE_AND_RETURN(result); 824 825 if (allocCache) 826 { 827 void* memory = GetAllocator().Alloc(sizeof(CalculatedTransform) * maxAnimMembers); 828 if (memory == NULL) 829 { 830 result |= Result::MASK_FAIL_BIT; 831 } 832 NW_ENSURE_AND_RETURN(result); 833 834 m_CacheTransforms = ut::MoveArray<CalculatedTransform>(memory, maxAnimMembers, &GetAllocator()); 835 m_CacheTransforms.Resize(animData.GetMemberAnimSetCount()); 836 } 837 838 return result; 839 } 840 841 bool m_IsScaleDisabled; //!< @details :private 842 bool m_IsRotateDisabled; //!< @details :private 843 bool m_IsTranslateDisabled; //!< @details :private 844 845 ut::MoveArray<CalculatedTransform> m_CacheTransforms; //!< @details :private 846 847 private: 848 // アニメーションカーブが存在しないメンバを、OriginalValueで初期化します。 849 void ResetNoAnimMember(AnimGroup* animGroup, anim::ResAnim animData); 850 851 const anim::AnimResult* GetResultFast(void* target, int memberIdx) const; 852 const anim::AnimResult* GetResultCommon(void* target, int memberIdx, bool writeNoAnimMember) const; 853 854 // メンバアニメーションを評価します。 855 // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。 856 void EvaluateMemberAnim( 857 CalculatedTransform* result, 858 anim::ResTransformAnim transformAnim, 859 float frame, 860 const math::Transform3* originalTransform, 861 bool writeNoAnimMember) const; 862 863 // ベイク済みのメンバアニメーションを評価します。 864 // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。 865 void EvaluateMemberBakedAnim( 866 CalculatedTransform* result, 867 anim::ResBakedTransformAnim transformAnim, 868 float frame, 869 const math::Transform3* originalTransform, 870 bool writeNoAnimMember) const; 871 872 void UpdateFlagsCommon(CalculatedTransform* transform) const; 873 void UpdateFlags(CalculatedTransform* transform) const; 874 875 // CalculatedTransformのフラグを、Bakeされた情報をもとにして更新します。 876 void ApplyBakedFlags(CalculatedTransform* transform, bit32 flags) const; 877 878 friend class AnimBinding; 879 }; 880 881 //--------------------------------------------------------------------------- 882 //! @brief トランスフォームアニメーション評価結果を補間ブレンドするクラスです。 883 //! 884 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 885 //! 886 //! 動作の詳細は、 AnimInterpolator をご覧ください。 887 //--------------------------------------------------------------------------- 888 class TransformAnimInterpolator : public AnimInterpolator 889 { 890 public: 891 NW_UT_RUNTIME_TYPEINFO; 892 893 //---------------------------------------- 894 //! @name 作成 895 //@{ 896 897 //! @brief トランスフォームアニメーション補間を構築するクラスです。 898 //! 899 //! バージョン 1.0.1 以前の補間法に戻すためには、IsOldMethod か IgnoreNoAnimMember に true を指定してください。 900 //! 901 //! 1.0.1 以前の補間方法と現在の補間方法の違いの詳細については、アニメーションのドキュメント(高度な機能)を参照ください。 902 class Builder 903 { 904 public: 905 //! コンストラクタです。 Builder()906 Builder() 907 : m_MaxAnimObjects(2), 908 m_IgnoreNoAnimMember(false) {} 909 910 //! 最大アニメーションオブジェクト数を設定します。 MaxAnimObjects(int maxAnimObjects)911 Builder& MaxAnimObjects(int maxAnimObjects) 912 { 913 NW_ASSERT(maxAnimObjects > 0); 914 m_MaxAnimObjects = maxAnimObjects; 915 return *this; 916 } 917 918 //! @brief アニメーションが存在しないメンバを無視するかどうかを設定します。 919 //! 920 //! デフォルトでは、アニメーションが存在しないメンバはバインド時の値がブレンドされます。 921 //! IgnoreNoAnimMember に true を設定すると、 922 //! 重みの正規化がメンバ毎に行なわれ、アニメーションが存在しないメンバは重み 0 としてブレンドされます。 923 //! 924 //! この挙動は バージョン 1.0.1 以前の補間法と同じです。 925 //! IgnoreNoAnimMember(bool ignoreNoAnimMember)926 Builder& IgnoreNoAnimMember(bool ignoreNoAnimMember) { m_IgnoreNoAnimMember = ignoreNoAnimMember; return *this; } 927 928 //! @brief 生成時に必要なメモリサイズを取得します。 929 //! 930 //! メモリサイズは Builder の設定によって変化します。 931 //! すべての設定が終わった後にこの関数を呼び出してください。 932 //! 933 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 934 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 935 { 936 os::MemorySizeCalculator size(alignment); 937 938 GetMemorySizeInternal(&size); 939 940 return size.GetSizeWithPadding(alignment); 941 } 942 943 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)944 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 945 { 946 os::MemorySizeCalculator& size = *pSize; 947 948 size += sizeof(TransformAnimInterpolator); 949 TransformAnimInterpolator::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); 950 } 951 952 //! @brief トランスフォームアニメーション補間を生成します。 953 //! 954 //! @param[in] allocator アロケータです。 955 //! 956 //! @return 生成されたトランスフォームアニメーション補間です。 957 //! Create(os::IAllocator * allocator)958 TransformAnimInterpolator* Create(os::IAllocator* allocator) 959 { 960 void* buf = allocator->Alloc(sizeof(TransformAnimInterpolator)); 961 962 if (buf == NULL) 963 { 964 return NULL; 965 } 966 967 TransformAnimInterpolator* interpolator = new(buf) TransformAnimInterpolator(allocator); 968 969 Result result = interpolator->Initialize(m_MaxAnimObjects, m_IgnoreNoAnimMember); 970 NW_ASSERT(result.IsSuccess()); 971 972 return interpolator; 973 } 974 975 private: 976 int m_MaxAnimObjects; 977 bool m_IgnoreNoAnimMember; 978 }; 979 980 //@} 981 982 //---------------------------------------- 983 //! @name 評価 984 //@{ 985 986 //! @brief メンバ単位でアニメーション結果を取得します。 987 //! 988 //! @param[out] target アニメーション結果を書き込む対象です。 989 //! @param[in] memberIdx メンバインデックスです。 990 //! 991 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 992 //! 993 virtual const anim::AnimResult* GetResult( 994 void* target, 995 int memberIdx) const; 996 997 //@} 998 999 protected: 1000 //---------------------------------------- 1001 //! @name コンストラクタ/デストラクタ 1002 //@{ 1003 1004 //! コンストラクタです。 1005 //! 1006 //! :private TransformAnimInterpolator(os::IAllocator * allocator)1007 TransformAnimInterpolator( 1008 os::IAllocator* allocator) 1009 : AnimInterpolator(allocator) 1010 {} 1011 1012 //! デストラクタです。 1013 //! 1014 //! :private ~TransformAnimInterpolator()1015 virtual ~TransformAnimInterpolator() {} 1016 1017 //@} 1018 }; 1019 1020 //--------------------------------------------------------------------------- 1021 //! @details :private 1022 //! @brief トランスフォームアニメーション評価結果を加算ブレンドするクラスです。 1023 //! 1024 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 1025 //--------------------------------------------------------------------------- 1026 class TransformAnimAdder : public AnimAdder 1027 { 1028 public: 1029 NW_UT_RUNTIME_TYPEINFO; 1030 1031 //---------------------------------------- 1032 //! @name 作成 1033 //@{ 1034 1035 //! トランスフォームアニメーション加算を構築するクラスです。 1036 class Builder 1037 { 1038 public: 1039 //! コンストラクタです。 Builder()1040 Builder() 1041 : m_MaxAnimObjects(2) {} 1042 1043 //! 最大アニメーションオブジェクト数を設定します。 MaxAnimObjects(int maxAnimObjects)1044 Builder& MaxAnimObjects(int maxAnimObjects) 1045 { 1046 NW_ASSERT(maxAnimObjects > 0); 1047 m_MaxAnimObjects = maxAnimObjects; 1048 return *this; 1049 } 1050 1051 //! @brief 生成時に必要なメモリサイズを取得します。 1052 //! 1053 //! メモリサイズは Builder の設定によって変化します。 1054 //! すべての設定が終わった後にこの関数を呼び出してください。 1055 //! 1056 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 1057 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 1058 { 1059 os::MemorySizeCalculator size(alignment); 1060 1061 GetMemorySizeInternal(&size); 1062 1063 return size.GetSizeWithPadding(alignment); 1064 } 1065 1066 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1067 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 1068 { 1069 os::MemorySizeCalculator& size = *pSize; 1070 1071 size += sizeof(TransformAnimAdder); 1072 TransformAnimAdder::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); 1073 } 1074 1075 //! @brief トランスフォームアニメーション加算を生成します。 1076 //! 1077 //! @param[in] allocator アロケータです。 1078 //! 1079 //! @return 生成されたトランスフォームアニメーション加算です。 1080 //! Create(os::IAllocator * allocator)1081 TransformAnimAdder* Create(os::IAllocator* allocator) 1082 { 1083 void* buf = allocator->Alloc(sizeof(TransformAnimAdder)); 1084 1085 if (buf == NULL) 1086 { 1087 return NULL; 1088 } 1089 1090 TransformAnimAdder* adder = new(buf) TransformAnimAdder(allocator); 1091 1092 Result result = adder->Initialize(m_MaxAnimObjects); 1093 NW_ASSERT(result.IsSuccess()); 1094 1095 return adder; 1096 } 1097 1098 private: 1099 int m_MaxAnimObjects; 1100 }; 1101 1102 //@} 1103 1104 //---------------------------------------- 1105 //! @name 評価 1106 //@{ 1107 1108 //! @brief メンバ単位でアニメーション結果を取得します。 1109 //! 1110 //! @param[out] target アニメーション結果を書き込む対象です。 1111 //! @param[in] memberIdx メンバインデックスです。 1112 //! 1113 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 1114 //! 1115 virtual const anim::AnimResult* GetResult( 1116 void* target, 1117 int memberIdx) const; 1118 1119 //@} 1120 1121 protected: 1122 //---------------------------------------- 1123 //! @name コンストラクタ/デストラクタ 1124 //@{ 1125 1126 //! コンストラクタです。 TransformAnimAdder(os::IAllocator * allocator)1127 TransformAnimAdder( 1128 os::IAllocator* allocator) 1129 : AnimAdder(allocator) 1130 {} 1131 1132 //! デストラクタです。 ~TransformAnimAdder()1133 virtual ~TransformAnimAdder() {} 1134 1135 //@} 1136 }; 1137 1138 //--------------------------------------------------------------------------- 1139 //! @brief トランスフォームアニメーション評価結果を上書きブレンドするクラスです。 1140 //! 1141 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 1142 //! 1143 //! 動作の詳細は、 AnimOverrider をご覧ください。 1144 //--------------------------------------------------------------------------- 1145 class TransformAnimOverrider : public AnimOverrider 1146 { 1147 public: 1148 NW_UT_RUNTIME_TYPEINFO; 1149 1150 //---------------------------------------- 1151 //! @name 作成 1152 //@{ 1153 1154 //! トランスフォームアニメーション上書きを構築するクラスです。 1155 class Builder 1156 { 1157 public: 1158 //! コンストラクタです。 Builder()1159 Builder() 1160 : m_MaxAnimObjects(2) {} 1161 1162 //! 最大アニメーションオブジェクト数を設定します。 MaxAnimObjects(int maxAnimObjects)1163 Builder& MaxAnimObjects(int maxAnimObjects) 1164 { 1165 NW_ASSERT(maxAnimObjects > 0); 1166 m_MaxAnimObjects = maxAnimObjects; 1167 return *this; 1168 } 1169 1170 //! @brief 生成時に必要なメモリサイズを取得します。 1171 //! 1172 //! メモリサイズは Builder の設定によって変化します。 1173 //! すべての設定が終わった後にこの関数を呼び出してください。 1174 //! 1175 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 1176 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 1177 { 1178 os::MemorySizeCalculator size(alignment); 1179 1180 GetMemorySizeInternal(&size); 1181 1182 return size.GetSizeWithPadding(alignment); 1183 } 1184 1185 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1186 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 1187 { 1188 os::MemorySizeCalculator& size = *pSize; 1189 1190 size += sizeof(TransformAnimOverrider); 1191 TransformAnimOverrider::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); 1192 } 1193 1194 //! @brief トランスフォームアニメーション上書きを生成します。 1195 //! 1196 //! @param[in] allocator アロケータです。 1197 //! 1198 //! @return 生成されたトランスフォームアニメーション上書きです。 1199 //! Create(os::IAllocator * allocator)1200 TransformAnimOverrider* Create(os::IAllocator* allocator) 1201 { 1202 void* buf = allocator->Alloc(sizeof(TransformAnimOverrider)); 1203 1204 if (buf == NULL) 1205 { 1206 return NULL; 1207 } 1208 1209 TransformAnimOverrider* overrider = new(buf) TransformAnimOverrider(allocator); 1210 1211 Result result = overrider->Initialize(m_MaxAnimObjects); 1212 NW_ASSERT(result.IsSuccess()); 1213 1214 return overrider; 1215 } 1216 1217 private: 1218 int m_MaxAnimObjects; 1219 }; 1220 1221 //@} 1222 1223 //---------------------------------------- 1224 //! @name 評価 1225 //@{ 1226 1227 //! @brief メンバ単位でアニメーション結果を取得します。 1228 //! 1229 //! @param[out] target アニメーション結果を書き込む対象です。 1230 //! @param[in] memberIdx メンバインデックスです。 1231 //! 1232 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 1233 //! 1234 virtual const anim::AnimResult* GetResult( 1235 void* target, 1236 int memberIdx) const; 1237 1238 //@} 1239 1240 protected: 1241 //---------------------------------------- 1242 //! @name コンストラクタ/デストラクタ 1243 //@{ 1244 1245 //! コンストラクタです。 1246 //! 1247 //! :private TransformAnimOverrider(os::IAllocator * allocator)1248 TransformAnimOverrider( 1249 os::IAllocator* allocator) 1250 : AnimOverrider(allocator) 1251 {} 1252 1253 //! デストラクタです。 1254 //! 1255 //! :private ~TransformAnimOverrider()1256 virtual ~TransformAnimOverrider() {} 1257 1258 //@} 1259 }; 1260 1261 } // namespace gfx 1262 } // namespace nw 1263 1264 #endif // NW_GFX_TRANSFORMANIM_H_ 1265