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