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: 25986 $ 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 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 566 { 567 os::MemorySizeCalculator size(alignment); 568 569 GetMemorySizeInternal(&size); 570 571 return size.GetSizeWithPadding(alignment); 572 } 573 574 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)575 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 576 { 577 os::MemorySizeCalculator& size = *pSize; 578 579 size += sizeof(TransformAnimEvaluator); 580 BaseAnimEvaluator::GetMemorySizeForInitialize(pSize, m_MaxMembers, m_MaxAnimMembers); 581 582 if (m_AllocCache) 583 { 584 size += sizeof(CalculatedTransform) * m_MaxAnimMembers; 585 } 586 } 587 588 //! @brief トランスフォームアニメーション評価を生成します。 589 //! 590 //! @param[in] allocator アロケータです。 591 //! 592 //! @return 生成されたトランスフォームアニメーション評価です。 593 //! Create(os::IAllocator * allocator)594 TransformAnimEvaluator* Create(os::IAllocator* allocator) 595 { 596 void* buf = allocator->Alloc(sizeof(TransformAnimEvaluator)); 597 598 if (buf == NULL) 599 { 600 return NULL; 601 } 602 603 TransformAnimEvaluator* evaluator = new(buf) TransformAnimEvaluator(allocator); 604 605 Result result = evaluator->Initialize(m_AnimData, m_MaxMembers, m_MaxAnimMembers, m_AllocCache); 606 NW_ASSERT(result.IsSuccess()); 607 608 return evaluator; 609 } 610 611 private: 612 anim::ResAnim m_AnimData; 613 int m_MaxMembers; 614 int m_MaxAnimMembers; 615 bool m_AllocCache; 616 }; 617 618 //@} 619 620 //---------------------------------------- 621 //! @name 基本操作 622 //@{ 623 624 //! @brief アニメーションを関連付けます。 625 //! 626 //! Bind() よりも詳細なバインド結果を得ることができます。 627 //! 628 //! アニメーションデータがないメンバには、この時点でバインドポーズをコピーします。 629 //! そのため、この関数を呼び出した後からアニメーション評価を行うまでの間は 630 //! スケルトンの姿勢が正しくない状態になりますのでご注意ください。 631 //! 632 //! @param[in] animGroup アニメーショングループです。 633 //! 634 //! @return バインドの結果を返します。 635 //! 636 //! @sa Bind 637 //! @sa BindResult 638 virtual Result TryBind(AnimGroup* animGroup); 639 640 //! @brief アニメーションを変更します。 641 //! 642 //! 内部で Bind() を呼び出すため、スケルトンの姿勢が変化します。 643 //! 644 //! GetCacheBufferSizeNeeded() の値が変化しますので、 645 //! SetCacheBuffer() している場合はバッファの再設定が必要です。 646 //! 647 //! 内部で確保したキャッシュバッファは、自動的にサイズ変更されます。 648 //! 649 //! @sa Bind 650 //! @sa BaseAnimEvaluator::ChangeAnim 651 //! @param animData アニメーションデータです。 ChangeAnim(const nw::anim::ResAnim animData)652 virtual void ChangeAnim(const nw::anim::ResAnim animData) 653 { 654 // BaseAnimEvaluator::ChangeAnim()内でBind()が呼ばれ、 655 // そこでキャッシュを書き換えるので、キャッシュのResizeを先に行う 656 if (!m_IsCacheExternal && !m_CacheTransforms.Empty()) 657 { 658 m_CacheTransforms.Resize(animData.GetMemberAnimSetCount()); 659 } 660 661 BaseAnimEvaluator::ChangeAnim(animData); 662 } 663 664 //@} 665 666 //---------------------------------------- 667 //! @name 評価 668 //@{ 669 670 //! @brief メンバ単位でアニメーション結果を取得します。 671 //! 672 //! @param[out] target アニメーション結果を書き込む対象です。 673 //! @param[in] memberIdx メンバインデックスです。 674 //! 675 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 676 //! 677 virtual const anim::AnimResult* GetResult( 678 void* target, 679 int memberIdx) const; 680 681 //@} 682 683 //---------------------------------------- 684 //! @name 取得/設定 685 //@{ 686 687 //! スケールアニメを無効化しているかを取得します。 GetIsScaleDisabled()688 bool GetIsScaleDisabled() const { return m_IsScaleDisabled; } 689 690 //! スケールアニメを無効化しているかを設定します。 SetIsScaleDisabled(bool isDisabled)691 void SetIsScaleDisabled(bool isDisabled) { m_IsScaleDisabled = isDisabled; } 692 693 //! 回転アニメを無効化しているかを取得します。 GetIsRotateDisabled()694 bool GetIsRotateDisabled() const { return m_IsRotateDisabled; } 695 696 //! 回転アニメを無効化しているかを設定します。 SetIsRotateDisabled(bool isDisabled)697 void SetIsRotateDisabled(bool isDisabled) { m_IsRotateDisabled = isDisabled; } 698 699 //! 移動アニメを無効化しているかを取得します。 GetIsTranslateDisabled()700 bool GetIsTranslateDisabled() const { return m_IsTranslateDisabled; } 701 702 //! 移動アニメを無効化しているかを設定します。 SetIsTranslateDisabled(bool isDisabled)703 void SetIsTranslateDisabled(bool isDisabled) { m_IsTranslateDisabled = isDisabled; } 704 705 //! @brief メンバに関連付けられたアニメーションが存在するかどうかを取得します。 706 //! 707 //! @param[in] memberIdx メンバインデックスです。 708 //! 709 //! @return アニメーションが存在すれば true を返します。 710 //! HasMemberAnim(int memberIdx)711 virtual bool HasMemberAnim(int memberIdx) const 712 { 713 NW_MINMAXLT_ASSERT(memberIdx, 0, m_BindIndexTable.Size()); 714 if (m_AnimData.ptr() == NULL) 715 { 716 return (0 <= memberIdx && memberIdx < m_AnimGroup->GetMemberCount()); 717 } 718 else 719 { 720 return m_BindIndexTable[memberIdx] != NotFoundIndex; 721 } 722 } 723 724 //@} 725 726 //---------------------------------------- 727 //! @name キャッシュ 728 //@{ 729 730 //! アニメーション評価結果の内部キャッシュが古ければ更新します。 731 virtual void UpdateCache(); 732 733 //! キャッシュバッファに必要なサイズ(バイト数)を取得します。 GetCacheBufferSizeNeeded()734 virtual int GetCacheBufferSizeNeeded() const 735 { 736 return m_AnimData.GetMemberAnimSetCount() * sizeof(CalculatedTransform); 737 } 738 739 //! キャッシュバッファを取得します。 GetCacheBuffer()740 virtual const void* GetCacheBuffer() const { return m_CacheTransforms.Elements(); } 741 742 //! @brief キャッシュバッファを設定します。 743 //! この関数で指定したキャッシュバッファはデストラクタで開放されません。 744 //! 745 //! @param[in] buf キャッシュバッファ用のメモリの先頭アドレスです。 746 //! NULL の場合、キャッシュが無効になります。 747 //! @param[in] size キャッシュバッファのサイズ(バイト数)です。 748 //! SetCacheBuffer(void * buf,int size)749 virtual void SetCacheBuffer(void* buf, int size) 750 { 751 if (buf != NULL) 752 { 753 NW_ASSERT(size >= GetCacheBufferSizeNeeded()); 754 const int maxCalculatedTransforms = size / sizeof(CalculatedTransform); 755 m_CacheTransforms = ut::MoveArray<CalculatedTransform>(buf, maxCalculatedTransforms); 756 m_CacheTransforms.Resize(maxCalculatedTransforms); 757 m_IsCacheDirty = true; 758 m_IsCacheExternal = true; 759 } 760 else 761 { 762 m_CacheTransforms = ut::MoveArray<CalculatedTransform>(); 763 } 764 } 765 766 //@} 767 768 protected: 769 //---------------------------------------- 770 //! @name コンストラクタ/デストラクタ 771 //@{ 772 773 //! コンストラクタです。 774 //! 775 //! :private TransformAnimEvaluator(os::IAllocator * allocator)776 TransformAnimEvaluator( 777 os::IAllocator* allocator) 778 : BaseAnimEvaluator(allocator), 779 m_IsScaleDisabled(false), 780 m_IsRotateDisabled(false), 781 m_IsTranslateDisabled(false) 782 { 783 } 784 785 //! デストラクタです。 786 //! 787 //! :private ~TransformAnimEvaluator()788 virtual ~TransformAnimEvaluator() {} 789 790 //@} 791 792 //! @details :private Initialize(const anim::ResAnim & animData,const int maxMembers,const int maxAnimMembers,bool allocCache)793 virtual Result Initialize( 794 const anim::ResAnim& animData, 795 const int maxMembers, 796 const int maxAnimMembers, 797 bool allocCache) 798 { 799 Result result = BaseAnimEvaluator::Initialize(animData, maxMembers, maxAnimMembers); 800 NW_ENSURE_AND_RETURN(result); 801 802 if (allocCache) 803 { 804 void* memory = GetAllocator().Alloc(sizeof(CalculatedTransform) * maxAnimMembers); 805 if (memory == NULL) 806 { 807 result |= Result::MASK_FAIL_BIT; 808 } 809 NW_ENSURE_AND_RETURN(result); 810 811 m_CacheTransforms = ut::MoveArray<CalculatedTransform>(memory, maxAnimMembers, &GetAllocator()); 812 m_CacheTransforms.Resize(animData.GetMemberAnimSetCount()); 813 } 814 815 return result; 816 } 817 818 bool m_IsScaleDisabled; //!< @details :private 819 bool m_IsRotateDisabled; //!< @details :private 820 bool m_IsTranslateDisabled; //!< @details :private 821 822 ut::MoveArray<CalculatedTransform> m_CacheTransforms; //!< @details :private 823 824 private: 825 // アニメーションカーブが存在しないメンバを、OriginalValueで初期化します。 826 void ResetNoAnimMember(AnimGroup* animGroup, anim::ResAnim animData); 827 828 const anim::AnimResult* GetResultFast(void* target, int memberIdx) const; 829 const anim::AnimResult* GetResultCommon(void* target, int memberIdx, bool writeNoAnimMember) const; 830 831 // メンバアニメーションを評価します。 832 // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。 833 void EvaluateMemberAnim( 834 CalculatedTransform* result, 835 anim::ResTransformAnim transformAnim, 836 float frame, 837 const math::Transform3* originalTransform, 838 bool writeNoAnimMember) const; 839 840 // ベイク済みのメンバアニメーションを評価します。 841 // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。 842 void EvaluateMemberBakedAnim( 843 CalculatedTransform* result, 844 anim::ResBakedTransformAnim transformAnim, 845 float frame, 846 const math::Transform3* originalTransform, 847 bool writeNoAnimMember) const; 848 849 void UpdateFlagsCommon(CalculatedTransform* transform) const; 850 void UpdateFlags(CalculatedTransform* transform) const; 851 852 // CalculatedTransformのフラグを、Bakeされた情報をもとにして更新します。 853 void ApplyBakedFlags(CalculatedTransform* transform, bit32 flags) const; 854 855 friend class AnimBinding; 856 }; 857 858 //--------------------------------------------------------------------------- 859 //! @brief トランスフォームアニメーション評価結果を補間ブレンドするクラスです。 860 //! 861 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 862 //! 863 //! 動作の詳細は、 AnimInterpolator をご覧ください。 864 //--------------------------------------------------------------------------- 865 class TransformAnimInterpolator : public AnimInterpolator 866 { 867 public: 868 NW_UT_RUNTIME_TYPEINFO; 869 870 //---------------------------------------- 871 //! @name 作成 872 //@{ 873 874 //! @brief トランスフォームアニメーション補間を構築するクラスです。 875 //! 876 //! バージョン 1.0.1 以前の補間法に戻すためには、IsOldMethod か IgnoreNoAnimMember に true を指定してください。 877 //! 878 //! 1.0.1 以前の補間方法と現在の補間方法の違いの詳細については、アニメーションのドキュメント(高度な機能)を参照ください。 879 class Builder 880 { 881 public: 882 //! コンストラクタです。 Builder()883 Builder() 884 : m_MaxAnimObjects(2), 885 m_IgnoreNoAnimMember(false) {} 886 887 //! 最大アニメーションオブジェクト数を設定します。 MaxAnimObjects(int maxAnimObjects)888 Builder& MaxAnimObjects(int maxAnimObjects) 889 { 890 NW_ASSERT(maxAnimObjects > 0); 891 m_MaxAnimObjects = maxAnimObjects; 892 return *this; 893 } 894 895 //! @brief バージョン 1.0.1 以前の補間法に戻すかどうかを設定します。 896 //! 897 //! 1.0.1 以前の補間法は IgnoreNoAnimMember() に true を指定したときと同じであり、 898 //! この関数は IgnoreNoAnimMember() のエイリアスです。 899 //! 900 //! この設定はバージョン 1.3.0 以降で削除されます。 901 NW_DEPRECATED_FUNCTION_MSG( 902 Builder& IsOldMethod(bool isOldMethod), 903 "TransformAnimIntepolator::IsOldMethod() is deprecated. Use IgnoreNoAnimMember()") 904 { 905 return IgnoreNoAnimMember(isOldMethod); 906 } 907 908 //! @brief アニメーションが存在しないメンバを無視するかどうかを設定します。 909 //! 910 //! デフォルトでは、アニメーションが存在しないメンバはバインド時の値がブレンドされます。 911 //! IgnoreNoAnimMember に true を設定すると、 912 //! 重みの正規化がメンバ毎に行なわれ、アニメーションが存在しないメンバは重み 0 としてブレンドされます。 913 //! 914 //! この挙動は バージョン 1.0.1 以前の補間法と同じです。 915 //! IgnoreNoAnimMember(bool ignoreNoAnimMember)916 Builder& IgnoreNoAnimMember(bool ignoreNoAnimMember) { m_IgnoreNoAnimMember = ignoreNoAnimMember; return *this; } 917 918 //! @brief 生成時に必要なメモリサイズを取得します。 919 //! 920 //! メモリサイズは Builder の設定によって変化します。 921 //! すべての設定が終わった後にこの関数を呼び出してください。 922 //! 923 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 924 { 925 os::MemorySizeCalculator size(alignment); 926 927 GetMemorySizeInternal(&size); 928 929 return size.GetSizeWithPadding(alignment); 930 } 931 932 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)933 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 934 { 935 os::MemorySizeCalculator& size = *pSize; 936 937 size += sizeof(TransformAnimInterpolator); 938 TransformAnimInterpolator::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); 939 } 940 941 //! @brief トランスフォームアニメーション補間を生成します。 942 //! 943 //! @param[in] allocator アロケータです。 944 //! 945 //! @return 生成されたトランスフォームアニメーション補間です。 946 //! Create(os::IAllocator * allocator)947 TransformAnimInterpolator* Create(os::IAllocator* allocator) 948 { 949 void* buf = allocator->Alloc(sizeof(TransformAnimInterpolator)); 950 951 if (buf == NULL) 952 { 953 return NULL; 954 } 955 956 TransformAnimInterpolator* interpolator = new(buf) TransformAnimInterpolator(allocator); 957 958 Result result = interpolator->Initialize(m_MaxAnimObjects, m_IgnoreNoAnimMember); 959 NW_ASSERT(result.IsSuccess()); 960 961 return interpolator; 962 } 963 964 private: 965 int m_MaxAnimObjects; 966 bool m_IgnoreNoAnimMember; 967 }; 968 969 //@} 970 971 //---------------------------------------- 972 //! @name 評価 973 //@{ 974 975 //! @brief メンバ単位でアニメーション結果を取得します。 976 //! 977 //! @param[out] target アニメーション結果を書き込む対象です。 978 //! @param[in] memberIdx メンバインデックスです。 979 //! 980 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 981 //! 982 virtual const anim::AnimResult* GetResult( 983 void* target, 984 int memberIdx) const; 985 986 //@} 987 988 protected: 989 //---------------------------------------- 990 //! @name コンストラクタ/デストラクタ 991 //@{ 992 993 //! コンストラクタです。 994 //! 995 //! :private TransformAnimInterpolator(os::IAllocator * allocator)996 TransformAnimInterpolator( 997 os::IAllocator* allocator) 998 : AnimInterpolator(allocator) 999 {} 1000 1001 //! デストラクタです。 1002 //! 1003 //! :private ~TransformAnimInterpolator()1004 virtual ~TransformAnimInterpolator() {} 1005 1006 //@} 1007 }; 1008 1009 //--------------------------------------------------------------------------- 1010 //! @details :private 1011 //! @brief トランスフォームアニメーション評価結果を加算ブレンドするクラスです。 1012 //! 1013 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 1014 //--------------------------------------------------------------------------- 1015 class TransformAnimAdder : public AnimAdder 1016 { 1017 public: 1018 NW_UT_RUNTIME_TYPEINFO; 1019 1020 //---------------------------------------- 1021 //! @name 作成 1022 //@{ 1023 1024 //! トランスフォームアニメーション加算を構築するクラスです。 1025 class Builder 1026 { 1027 public: 1028 //! コンストラクタです。 Builder()1029 Builder() 1030 : m_MaxAnimObjects(2) {} 1031 1032 //! 最大アニメーションオブジェクト数を設定します。 MaxAnimObjects(int maxAnimObjects)1033 Builder& MaxAnimObjects(int maxAnimObjects) 1034 { 1035 NW_ASSERT(maxAnimObjects > 0); 1036 m_MaxAnimObjects = maxAnimObjects; 1037 return *this; 1038 } 1039 1040 //! @brief 生成時に必要なメモリサイズを取得します。 1041 //! 1042 //! メモリサイズは Builder の設定によって変化します。 1043 //! すべての設定が終わった後にこの関数を呼び出してください。 1044 //! 1045 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 1046 { 1047 os::MemorySizeCalculator size(alignment); 1048 1049 GetMemorySizeInternal(&size); 1050 1051 return size.GetSizeWithPadding(alignment); 1052 } 1053 1054 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1055 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 1056 { 1057 os::MemorySizeCalculator& size = *pSize; 1058 1059 size += sizeof(TransformAnimAdder); 1060 TransformAnimAdder::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); 1061 } 1062 1063 //! @brief トランスフォームアニメーション加算を生成します。 1064 //! 1065 //! @param[in] allocator アロケータです。 1066 //! 1067 //! @return 生成されたトランスフォームアニメーション加算です。 1068 //! Create(os::IAllocator * allocator)1069 TransformAnimAdder* Create(os::IAllocator* allocator) 1070 { 1071 void* buf = allocator->Alloc(sizeof(TransformAnimAdder)); 1072 1073 if (buf == NULL) 1074 { 1075 return NULL; 1076 } 1077 1078 TransformAnimAdder* adder = new(buf) TransformAnimAdder(allocator); 1079 1080 Result result = adder->Initialize(m_MaxAnimObjects); 1081 NW_ASSERT(result.IsSuccess()); 1082 1083 return adder; 1084 } 1085 1086 private: 1087 int m_MaxAnimObjects; 1088 }; 1089 1090 //@} 1091 1092 //---------------------------------------- 1093 //! @name 評価 1094 //@{ 1095 1096 //! @brief メンバ単位でアニメーション結果を取得します。 1097 //! 1098 //! @param[out] target アニメーション結果を書き込む対象です。 1099 //! @param[in] memberIdx メンバインデックスです。 1100 //! 1101 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 1102 //! 1103 virtual const anim::AnimResult* GetResult( 1104 void* target, 1105 int memberIdx) const; 1106 1107 //@} 1108 1109 protected: 1110 //---------------------------------------- 1111 //! @name コンストラクタ/デストラクタ 1112 //@{ 1113 1114 //! コンストラクタです。 TransformAnimAdder(os::IAllocator * allocator)1115 TransformAnimAdder( 1116 os::IAllocator* allocator) 1117 : AnimAdder(allocator) 1118 {} 1119 1120 //! デストラクタです。 ~TransformAnimAdder()1121 virtual ~TransformAnimAdder() {} 1122 1123 //@} 1124 }; 1125 1126 //--------------------------------------------------------------------------- 1127 //! @brief トランスフォームアニメーション評価結果を上書きブレンドするクラスです。 1128 //! 1129 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 1130 //! 1131 //! 動作の詳細は、 AnimOverrider をご覧ください。 1132 //--------------------------------------------------------------------------- 1133 class TransformAnimOverrider : public AnimOverrider 1134 { 1135 public: 1136 NW_UT_RUNTIME_TYPEINFO; 1137 1138 //---------------------------------------- 1139 //! @name 作成 1140 //@{ 1141 1142 //! トランスフォームアニメーション上書きを構築するクラスです。 1143 class Builder 1144 { 1145 public: 1146 //! コンストラクタです。 Builder()1147 Builder() 1148 : m_MaxAnimObjects(2) {} 1149 1150 //! 最大アニメーションオブジェクト数を設定します。 MaxAnimObjects(int maxAnimObjects)1151 Builder& MaxAnimObjects(int maxAnimObjects) 1152 { 1153 NW_ASSERT(maxAnimObjects > 0); 1154 m_MaxAnimObjects = maxAnimObjects; 1155 return *this; 1156 } 1157 1158 //! @brief 生成時に必要なメモリサイズを取得します。 1159 //! 1160 //! メモリサイズは Builder の設定によって変化します。 1161 //! すべての設定が終わった後にこの関数を呼び出してください。 1162 //! 1163 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 1164 { 1165 os::MemorySizeCalculator size(alignment); 1166 1167 GetMemorySizeInternal(&size); 1168 1169 return size.GetSizeWithPadding(alignment); 1170 } 1171 1172 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1173 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 1174 { 1175 os::MemorySizeCalculator& size = *pSize; 1176 1177 size += sizeof(TransformAnimOverrider); 1178 TransformAnimOverrider::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); 1179 } 1180 1181 //! @brief トランスフォームアニメーション上書きを生成します。 1182 //! 1183 //! @param[in] allocator アロケータです。 1184 //! 1185 //! @return 生成されたトランスフォームアニメーション上書きです。 1186 //! Create(os::IAllocator * allocator)1187 TransformAnimOverrider* Create(os::IAllocator* allocator) 1188 { 1189 void* buf = allocator->Alloc(sizeof(TransformAnimOverrider)); 1190 1191 if (buf == NULL) 1192 { 1193 return NULL; 1194 } 1195 1196 TransformAnimOverrider* overrider = new(buf) TransformAnimOverrider(allocator); 1197 1198 Result result = overrider->Initialize(m_MaxAnimObjects); 1199 NW_ASSERT(result.IsSuccess()); 1200 1201 return overrider; 1202 } 1203 1204 private: 1205 int m_MaxAnimObjects; 1206 }; 1207 1208 //@} 1209 1210 //---------------------------------------- 1211 //! @name 評価 1212 //@{ 1213 1214 //! @brief メンバ単位でアニメーション結果を取得します。 1215 //! 1216 //! @param[out] target アニメーション結果を書き込む対象です。 1217 //! @param[in] memberIdx メンバインデックスです。 1218 //! 1219 //! @return アニメーション結果を適用した場合は NULL でない値を返します。 1220 //! 1221 virtual const anim::AnimResult* GetResult( 1222 void* target, 1223 int memberIdx) const; 1224 1225 //@} 1226 1227 protected: 1228 //---------------------------------------- 1229 //! @name コンストラクタ/デストラクタ 1230 //@{ 1231 1232 //! コンストラクタです。 1233 //! 1234 //! :private TransformAnimOverrider(os::IAllocator * allocator)1235 TransformAnimOverrider( 1236 os::IAllocator* allocator) 1237 : AnimOverrider(allocator) 1238 {} 1239 1240 //! デストラクタです。 1241 //! 1242 //! :private ~TransformAnimOverrider()1243 virtual ~TransformAnimOverrider() {} 1244 1245 //@} 1246 }; 1247 1248 } // namespace gfx 1249 } // namespace nw 1250 1251 #endif // NW_GFX_TRANSFORMANIM_H_ 1252