1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: gfx_AnimInterpolator.h 4 5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain proprietary 8 information of Nintendo and/or its licensed developers and are protected by 9 national and international copyright laws. They may not be disclosed to third 10 parties or copied or duplicated in any form, in whole or in part, without the 11 prior written consent of Nintendo. 12 13 The content herein is highly confidential and should be handled accordingly. 14 15 $Revision: 31311 $ 16 *---------------------------------------------------------------------------*/ 17 18 #ifndef NW_GFX_ANIMINTERPOLATOR_H_ 19 #define NW_GFX_ANIMINTERPOLATOR_H_ 20 21 #include <nw/gfx/gfx_AnimBlender.h> 22 #include <nw/ut/ut_MoveArray.h> 23 #include <nw/ut/ut_RuntimeTypeInfo.h> 24 25 namespace nw { 26 namespace gfx { 27 28 //--------------------------------------------------------------------------- 29 //! @brief 汎用アニメーション評価結果を補間ブレンドするクラスです。 30 //! 31 //! 登録された全てのアニメーションオブジェクトの結果に重みをかけて、ブレンドした結果を採用します。 32 //! アニメーションが無いメンバの場合は、モデルのロード時の状態(OriginalValue)をブレンド計算に使用します。 33 //! 34 //! デフォルトでは、ブレンドの重みは合計が 1.0 となるように正規化されてからブレンドされるので、重みの比率だけが意味を持ちます。 35 //! 正規化が不要な場合は、 SetNormalizationEnabled() で無効化できます。 36 //--------------------------------------------------------------------------- 37 class AnimInterpolator : public AnimBlender 38 { 39 public: 40 NW_UT_RUNTIME_TYPEINFO; 41 42 //---------------------------------------- 43 //! @name 作成 44 //@{ 45 46 //! @brief 汎用アニメーション補間を構築するクラスです。 47 //! 48 //! バージョン 1.0.1 以前の補間法に戻すためには、IsOldMethod か IgnoreNoAnimMember に true を指定してください。 49 //! 50 //! 1.0.1 以前の補間方法と現在の補間方法の違いの詳細については、アニメーションのドキュメント(高度な機能)を参照ください。 51 class Builder 52 { 53 public: 54 //! コンストラクタです。 Builder()55 Builder() 56 : m_MaxAnimObjects(2), 57 m_IgnoreNoAnimMember(false) {} 58 59 //! 最大アニメーションオブジェクト数を設定します。 MaxAnimObjects(int maxAnimObjects)60 Builder& MaxAnimObjects(int maxAnimObjects) 61 { 62 NW_ASSERT(maxAnimObjects > 0); 63 m_MaxAnimObjects = maxAnimObjects; 64 return *this; 65 } 66 67 //! @brief アニメーションが存在しないメンバを無視するかどうかを設定します。 68 //! 69 //! デフォルトでは、アニメーションが存在しないメンバはバインド時の値がブレンドされます。 70 //! IgnoreNoAnimMember に true を設定すると、 71 //! 重みの正規化がメンバ毎に行なわれ、アニメーションが存在しないメンバは重み 0 としてブレンドされます。 72 //! 73 //! この挙動は バージョン 1.0.1 以前の補間法と同じです。 74 //! IgnoreNoAnimMember(bool ignoreNoAnimMember)75 Builder& IgnoreNoAnimMember(bool ignoreNoAnimMember) { m_IgnoreNoAnimMember = ignoreNoAnimMember; return *this; } 76 77 //! @brief 生成時に必要なメモリサイズを取得します。 78 //! 79 //! メモリサイズは Builder の設定によって変化します。 80 //! すべての設定が終わった後にこの関数を呼び出してください。 81 //! 82 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 83 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 84 { 85 os::MemorySizeCalculator size(alignment); 86 87 GetMemorySizeInternal(&size); 88 89 return size.GetSizeWithPadding(alignment); 90 } 91 92 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)93 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 94 { 95 os::MemorySizeCalculator& size = *pSize; 96 97 size += sizeof(AnimInterpolator); 98 AnimInterpolator::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects); 99 } 100 101 //! @brief 汎用アニメーション補間を生成します。 102 //! 103 //! @param[in] allocator アロケータです。 104 //! 105 //! @return 生成された汎用アニメーション補間です。 106 //! Create(os::IAllocator * allocator)107 AnimInterpolator* Create(os::IAllocator* allocator) 108 { 109 void* buf = allocator->Alloc(sizeof(AnimInterpolator)); 110 111 if (buf == NULL) 112 { 113 return NULL; 114 } 115 116 AnimInterpolator* animInterpolator = new(buf) AnimInterpolator(allocator); 117 118 Result result = animInterpolator->Initialize(m_MaxAnimObjects, m_IgnoreNoAnimMember); 119 NW_ASSERT(result.IsSuccess()); 120 121 return animInterpolator; 122 } 123 124 private: 125 int m_MaxAnimObjects; 126 bool m_IgnoreNoAnimMember; 127 }; 128 129 //@} 130 131 //---------------------------------------- 132 //! @name 評価 133 //@{ 134 135 //! @brief メンバ単位でアニメーション結果を取得します。 136 //! 137 //! @param[out] target アニメーション結果を書き込む対象です。 138 //! @param[in] memberIdx メンバインデックスです。 139 //! 140 //! @return アニメーション結果を返します。 141 //! ブレンドオペレーションを使用する場合は、返り値のアニメーション結果を使用してください。 142 //! 143 virtual const anim::AnimResult* GetResult( 144 void* target, 145 int memberIdx) const; 146 147 //@} 148 149 //---------------------------------------- 150 //! @name 取得/設定 151 //@{ 152 153 //! @brief アニメーションのブレンド重みを取得します。 154 //! 155 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。 156 //! 157 //! @return 重みです。 158 //! GetWeight(int animObjIdx)159 float GetWeight(int animObjIdx) const 160 { 161 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_Weights.Size()); 162 return m_Weights[animObjIdx]; 163 } 164 165 //! @brief アニメーションのブレンド重みを設定します。 166 //! 167 //! ブレンド重みの解釈については、 SetNormalizationEnabled() を参照してください。 168 //! 169 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。 170 //! @param[in] weight 重みです。 171 //! @sa SetNormalizationEnabled 172 //! SetWeight(int animObjIdx,float weight)173 void SetWeight(int animObjIdx, float weight) 174 { 175 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_Weights.Size()); 176 m_Weights[animObjIdx] = weight; 177 m_NormalizedWeights[animObjIdx] = weight; 178 m_IsWeightDirty = true; 179 } 180 181 //! @brief アニメーションのブレンド重みを正規化するかを設定します。 182 //! 183 //! true を指定すると、ブレンド重みが合計で 1 になるよう正規化してからブレンドを行います。 184 //! false を指定すると、SetWeight() で指定された重みがそのままブレンドに使用されますので、 185 //! 重みの設定に注意してください。 186 //! 187 //! 正規化処理は、 SetWeight() 実行後の最初のアニメーションブレンド時に 1 度だけ行われます。 188 //! 189 //! Builder::IsOldMethod で true を指定していると、この設定は無視されます。 190 //! 191 //! デフォルト値は true です。 SetNormalizationEnabled(bool enabled)192 void SetNormalizationEnabled(bool enabled){ m_IsWeightNormalizationEnabled = enabled; } 193 194 //! @brief アニメーションのブレンド重みを正規化するかの設定を取得します。 GetNormalizationEnabled()195 bool GetNormalizationEnabled() const { return m_IsWeightNormalizationEnabled; } 196 197 //@} 198 199 protected: 200 //---------------------------------------- 201 //! @name コンストラクタ/デストラクタ 202 //@{ 203 204 //! コンストラクタです。 205 //! 206 //! :private AnimInterpolator(os::IAllocator * allocator)207 AnimInterpolator( 208 os::IAllocator* allocator) 209 : AnimBlender(allocator), 210 m_IsOldMethod(false), 211 m_IsWeightDirty(false), 212 m_IsWeightNormalizationEnabled(true) 213 { 214 } 215 216 //! デストラクタです。 217 //! 218 //! :private ~AnimInterpolator()219 virtual ~AnimInterpolator() {} 220 221 //@} 222 223 //! Initialize() の実行に必要なメモリサイズを取得します。 224 //! 225 //! :private GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,int maxAnimObjects)226 static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, int maxAnimObjects) 227 { 228 os::MemorySizeCalculator& size = *pSize; 229 230 AnimBlender::GetMemorySizeForInitialize(pSize, maxAnimObjects); 231 size += sizeof(float) * maxAnimObjects; 232 size += sizeof(float) * maxAnimObjects; 233 } 234 235 //! @details :private Initialize(int maxAnimObjects,bool ignoreNoAnimMember)236 Result Initialize(int maxAnimObjects, bool ignoreNoAnimMember) 237 { 238 Result result = AnimBlender::Initialize(maxAnimObjects); 239 NW_ENSURE_AND_RETURN(result); 240 241 { 242 void* memory = GetAllocator().Alloc(sizeof(float) * maxAnimObjects); 243 if (memory == NULL) 244 { 245 result |= Result::MASK_FAIL_BIT; 246 } 247 NW_ENSURE_AND_RETURN(result); 248 249 m_Weights = ut::MoveArray<float>(memory, maxAnimObjects, &GetAllocator()); 250 for (int animObjIdx = 0; animObjIdx < maxAnimObjects; ++animObjIdx) 251 { 252 m_Weights.PushBackFast(animObjIdx == 0 ? 1.0f : 0.0f); 253 } 254 } 255 256 { 257 void* memory = GetAllocator().Alloc(sizeof(float) * maxAnimObjects); 258 if (memory == NULL) 259 { 260 result |= Result::MASK_FAIL_BIT; 261 } 262 NW_ENSURE_AND_RETURN(result); 263 264 m_NormalizedWeights = ut::MoveArray<float>(memory, maxAnimObjects, &GetAllocator()); 265 for (int animObjIdx = 0; animObjIdx < maxAnimObjects; ++animObjIdx) 266 { 267 m_NormalizedWeights.PushBackFast(animObjIdx == 0 ? 1.0f : 0.0f); 268 } 269 } 270 271 // TODO: 変数名その他を変更。 272 m_IsOldMethod = ignoreNoAnimMember; 273 274 return result; 275 } 276 277 //! @brief ブレンド重みを正規化します。 278 //! 279 //! :private NormalizeWeight()280 void NormalizeWeight() const 281 { 282 float weightSum = 0.0f; 283 float normalizeScale; 284 for (int i = 0; i < m_Weights.Size(); ++i) 285 { 286 weightSum += m_Weights[i]; 287 } 288 normalizeScale = GetAnimWeightNormalizeScale(weightSum); 289 for (int i = 0; i < m_Weights.Size(); ++i) 290 { 291 m_NormalizedWeights[i] = m_Weights[i] * normalizeScale; 292 } 293 m_IsWeightDirty = false; 294 } 295 296 ut::MoveArray<float> m_Weights; //!< @details :private 297 mutable ut::MoveArray<float> m_NormalizedWeights; //!< @details :private 298 299 bool m_IsOldMethod; //!< @details :private 300 mutable bool m_IsWeightDirty; //!< @details :private 301 bool m_IsWeightNormalizationEnabled; //!< @details :private 302 }; 303 304 } // namespace gfx 305 } // namespace nw 306 307 #endif // NW_GFX_ANIMINTERPOLATOR_H_ 308