/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_TransformAnim.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 28677 $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_TRANSFORMANIM_H_ #define NW_GFX_TRANSFORMANIM_H_ #include #include namespace nw { namespace gfx { //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーションのブレンドオペレーションの基底クラスです。 //--------------------------------------------------------------------------- class TransformAnimBlendOp : public anim::AnimBlendOp { public: //! 無効な重み値です。 //! //! :private static const float WeightDiscard; //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! @brief コンストラクタです。 //! //! @param[in] hasBlend ブレンド処理があるかどうかです。 //! @param[in] hasPostBlend ブレンド後の処理があるかどうかです。 //! TransformAnimBlendOp(bool hasBlend, bool hasPostBlend) : AnimBlendOp(hasBlend, hasPostBlend) {} //! デストラクタです。 virtual ~TransformAnimBlendOp() {} //@} //---------------------------------------- //! @name 適用 //@{ //! @brief ブレンド処理結果を対象に適用します。 //! //! @param[out] target ブレンド処理結果を適用する対象です。 //! @param[in] result ブレンド処理結果です。 //! virtual void Apply(void* target, const anim::AnimResult* result) const; //! @brief 対象を AnimResult に変換します。 //! //! @param[out] result 出力の AnimResult です。 //! @param[in] source 変換元へのポインタです。 //! //! :private virtual void ConvertToAnimResult(anim::AnimResult* result, const void* source) const; //@} protected: //---------------------------------------- //! @name 基本ブレンド処理 //@{ //! @details :private enum BasicBlendFlags { FLAG_ACCURATE_SCALE_SHIFT = 0, FLAG_QUATERNION_ROTATE_SHIFT = 1, // 正確なスケールブレンドをするかどうかです。 FLAG_ACCURATE_SCALE = 0x1 << FLAG_ACCURATE_SCALE_SHIFT, // クォータニオンで回転をブレンドするかどうかです。オフなら行列の回転成分をブレンドします。 FLAG_QUATERNION_ROTATE = 0x1 << FLAG_QUATERNION_ROTATE_SHIFT }; //! @brief 標準的なスケールのブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] weight ブレンド処理の入力の重みです。 //! //! :private void BlendScaleStandard( CalculatedTransform* dst, const CalculatedTransform* src, const float weight) const; //! @brief 正確なスケールのブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] weight ブレンド処理の入力の重みです。 //! //! :private void BlendScaleAccurate( CalculatedTransform* dst, const CalculatedTransform* src, const float weight) const; //! @brief 正確なスケールブレンドのブレンド後の処理を行います。 //! //! :private //! //! @param[in,out] transform トランスフォームです。 //! //! @return 正しく処理できれば true を返します。 bool PostBlendAccurateScale(CalculatedTransform* transform) const; //! @brief 行列の回転のブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] weight ブレンド処理の入力の重みです。 //! //! :private void BlendRotateMatrix( CalculatedTransform* dst, const CalculatedTransform* src, const float weight) const; //! @brief クォータニオンの回転のブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] weight ブレンド処理の入力の重みです。 //! //! :private void BlendRotateQuaternion( CalculatedTransform* dst, const CalculatedTransform* src, const float weight) const; //! @brief 移動のブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] weight ブレンド処理の入力の重みです。 //! //! :private void BlendTranslate( CalculatedTransform* dst, const CalculatedTransform* src, const float weight) const; //! @brief トランスフォームの上書き処理を行います。 //! //! :private //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] blendFlags ブレンド処理のフラグです。 //! //! @return すべての成分が上書きされたら true を返します。 bool OverrideTransform( CalculatedTransform* dst, const CalculatedTransform* src, const bit32 blendFlags ) const; //@} }; //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーションの標準的なブレンドオペレーションのクラスです。 //! 回転行列の各成分をブレンドした後に、正規直交化します。 //--------------------------------------------------------------------------- class TransformAnimBlendOpStandard : public TransformAnimBlendOp { public: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 TransformAnimBlendOpStandard() : TransformAnimBlendOp(true, true) {} //! デストラクタです。 virtual ~TransformAnimBlendOpStandard() {} //@} //---------------------------------------- //! @name ブレンド //@{ //! @brief ブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] srcWeights ブレンド処理の入力の重みです。 //! //! @return ブレンド処理のループを継続するなら true を返します。 //! virtual bool Blend( anim::AnimResult* dst, float* dstWeights, const anim::AnimResult* src, const float* srcWeights) const { (void)dstWeights; CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); BlendScaleStandard(dstX, srcX, srcWeights[0]); BlendRotateMatrix (dstX, srcX, srcWeights[1]); BlendTranslate (dstX, srcX, srcWeights[2]); return true; } //! @brief ブレンド後の処理を行います。 //! //! @param[in,out] result ブレンド処理結果です。 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! //! @return 成功すれば true を返します。 //! virtual bool PostBlend(anim::AnimResult* result, const float* weights) const { (void)weights; CalculatedTransform* dstX = reinterpret_cast(result); return dstX->NormalizeRotateMatrix(); } //! @brief 上書き処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! //! @return すべての成分が上書きされたら true を返します。 //! virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const { CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); return OverrideTransform(dstX, srcX, 0); } //@} }; //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーションの正確なスケールブレンドに対応したブレンドオペレーションのクラスです。 //--------------------------------------------------------------------------- class TransformAnimBlendOpAccScale : public TransformAnimBlendOp { public: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 TransformAnimBlendOpAccScale() : TransformAnimBlendOp(true, true) {} //! デストラクタです。 virtual ~TransformAnimBlendOpAccScale() {} //@} //---------------------------------------- //! @name ブレンド //@{ //! @brief ブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] srcWeights ブレンド処理の入力の重みです。 //! //! @return ブレンド処理のループを継続するなら true を返します。 //! virtual bool Blend( anim::AnimResult* dst, float* dstWeights, const anim::AnimResult* src, const float* srcWeights) const { (void)dstWeights; CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); BlendScaleAccurate(dstX, srcX, srcWeights[0]); BlendRotateMatrix (dstX, srcX, srcWeights[1]); BlendTranslate (dstX, srcX, srcWeights[2]); return true; } //! @brief ブレンド後の処理を行います。 //! //! @param[in,out] result ブレンド処理結果です。 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! //! @return 成功すれば true を返します。 //! virtual bool PostBlend(anim::AnimResult* result, const float* weights) const { (void)weights; CalculatedTransform* dstX = reinterpret_cast(result); const bool scaleRet = PostBlendAccurateScale(dstX); return dstX->NormalizeRotateMatrix() && scaleRet; } //! @brief 上書き処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! //! @return すべての成分が上書きされたら true を返します。 //! virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const { CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); return OverrideTransform(dstX, srcX, FLAG_ACCURATE_SCALE); } //@} }; //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーションのクォータニオンによる回転ブレンドに対応したブレンドオペレーションのクラスです。 //--------------------------------------------------------------------------- class TransformAnimBlendOpQuat : public TransformAnimBlendOp { public: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 TransformAnimBlendOpQuat() : TransformAnimBlendOp(true, true) {} //! デストラクタです。 virtual ~TransformAnimBlendOpQuat() {} //@} //---------------------------------------- //! @name ブレンド //@{ //! @brief ブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] srcWeights ブレンド処理の入力の重みです。 //! //! @return ブレンド処理のループを継続するなら true を返します。 //! virtual bool Blend( anim::AnimResult* dst, float* dstWeights, const anim::AnimResult* src, const float* srcWeights) const { (void)dstWeights; CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); BlendScaleStandard (dstX, srcX, srcWeights[0]); BlendRotateQuaternion(dstX, srcX, srcWeights[1]); BlendTranslate (dstX, srcX, srcWeights[2]); return true; } //! @brief ブレンド後の処理を行います。 //! //! @param[in,out] result ブレンド処理結果です。 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! //! @return 成功すれば true を返します。 //! virtual bool PostBlend(anim::AnimResult* result, const float* weights) const { (void)weights; CalculatedTransform* dstX = reinterpret_cast(result); return dstX->QuaternionToRotateMatrix(); } //! @brief 上書き処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! //! @return すべての成分が上書きされたら true を返します。 //! virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const { CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); return OverrideTransform(dstX, srcX, FLAG_QUATERNION_ROTATE); } //@} }; //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーションの正確なスケールブレンドとクォータニオンによる回転ブレンドに対応したブレンドオペレーションのクラスです。 //--------------------------------------------------------------------------- class TransformAnimBlendOpAccScaleQuat : public TransformAnimBlendOp { public: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 TransformAnimBlendOpAccScaleQuat() : TransformAnimBlendOp(true, true) {} //! デストラクタです。 virtual ~TransformAnimBlendOpAccScaleQuat() {} //@} //---------------------------------------- //! @name ブレンド //@{ //! @brief ブレンド処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! @param[in] src ブレンド処理の入力です。 //! @param[in] srcWeights ブレンド処理の入力の重みです。 //! //! @return ブレンド処理のループを継続するなら true を返します。 //! virtual bool Blend( anim::AnimResult* dst, float* dstWeights, const anim::AnimResult* src, const float* srcWeights) const { (void)dstWeights; CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); BlendScaleAccurate (dstX, srcX, srcWeights[0]); BlendRotateQuaternion(dstX, srcX, srcWeights[1]); BlendTranslate (dstX, srcX, srcWeights[2]); return true; } //! @brief ブレンド後の処理を行います。 //! //! @param[in,out] result ブレンド処理結果です。 //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。 //! このブレンドオペレーションでは使用しません。 //! //! @return 成功すれば true を返します。 //! virtual bool PostBlend(anim::AnimResult* result, const float* weights) const { (void)weights; CalculatedTransform* dstX = reinterpret_cast(result); const bool scaleRet = PostBlendAccurateScale(dstX); return dstX->QuaternionToRotateMatrix() && scaleRet; } //! @brief 上書き処理を行います。 //! //! @param[in,out] dst ブレンド処理結果です。 //! @param[in] src ブレンド処理の入力です。 //! //! @return すべての成分が上書きされたら true を返します。 //! virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const { CalculatedTransform* dstX = reinterpret_cast(dst); const CalculatedTransform* srcX = reinterpret_cast(src); return OverrideTransform(dstX, srcX, FLAG_ACCURATE_SCALE | FLAG_QUATERNION_ROTATE); } //@} }; //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーションを評価するクラスです。 //! //! アニメーションデータを保持し、ファンクションカーブの評価を行います。 //--------------------------------------------------------------------------- class TransformAnimEvaluator : public BaseAnimEvaluator { public: NW_UT_RUNTIME_TYPEINFO; //---------------------------------------- //! @name 作成 //@{ //! トランスフォームアニメーション評価を構築するクラスです。 class Builder { public: //! コンストラクタです。 Builder() : m_AnimData(NULL), m_MaxMembers(64), m_MaxAnimMembers(64), m_AllocCache(false) {} //! アニメーションデータを設定します。 Builder& AnimData(const anim::ResAnim& animData) { m_AnimData = animData; return *this; } //! @brief アニメーション対象メンバの最大数を設定します。 //! //! TransformAnimEvaluator::Bind に渡す AnimGroup の AnimGroup::GetMemberCount の値を設定してください。 //! 複数の AnimGroup に Bind する場合は、最大値を設定してください。 Builder& MaxMembers(int maxMembers) { NW_ASSERT(maxMembers > 0); m_MaxMembers = maxMembers; return *this; } //! @brief 実際にアニメーションするメンバの最大数を設定します。 //! //! AnimData() に渡す anim::res::ResAnim の anim::res::ResAnim::GetMemberAnimSetCount の値を設定してください。 //! TransformAnimEvaluator::ChangeAnim で複数の ResAnim を切り替える場合は、最大値を設定してください。 Builder& MaxAnimMembers(int maxAnimMembers) { NW_ASSERT(maxAnimMembers > 0); m_MaxAnimMembers = maxAnimMembers; return *this; } //! キャッシュバッファを確保してキャッシュを有効にするかどうかを設定します。 Builder& AllocCache(bool allocCache) { m_AllocCache = allocCache; return *this; } //! @brief 生成時に必要なメモリサイズを取得します。 //! //! メモリサイズは Builder の設定によって変化します。 //! すべての設定が終わった後にこの関数を呼び出してください。 //! //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const { os::MemorySizeCalculator size(alignment); GetMemorySizeInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const { os::MemorySizeCalculator& size = *pSize; size += sizeof(TransformAnimEvaluator); BaseAnimEvaluator::GetMemorySizeForInitialize(pSize, m_MaxMembers, m_MaxAnimMembers); if (m_AllocCache) { size += sizeof(CalculatedTransform) * m_MaxAnimMembers; } } //! @brief トランスフォームアニメーション評価を生成します。 //! //! @param[in] allocator アロケータです。 //! //! @return 生成されたトランスフォームアニメーション評価です。 //! TransformAnimEvaluator* Create(os::IAllocator* allocator) { void* buf = allocator->Alloc(sizeof(TransformAnimEvaluator)); if (buf == NULL) { return NULL; } TransformAnimEvaluator* evaluator = new(buf) TransformAnimEvaluator(allocator); Result result = evaluator->Initialize(m_AnimData, m_MaxMembers, m_MaxAnimMembers, m_AllocCache); NW_ASSERT(result.IsSuccess()); return evaluator; } private: anim::ResAnim m_AnimData; int m_MaxMembers; int m_MaxAnimMembers; bool m_AllocCache; }; //@} //---------------------------------------- //! @name 基本操作 //@{ //! @brief アニメーションを関連付けます。 //! //! Bind() よりも詳細なバインド結果を得ることができます。 //! //! アニメーションデータがあるボーンの、アニメーションカーブがないSRT要素に、 //! この時点でバインドポーズをコピーします。 //! そのため、この関数を呼び出した後からアニメーション評価を行うまでの間は //! スケルトンの姿勢が正しくない状態になりますのでご注意ください。 //! //! @param[in] animGroup アニメーショングループです。 //! //! @return バインドの結果を返します。 //! //! @sa Bind //! @sa BindResult virtual Result TryBind(AnimGroup* animGroup); //! @brief アニメーションを変更します。 //! //! 内部で Bind() を呼び出すため、スケルトンの姿勢が変化します。 //! //! GetCacheBufferSizeNeeded() の値が変化しますので、 //! SetCacheBuffer() している場合はバッファの再設定が必要です。 //! //! 内部で確保したキャッシュバッファは、自動的にサイズ変更されます。 //! //! @sa Bind //! @sa BaseAnimEvaluator::ChangeAnim //! @param animData アニメーションデータです。 virtual void ChangeAnim(const nw::anim::ResAnim animData) { // BaseAnimEvaluator::ChangeAnim()内でBind()が呼ばれ、 // そこでキャッシュを書き換えるので、キャッシュのResizeを先に行う if (!m_IsCacheExternal && !m_CacheTransforms.Empty()) { m_CacheTransforms.Resize(animData.GetMemberAnimSetCount()); } BaseAnimEvaluator::ChangeAnim(animData); } //@} //---------------------------------------- //! @name 評価 //@{ //! @brief メンバ単位でアニメーション結果を取得します。 //! //! @param[out] target アニメーション結果を書き込む対象です。 //! @param[in] memberIdx メンバインデックスです。 //! //! @return アニメーション結果を適用した場合は NULL でない値を返します。 //! virtual const anim::AnimResult* GetResult( void* target, int memberIdx) const; //@} //---------------------------------------- //! @name 取得/設定 //@{ //! スケールアニメを無効化しているかを取得します。 bool GetIsScaleDisabled() const { return m_IsScaleDisabled; } //! スケールアニメを無効化しているかを設定します。 void SetIsScaleDisabled(bool isDisabled) { m_IsScaleDisabled = isDisabled; } //! 回転アニメを無効化しているかを取得します。 bool GetIsRotateDisabled() const { return m_IsRotateDisabled; } //! 回転アニメを無効化しているかを設定します。 void SetIsRotateDisabled(bool isDisabled) { m_IsRotateDisabled = isDisabled; } //! 移動アニメを無効化しているかを取得します。 bool GetIsTranslateDisabled() const { return m_IsTranslateDisabled; } //! 移動アニメを無効化しているかを設定します。 void SetIsTranslateDisabled(bool isDisabled) { m_IsTranslateDisabled = isDisabled; } //! @brief メンバに関連付けられたアニメーションが存在するかどうかを取得します。 //! //! @param[in] memberIdx メンバインデックスです。 //! //! @return アニメーションが存在すれば true を返します。 //! virtual bool HasMemberAnim(int memberIdx) const { NW_MINMAXLT_ASSERT(memberIdx, 0, m_BindIndexTable.Size()); if (m_AnimData.ptr() == NULL) { return (0 <= memberIdx && memberIdx < m_AnimGroup->GetMemberCount()); } else { return m_BindIndexTable[memberIdx] != NotFoundIndex; } } //@} //---------------------------------------- //! @name キャッシュ //@{ //---------------------------------------------------------- //! :private void UpdateCacheNonVirtual() { if (!m_CacheTransforms.Empty() && m_IsCacheDirty) { if (m_AnimData.ptr() != NULL) { for (int memberIdx = 0; memberIdx < m_AnimGroup->GetMemberCount(); ++memberIdx) { const int animIdx = m_BindIndexTable[memberIdx]; if (animIdx != NotFoundIndex) { GetResult(&m_CacheTransforms[animIdx], memberIdx); } } } m_IsCacheDirty = false; } } //! アニメーション評価結果の内部キャッシュが古ければ更新します。 virtual void UpdateCache() { this->UpdateCacheNonVirtual(); } //! キャッシュバッファに必要なサイズ(バイト数)を取得します。 virtual int GetCacheBufferSizeNeeded() const { return m_AnimData.GetMemberAnimSetCount() * sizeof(CalculatedTransform); } //! キャッシュバッファを取得します。 virtual const void* GetCacheBuffer() const { return m_CacheTransforms.Elements(); } //! @brief キャッシュバッファを設定します。 //! この関数で指定したキャッシュバッファはデストラクタで開放されません。 //! //! @param[in] buf キャッシュバッファ用のメモリの先頭アドレスです。 //! NULL の場合、キャッシュが無効になります。 //! @param[in] size キャッシュバッファのサイズ(バイト数)です。 //! virtual void SetCacheBuffer(void* buf, int size) { if (buf != NULL) { NW_ASSERT(size >= GetCacheBufferSizeNeeded()); const int maxCalculatedTransforms = size / sizeof(CalculatedTransform); m_CacheTransforms = ut::MoveArray(buf, maxCalculatedTransforms); m_CacheTransforms.Resize(maxCalculatedTransforms); m_IsCacheDirty = true; m_IsCacheExternal = true; } else { m_CacheTransforms = ut::MoveArray(); } } //@} protected: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 //! //! :private TransformAnimEvaluator( os::IAllocator* allocator) : BaseAnimEvaluator(allocator, ANIMTYPE_TRANSFORM_SIMPLE), m_IsScaleDisabled(false), m_IsRotateDisabled(false), m_IsTranslateDisabled(false) { } //! デストラクタです。 //! //! :private virtual ~TransformAnimEvaluator() {} //@} //! @details :private virtual Result Initialize( const anim::ResAnim& animData, const int maxMembers, const int maxAnimMembers, bool allocCache) { Result result = BaseAnimEvaluator::Initialize(animData, maxMembers, maxAnimMembers); NW_ENSURE_AND_RETURN(result); if (allocCache) { void* memory = GetAllocator().Alloc(sizeof(CalculatedTransform) * maxAnimMembers); if (memory == NULL) { result |= Result::MASK_FAIL_BIT; } NW_ENSURE_AND_RETURN(result); m_CacheTransforms = ut::MoveArray(memory, maxAnimMembers, &GetAllocator()); m_CacheTransforms.Resize(animData.GetMemberAnimSetCount()); } return result; } bool m_IsScaleDisabled; //!< @details :private bool m_IsRotateDisabled; //!< @details :private bool m_IsTranslateDisabled; //!< @details :private ut::MoveArray m_CacheTransforms; //!< @details :private private: // アニメーションカーブが存在しないメンバを、OriginalValueで初期化します。 void ResetNoAnimMember(AnimGroup* animGroup, anim::ResAnim animData); const anim::AnimResult* GetResultFast(void* target, int memberIdx) const; const anim::AnimResult* GetResultCommon(void* target, int memberIdx, bool writeNoAnimMember) const; // メンバアニメーションを評価します。 // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。 void EvaluateMemberAnim( CalculatedTransform* result, anim::ResTransformAnim transformAnim, float frame, const math::Transform3* originalTransform, bool writeNoAnimMember) const; // ベイク済みのメンバアニメーションを評価します。 // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。 void EvaluateMemberBakedAnim( CalculatedTransform* result, anim::ResBakedTransformAnim transformAnim, float frame, const math::Transform3* originalTransform, bool writeNoAnimMember) const; void UpdateFlagsCommon(CalculatedTransform* transform) const; void UpdateFlags(CalculatedTransform* transform) const; // CalculatedTransformのフラグを、Bakeされた情報をもとにして更新します。 void ApplyBakedFlags(CalculatedTransform* transform, bit32 flags) const; friend class AnimBinding; }; //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーション評価結果を補間ブレンドするクラスです。 //! //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 //! //! 動作の詳細は、 AnimInterpolator をご覧ください。 //--------------------------------------------------------------------------- class TransformAnimInterpolator : public AnimInterpolator { public: NW_UT_RUNTIME_TYPEINFO; //---------------------------------------- //! @name 作成 //@{ //! @brief トランスフォームアニメーション補間を構築するクラスです。 //! //! バージョン 1.0.1 以前の補間法に戻すためには、IsOldMethod か IgnoreNoAnimMember に true を指定してください。 //! //! 1.0.1 以前の補間方法と現在の補間方法の違いの詳細については、アニメーションのドキュメント(高度な機能)を参照ください。 class Builder { public: //! コンストラクタです。 Builder() : m_MaxAnimObjects(2), m_IgnoreNoAnimMember(false) {} //! 最大アニメーションオブジェクト数を設定します。 Builder& MaxAnimObjects(int maxAnimObjects) { NW_ASSERT(maxAnimObjects > 0); m_MaxAnimObjects = maxAnimObjects; return *this; } //! @brief アニメーションが存在しないメンバを無視するかどうかを設定します。 //! //! デフォルトでは、アニメーションが存在しないメンバはバインド時の値がブレンドされます。 //! IgnoreNoAnimMember に true を設定すると、 //! 重みの正規化がメンバ毎に行なわれ、アニメーションが存在しないメンバは重み 0 としてブレンドされます。 //! //! この挙動は バージョン 1.0.1 以前の補間法と同じです。 //! Builder& IgnoreNoAnimMember(bool ignoreNoAnimMember) { m_IgnoreNoAnimMember = ignoreNoAnimMember; return *this; } //! @brief 生成時に必要なメモリサイズを取得します。 //! //! メモリサイズは Builder の設定によって変化します。 //! すべての設定が終わった後にこの関数を呼び出してください。 //! //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const { os::MemorySizeCalculator size(alignment); GetMemorySizeInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const { os::MemorySizeCalculator& size = *pSize; size += sizeof(TransformAnimInterpolator); TransformAnimInterpolator::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); } //! @brief トランスフォームアニメーション補間を生成します。 //! //! @param[in] allocator アロケータです。 //! //! @return 生成されたトランスフォームアニメーション補間です。 //! TransformAnimInterpolator* Create(os::IAllocator* allocator) { void* buf = allocator->Alloc(sizeof(TransformAnimInterpolator)); if (buf == NULL) { return NULL; } TransformAnimInterpolator* interpolator = new(buf) TransformAnimInterpolator(allocator); Result result = interpolator->Initialize(m_MaxAnimObjects, m_IgnoreNoAnimMember); NW_ASSERT(result.IsSuccess()); return interpolator; } private: int m_MaxAnimObjects; bool m_IgnoreNoAnimMember; }; //@} //---------------------------------------- //! @name 評価 //@{ //! @brief メンバ単位でアニメーション結果を取得します。 //! //! @param[out] target アニメーション結果を書き込む対象です。 //! @param[in] memberIdx メンバインデックスです。 //! //! @return アニメーション結果を適用した場合は NULL でない値を返します。 //! virtual const anim::AnimResult* GetResult( void* target, int memberIdx) const; //@} protected: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 //! //! :private TransformAnimInterpolator( os::IAllocator* allocator) : AnimInterpolator(allocator) {} //! デストラクタです。 //! //! :private virtual ~TransformAnimInterpolator() {} //@} }; //--------------------------------------------------------------------------- //! @details :private //! @brief トランスフォームアニメーション評価結果を加算ブレンドするクラスです。 //! //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 //--------------------------------------------------------------------------- class TransformAnimAdder : public AnimAdder { public: NW_UT_RUNTIME_TYPEINFO; //---------------------------------------- //! @name 作成 //@{ //! トランスフォームアニメーション加算を構築するクラスです。 class Builder { public: //! コンストラクタです。 Builder() : m_MaxAnimObjects(2) {} //! 最大アニメーションオブジェクト数を設定します。 Builder& MaxAnimObjects(int maxAnimObjects) { NW_ASSERT(maxAnimObjects > 0); m_MaxAnimObjects = maxAnimObjects; return *this; } //! @brief 生成時に必要なメモリサイズを取得します。 //! //! メモリサイズは Builder の設定によって変化します。 //! すべての設定が終わった後にこの関数を呼び出してください。 //! //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const { os::MemorySizeCalculator size(alignment); GetMemorySizeInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const { os::MemorySizeCalculator& size = *pSize; size += sizeof(TransformAnimAdder); TransformAnimAdder::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); } //! @brief トランスフォームアニメーション加算を生成します。 //! //! @param[in] allocator アロケータです。 //! //! @return 生成されたトランスフォームアニメーション加算です。 //! TransformAnimAdder* Create(os::IAllocator* allocator) { void* buf = allocator->Alloc(sizeof(TransformAnimAdder)); if (buf == NULL) { return NULL; } TransformAnimAdder* adder = new(buf) TransformAnimAdder(allocator); Result result = adder->Initialize(m_MaxAnimObjects); NW_ASSERT(result.IsSuccess()); return adder; } private: int m_MaxAnimObjects; }; //@} //---------------------------------------- //! @name 評価 //@{ //! @brief メンバ単位でアニメーション結果を取得します。 //! //! @param[out] target アニメーション結果を書き込む対象です。 //! @param[in] memberIdx メンバインデックスです。 //! //! @return アニメーション結果を適用した場合は NULL でない値を返します。 //! virtual const anim::AnimResult* GetResult( void* target, int memberIdx) const; //@} protected: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 TransformAnimAdder( os::IAllocator* allocator) : AnimAdder(allocator) {} //! デストラクタです。 virtual ~TransformAnimAdder() {} //@} }; //--------------------------------------------------------------------------- //! @brief トランスフォームアニメーション評価結果を上書きブレンドするクラスです。 //! //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。 //! //! 動作の詳細は、 AnimOverrider をご覧ください。 //--------------------------------------------------------------------------- class TransformAnimOverrider : public AnimOverrider { public: NW_UT_RUNTIME_TYPEINFO; //---------------------------------------- //! @name 作成 //@{ //! トランスフォームアニメーション上書きを構築するクラスです。 class Builder { public: //! コンストラクタです。 Builder() : m_MaxAnimObjects(2) {} //! 最大アニメーションオブジェクト数を設定します。 Builder& MaxAnimObjects(int maxAnimObjects) { NW_ASSERT(maxAnimObjects > 0); m_MaxAnimObjects = maxAnimObjects; return *this; } //! @brief 生成時に必要なメモリサイズを取得します。 //! //! メモリサイズは Builder の設定によって変化します。 //! すべての設定が終わった後にこの関数を呼び出してください。 //! //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const { os::MemorySizeCalculator size(alignment); GetMemorySizeInternal(&size); return size.GetSizeWithPadding(alignment); } //! @details :private void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const { os::MemorySizeCalculator& size = *pSize; size += sizeof(TransformAnimOverrider); TransformAnimOverrider::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); } //! @brief トランスフォームアニメーション上書きを生成します。 //! //! @param[in] allocator アロケータです。 //! //! @return 生成されたトランスフォームアニメーション上書きです。 //! TransformAnimOverrider* Create(os::IAllocator* allocator) { void* buf = allocator->Alloc(sizeof(TransformAnimOverrider)); if (buf == NULL) { return NULL; } TransformAnimOverrider* overrider = new(buf) TransformAnimOverrider(allocator); Result result = overrider->Initialize(m_MaxAnimObjects); NW_ASSERT(result.IsSuccess()); return overrider; } private: int m_MaxAnimObjects; }; //@} //---------------------------------------- //! @name 評価 //@{ //! @brief メンバ単位でアニメーション結果を取得します。 //! //! @param[out] target アニメーション結果を書き込む対象です。 //! @param[in] memberIdx メンバインデックスです。 //! //! @return アニメーション結果を適用した場合は NULL でない値を返します。 //! virtual const anim::AnimResult* GetResult( void* target, int memberIdx) const; //@} protected: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 //! //! :private TransformAnimOverrider( os::IAllocator* allocator) : AnimOverrider(allocator) {} //! デストラクタです。 //! //! :private virtual ~TransformAnimOverrider() {} //@} }; } // namespace gfx } // namespace nw #endif // NW_GFX_TRANSFORMANIM_H_