1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: gfx_AnimBinding.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_ANIMBINDING_H_ 19 #define NW_GFX_ANIMBINDING_H_ 20 21 #include <nw/gfx/gfx_AnimGroup.h> 22 #include <nw/gfx/gfx_AnimObject.h> 23 #include <nw/gfx/gfx_GfxObject.h> 24 #include <nw/ut/ut_MoveArray.h> 25 #include <nw/ut/ut_RuntimeTypeInfo.h> 26 27 namespace nw { 28 namespace gfx { 29 30 class AnimEvaluator; 31 class TransformAnimEvaluator; 32 33 //--------------------------------------------------------------------------- 34 //! @brief アニメーションの関連付け情報のクラスです。 35 //! 36 //! AnimObject と AnimGroup を関連付けて、アニメーションの再生を行います。 37 //--------------------------------------------------------------------------- 38 class AnimBinding : public GfxObject 39 { 40 public: 41 42 //! アニメーショングループの MoveArray の定義です。 43 //! 44 //! :private 45 typedef ut::MoveArray<AnimGroup*> AnimGroupArray; 46 47 //! アニメーションオブジェクトの MoveArray の定義です。 48 //! 49 //! :private 50 typedef ut::MoveArray<AnimObject*> AnimObjectArray; 51 52 //---------------------------------------- 53 //! @name 作成 54 //@{ 55 56 //! アニメーションバインディングを構築するクラスです。 57 class Builder 58 { 59 public: 60 //! コンストラクタです。 Builder()61 Builder() 62 : 63 m_MaxAnimGroups(1), 64 m_MaxAnimObjectsPerGroup(1) {} 65 66 //! 最大アニメーショングループ数を設定します。 MaxAnimGroups(int maxAnimGroups)67 Builder& MaxAnimGroups(int maxAnimGroups) 68 { 69 NW_ASSERT(maxAnimGroups > 0); 70 m_MaxAnimGroups = maxAnimGroups; 71 return *this; 72 } 73 74 //! @brief アニメーショングループ内での最大アニメーションオブジェクト数を設定します。 75 //! 76 //! @details 複数のアニメーショングループを持つ場合は、そのうち最大のものを指定してください。 MaxAnimObjectsPerGroup(int maxAnimObjects)77 Builder& MaxAnimObjectsPerGroup(int maxAnimObjects) 78 { 79 NW_ASSERT(maxAnimObjects > 0); 80 m_MaxAnimObjectsPerGroup = maxAnimObjects; 81 return *this; 82 } 83 84 //! @brief 生成時に必要なメモリサイズを取得します。 85 //! 86 //! メモリサイズは Builder の設定によって変化します。 87 //! すべての設定が終わった後にこの関数を呼び出してください。 88 //! 89 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 90 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const 91 { 92 os::MemorySizeCalculator size(alignment); 93 94 GetMemorySizeInternal(&size); 95 96 return size.GetSizeWithPadding(alignment); 97 } 98 99 //! @details :private GetMemorySizeInternal(os::MemorySizeCalculator * pSize)100 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const 101 { 102 os::MemorySizeCalculator& size = *pSize; 103 104 size += sizeof(AnimBinding); 105 AnimBinding::GetMemorySizeForInitialize(pSize, m_MaxAnimGroups, m_MaxAnimObjectsPerGroup); 106 } 107 108 //! @brief アニメーションバインディングを生成します。 109 //! 110 //! @param[in] allocator アロケータです。 111 //! 112 //! @return 生成されたアニメーションバインディングです。 113 //! Create(os::IAllocator * allocator)114 AnimBinding* Create(os::IAllocator* allocator) 115 { 116 void* buf = allocator->Alloc(sizeof(AnimBinding)); 117 118 if (buf == NULL) 119 { 120 return NULL; 121 } 122 123 AnimBinding* animBinding = new(buf) AnimBinding(allocator, m_MaxAnimObjectsPerGroup); 124 125 Result result = animBinding->Initialize(m_MaxAnimGroups, m_MaxAnimObjectsPerGroup); 126 127 if (result.IsSuccess()) 128 { 129 return animBinding; 130 } 131 else 132 { 133 SafeDestroy(animBinding); 134 return NULL; 135 } 136 } 137 138 private: 139 int m_MaxAnimGroups; 140 int m_MaxAnimObjectsPerGroup; 141 }; 142 143 //@} 144 145 //---------------------------------------- 146 //! @name 基本操作 147 //@{ 148 149 //! @brief アニメーションを評価して対象に書き込みます。 150 //! 151 //! SceneUpdater::UpdateAll から自動的に呼び出されます。 152 //! 通常は、ユーザーが呼び出す必要はありません。 153 //! 154 //! @param[in] timing 評価タイミングです。 155 //! 156 void Evaluate(anim::ResGraphicsAnimGroup::EvaluationTiming timing); 157 158 //! @brief 設定されたすべてのアニメーションオブジェクトのフレームを更新します。 159 //! 160 //! SceneUpdater::UpdateAll から自動的に呼び出されます。 161 //! 通常は、ユーザーが呼び出す必要はありません。 UpdateFrame()162 void UpdateFrame() 163 { 164 for (int animObjIdx = 0; animObjIdx < m_AnimObjects.Size(); ++animObjIdx) 165 { 166 if (m_AnimObjects[animObjIdx] != NULL) 167 { 168 m_AnimObjects[animObjIdx]->UpdateFrame(); 169 } 170 } 171 } 172 173 //@} 174 175 //---------------------------------------- 176 //! @name 取得/設定 177 //@{ 178 179 //! アニメーショングループ数を取得します。 GetAnimGroupCount()180 int GetAnimGroupCount() const { return m_AnimGroups.Size(); } 181 182 //! アニメーショングループを取得します。 GetAnimGroup(int groupIdx)183 const AnimGroup* GetAnimGroup(int groupIdx) const 184 { 185 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size()); 186 return m_AnimGroups[groupIdx]; 187 } 188 189 //! アニメーショングループを取得します。 GetAnimGroup(int groupIdx)190 AnimGroup* GetAnimGroup(int groupIdx) 191 { 192 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size()); 193 return m_AnimGroups[groupIdx]; 194 } 195 196 //! @brief アニメーショングループ名から、登録されているグループのインデックスを取得します。 197 //! 198 //! @param[in] animGroupName アニメーショングループ名です。 199 //! 200 //! @return アニメーショングループのインデックスです。 201 //! animGroupName に対応するアニメーショングループがない場合は -1 を返します。 202 //! GetAnimGroupIndex(const char * animGroupName)203 int GetAnimGroupIndex(const char* animGroupName) const 204 { 205 for (int groupIdx = 0; groupIdx < m_AnimGroups.Size(); ++groupIdx) 206 { 207 if (m_AnimGroups[groupIdx] != NULL && 208 ::std::strcmp(m_AnimGroups[groupIdx]->GetName(), animGroupName) == 0) 209 { 210 return groupIdx; 211 } 212 } 213 return -1; 214 } 215 216 //! アニメーショングループを設定します。 SetAnimGroup(int groupIdx,AnimGroup * animGroup)217 void SetAnimGroup(int groupIdx, AnimGroup* animGroup) 218 { 219 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size()); 220 m_AnimGroups[groupIdx] = animGroup; 221 } 222 223 //! アニメーションオブジェクトを取得します。 224 const AnimObject* GetAnimObject(int groupIdx, int objectIdx = 0) const 225 { 226 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimObjects.Size()); 227 NW_MINMAXLT_ASSERT(objectIdx, 0, m_AnimObjectCountPerGroup); 228 229 const int index = groupIdx * m_AnimObjectCountPerGroup + objectIdx; 230 return m_AnimObjects[index]; 231 } 232 233 //! アニメーションオブジェクトを取得します。 234 AnimObject* GetAnimObject(int groupIdx, int objectIdx = 0) 235 { 236 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size()); 237 NW_MINMAXLT_ASSERT(objectIdx, 0, m_AnimObjectCountPerGroup); 238 239 const int index = groupIdx * m_AnimObjectCountPerGroup + objectIdx; 240 return m_AnimObjects[index]; 241 } 242 243 //! @brief アニメーションオブジェクトを設定します。 244 //! アニメーションオブジェクトにバインドされたアニメーショングループの名前から、 245 //! アニメーションバインディング中の設定先グループを決定します。 246 //! 247 //! @param[in] animObject アニメーションオブジェクトです。 248 //! アニメーショングループにバインドされている必要があります。 249 //! @param[in] objectIdx アニメーショングループについてのアニメーションオブジェクトのindexです。 250 //! 複数個のアニメーションオブジェクトを一つのグループにバインドする際に指定します。 251 //! 252 //! @return 成功すれば true を返します。 253 //! 254 bool SetAnimObject(AnimObject* animObject, int objectIdx = 0) 255 { 256 const AnimGroup* animGroup = animObject->GetAnimGroup(); 257 NW_NULL_ASSERT(animGroup); 258 return SetAnimObject(animGroup->GetName(), animObject, objectIdx); 259 } 260 261 //! @brief アニメーションオブジェクトを設定します。 262 //! 263 //! @param[in] groupIdx アニメーションバインディング中の、バインド対象のグループのインデックスです。 264 //! @param[in] animObject アニメーションオブジェクトです。 265 //! @param[in] objectIdx アニメーショングループについてのアニメーションオブジェクトのindexです。 266 //! 複数個のアニメーションオブジェクトを一つのグループにバインドする際に指定します。 267 //! 268 //! @return 成功すれば true を返します。 269 //! 270 bool SetAnimObject(int groupIdx, AnimObject* animObject, int objectIdx = 0) 271 { 272 // ここでgroupIdxに入っているのは、対象のグループのインデックス 273 if ((0 <= groupIdx && groupIdx < m_AnimGroups.Size()) && 274 (0 <= objectIdx && objectIdx < m_AnimObjectCountPerGroup)) 275 { 276 const int index = groupIdx * m_AnimObjectCountPerGroup + objectIdx; 277 m_AnimObjects[index] = animObject; 278 return true; 279 } 280 return false; 281 } 282 283 //! @brief アニメーションオブジェクトを設定します。 284 //! 285 //! @param[in] animGroupName アニメーショングループ名です。 286 //! @param[in] animObject アニメーションオブジェクトです。 287 //! @param[in] objectIdx アニメーショングループについてのアニメーションオブジェクトのindexです。 288 //! 複数個のアニメーションオブジェクトを一つのグループにバインドする際に指定します。 289 //! 290 //! @return 成功すれば true を返します。 291 //! 292 bool SetAnimObject(const char* animGroupName, AnimObject* animObject, int objectIdx = 0) 293 { 294 return SetAnimObject(GetAnimGroupIndex(animGroupName), animObject, objectIdx); 295 } 296 297 //@} 298 299 protected: 300 //---------------------------------------- 301 //! @name コンストラクタ/デストラクタ 302 //@{ 303 304 //! コンストラクタです。 305 //! 306 //! :private AnimBinding(os::IAllocator * allocator,int maxAnimObjects)307 AnimBinding( 308 os::IAllocator* allocator, 309 int maxAnimObjects) 310 : GfxObject(allocator) 311 , m_AnimObjectCountPerGroup(maxAnimObjects) 312 { 313 } 314 315 //! デストラクタです。 316 //! 317 //! :private ~AnimBinding()318 virtual ~AnimBinding() 319 { 320 // AnimGroups, AnimObjects共に、中身は生成元で削除します。 321 // AnimBindingでは参照しているだけなので、何も行いません。 322 } 323 324 //@} 325 326 //! Initialize() の実行に必要なメモリサイズを取得します。 327 //! 328 //! :private GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,int maxAnimGroups,int maxAnimObjects)329 static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, int maxAnimGroups, int maxAnimObjects) 330 { 331 os::MemorySizeCalculator& size = *pSize; 332 333 const int animObjectCount = maxAnimGroups * maxAnimObjects; 334 335 size += sizeof(AnimGroup*) * maxAnimGroups; 336 size += sizeof(AnimObject*) * animObjectCount; 337 } 338 339 //! メンバを初期化します。 340 //! 341 //! :private Initialize(int maxAnimGroups,int maxAnimObjects)342 Result Initialize(int maxAnimGroups, int maxAnimObjects) 343 { 344 // AnimObjectの個数は、Builderで設定されたAnimObjectsの数 * Groupの数です。 345 const int animObjectCount = maxAnimGroups * maxAnimObjects; 346 347 Result result = INITIALIZE_RESULT_OK; 348 349 { 350 void* memory = GetAllocator().Alloc(sizeof(AnimGroup*) * maxAnimGroups); 351 if (memory == NULL) 352 { 353 result |= Result::MASK_FAIL_BIT; 354 } 355 NW_ENSURE_AND_RETURN(result); 356 357 m_AnimGroups = AnimGroupArray(memory, maxAnimGroups, &GetAllocator()); 358 } 359 { 360 void* memory = GetAllocator().Alloc(sizeof(AnimObject*) * animObjectCount); 361 if (memory == NULL) 362 { 363 result |= Result::MASK_FAIL_BIT; 364 } 365 NW_ENSURE_AND_RETURN(result); 366 367 m_AnimObjects = AnimObjectArray(memory, animObjectCount, &GetAllocator()); 368 } 369 370 for (int animGroupIdx = 0; animGroupIdx < maxAnimGroups; ++animGroupIdx) 371 { 372 m_AnimGroups.PushBackFast<AnimGroup*>(NULL); 373 } 374 375 for (int animObjectIdx = 0; animObjectIdx < animObjectCount; ++animObjectIdx) 376 { 377 m_AnimObjects.PushBackFast<AnimObject*>(NULL); 378 } 379 380 return result; 381 } 382 383 private: 384 //---------------------------------------- 385 // 評価 386 387 // ブレンダを使用しない場合の評価処理です。 388 // 不要なループを省略し、高速に処理します。 389 NW_FORCE_INLINE void EvaluateSimple(AnimGroup* animGroup, AnimEvaluator* evaluator); 390 NW_FORCE_INLINE void EvaluateTransformSimple(AnimGroup* animGroup, TransformAnimEvaluator* evaluator); 391 392 // ブレンダを使用する場合の評価処理です。 393 NW_FORCE_INLINE void EvaluateBlender(AnimGroup* animGroup, AnimObject* animObj); 394 395 NW_FORCE_INLINE void EvaluateTransformMember(AnimGroup* animGroup, int memberIdx, AnimObject* animObj); //!< @details :private 396 NW_FORCE_INLINE void EvaluateTransformMemberFast(AnimGroup* animGroup, int memberIdx, TransformAnimEvaluator* evaluator); //!< @details :private 397 NW_FORCE_INLINE void EvaluateMember(AnimGroup* animGroup, int memberIdx, AnimObject* animObj, int& lastTargetObjIdx, bool& targetObjSkipFlag); //!< @details :private 398 399 AnimGroupArray m_AnimGroups; //!< @details :private 400 AnimObjectArray m_AnimObjects; //!< @details :private 401 const int m_AnimObjectCountPerGroup; //!< @details :private 402 }; 403 404 } // namespace gfx 405 } // namespace nw 406 407 #endif // NW_GFX_ANIMBINDING_H_ 408