1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_AnimObject.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_ANIMOBJECT_H_
17 #define NW_GFX_ANIMOBJECT_H_
18
19 #include <nw/anim/anim_AnimFrameController.h>
20 #include <nw/anim/res/anim_ResAnim.h>
21 #include <nw/anim/res/anim_ResAnimGroup.h>
22 #include <nw/gfx/gfx_GfxObject.h>
23 #include <nw/math.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 SceneNode;
31 class AnimEvaluator;
32 class TransformAnimEvaluator;
33
34 //---------------------------------------------------------------------------
35 //! @brief アニメーションの重みを比較します。
36 //!
37 //! @param[in] weight 重み
38 //! @param[in] value 比較する値
39 //!
40 //! @return 重みと比較する値の誤差が許容値以下なら true を返します。
41 //---------------------------------------------------------------------------
42 NW_INLINE bool
AnimWeightNearlyEqual(const float weight,const float value)43 AnimWeightNearlyEqual(const float weight, const float value)
44 {
45 // 0.1%未満は無視することとします。
46 const float Epsilon = 0.001f;
47 return math::FAbs(weight - value) <= Epsilon;
48 }
49
50 //---------------------------------------------------------------------------
51 //! @brief アニメーションの重みが 0 にほぼ等しいか比較します。
52 //!
53 //! @param[in] weight 重み
54 //!
55 //! @return 重みと 0 との誤差が許容値以下なら true を返します。
56 //---------------------------------------------------------------------------
57 NW_INLINE bool
AnimWeightNearlyEqualZero(const float weight)58 AnimWeightNearlyEqualZero(const float weight)
59 {
60 return AnimWeightNearlyEqual(weight, 0.0f);
61 }
62
63 //---------------------------------------------------------------------------
64 //! @brief アニメーションの重みが 1 にほぼ等しいか比較します。
65 //!
66 //! @param[in] weight 重み
67 //!
68 //! @return 重みと 1 との誤差が許容値以下なら true を返します。
69 //---------------------------------------------------------------------------
70 NW_INLINE bool
AnimWeightNearlyEqualOne(const float weight)71 AnimWeightNearlyEqualOne(const float weight)
72 {
73 return AnimWeightNearlyEqual(weight, 1.0f);
74 }
75
76 //---------------------------------------------------------------------------
77 //! @brief アニメーションブレンドの重みを正規化するスケールを取得します。
78 //!
79 //! @param[in] weightSum 重みの合計です。
80 //!
81 //! @return 重みを正規化するスケールです。
82 //---------------------------------------------------------------------------
83 NW_INLINE float
GetAnimWeightNormalizeScale(float weightSum)84 GetAnimWeightNormalizeScale(float weightSum)
85 {
86 return
87 AnimWeightNearlyEqualOne(weightSum) ||
88 AnimWeightNearlyEqualZero(weightSum) ?
89 1.0f : 1.0f / weightSum;
90 }
91
92 //---------------------------------------------------------------------------
93 //! @brief アニメーション対象を抽象化するクラスです。
94 //!
95 //! アニメーション対象メンバへのポインタを保持します。
96 //! 対象メンバとはボーンのトランスフォーム、マテリアルのディフューズカラーといった単位です。
97 //!
98 //! また、対象メンバのオリジナル値(インスタンス生成時の値)を保存しています。
99 //---------------------------------------------------------------------------
100 class AnimGroup : public GfxObject
101 {
102 public:
103 //! @brief 評価前コールバック関数の定義です。
104 //! 対象オブジェクトの評価が必要なら true を返します。
105 typedef bool (*PreEvaluateCallback)(AnimGroup* animGroup, int targetObjIdx);
106
107 //----------------------------------------
108 //! @name 作成
109 //@{
110
111 //! アニメーショングループを構築するクラスです。
112 class Builder
113 {
114 public:
115 //! コンストラクタです。
Builder()116 Builder()
117 : m_SceneNode(NULL),
118 m_UseOriginalValue(false) {}
119
120 //! アニメーショングループリソースを設定します。
ResAnimGroup(anim::ResAnimGroup resAnimGroup)121 Builder& ResAnimGroup(anim::ResAnimGroup resAnimGroup)
122 {
123 m_ResAnimGroup = resAnimGroup;
124 return *this;
125 }
126
127 //! 対象となるシーンノードを設定します。
SetSceneNode(SceneNode * sceneNode)128 Builder& SetSceneNode(SceneNode* sceneNode) { m_SceneNode = sceneNode; return *this; }
129
130 //! オリジナル値を使用するかどうかを設定します。
UseOriginalValue(bool use)131 Builder& UseOriginalValue(bool use) { m_UseOriginalValue = use; return *this; }
132
133 //! @brief 生成時に必要なメモリサイズを取得します。
134 //!
135 //! メモリサイズは Builder の設定によって変化します。
136 //! すべての設定が終わった後にこの関数を呼び出してください。
137 //!
138 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
139 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
140 {
141 os::MemorySizeCalculator size(alignment);
142
143 GetMemorySizeInternal(&size);
144
145 return size.GetSizeWithPadding(alignment);
146 }
147
148 //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)149 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
150 {
151 os::MemorySizeCalculator& size = *pSize;
152
153 size += sizeof(AnimGroup);
154 AnimGroup::GetMemorySizeForInitialize(pSize, m_ResAnimGroup, m_UseOriginalValue);
155 }
156
157 //! @brief アニメーショングループを生成します。
158 //!
159 //! @param[in] allocator アロケータです。
160 //!
161 //! @return 生成されたアニメーショングループです。
162 //!
Create(os::IAllocator * allocator)163 AnimGroup* Create(os::IAllocator* allocator)
164 {
165 void* buf = allocator->Alloc(sizeof(AnimGroup));
166
167 if (buf == NULL)
168 {
169 return NULL;
170 }
171
172 AnimGroup* animGroup = new(buf) AnimGroup(m_ResAnimGroup, m_SceneNode, allocator);
173
174 Result result = animGroup->Initialize(m_UseOriginalValue);
175
176 if (result.IsSuccess())
177 {
178 return animGroup;
179 }
180 else
181 {
182 SafeDestroy(animGroup);
183 return NULL;
184 }
185 }
186
187 private:
188 SceneNode* m_SceneNode;
189 anim::ResAnimGroup m_ResAnimGroup;
190 bool m_UseOriginalValue;
191 };
192
193 //@}
194
195 //----------------------------------------
196 //! @name 取得/設定
197 //@{
198
199 //! アニメーショングループリソースを取得します。
GetResAnimGroup()200 anim::ResAnimGroup GetResAnimGroup() const { return m_ResAnimGroup; }
201
202 //! グラフィックスアニメーショングループリソースを取得します。
GetResGraphicsAnimGroup()203 anim::ResGraphicsAnimGroup GetResGraphicsAnimGroup() const
204 {
205 return *reinterpret_cast<const anim::ResGraphicsAnimGroup*>(&m_ResAnimGroup);
206 }
207
208 //! アニメーショングループメンバリソースを取得します。
GetResAnimGroupMember(int memberIdx)209 anim::ResAnimGroupMember GetResAnimGroupMember(int memberIdx) const { return m_ResAnimGroup.GetMemberInfoSet(memberIdx); }
210
211 //! アニメーショングループメンバリソースを取得します。
GetResAnimGroupMember(const char * key)212 anim::ResAnimGroupMember GetResAnimGroupMember(const char* key) const { return m_ResAnimGroup.GetMemberInfoSet(key); }
213
214 //! アニメーショングループメンバリソースのインデックスを取得します。
GetResAnimGroupMemberIndex(const char * key)215 int GetResAnimGroupMemberIndex(const char* key) const { return m_ResAnimGroup.GetMemberInfoSetIndex(key); }
216
217 //! 名前を取得します。
GetName()218 const char* GetName() const { return m_ResAnimGroup.GetName(); }
219
220 //! アニメーショングループメンバ数を取得します。
GetMemberCount()221 s32 GetMemberCount() const { return m_ResAnimGroup.GetMemberInfoSetCount(); }
222
223 //! アニメーショングループ内のブレンドオペレーションを取得します。
GetBlendOperationInGroup(int blendOpIdx)224 const anim::AnimBlendOp* GetBlendOperationInGroup(int blendOpIdx) const
225 {
226 NW_MINMAXLT_ASSERT(blendOpIdx, 0, m_BlendOperations.Size());
227 return m_BlendOperations[blendOpIdx];
228 }
229
230 //! アニメーショングループ内のブレンドオペレーションを設定します。
SetBlendOperationInGroup(int blendOpIdx,anim::AnimBlendOp * blendOp)231 void SetBlendOperationInGroup(int blendOpIdx, anim::AnimBlendOp* blendOp)
232 {
233 NW_MINMAXLT_ASSERT(blendOpIdx, 0, m_BlendOperations.Size());
234 m_BlendOperations[blendOpIdx] = blendOp;
235 }
236
237 //! メンバに対するブレンドオペレーションを取得します。
GetBlendOperation(int memberIdx)238 const anim::AnimBlendOp* GetBlendOperation(int memberIdx) const
239 {
240 return GetBlendOperationInGroup(
241 GetResAnimGroupMember(memberIdx).GetBlendOperationIndex());
242 }
243
244 //! 対象オブジェクトが属するシーンノードを取得します。
GetSceneNode()245 SceneNode* GetSceneNode() const { return m_SceneNode; }
246
247 //! 対象オブジェクトのインデックスを取得します。
GetTargetObjectIndex(int memberIdx)248 int GetTargetObjectIndex(int memberIdx) const
249 {
250 NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjectIndicies.Size());
251 return m_TargetObjectIndicies[memberIdx];
252 }
253
254 //! 対象オブジェクトのインデックスを設定します。
SetTargetObjectIndex(int memberIdx,const int targetObjIdx)255 void SetTargetObjectIndex(int memberIdx, const int targetObjIdx)
256 {
257 NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjectIndicies.Size());
258 m_TargetObjectIndicies[memberIdx] = targetObjIdx;
259 }
260
261 //! 対象オブジェクトのポインタを取得します。
GetTargetObject(int memberIdx)262 void* GetTargetObject(int memberIdx) const
263 {
264 NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjects.Size());
265 return m_TargetObjects[memberIdx];
266 }
267
268 //! 対象オブジェクトのポインタを設定します。
SetTargetObject(int memberIdx,void * object)269 void SetTargetObject(int memberIdx, void* object)
270 {
271 NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetObjects.Size());
272 m_TargetObjects[memberIdx] = object;
273 }
274
275 //! 対象メンバのポインタを取得します。
GetTargetPtr(int memberIdx)276 void* GetTargetPtr(int memberIdx) const
277 {
278 NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetPtrs.Size());
279 return m_TargetPtrs[memberIdx];
280 }
281
282 //! 対象メンバのポインタを設定します。
SetTargetPtr(int memberIdx,void * target)283 void SetTargetPtr(int memberIdx, void* target)
284 {
285 NW_MINMAXLT_ASSERT(memberIdx, 0, m_TargetPtrs.Size());
286 m_TargetPtrs[memberIdx] = target;
287 }
288
289 //! メンバのオリジナル値を持っているかどうかを取得します。
HasOriginalValue()290 bool HasOriginalValue() const { return m_OriginalValues.Size() != 0; }
291
292 //! メンバのオリジナル値を取得します。
GetOriginalValue(int memberIdx)293 const void* GetOriginalValue(int memberIdx) const
294 {
295 NW_MINMAXLT_ASSERT(memberIdx, 0, m_OriginalValues.Size());
296 return m_OriginalValues[memberIdx];
297 }
298
299 //! メンバのオリジナル値を設定します。
SetOriginalValue(int memberIdx,const void * value)300 void SetOriginalValue(int memberIdx, const void* value)
301 {
302 NW_MINMAXLT_ASSERT(memberIdx, 0, m_OriginalValues.Size());
303 m_OriginalValues[memberIdx] = value;
304 }
305
306 //! 評価前コールバック関数を取得します。
GetPreEvaluateCallback()307 PreEvaluateCallback GetPreEvaluateCallback() const { return m_PreEvaluateCallback; }
308
309 //! 評価前コールバック関数を設定します。
SetPreEvaluateCallback(PreEvaluateCallback function)310 void SetPreEvaluateCallback(PreEvaluateCallback function) { m_PreEvaluateCallback = function; }
311
312 //! フルベイクアニメーションを使用するかを取得します。
313 //!
314 //! :private
GetFullBakedAnimEnabled()315 bool GetFullBakedAnimEnabled() const { return m_FullBakedAnimEnabled; }
316
317 //! フルベイクアニメーションを使用するかを設定します。
318 //!
319 //! :private
SetFullBakedAnimEnabled(bool enable)320 void SetFullBakedAnimEnabled(bool enable) { m_FullBakedAnimEnabled = enable; }
321
322 //! @brief すべてのメンバをオリジナル値にリセットします。
323 void Reset();
324
325 //@}
326
327 protected:
328 //----------------------------------------
329 //! @name コンストラクタ/デストラクタ
330 //@{
331
332 //! コンストラクタです。
333 //!
334 //! :private
335 AnimGroup(
336 anim::ResAnimGroup resAnimGroup,
337 SceneNode* sceneNode,
338 os::IAllocator* allocator);
339
340 //! デストラクタです。
341 //!
342 //! :private
~AnimGroup()343 virtual ~AnimGroup() {}
344
345 //@}
346
347 //! Initialize() の実行に必要なメモリサイズを取得します。
348 //!
349 //! :private
350 static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, const anim::ResAnimGroup resAnimGroup, bool useOriginalValue);
351
352 //! メンバを初期化します。
353 //!
354 //! :private
355 Result Initialize(bool useOriginalValue);
356
357 private:
358 anim::ResAnimGroup m_ResAnimGroup; //!< アニメーショングループのリソースです。
359 ut::MoveArray<anim::AnimBlendOp*> m_BlendOperations; //!< ブレンドオペレーションです。
360
361 SceneNode* m_SceneNode; //!< 対象オブジェクトが属するシーンノードです。
362 ut::MoveArray<int> m_TargetObjectIndicies; //!< メンバごとの対象オブジェクトのインデックスです。
363 ut::MoveArray<void*> m_TargetObjects; //!< メンバごとの対象オブジェクトのポインタです。
364 ut::MoveArray<void*> m_TargetPtrs; //!< メンバごとの対象のポインタです。
365 ut::MoveArray<const void*> m_OriginalValues; //!< メンバごとのオリジナル値です。
366
367 PreEvaluateCallback m_PreEvaluateCallback; //!< 評価前コールバック関数です。
368
369 bool m_FullBakedAnimEnabled; //!< フルベイクアニメを使用するかを指定します。
370 };
371
372 //---------------------------------------------------------------------------
373 //! @brief アニメーション評価を抽象化するクラスです。
374 //! 抽象クラスですのでインスタンス化して使用することはできません。
375 //!
376 //! フレームを進める、各フレームの値を取得する、などの動作を抽象化しています。
377 //! 単一のアニメーションを評価する AnimEvaluator, 複数のアニメーションをブレンドする AnimBlender などの派生クラスがあります。
378 //---------------------------------------------------------------------------
379 class AnimObject : public GfxObject
380 {
381 public:
382 //! @details :private
383 NW_UT_RUNTIME_TYPEINFO;
384
385 //----------------------------------------
386 //! @name コンストラクタ/デストラクタ
387 //@{
388
389 //! コンストラクタです。
AnimObject(os::IAllocator * allocator,u32 animType)390 AnimObject(os::IAllocator* allocator, u32 animType)
391 : GfxObject(allocator),
392 m_AnimGroup(NULL),
393 m_AnimType(animType) {}
394
395 //! デストラクタです。
~AnimObject()396 virtual ~AnimObject() {}
397
398 //@}
399
400 //----------------------------------------
401 //! @name 基本操作
402 //@{
403
404 //! @brief アニメーションを関連付けます。
405 //!
406 //! @param[in] animGroup アニメーショングループです。
407 //!
408 //! @return バインドに成功したら true を返します。
409 //!
410 //! @sa TryBind
Bind(AnimGroup * animGroup)411 bool Bind(AnimGroup* animGroup)
412 {
413 return TryBind(animGroup).IsSuccess();
414 }
415
416 //! @brief アニメーションを関連付けます。
417 //!
418 //! Bind() よりも詳細なバインド結果を得ることができます。
419 //!
420 //! @param[in] animGroup アニメーショングループです。
421 //!
422 //! @return バインドの結果を返します。
423 //!
424 //! @sa Bind
425 //! @sa BindResult
426 virtual Result TryBind(AnimGroup* animGroup) = 0;
427
428 //! アニメーションの関連付けを解除します。
429 virtual void Release() = 0;
430
431 //! フレームを更新します。
432 virtual void UpdateFrame() = 0;
433
434 //@}
435
436 //----------------------------------------
437 //! @name 評価
438 //@{
439
440 //! @brief メンバ単位でアニメーション結果を取得します。
441 //!
442 //! @param[out] target アニメーション結果を書き込む対象です。
443 //! @param[in] memberIdx メンバインデックスです。
444 //!
445 //! @return アニメーション結果を返します。
446 //! ブレンドオペレーションを使用する場合は、返り値のアニメーション結果を使用してください。
447 //!
448 virtual const anim::AnimResult* GetResult(
449 void* target,
450 int memberIdx) const = 0;
451
452 //@}
453
454 //----------------------------------------
455 //! @name 取得/設定
456 //@{
457
458 //! アニメーショングループを取得します。
GetAnimGroup()459 const AnimGroup* GetAnimGroup() const { return m_AnimGroup; }
460
461 //! アニメーショングループを取得します。
GetAnimGroup()462 AnimGroup* GetAnimGroup() { return m_AnimGroup; }
463
464 //! アニメーショングループを設定します。
SetAnimGroup(AnimGroup * group)465 void SetAnimGroup(AnimGroup* group) { m_AnimGroup = group; }
466
467 //! @brief メンバに関連付けられたアニメーションが存在するかどうかを取得します。
468 //!
469 //! @param[in] memberIdx メンバインデックスです。
470 //!
471 //! @return アニメーションが存在すれば true を返します。
472 //!
473 virtual bool HasMemberAnim(int memberIdx) const = 0;
474
475 //@}
476
477 //----------------------------------------
478 //! @name キャッシュ
479 //@{
480
481 //! アニメーション評価結果の内部キャッシュが古ければ更新します。
482 virtual void UpdateCache() = 0;
483
484 //! @details :private
485 enum
486 {
487 ANIMTYPE_SIMPLE,
488 ANIMTYPE_TRANSFORM_SIMPLE,
489 ANIMTYPE_BLENDER
490 };
491
492 //! @details :private
GetAnimType()493 u32 GetAnimType() const { return m_AnimType; }
494
495 //@}
496
497 protected:
498 //! @details :private
499 AnimGroup* m_AnimGroup;
500 //! @details :private
501 u32 m_AnimType;
502 };
503
504 //---------------------------------------------------------------------------
505 //! @brief アニメーションの関連付け情報のクラスです。
506 //!
507 //! AnimObject と AnimGroup を関連付けて、アニメーションの再生を行います。
508 //---------------------------------------------------------------------------
509 class AnimBinding : public GfxObject
510 {
511 public:
512
513 //! アニメーショングループの MoveArray の定義です。
514 //!
515 //! :private
516 typedef ut::MoveArray<AnimGroup*> AnimGroupArray;
517
518 //! アニメーションオブジェクトの MoveArray の定義です。
519 //!
520 //! :private
521 typedef ut::MoveArray<AnimObject*> AnimObjectArray;
522
523 //----------------------------------------
524 //! @name 作成
525 //@{
526
527 //! アニメーションバインディングを構築するクラスです。
528 class Builder
529 {
530 public:
531 //! コンストラクタです。
Builder()532 Builder()
533 :
534 m_MaxAnimGroups(1),
535 m_MaxAnimObjectsPerGroup(1) {}
536
537 //! 最大アニメーショングループ数を設定します。
MaxAnimGroups(int maxAnimGroups)538 Builder& MaxAnimGroups(int maxAnimGroups)
539 {
540 NW_ASSERT(maxAnimGroups > 0);
541 m_MaxAnimGroups = maxAnimGroups;
542 return *this;
543 }
544
545 //! @brief アニメーショングループ内での最大アニメーションオブジェクト数を設定します。
546 //!
547 //! @details 複数のアニメーショングループを持つ場合は、そのうち最大のものを指定してください。
MaxAnimObjectsPerGroup(int maxAnimObjects)548 Builder& MaxAnimObjectsPerGroup(int maxAnimObjects)
549 {
550 NW_ASSERT(maxAnimObjects > 0);
551 m_MaxAnimObjectsPerGroup = maxAnimObjects;
552 return *this;
553 }
554
555 //! @brief 生成時に必要なメモリサイズを取得します。
556 //!
557 //! メモリサイズは Builder の設定によって変化します。
558 //! すべての設定が終わった後にこの関数を呼び出してください。
559 //!
560 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
561 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
562 {
563 os::MemorySizeCalculator size(alignment);
564
565 GetMemorySizeInternal(&size);
566
567 return size.GetSizeWithPadding(alignment);
568 }
569
570 //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)571 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
572 {
573 os::MemorySizeCalculator& size = *pSize;
574
575 size += sizeof(AnimBinding);
576 AnimBinding::GetMemorySizeForInitialize(pSize, m_MaxAnimGroups, m_MaxAnimObjectsPerGroup);
577 }
578
579 //! @brief アニメーションバインディングを生成します。
580 //!
581 //! @param[in] allocator アロケータです。
582 //!
583 //! @return 生成されたアニメーションバインディングです。
584 //!
Create(os::IAllocator * allocator)585 AnimBinding* Create(os::IAllocator* allocator)
586 {
587 void* buf = allocator->Alloc(sizeof(AnimBinding));
588
589 if (buf == NULL)
590 {
591 return NULL;
592 }
593
594 AnimBinding* animBinding = new(buf) AnimBinding(allocator, m_MaxAnimObjectsPerGroup);
595
596 Result result = animBinding->Initialize(m_MaxAnimGroups, m_MaxAnimObjectsPerGroup);
597
598 if (result.IsSuccess())
599 {
600 return animBinding;
601 }
602 else
603 {
604 SafeDestroy(animBinding);
605 return NULL;
606 }
607 }
608
609 private:
610 int m_MaxAnimGroups;
611 int m_MaxAnimObjectsPerGroup;
612 };
613
614 //@}
615
616 //----------------------------------------
617 //! @name 基本操作
618 //@{
619
620 //! @brief アニメーションを評価して対象に書き込みます。
621 //!
622 //! SceneUpdater::UpdateAll から自動的に呼び出されます。
623 //! 通常は、ユーザーが呼び出す必要はありません。
624 //!
625 //! @param[in] timing 評価タイミングです。
626 //!
627 void Evaluate(anim::ResGraphicsAnimGroup::EvaluationTiming timing);
628
629 //! @brief 設定されたすべてのアニメーションオブジェクトのフレームを更新します。
630 //!
631 //! SceneUpdater::UpdateAll から自動的に呼び出されます。
632 //! 通常は、ユーザーが呼び出す必要はありません。
UpdateFrame()633 void UpdateFrame()
634 {
635 for (int animObjIdx = 0; animObjIdx < m_AnimObjects.Size(); ++animObjIdx)
636 {
637 if (m_AnimObjects[animObjIdx] != NULL)
638 {
639 m_AnimObjects[animObjIdx]->UpdateFrame();
640 }
641 }
642 }
643
644 //@}
645
646 //----------------------------------------
647 //! @name 取得/設定
648 //@{
649
650 //! アニメーショングループ数を取得します。
GetAnimGroupCount()651 int GetAnimGroupCount() const { return m_AnimGroups.Size(); }
652
653 //! アニメーショングループを取得します。
GetAnimGroup(int groupIdx)654 const AnimGroup* GetAnimGroup(int groupIdx) const
655 {
656 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size());
657 return m_AnimGroups[groupIdx];
658 }
659
660 //! アニメーショングループを取得します。
GetAnimGroup(int groupIdx)661 AnimGroup* GetAnimGroup(int groupIdx)
662 {
663 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size());
664 return m_AnimGroups[groupIdx];
665 }
666
667 //! @brief アニメーショングループ名から、登録されているグループのインデックスを取得します。
668 //!
669 //! @param[in] animGroupName アニメーショングループ名です。
670 //!
671 //! @return アニメーショングループのインデックスです。
672 //! animGroupName に対応するアニメーショングループがない場合は -1 を返します。
673 //!
GetAnimGroupIndex(const char * animGroupName)674 int GetAnimGroupIndex(const char* animGroupName) const
675 {
676 for (int groupIdx = 0; groupIdx < m_AnimGroups.Size(); ++groupIdx)
677 {
678 if (m_AnimGroups[groupIdx] != NULL &&
679 ::std::strcmp(m_AnimGroups[groupIdx]->GetName(), animGroupName) == 0)
680 {
681 return groupIdx;
682 }
683 }
684 return -1;
685 }
686
687 //! アニメーショングループを設定します。
SetAnimGroup(int groupIdx,AnimGroup * animGroup)688 void SetAnimGroup(int groupIdx, AnimGroup* animGroup)
689 {
690 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size());
691 m_AnimGroups[groupIdx] = animGroup;
692 }
693
694 //! アニメーションオブジェクトを取得します。
695 const AnimObject* GetAnimObject(int groupIdx, int objectIdx = 0) const
696 {
697 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimObjects.Size());
698 NW_MINMAXLT_ASSERT(objectIdx, 0, m_AnimObjectCountPerGroup);
699
700 const int index = groupIdx * m_AnimObjectCountPerGroup + objectIdx;
701 return m_AnimObjects[index];
702 }
703
704 //! アニメーションオブジェクトを取得します。
705 AnimObject* GetAnimObject(int groupIdx, int objectIdx = 0)
706 {
707 NW_MINMAXLT_ASSERT(groupIdx, 0, m_AnimGroups.Size());
708 NW_MINMAXLT_ASSERT(objectIdx, 0, m_AnimObjectCountPerGroup);
709
710 const int index = groupIdx * m_AnimObjectCountPerGroup + objectIdx;
711 return m_AnimObjects[index];
712 }
713
714 //! @brief アニメーションオブジェクトを設定します。
715 //! アニメーションオブジェクトにバインドされたアニメーショングループの名前から、
716 //! アニメーションバインディング中の設定先グループを決定します。
717 //!
718 //! @param[in] animObject アニメーションオブジェクトです。
719 //! アニメーショングループにバインドされている必要があります。
720 //! @param[in] objectIdx アニメーショングループについてのアニメーションオブジェクトのindexです。
721 //! 複数個のアニメーションオブジェクトを一つのグループにバインドする際に指定します。
722 //!
723 //! @return 成功すれば true を返します。
724 //!
725 bool SetAnimObject(AnimObject* animObject, int objectIdx = 0)
726 {
727 const AnimGroup* animGroup = animObject->GetAnimGroup();
728 NW_NULL_ASSERT(animGroup);
729 return SetAnimObject(animGroup->GetName(), animObject, objectIdx);
730 }
731
732 //! @brief アニメーションオブジェクトを設定します。
733 //!
734 //! @param[in] groupIdx アニメーションバインディング中の、バインド対象のグループのインデックスです。
735 //! @param[in] animObject アニメーションオブジェクトです。
736 //! @param[in] objectIdx アニメーショングループについてのアニメーションオブジェクトのindexです。
737 //! 複数個のアニメーションオブジェクトを一つのグループにバインドする際に指定します。
738 //!
739 //! @return 成功すれば true を返します。
740 //!
741 bool SetAnimObject(int groupIdx, AnimObject* animObject, int objectIdx = 0)
742 {
743 // ここでgroupIdxに入っているのは、対象のグループのインデックス
744 if ((0 <= groupIdx && groupIdx < m_AnimGroups.Size()) &&
745 (0 <= objectIdx && objectIdx < m_AnimObjectCountPerGroup))
746 {
747 const int index = groupIdx * m_AnimObjectCountPerGroup + objectIdx;
748 m_AnimObjects[index] = animObject;
749 return true;
750 }
751 return false;
752 }
753
754 //! @brief アニメーションオブジェクトを設定します。
755 //!
756 //! @param[in] animGroupName アニメーショングループ名です。
757 //! @param[in] animObject アニメーションオブジェクトです。
758 //! @param[in] objectIdx アニメーショングループについてのアニメーションオブジェクトのindexです。
759 //! 複数個のアニメーションオブジェクトを一つのグループにバインドする際に指定します。
760 //!
761 //! @return 成功すれば true を返します。
762 //!
763 bool SetAnimObject(const char* animGroupName, AnimObject* animObject, int objectIdx = 0)
764 {
765 return SetAnimObject(GetAnimGroupIndex(animGroupName), animObject, objectIdx);
766 }
767
768 //@}
769
770 protected:
771 //----------------------------------------
772 //! @name コンストラクタ/デストラクタ
773 //@{
774
775 //! コンストラクタです。
776 //!
777 //! :private
AnimBinding(os::IAllocator * allocator,int maxAnimObjects)778 AnimBinding(
779 os::IAllocator* allocator,
780 int maxAnimObjects)
781 : GfxObject(allocator)
782 , m_AnimObjectCountPerGroup(maxAnimObjects)
783 {
784 }
785
786 //! デストラクタです。
787 //!
788 //! :private
~AnimBinding()789 virtual ~AnimBinding()
790 {
791 // AnimGroups, AnimObjects共に、中身は生成元で削除します。
792 // AnimBindingでは参照しているだけなので、何も行いません。
793 }
794
795 //@}
796
797 //! Initialize() の実行に必要なメモリサイズを取得します。
798 //!
799 //! :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,int maxAnimGroups,int maxAnimObjects)800 static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, int maxAnimGroups, int maxAnimObjects)
801 {
802 os::MemorySizeCalculator& size = *pSize;
803
804 const int animObjectCount = maxAnimGroups * maxAnimObjects;
805
806 size += sizeof(AnimGroup*) * maxAnimGroups;
807 size += sizeof(AnimObject*) * animObjectCount;
808 }
809
810 //! メンバを初期化します。
811 //!
812 //! :private
Initialize(int maxAnimGroups,int maxAnimObjects)813 Result Initialize(int maxAnimGroups, int maxAnimObjects)
814 {
815 // AnimObjectの個数は、Builderで設定されたAnimObjectsの数 * Groupの数です。
816 const int animObjectCount = maxAnimGroups * maxAnimObjects;
817
818 Result result = INITIALIZE_RESULT_OK;
819
820 {
821 void* memory = GetAllocator().Alloc(sizeof(AnimGroup*) * maxAnimGroups);
822 if (memory == NULL)
823 {
824 result |= Result::MASK_FAIL_BIT;
825 }
826 NW_ENSURE_AND_RETURN(result);
827
828 m_AnimGroups = AnimGroupArray(memory, maxAnimGroups, &GetAllocator());
829 }
830 {
831 void* memory = GetAllocator().Alloc(sizeof(AnimObject*) * animObjectCount);
832 if (memory == NULL)
833 {
834 result |= Result::MASK_FAIL_BIT;
835 }
836 NW_ENSURE_AND_RETURN(result);
837
838 m_AnimObjects = AnimObjectArray(memory, animObjectCount, &GetAllocator());
839 }
840
841 for (int animGroupIdx = 0; animGroupIdx < maxAnimGroups; ++animGroupIdx)
842 {
843 m_AnimGroups.PushBackFast<AnimGroup*>(NULL);
844 }
845
846 for (int animObjectIdx = 0; animObjectIdx < animObjectCount; ++animObjectIdx)
847 {
848 m_AnimObjects.PushBackFast<AnimObject*>(NULL);
849 }
850
851 return result;
852 }
853
854 private:
855 //----------------------------------------
856 // 評価
857
858 // ブレンダを使用しない場合の評価処理です。
859 // 不要なループを省略し、高速に処理します。
860 NW_FORCE_INLINE void EvaluateSimple(AnimGroup* animGroup, AnimEvaluator* evaluator);
861 NW_FORCE_INLINE void EvaluateTransformSimple(AnimGroup* animGroup, TransformAnimEvaluator* evaluator);
862
863 // ブレンダを使用する場合の評価処理です。
864 NW_FORCE_INLINE void EvaluateBlender(AnimGroup* animGroup, AnimObject* animObj);
865
866 NW_FORCE_INLINE void EvaluateTransformMember(AnimGroup* animGroup, int memberIdx, AnimObject* animObj); //!< @details :private
867 NW_FORCE_INLINE void EvaluateTransformMemberFast(AnimGroup* animGroup, int memberIdx, TransformAnimEvaluator* evaluator); //!< @details :private
868 NW_FORCE_INLINE void EvaluateMember(AnimGroup* animGroup, int memberIdx, AnimObject* animObj, int& lastTargetObjIdx, bool& targetObjSkipFlag); //!< @details :private
869
870 AnimGroupArray m_AnimGroups; //!< @details :private
871 AnimObjectArray m_AnimObjects; //!< @details :private
872 const int m_AnimObjectCountPerGroup; //!< @details :private
873 };
874
875 //---------------------------------------------------------------------------
876 //! @brief アニメーション評価の基底クラスです。
877 //! 抽象クラスですのでインスタンス化して使用することはできません。
878 //---------------------------------------------------------------------------
879 class BaseAnimEvaluator : public AnimObject
880 {
881 public:
882 NW_UT_RUNTIME_TYPEINFO;
883
884 //! 関連付け対象がない場合のインデックスです。
885 //!
886 //! :private
887 static const int NotFoundIndex;
888
889 //----------------------------------------
890 //! @name コンストラクタ/デストラクタ
891 //@{
892
893 //! コンストラクタです。
BaseAnimEvaluator(os::IAllocator * allocator,u32 animType)894 BaseAnimEvaluator(
895 os::IAllocator* allocator, u32 animType)
896 : AnimObject(allocator, animType),
897 m_IsCacheDirty(true),
898 m_IsCacheExternal(false)
899 {
900 }
901
902 //! デストラクタです。
~BaseAnimEvaluator()903 virtual ~BaseAnimEvaluator() {}
904
905 //@}
906
907 //----------------------------------------
908 //! @name 基本操作
909 //@{
910
911 //! @brief アニメーションを関連付けます。
912 //!
913 //! Bind よりも詳細なバインド結果を得ることができます。
914 //!
915 //! @param[in] animGroup アニメーショングループです。
916 //!
917 //! @return バインドの結果を返します。
918 //!
919 //! @sa Bind
920 //! @sa TryBindResult
921 virtual Result TryBind(AnimGroup* animGroup);
922
923 //! アニメーションの関連付けを解除します。
Release()924 virtual void Release()
925 {
926 m_AnimGroup = NULL;
927 }
928
929 //! フレームを更新します。
UpdateFrame()930 virtual void UpdateFrame()
931 {
932 // 更新フレームが 0 の場合は、SetStepFrame() で
933 // キャッシュを更新済みです。
934 if (GetStepFrame() != 0.0f)
935 {
936 m_AnimFrameController.UpdateFrame();
937 m_IsCacheDirty = true;
938 }
939 }
940
941 //! @brief アニメーションを変更します。
942 //!
943 //! AnimEvaluator::Bind の後でアニメーションを差し替える場合に使用します。
944 //! AnimEvaluator を破棄して再生成するより高速です。
945 //!
946 //! 再生フレームは 0.0f にリセットされます。
947 //!
948 //! @param animData アニメーションデータです。
ChangeAnim(const nw::anim::ResAnim animData)949 virtual void ChangeAnim(const nw::anim::ResAnim animData)
950 {
951 NW_NULL_ASSERT(m_AnimGroup);
952
953 // このASSERTが失敗した場合は、Builder::MaxAnimMembers の値を大きくしてください
954 NW_ASSERT(animData.GetMemberAnimSetCount() <= m_ReverseBindIndexTable.Capacity());
955
956 SetResAnim(animData);
957
958 AnimGroup* animGroup = m_AnimGroup;
959 Release();
960 Bind(animGroup);
961 }
962
963 //! @brief すべてのアニメーション対象メンバーを生成時の状態に戻します。
964 //!
965 //! マテリアルに対して行う場合、マテリアルのバッファを生成する必要があります。
966 //! SceneBuilder クラスでモデルを作成する際のオプションで、
967 //! SceneBuilder::MaterialBufferCount と SceneBuilder::BufferOption を設定してください。
968 //! BufferOption には、 Model::MULTI_FLAG_ANIMATABLE_MATERIAL の内容が最低限必要です。
Reset()969 void Reset()
970 {
971 for (int i = (m_AnimGroup->GetMemberCount() - 1); i >= 0; --i)
972 {
973 this->ResetMember(i);
974 }
975 }
976
977 //! @brief 指定されたメンバーを生成時の状態に戻します。
978 //! @param memberIdx 対象のメンバーです。
979 void ResetMember(int memberIdx);
980
981 //@}
982
983 //----------------------------------------
984 //! @name フレーム制御
985 //@{
986
987 //! フレームを取得します。
GetFrame()988 float GetFrame() const { return m_AnimFrameController.GetFrame(); }
989
990 //! @brief フレームを設定します。
991 //!
992 //! @param[in] frame 設定するフレームです。
993 //!
SetFrame(float frame)994 void SetFrame(float frame)
995 {
996 m_AnimFrameController.SetFrame(frame);
997 m_IsCacheDirty = true;
998 }
999
1000 //! @brief フレームをリセットします。
1001 //!
1002 //! @param[in] frame 設定するフレームです。
1003 //!
ResetFrame(f32 frame)1004 void ResetFrame(f32 frame)
1005 {
1006 m_AnimFrameController.GetAnimFrame().ResetFrame(frame);
1007 m_IsCacheDirty = true;
1008 }
1009
1010 //! @brief フレームの増分を取得します。
1011 //! @sa SetStepFrame
GetStepFrame()1012 float GetStepFrame() const { return m_AnimFrameController.GetStepFrame(); }
1013
1014 //! @brief フレームの増分を設定します。
1015 //!
1016 //! UpdateFrame() を呼び出すと、現在のフレームにフレームの増分が加算されます。
1017 //! 例えば SetStepFrame(2.0f) とすると、2倍速再生になります。
1018 //!
1019 //! @param[in] stepFrame フレームの増分です。
SetStepFrame(float stepFrame)1020 void SetStepFrame(float stepFrame)
1021 {
1022 m_AnimFrameController.SetStepFrame(stepFrame);
1023 if (stepFrame == 0.0f)
1024 {
1025 m_IsCacheDirty = true;
1026 UpdateCache();
1027 }
1028 }
1029
1030 //! @brief 開始フレームを取得します。
1031 //! @sa SetStartFrame
GetStartFrame()1032 float GetStartFrame() const { return m_AnimFrameController.GetStartFrame(); }
1033
1034 //! @brief 開始フレームを設定します。
1035 //!
1036 //! 開始フレームを現在のフレームより後に設定した場合、
1037 //! 現在のフレームを開始フレームに移動します。
1038 //!
1039 //! @param[in] startFrame 開始フレームです。
SetStartFrame(float startFrame)1040 void SetStartFrame(float startFrame)
1041 {
1042 m_AnimFrameController.SetStartFrame(startFrame);
1043 if (startFrame > GetFrame())
1044 {
1045 SetFrame(startFrame);
1046 }
1047 }
1048
1049 //! @brief 終了フレームを取得します。
1050 //! @sa SetEndFrame
GetEndFrame()1051 float GetEndFrame() const { return m_AnimFrameController.GetEndFrame(); }
1052
1053 //! @brief 終了フレームを設定します。
1054 //!
1055 //! 終了フレームを現在のフレームより前に設定した場合、
1056 //! 現在のフレームを終了フレームに移動します。
1057 //!
1058 //! @param[in] endFrame 終了フレームです。
SetEndFrame(float endFrame)1059 void SetEndFrame(float endFrame)
1060 {
1061 m_AnimFrameController.SetEndFrame(endFrame);
1062 if (endFrame < GetFrame())
1063 {
1064 SetFrame(endFrame);
1065 }
1066 }
1067
1068 //! アニメーション再生方法を取得します。
GetPlayPolicy()1069 nw::anim::AnimFrameController::PlayPolicy GetPlayPolicy() const
1070 {
1071 return m_AnimFrameController.GetPlayPolicy();
1072 }
1073
1074 //! @brief アニメーション再生方法を設定します。
1075 //!
1076 //! @param[in] playPolicy 設定するアニメーション再生方法です。
1077 //! @sa nw::anim::AnimFrameController::SetPlayPolicy
SetPlayPolicy(nw::anim::AnimFrameController::PlayPolicy playPolicy)1078 void SetPlayPolicy(nw::anim::AnimFrameController::PlayPolicy playPolicy)
1079 {
1080 m_AnimFrameController.SetPlayPolicy(playPolicy);
1081 m_IsCacheDirty = true;
1082 }
1083
1084 //! アニメーションフレーム制御情報を取得します。
AnimFrameController()1085 const nw::anim::AnimFrameController& AnimFrameController() const { return m_AnimFrameController; }
1086
1087 //@}
1088
1089 //----------------------------------------
1090 //! @name 取得/設定
1091 //@{
1092
1093 //! ユーザーデータを取得します。
GetUserData()1094 const void* GetUserData() const { return m_AnimFrameController.GetUserData(); }
1095
1096 //! ユーザーデータを取得します。
GetUserData()1097 void* GetUserData() { return m_AnimFrameController.GetUserData(); }
1098
1099 //! @brief ユーザーデータを設定します。
1100 //!
1101 //! @param[in] userData 設定するユーザーデータです。
1102 //! @sa nw::anim::AnimFrameController::SetUserData
1103 //!
SetUserData(void * userData)1104 void SetUserData(void* userData) { m_AnimFrameController.SetUserData(userData); }
1105
1106 //! ResAnimGroupMember のインデックスから ResMemberAnim のインデックスへの変換テーブルを取得します。
BindIndexTable()1107 const ut::MoveArray<int>& BindIndexTable() const { return m_BindIndexTable; }
1108
1109 //! ResAnimGroupMember のインデックスから ResMemberAnim のインデックスへの変換テーブルを取得します。
BindIndexTable()1110 ut::MoveArray<int>& BindIndexTable() { return m_BindIndexTable; }
1111
1112 //! ResMemberAnim のインデックスから ResAnimGroupMember のインデックスへの変換テーブルを取得します。
ReverseBindIndexTable()1113 const ut::MoveArray<int>& ReverseBindIndexTable() const { return m_ReverseBindIndexTable; }
1114
1115 //! ResMemberAnim のインデックスから ResAnimGroupMember のインデックスへの変換テーブルを取得します。
ReverseBindIndexTable()1116 ut::MoveArray<int>& ReverseBindIndexTable() { return m_ReverseBindIndexTable; }
1117
1118 //! アニメーションデータを取得します。
GetAnimData()1119 const nw::anim::ResAnim GetAnimData() const { return m_AnimData; }
1120
1121 //@}
1122
1123 //----------------------------------------
1124 //! @name キャッシュ
1125 //@{
1126
1127 //! キャッシュバッファを取得します。
GetCacheBuffer()1128 virtual const void* GetCacheBuffer() const { return NULL; }
1129
1130 //! キャッシュバッファに必要なサイズ(バイト数)を取得します。
GetCacheBufferSizeNeeded()1131 virtual int GetCacheBufferSizeNeeded() const { return 0; }
1132
1133 //! @brief キャッシュバッファを設定します。
1134 //! この関数で指定したキャッシュバッファはデストラクタで解放されません。
1135 //!
1136 //! @param[in] buf キャッシュバッファ用のメモリの先頭アドレスです。
1137 //! NULL の場合、キャッシュが無効になります。
1138 //! @param[in] size キャッシュバッファのサイズ(バイト数)です。
1139 //!
SetCacheBuffer(void * buf,int size)1140 virtual void SetCacheBuffer(void* buf, int size)
1141 {
1142 (void)buf;
1143 (void)size;
1144 }
1145
1146 //@}
1147
1148 protected:
1149 //! Initialize() の実行に必要なメモリサイズを取得します。
1150 //!
1151 //! :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,const int maxMembers,const int maxAnimMembers)1152 static void GetMemorySizeForInitialize(
1153 os::MemorySizeCalculator* pSize,
1154 const int maxMembers,
1155 const int maxAnimMembers)
1156 {
1157 os::MemorySizeCalculator& size = *pSize;
1158
1159 size += sizeof(int) * maxMembers;
1160 size += sizeof(int) * maxAnimMembers;
1161 }
1162
1163 //! メンバを初期化します。
1164 //!
1165 //! :private
Initialize(const nw::anim::ResAnim & animData,const int maxMembers,const int maxAnimMembers)1166 virtual Result Initialize(
1167 const nw::anim::ResAnim& animData,
1168 const int maxMembers,
1169 const int maxAnimMembers)
1170 {
1171 Result result = INITIALIZE_RESULT_OK;
1172
1173 SetResAnim(animData);
1174
1175 {
1176 void* memory = GetAllocator().Alloc(sizeof(int) * maxMembers);
1177 if (memory == NULL)
1178 {
1179 result |= Result::MASK_FAIL_BIT;
1180 }
1181 NW_ENSURE_AND_RETURN(result);
1182
1183 m_BindIndexTable = ut::MoveArray<int>(memory, maxMembers, &GetAllocator());
1184 }
1185
1186 {
1187 void* memory = GetAllocator().Alloc(sizeof(int) * maxAnimMembers);
1188 if (memory == NULL)
1189 {
1190 result |= Result::MASK_FAIL_BIT;
1191 }
1192 NW_ENSURE_AND_RETURN(result);
1193
1194 m_ReverseBindIndexTable = ut::MoveArray<int>(memory, maxAnimMembers, &GetAllocator());
1195 }
1196
1197 return result;
1198 }
1199
1200 //! AnimGroupMemberのIndex -> MemberAnimのIndex
1201 //!
1202 //! :private
1203 ut::MoveArray<int> m_BindIndexTable;
1204
1205 //! MemberAnimのIndex -> AnimGroupMemberのIndex
1206 //!
1207 //! :private
1208 ut::MoveArray<int> m_ReverseBindIndexTable;
1209
1210 anim::AnimFrameController m_AnimFrameController; //!< @details :private
1211 anim::ResAnim m_AnimData; //!< @details :private
1212
1213 //! キャッシュの内容が古ければ true
1214 //!
1215 //! :private
1216 bool m_IsCacheDirty;
1217
1218 //! 外部から指定したキャッシュバッファなら true
1219 //!
1220 //! :private
1221 bool m_IsCacheExternal;
1222
1223 private:
SetResAnim(const nw::anim::ResAnim animData)1224 void SetResAnim(const nw::anim::ResAnim animData)
1225 {
1226 m_AnimData = animData;
1227 m_AnimFrameController.SetStepFrame(1.0f);
1228 m_AnimFrameController.SetStartFrame(0.0f);
1229 m_AnimFrameController.SetEndFrame(animData.GetFrameSize());
1230 m_AnimFrameController.GetAnimFrame().ResetFrame(0.0f);
1231
1232 switch (animData.GetLoopMode())
1233 {
1234 case nw::anim::ResAnimData::LOOP_MODE_ONETIME:
1235 m_AnimFrameController.SetPlayPolicy(nw::anim::PlayPolicy_Onetime);
1236 break;
1237
1238 case nw::anim::ResAnimData::LOOP_MODE_LOOP:
1239 m_AnimFrameController.SetPlayPolicy(nw::anim::PlayPolicy_Loop);
1240 break;
1241
1242 default:
1243 NW_ASSERT(false);
1244 }
1245
1246 m_IsCacheDirty = true;
1247 }
1248 };
1249
1250 //---------------------------------------------------------------------------
1251 //! @brief 汎用アニメーションを評価するクラスです。
1252 //!
1253 //! アニメーションデータを保持し、ファンクションカーブの評価を行います。
1254 //---------------------------------------------------------------------------
1255 class AnimEvaluator : public BaseAnimEvaluator
1256 {
1257 public:
1258 NW_UT_RUNTIME_TYPEINFO;
1259
1260 //----------------------------------------
1261 //! @name 作成
1262 //@{
1263
1264 //! 汎用アニメーション評価を構築するクラスです。
1265 class Builder
1266 {
1267 public:
1268 //! コンストラクタです。
Builder()1269 Builder()
1270 : m_AnimData(NULL),
1271 m_MaxMembers(64),
1272 m_MaxAnimMembers(64),
1273 m_AllocCache(false) {}
1274
1275 //! アニメーションデータを設定します。
AnimData(const nw::anim::ResAnim & animData)1276 Builder& AnimData(const nw::anim::ResAnim& animData) { m_AnimData = animData; return *this; }
1277
1278 //! @brief アニメーション対象メンバの最大数を設定します。
1279 //!
1280 //! AnimEvaluator::Bind に渡す AnimGroup の AnimGroup::GetMemberCount の値を設定してください。
1281 //! 複数の AnimGroup に Bind する場合は、最大値を設定してください。
MaxMembers(int maxMembers)1282 Builder& MaxMembers(int maxMembers)
1283 {
1284 NW_ASSERT(maxMembers > 0);
1285 m_MaxMembers = maxMembers;
1286 return *this;
1287 }
1288
1289 //! @brief 実際にアニメーションするメンバの最大数を設定します。
1290 //!
1291 //! AnimData() に渡す anim::res::ResAnim の anim::res::ResAnim::GetMemberAnimSetCount の値を設定してください。
1292 //! AnimEvaluator::ChangeAnim で複数の ResAnim を切り替える場合は、最大値を設定してください。
MaxAnimMembers(int maxAnimMembers)1293 Builder& MaxAnimMembers(int maxAnimMembers)
1294 {
1295 NW_ASSERT(maxAnimMembers > 0);
1296 m_MaxAnimMembers = maxAnimMembers;
1297 return *this;
1298 }
1299
1300 //! キャッシュバッファを確保してキャッシュを有効にするかどうかを設定します。
AllocCache(bool allocCache)1301 Builder& AllocCache(bool allocCache) { m_AllocCache = allocCache; return *this; }
1302
1303 //! @brief 生成時に必要なメモリサイズを取得します。
1304 //!
1305 //! メモリサイズは Builder の設定によって変化します。
1306 //! すべての設定が終わった後にこの関数を呼び出してください。
1307 //!
1308 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
1309 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
1310 {
1311 os::MemorySizeCalculator size(alignment);
1312
1313 GetMemorySizeInternal(&size);
1314
1315 return size.GetSizeWithPadding(alignment);
1316 }
1317
1318 //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1319 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
1320 {
1321 os::MemorySizeCalculator& size = *pSize;
1322
1323 size += sizeof(AnimEvaluator);
1324 AnimEvaluator::GetMemorySizeForInitialize(pSize, m_AnimData, m_MaxMembers, m_MaxAnimMembers, m_AllocCache);
1325 }
1326
1327 //! @brief 汎用アニメーション評価を生成します。
1328 //!
1329 //! @param[in] allocator アロケータです。
1330 //!
1331 //! @return 生成された汎用アニメーション評価です。
1332 //!
Create(os::IAllocator * allocator)1333 AnimEvaluator* Create(os::IAllocator* allocator)
1334 {
1335 void* buf = allocator->Alloc(sizeof(AnimEvaluator));
1336
1337 if (buf == NULL)
1338 {
1339 return NULL;
1340 }
1341
1342 AnimEvaluator* animEvaluator = new(buf) AnimEvaluator(allocator);
1343
1344 Result result = animEvaluator->Initialize(m_AnimData, m_MaxMembers, m_MaxAnimMembers, m_AllocCache);
1345 NW_ASSERT(result.IsSuccess());
1346
1347 return animEvaluator;
1348 }
1349
1350 private:
1351 nw::anim::ResAnim m_AnimData;
1352 int m_MaxMembers;
1353 int m_MaxAnimMembers;
1354 bool m_AllocCache;
1355 };
1356
1357 //@}
1358
1359 //----------------------------------------
1360 //! @name 基本操作
1361 //@{
1362
1363 //! @brief アニメーションを変更します。
1364 //!
1365 //! GetCacheBufferSizeNeeded() の値が変化しますので、
1366 //! SetCacheBuffer() している場合はバッファの再設定が必要です。
1367 //!
1368 //! 内部で確保したキャッシュバッファは、自動的にサイズ変更されます。
1369 //!
1370 //! @param animData アニメーションデータです。
1371 //! @sa BaseAnimEvaluator::ChangeAnim
ChangeAnim(const nw::anim::ResAnim animData)1372 virtual void ChangeAnim(const nw::anim::ResAnim animData)
1373 {
1374 // キャッシュサイズを求めるのにm_AnimDataを参照するので、
1375 // 先に更新する必要がある
1376 BaseAnimEvaluator::ChangeAnim(animData);
1377
1378 m_CachePtrs.Resize(animData.GetMemberAnimSetCount());
1379
1380 if (!m_IsCacheExternal && m_CacheBuf != NULL)
1381 {
1382 os::SafeFree(m_CacheBuf, &GetAllocator());
1383
1384 // サイズ0でのAllocを回避する
1385 // CreateEmpty~Anim()などを使用した場合に起こりうる
1386 if (animData.GetMemberAnimSetCount() != 0)
1387 {
1388 m_CacheBuf = GetAllocator().Alloc(GetCacheBufferSizeNeeded());
1389 NW_NULL_ASSERT(m_CacheBuf);
1390
1391 SetCacheBufferPointers();
1392 }
1393 }
1394 }
1395
1396 //@}
1397
1398 //----------------------------------------
1399 //! @name 評価
1400 //@{
1401
1402 //! @brief メンバ単位でアニメーション結果を取得します。
1403 //!
1404 //! @param[out] target アニメーション結果を書き込む対象です。
1405 //! @param[in] memberIdx メンバインデックスです。
1406 //!
1407 //! @return アニメーション結果を返します。
1408 //! ブレンドオペレーションを使用する場合は、返り値のアニメーション結果を使用してください。
1409 //!
1410 virtual const anim::AnimResult* GetResult(
1411 void* target,
1412 int memberIdx) const;
1413
1414 //@}
1415
1416 //----------------------------------------
1417 //! @name 取得/設定
1418 //@{
1419
1420 //! @brief メンバに関連付けられたアニメーションが存在するかどうかを取得します。
1421 //!
1422 //! @param[in] memberIdx メンバインデックスです。
1423 //!
1424 //! @return アニメーションが存在すれば true を返します。
1425 //!
HasMemberAnim(int memberIdx)1426 virtual bool HasMemberAnim(int memberIdx) const
1427 {
1428 NW_MINMAXLT_ASSERT(memberIdx, 0, m_BindIndexTable.Size());
1429 return m_BindIndexTable[memberIdx] != NotFoundIndex;
1430 }
1431
1432 //@}
1433
1434 //----------------------------------------
1435 //! @name キャッシュ
1436 //@{
1437
1438 //! アニメーション評価結果の内部キャッシュが古ければ更新します。
UpdateCache()1439 virtual void UpdateCache() { this->UpdateCacheNonVirtual(); }
1440
1441 //! :private
1442 void UpdateCacheNonVirtual();
1443
1444 //! キャッシュバッファに必要なサイズ(バイト数)を取得します。
1445 //! @return 必要なサイズ(バイト数)です。
1446 virtual int GetCacheBufferSizeNeeded() const;
1447
1448 //! キャッシュバッファを取得します。
GetCacheBuffer()1449 virtual const void* GetCacheBuffer() const { return m_CacheBuf; }
1450
1451 //! @brief キャッシュバッファを設定します。
1452 //! この関数で指定したキャッシュバッファはデストラクタで解放されません。
1453 //!
1454 //! @param[in] buf キャッシュバッファ用のメモリの先頭アドレスです。
1455 //! NULL の場合、キャッシュが無効になります。
1456 //! @param[in] size キャッシュバッファのサイズ(バイト数)です。
1457 //!
SetCacheBuffer(void * buf,int size)1458 virtual void SetCacheBuffer(void* buf, int size)
1459 {
1460 m_CacheBuf = buf;
1461 if (buf != NULL)
1462 {
1463 NW_ASSERT(size >= GetCacheBufferSizeNeeded());
1464 (void)size;
1465 m_IsCacheDirty = true;
1466 m_IsCacheExternal = true;
1467 SetCacheBufferPointers();
1468 }
1469 }
1470
1471 //@}
1472
1473 protected:
1474 //----------------------------------------
1475 //! @name コンストラクタ/デストラクタ
1476 //@{
1477
1478 //! コンストラクタです。
1479 //!
1480 //! :private
1481 AnimEvaluator(
1482 os::IAllocator* allocator);
1483
1484 //! デストラクタです。
1485 //!
1486 //! :private
~AnimEvaluator()1487 virtual ~AnimEvaluator()
1488 {
1489 if (!m_IsCacheExternal && m_CacheBuf != NULL)
1490 {
1491 GetAllocator().Free(m_CacheBuf);
1492 }
1493 }
1494
1495 //@}
1496
1497 //! Initialize() の実行に必要なメモリサイズを取得します。
1498 //!
1499 //! :private
1500 static void GetMemorySizeForInitialize(
1501 os::MemorySizeCalculator* pSize,
1502 const nw::anim::ResAnim& animData,
1503 const int maxMembers,
1504 const int maxAnimMembers,
1505 bool allocCache);
1506
1507 //! @details :private
1508 virtual Result Initialize(
1509 const nw::anim::ResAnim& animData,
1510 const int maxMembers,
1511 const int maxAnimMembers,
1512 bool allocCache);
1513
1514 //! キャッシュバッファに必要なサイズ(バイト数)を取得します。
1515 //!
1516 //! :private
1517 static int GetCacheBufferSizeNeeded(const anim::ResAnim& animData);
1518
1519 //! 各メンバアニメのキャッシュバッファへのポインタを設定します。
1520 //!
1521 //! :private
1522 void SetCacheBufferPointers();
1523
1524 //! AnimResult を実サイズで詰めたバッファ
1525 //!
1526 //! :private
1527 void* m_CacheBuf;
1528
1529 //! 各メンバアニメの m_CacheBuf 中のポインタ
1530 //!
1531 //! :private
1532 ut::MoveArray<anim::AnimResult*> m_CachePtrs;
1533 };
1534
1535 //---------------------------------------------------------------------------
1536 //! @brief 汎用アニメーションブレンドの基底クラスです。
1537 //! 抽象クラスですのでインスタンス化して使用することはできません。
1538 //!
1539 //! AnimBlender は複数の AnimEvaluator のアニメーション評価結果をブレンドします。
1540 //! AnimBlender で他の AnimBlender のアニメーション評価結果をブレンドすることも可能です。
1541 //---------------------------------------------------------------------------
1542 class AnimBlender : public AnimObject
1543 {
1544 public:
1545 NW_UT_RUNTIME_TYPEINFO;
1546
1547 //! アニメーションオブジェクトの MoveArray の定義です。
1548 //!
1549 //! :private
1550 typedef ut::MoveArray<AnimObject*> AnimObjectArray;
1551
1552 //----------------------------------------
1553 //! @name コンストラクタ/デストラクタ
1554 //@{
1555
1556 //! コンストラクタです。
AnimBlender(os::IAllocator * allocator)1557 AnimBlender(
1558 os::IAllocator* allocator)
1559 : AnimObject(allocator, ANIMTYPE_BLENDER)
1560 {
1561 }
1562
1563 //! デストラクタです。
~AnimBlender()1564 virtual ~AnimBlender() {}
1565
1566 //@}
1567
1568 //----------------------------------------
1569 //! @name 基本操作
1570 //@{
1571
1572 //! @brief アニメーションを関連付けます。
1573 //!
1574 //! Bind よりも詳細なバインド結果を得ることができます。
1575 //!
1576 //! @param[in] animGroup アニメーショングループです。
1577 //!
1578 //! @return バインドの結果を返します。
1579 //!
1580 //! @sa Bind
1581 //! @sa TryBindResult
TryBind(AnimGroup * animGroup)1582 virtual Result TryBind(AnimGroup* animGroup)
1583 {
1584 NW_NULL_ASSERT(animGroup);
1585 NW_ASSERT(m_AnimGroup == NULL);
1586 m_AnimGroup = animGroup;
1587 return Result(BIND_RESULT_OK);
1588 }
1589
1590 //! アニメーションの関連付けを解除します。
Release()1591 virtual void Release()
1592 {
1593 m_AnimGroup = NULL;
1594 }
1595
1596 //! フレームを更新します。
UpdateFrame()1597 virtual void UpdateFrame()
1598 {
1599 for (int animObjIdx = 0; animObjIdx < m_AnimObjects.Size(); ++animObjIdx)
1600 {
1601 if (m_AnimObjects[animObjIdx] != NULL)
1602 {
1603 m_AnimObjects[animObjIdx]->UpdateFrame();
1604 }
1605 }
1606 }
1607
1608 //@}
1609
1610 //----------------------------------------
1611 //! @name 取得/設定
1612 //@{
1613
1614 //! @brief メンバに関連付けられたアニメーションが存在するかどうかを取得します。
1615 //!
1616 //! @param[in] memberIdx メンバインデックスです。
1617 //!
1618 //! @return アニメーションが存在すれば true を返します。
1619 //!
HasMemberAnim(int memberIdx)1620 virtual bool HasMemberAnim(int memberIdx) const
1621 {
1622 for (int animObjIdx = 0; animObjIdx < m_AnimObjects.Size(); ++animObjIdx)
1623 {
1624 if (m_AnimObjects[animObjIdx] != NULL &&
1625 m_AnimObjects[animObjIdx]->HasMemberAnim(memberIdx))
1626 {
1627 return true;
1628 }
1629 }
1630 return false;
1631 }
1632
1633 //@}
1634
1635 //----------------------------------------
1636 //! @name アニメーションオブジェクト
1637 //@{
1638
1639 //! @brief アニメーションオブジェクトを追加します。
1640 //!
1641 //! @param[in] animObj 追加するアニメーションオブジェクトです。
1642 //! NULL を指定しておいて、後で ReplaceAnimObject() で置き換えることも可能です。
1643 //!
AddAnimObject(AnimObject * animObj)1644 void AddAnimObject(AnimObject* animObj)
1645 {
1646 NW_ASSERT(m_AnimObjects.Size() < m_AnimObjects.Capacity());
1647 m_AnimObjects.PushBack(animObj);
1648 }
1649
1650 //! @brief アニメーションオブジェクトを取得します。
1651 //!
1652 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。
1653 //!
1654 //! @return アニメーションオブジェクトです。
1655 //!
GetAnimObject(int animObjIdx)1656 const AnimObject* GetAnimObject(int animObjIdx) const
1657 {
1658 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_AnimObjects.Size());
1659 return m_AnimObjects[animObjIdx];
1660 }
1661
1662 //! @brief アニメーションオブジェクトを取得します。
1663 //!
1664 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。
1665 //!
1666 //! @return アニメーションオブジェクトです。
1667 //!
GetAnimObject(int animObjIdx)1668 AnimObject* GetAnimObject(int animObjIdx)
1669 {
1670 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_AnimObjects.Size());
1671 return m_AnimObjects[animObjIdx];
1672 }
1673
1674 //! @brief アニメーションオブジェクトを置き替えます。
1675 //!
1676 //! @param[in] animObjIdx 置き替えるアニメーションオブジェクトのインデックスです。
1677 //! @param[in] animObj アニメーションオブジェクトです。
1678 //! NULL を指定した場合、アニメーションオブジェクトがない状態になります。
1679 //!
1680 //! @return 置き替える前のアニメーションオブジェクトです。
1681 //!
ReplaceAnimObject(int animObjIdx,AnimObject * animObj)1682 AnimObject* ReplaceAnimObject(int animObjIdx, AnimObject* animObj)
1683 {
1684 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_AnimObjects.Size());
1685 AnimObject* oldObj = m_AnimObjects[animObjIdx];
1686 m_AnimObjects[animObjIdx] = animObj;
1687 return oldObj;
1688 }
1689
1690 //! アニメーションオブジェクトをクリアします。
ClearAnimObjects()1691 void ClearAnimObjects()
1692 {
1693 m_AnimObjects.Clear();
1694 }
1695
1696 //! 追加されているアニメーションオブジェクト数を取得します。
GetAnimObjectCount()1697 int GetAnimObjectCount() const
1698 {
1699 return m_AnimObjects.Size();
1700 }
1701
1702 //! アニメーションオブジェクトの最大数を取得します。
GetMaxAnimObjects()1703 int GetMaxAnimObjects() const
1704 {
1705 return m_AnimObjects.Capacity();
1706 }
1707
1708 //@}
1709
1710 //----------------------------------------
1711 //! @name キャッシュ
1712 //@{
1713
1714 //! アニメーション評価結果の内部キャッシュが古ければ更新します。
UpdateCache()1715 virtual void UpdateCache()
1716 {
1717 for (int animObjIdx = 0; animObjIdx < m_AnimObjects.Size(); ++animObjIdx)
1718 {
1719 if (m_AnimObjects[animObjIdx] != NULL)
1720 {
1721 m_AnimObjects[animObjIdx]->UpdateCache();
1722 }
1723 }
1724 }
1725
1726 //@}
1727
1728 protected:
1729 //! Initialize() の実行に必要なメモリサイズを取得します。
1730 //!
1731 //! :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,int maxAnimObjects)1732 static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, int maxAnimObjects)
1733 {
1734 os::MemorySizeCalculator& size = *pSize;
1735
1736 size += sizeof(AnimObject*) * maxAnimObjects;
1737 }
1738
1739 //! @details :private
Initialize(int maxAnimObjects)1740 virtual Result Initialize(int maxAnimObjects)
1741 {
1742 Result result = INITIALIZE_RESULT_OK;
1743
1744 void* memory = GetAllocator().Alloc(sizeof(AnimObject*) * maxAnimObjects);
1745
1746 if (memory == NULL)
1747 {
1748 result |= Result::MASK_FAIL_BIT;
1749 }
1750 NW_ENSURE_AND_RETURN(result);
1751
1752 m_AnimObjects = AnimObjectArray(memory, maxAnimObjects, &GetAllocator());
1753
1754 return result;
1755 }
1756
1757 AnimObjectArray m_AnimObjects; //!< @details :private
1758 };
1759
1760 //---------------------------------------------------------------------------
1761 //! @brief 汎用アニメーション評価結果を補間ブレンドするクラスです。
1762 //!
1763 //! 登録された全てのアニメーションオブジェクトの結果に重みをかけて、ブレンドした結果を採用します。
1764 //! アニメーションが無いメンバの場合は、モデルのロード時の状態(OriginalValue)をブレンド計算に使用します。
1765 //!
1766 //! デフォルトでは、ブレンドの重みは合計が 1.0 となるように正規化されてからブレンドされるので、重みの比率だけが意味を持ちます。
1767 //! 正規化が不要な場合は、 SetNormalizationEnabled() で無効化できます。
1768 //---------------------------------------------------------------------------
1769 class AnimInterpolator : public AnimBlender
1770 {
1771 public:
1772 NW_UT_RUNTIME_TYPEINFO;
1773
1774 //----------------------------------------
1775 //! @name 作成
1776 //@{
1777
1778 //! @brief 汎用アニメーション補間を構築するクラスです。
1779 //!
1780 //! バージョン 1.0.1 以前の補間法に戻すためには、IsOldMethod か IgnoreNoAnimMember に true を指定してください。
1781 //!
1782 //! 1.0.1 以前の補間方法と現在の補間方法の違いの詳細については、アニメーションのドキュメント(高度な機能)を参照ください。
1783 class Builder
1784 {
1785 public:
1786 //! コンストラクタです。
Builder()1787 Builder()
1788 : m_MaxAnimObjects(2),
1789 m_IgnoreNoAnimMember(false) {}
1790
1791 //! 最大アニメーションオブジェクト数を設定します。
MaxAnimObjects(int maxAnimObjects)1792 Builder& MaxAnimObjects(int maxAnimObjects)
1793 {
1794 NW_ASSERT(maxAnimObjects > 0);
1795 m_MaxAnimObjects = maxAnimObjects;
1796 return *this;
1797 }
1798
1799 //! @brief アニメーションが存在しないメンバを無視するかどうかを設定します。
1800 //!
1801 //! デフォルトでは、アニメーションが存在しないメンバはバインド時の値がブレンドされます。
1802 //! IgnoreNoAnimMember に true を設定すると、
1803 //! 重みの正規化がメンバ毎に行なわれ、アニメーションが存在しないメンバは重み 0 としてブレンドされます。
1804 //!
1805 //! この挙動は バージョン 1.0.1 以前の補間法と同じです。
1806 //!
IgnoreNoAnimMember(bool ignoreNoAnimMember)1807 Builder& IgnoreNoAnimMember(bool ignoreNoAnimMember) { m_IgnoreNoAnimMember = ignoreNoAnimMember; return *this; }
1808
1809 //! @brief 生成時に必要なメモリサイズを取得します。
1810 //!
1811 //! メモリサイズは Builder の設定によって変化します。
1812 //! すべての設定が終わった後にこの関数を呼び出してください。
1813 //!
1814 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
1815 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
1816 {
1817 os::MemorySizeCalculator size(alignment);
1818
1819 GetMemorySizeInternal(&size);
1820
1821 return size.GetSizeWithPadding(alignment);
1822 }
1823
1824 //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1825 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
1826 {
1827 os::MemorySizeCalculator& size = *pSize;
1828
1829 size += sizeof(AnimInterpolator);
1830 AnimInterpolator::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects);
1831 }
1832
1833 //! @brief 汎用アニメーション補間を生成します。
1834 //!
1835 //! @param[in] allocator アロケータです。
1836 //!
1837 //! @return 生成された汎用アニメーション補間です。
1838 //!
Create(os::IAllocator * allocator)1839 AnimInterpolator* Create(os::IAllocator* allocator)
1840 {
1841 void* buf = allocator->Alloc(sizeof(AnimInterpolator));
1842
1843 if (buf == NULL)
1844 {
1845 return NULL;
1846 }
1847
1848 AnimInterpolator* animInterpolator = new(buf) AnimInterpolator(allocator);
1849
1850 Result result = animInterpolator->Initialize(m_MaxAnimObjects, m_IgnoreNoAnimMember);
1851 NW_ASSERT(result.IsSuccess());
1852
1853 return animInterpolator;
1854 }
1855
1856 private:
1857 int m_MaxAnimObjects;
1858 bool m_IgnoreNoAnimMember;
1859 };
1860
1861 //@}
1862
1863 //----------------------------------------
1864 //! @name 評価
1865 //@{
1866
1867 //! @brief メンバ単位でアニメーション結果を取得します。
1868 //!
1869 //! @param[out] target アニメーション結果を書き込む対象です。
1870 //! @param[in] memberIdx メンバインデックスです。
1871 //!
1872 //! @return アニメーション結果を返します。
1873 //! ブレンドオペレーションを使用する場合は、返り値のアニメーション結果を使用してください。
1874 //!
1875 virtual const anim::AnimResult* GetResult(
1876 void* target,
1877 int memberIdx) const;
1878
1879 //@}
1880
1881 //----------------------------------------
1882 //! @name 取得/設定
1883 //@{
1884
1885 //! @brief アニメーションのブレンド重みを取得します。
1886 //!
1887 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。
1888 //!
1889 //! @return 重みです。
1890 //!
GetWeight(int animObjIdx)1891 float GetWeight(int animObjIdx) const
1892 {
1893 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_Weights.Size());
1894 return m_Weights[animObjIdx];
1895 }
1896
1897 //! @brief アニメーションのブレンド重みを設定します。
1898 //!
1899 //! ブレンド重みの解釈については、 SetNormalizationEnabled() を参照してください。
1900 //!
1901 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。
1902 //! @param[in] weight 重みです。
1903 //! @sa SetNormalizationEnabled
1904 //!
SetWeight(int animObjIdx,float weight)1905 void SetWeight(int animObjIdx, float weight)
1906 {
1907 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_Weights.Size());
1908 m_Weights[animObjIdx] = weight;
1909 m_NormalizedWeights[animObjIdx] = weight;
1910 m_IsWeightDirty = true;
1911 }
1912
1913 //! @brief アニメーションのブレンド重みを正規化するかを設定します。
1914 //!
1915 //! true を指定すると、ブレンド重みが合計で 1 になるよう正規化してからブレンドを行います。
1916 //! false を指定すると、SetWeight() で指定された重みがそのままブレンドに使用されますので、
1917 //! 重みの設定に注意してください。
1918 //!
1919 //! 正規化処理は、 SetWeight() 実行後の最初のアニメーションブレンド時に 1 度だけ行われます。
1920 //!
1921 //! Builder::IsOldMethod で true を指定していると、この設定は無視されます。
1922 //!
1923 //! デフォルト値は true です。
SetNormalizationEnabled(bool enabled)1924 void SetNormalizationEnabled(bool enabled){ m_IsWeightNormalizationEnabled = enabled; }
1925
1926 //! @brief アニメーションのブレンド重みを正規化するかの設定を取得します。
GetNormalizationEnabled()1927 bool GetNormalizationEnabled() const { return m_IsWeightNormalizationEnabled; }
1928
1929 //@}
1930
1931 protected:
1932 //----------------------------------------
1933 //! @name コンストラクタ/デストラクタ
1934 //@{
1935
1936 //! コンストラクタです。
1937 //!
1938 //! :private
AnimInterpolator(os::IAllocator * allocator)1939 AnimInterpolator(
1940 os::IAllocator* allocator)
1941 : AnimBlender(allocator),
1942 m_IsOldMethod(false),
1943 m_IsWeightDirty(false),
1944 m_IsWeightNormalizationEnabled(true)
1945 {
1946 }
1947
1948 //! デストラクタです。
1949 //!
1950 //! :private
~AnimInterpolator()1951 virtual ~AnimInterpolator() {}
1952
1953 //@}
1954
1955 //! Initialize() の実行に必要なメモリサイズを取得します。
1956 //!
1957 //! :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,int maxAnimObjects)1958 static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, int maxAnimObjects)
1959 {
1960 os::MemorySizeCalculator& size = *pSize;
1961
1962 AnimBlender::GetMemorySizeForInitialize(pSize, maxAnimObjects);
1963 size += sizeof(float) * maxAnimObjects;
1964 size += sizeof(float) * maxAnimObjects;
1965 }
1966
1967 //! @details :private
Initialize(int maxAnimObjects,bool ignoreNoAnimMember)1968 virtual Result Initialize(int maxAnimObjects, bool ignoreNoAnimMember)
1969 {
1970 Result result = AnimBlender::Initialize(maxAnimObjects);
1971 NW_ENSURE_AND_RETURN(result);
1972
1973 {
1974 void* memory = GetAllocator().Alloc(sizeof(float) * maxAnimObjects);
1975 if (memory == NULL)
1976 {
1977 result |= Result::MASK_FAIL_BIT;
1978 }
1979 NW_ENSURE_AND_RETURN(result);
1980
1981 m_Weights = ut::MoveArray<float>(memory, maxAnimObjects, &GetAllocator());
1982 for (int animObjIdx = 0; animObjIdx < maxAnimObjects; ++animObjIdx)
1983 {
1984 m_Weights.PushBackFast(animObjIdx == 0 ? 1.0f : 0.0f);
1985 }
1986 }
1987
1988 {
1989 void* memory = GetAllocator().Alloc(sizeof(float) * maxAnimObjects);
1990 if (memory == NULL)
1991 {
1992 result |= Result::MASK_FAIL_BIT;
1993 }
1994 NW_ENSURE_AND_RETURN(result);
1995
1996 m_NormalizedWeights = ut::MoveArray<float>(memory, maxAnimObjects, &GetAllocator());
1997 for (int animObjIdx = 0; animObjIdx < maxAnimObjects; ++animObjIdx)
1998 {
1999 m_NormalizedWeights.PushBackFast(animObjIdx == 0 ? 1.0f : 0.0f);
2000 }
2001 }
2002
2003 // TODO: 変数名その他を変更。
2004 m_IsOldMethod = ignoreNoAnimMember;
2005
2006 return result;
2007 }
2008
2009 //! @brief ブレンド重みを正規化します。
2010 //!
2011 //! :private
NormalizeWeight()2012 void NormalizeWeight() const
2013 {
2014 float weightSum = 0.0f;
2015 float normalizeScale;
2016 for (int i = 0; i < m_Weights.Size(); ++i)
2017 {
2018 weightSum += m_Weights[i];
2019 }
2020 normalizeScale = GetAnimWeightNormalizeScale(weightSum);
2021 for (int i = 0; i < m_Weights.Size(); ++i)
2022 {
2023 m_NormalizedWeights[i] = m_Weights[i] * normalizeScale;
2024 }
2025 m_IsWeightDirty = false;
2026 }
2027
2028 ut::MoveArray<float> m_Weights; //!< @details :private
2029 mutable ut::MoveArray<float> m_NormalizedWeights; //!< @details :private
2030
2031 bool m_IsOldMethod; //!< @details :private
2032 mutable bool m_IsWeightDirty; //!< @details :private
2033 bool m_IsWeightNormalizationEnabled; //!< @details :private
2034 };
2035
2036 //---------------------------------------------------------------------------
2037 //! @details :private
2038 //! @brief 汎用アニメーション評価結果を加算ブレンドするクラスです。
2039 //---------------------------------------------------------------------------
2040 class AnimAdder : public AnimBlender
2041 {
2042 public:
2043 NW_UT_RUNTIME_TYPEINFO;
2044
2045 //----------------------------------------
2046 //! @name 作成
2047 //@{
2048
2049 //! 汎用アニメーション補間を構築するクラスです。
2050 class Builder
2051 {
2052 public:
2053 //! コンストラクタです。
Builder()2054 Builder()
2055 : m_MaxAnimObjects(2) {}
2056
2057 //! 最大アニメーションオブジェクト数を設定します。
MaxAnimObjects(int maxAnimObjects)2058 Builder& MaxAnimObjects(int maxAnimObjects)
2059 {
2060 NW_ASSERT(maxAnimObjects > 0);
2061 m_MaxAnimObjects = maxAnimObjects;
2062 return *this;
2063 }
2064
2065 //! @brief 生成時に必要なメモリサイズを取得します。
2066 //!
2067 //! メモリサイズは Builder の設定によって変化します。
2068 //! すべての設定が終わった後にこの関数を呼び出してください。
2069 //!
2070 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
2071 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
2072 {
2073 os::MemorySizeCalculator size(alignment);
2074
2075 GetMemorySizeInternal(&size);
2076
2077 return size.GetSizeWithPadding(alignment);
2078 }
2079
2080 //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)2081 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
2082 {
2083 os::MemorySizeCalculator& size = *pSize;
2084
2085 size += sizeof(AnimAdder);
2086 AnimAdder::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects);
2087 }
2088
2089 //! @brief 汎用アニメーション補間を生成します。
2090 //!
2091 //! @param[in] allocator アロケータです。
2092 //!
2093 //! @return 生成された汎用アニメーション補間です。
2094 //!
Create(os::IAllocator * allocator)2095 AnimAdder* Create(os::IAllocator* allocator)
2096 {
2097 void* buf = allocator->Alloc(sizeof(AnimAdder));
2098
2099 if (buf == NULL)
2100 {
2101 return NULL;
2102 }
2103
2104 AnimAdder* animAdder = new(buf) AnimAdder(allocator);
2105
2106 Result result = animAdder->Initialize(m_MaxAnimObjects);
2107 NW_ASSERT(result.IsSuccess());
2108
2109 return animAdder;
2110 }
2111
2112 private:
2113 int m_MaxAnimObjects;
2114 };
2115
2116 //@}
2117
2118 //----------------------------------------
2119 //! @name 評価
2120 //@{
2121
2122 //! @brief メンバ単位でアニメーション結果を取得します。
2123 //!
2124 //! @param[out] target アニメーション結果を書き込む対象です。
2125 //! @param[in] memberIdx メンバインデックスです。
2126 //!
2127 //! @return アニメーション結果を返します。
2128 //! ブレンドオペレーションを使用する場合は、返り値のアニメーション結果を使用してください。
2129 //!
2130 virtual const anim::AnimResult* GetResult(
2131 void* target,
2132 int memberIdx) const;
2133
2134 //@}
2135
2136 //----------------------------------------
2137 //! @name 取得/設定
2138 //@{
2139
2140 //! @brief アニメーションのブレンド重みを取得します。
2141 //!
2142 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。
2143 //!
2144 //! @return 重みです。
2145 //!
GetWeight(int animObjIdx)2146 float GetWeight(int animObjIdx) const
2147 {
2148 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_Weights.Size());
2149 return m_Weights[animObjIdx];
2150 }
2151
2152 //! @brief アニメーションのブレンド重みを設定します。
2153 //!
2154 //! @param[in] animObjIdx アニメーションオブジェクトのインデックスです。
2155 //! @param[in] weight 重みです。
2156 //!
SetWeight(int animObjIdx,float weight)2157 void SetWeight(int animObjIdx, float weight)
2158 {
2159 NW_MINMAXLT_ASSERT(animObjIdx, 0, m_Weights.Size());
2160 m_Weights[animObjIdx] = weight;
2161 }
2162
2163 //@}
2164
2165 protected:
2166 //----------------------------------------
2167 //! @name コンストラクタ/デストラクタ
2168 //@{
2169
2170 //! コンストラクタです。
AnimAdder(os::IAllocator * allocator)2171 AnimAdder(
2172 os::IAllocator* allocator)
2173 : AnimBlender(allocator)
2174 {
2175 }
2176
2177 //! デストラクタです。
~AnimAdder()2178 virtual ~AnimAdder() {}
2179
2180 //@}
2181
2182 //! Initialize() の実行に必要なメモリサイズを取得します。
2183 //!
2184 //! :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,int maxAnimObjects)2185 static void GetMemorySizeForInitialize(os::MemorySizeCalculator* pSize, int maxAnimObjects)
2186 {
2187 os::MemorySizeCalculator& size = *pSize;
2188
2189 AnimBlender::GetMemorySizeForInitialize(pSize, maxAnimObjects);
2190 size += sizeof(float) * maxAnimObjects;
2191 }
2192
Initialize(int maxAnimObjects)2193 virtual Result Initialize(int maxAnimObjects)
2194 {
2195 Result result = AnimBlender::Initialize(maxAnimObjects);
2196 NW_ENSURE_AND_RETURN(result);
2197
2198 void* memory = GetAllocator().Alloc(sizeof(float) * maxAnimObjects);
2199 if (memory == NULL)
2200 {
2201 result |= Result::MASK_FAIL_BIT;
2202 }
2203 NW_ENSURE_AND_RETURN(result);
2204
2205 m_Weights = ut::MoveArray<float>(memory, maxAnimObjects, &GetAllocator());
2206 for (int animObjIdx = 0; animObjIdx < maxAnimObjects; ++animObjIdx)
2207 {
2208 m_Weights.PushBackFast(1.0f);
2209 }
2210
2211 return result;
2212 }
2213
2214 ut::MoveArray<float> m_Weights;
2215 };
2216
2217 //---------------------------------------------------------------------------
2218 //! @brief 汎用アニメーション評価結果を上書きブレンドするクラスです。
2219 //!
2220 //! AddAnimObject() で登録された順番にアニメーションオブジェクトを評価します。
2221 //! 同じメンバに複数のアニメーションがあった場合、後に登録されたアニメーションの結果で上書きされます。
2222 //! アニメーションを持っていないメンバについては、上書き処理は行われません。
2223 //---------------------------------------------------------------------------
2224 class AnimOverrider : public AnimBlender
2225 {
2226 public:
2227 NW_UT_RUNTIME_TYPEINFO;
2228
2229 //----------------------------------------
2230 //! @name 作成
2231 //@{
2232
2233 //! 汎用アニメーション補間を構築するクラスです。
2234 class Builder
2235 {
2236 public:
2237 //! コンストラクタです。
Builder()2238 Builder()
2239 : m_MaxAnimObjects(2) {}
2240
2241 //! 最大アニメーションオブジェクト数を設定します。
MaxAnimObjects(int maxAnimObjects)2242 Builder& MaxAnimObjects(int maxAnimObjects)
2243 {
2244 NW_ASSERT(maxAnimObjects > 0);
2245 m_MaxAnimObjects = maxAnimObjects;
2246 return *this;
2247 }
2248
2249 //! @brief 生成時に必要なメモリサイズを取得します。
2250 //!
2251 //! メモリサイズは Builder の設定によって変化します。
2252 //! すべての設定が終わった後にこの関数を呼び出してください。
2253 //!
2254 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
2255 size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
2256 {
2257 os::MemorySizeCalculator size(alignment);
2258
2259 GetMemorySizeInternal(&size);
2260
2261 return size.GetSizeWithPadding(alignment);
2262 }
2263
2264 //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)2265 void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
2266 {
2267 os::MemorySizeCalculator& size = *pSize;
2268
2269 size += sizeof(AnimOverrider);
2270 AnimOverrider::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects);
2271 }
2272
2273 //! @brief 汎用アニメーション補間を生成します。
2274 //!
2275 //! @param[in] allocator アロケータです。
2276 //!
2277 //! @return 生成された汎用アニメーション補間です。
2278 //!
Create(os::IAllocator * allocator)2279 AnimOverrider* Create(os::IAllocator* allocator)
2280 {
2281 void* buf = allocator->Alloc(sizeof(AnimOverrider));
2282
2283 if (buf == NULL)
2284 {
2285 return NULL;
2286 }
2287
2288 AnimOverrider* animOverrider = new(buf) AnimOverrider(allocator);
2289
2290 Result result = animOverrider->Initialize(m_MaxAnimObjects);
2291 NW_ASSERT(result.IsSuccess());
2292
2293 return animOverrider;
2294 }
2295
2296 private:
2297 int m_MaxAnimObjects;
2298 };
2299
2300 //@}
2301
2302 //----------------------------------------
2303 //! @name 評価
2304 //@{
2305
2306 //! @brief メンバ単位でアニメーション結果を取得します。
2307 //!
2308 //! @param[out] target アニメーション結果を書き込む対象です。
2309 //! @param[in] memberIdx メンバインデックスです。
2310 //!
2311 //! @return アニメーション結果を返します。
2312 //! ブレンドオペレーションを使用する場合は、返り値のアニメーション結果を使用してください。
2313 //!
2314 virtual const anim::AnimResult* GetResult(
2315 void* target,
2316 int memberIdx) const;
2317
2318 //@}
2319
2320 protected:
2321 //----------------------------------------
2322 //! @name コンストラクタ/デストラクタ
2323 //@{
2324
2325 //! コンストラクタです。
2326 //!
2327 //! :private
AnimOverrider(os::IAllocator * allocator)2328 AnimOverrider(
2329 os::IAllocator* allocator)
2330 : AnimBlender(allocator)
2331 {}
2332
2333 //! デストラクタです。
2334 //!
2335 //! :private
~AnimOverrider()2336 virtual ~AnimOverrider() {}
2337
2338 //@}
2339 };
2340
2341 } // namespace gfx
2342 } // namespace nw
2343
2344 #endif // NW_GFX_ANIMOBJECT_H_
2345