1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_TransformAnim.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_TRANSFORMANIM_H_
17 #define NW_GFX_TRANSFORMANIM_H_
18 
19 #include <nw/gfx/gfx_AnimObject.h>
20 #include <nw/gfx/gfx_CalculatedTransform.h>
21 
22 namespace nw {
23 namespace gfx {
24 
25 //---------------------------------------------------------------------------
26 //! @brief トランスフォームアニメーションのブレンドオペレーションの基底クラスです。
27 //---------------------------------------------------------------------------
28 class TransformAnimBlendOp : public anim::AnimBlendOp
29 {
30 public:
31     //! 無効な重み値です。
32     //!
33     //! :private
34     static const float WeightDiscard;
35 
36     //----------------------------------------
37     //! @name コンストラクタ/デストラクタ
38     //@{
39 
40     //! @brief コンストラクタです。
41     //!
42     //! @param[in] hasBlend ブレンド処理があるかどうかです。
43     //! @param[in] hasPostBlend ブレンド後の処理があるかどうかです。
44     //!
TransformAnimBlendOp(bool hasBlend,bool hasPostBlend)45     TransformAnimBlendOp(bool hasBlend, bool hasPostBlend)
46     : AnimBlendOp(hasBlend, hasPostBlend) {}
47 
48     //! デストラクタです。
~TransformAnimBlendOp()49     virtual ~TransformAnimBlendOp() {}
50 
51     //@}
52 
53 
54     //----------------------------------------
55     //! @name 適用
56     //@{
57 
58     //! @brief ブレンド処理結果を対象に適用します。
59     //!
60     //! @param[out] target ブレンド処理結果を適用する対象です。
61     //! @param[in] result ブレンド処理結果です。
62     //!
63     virtual void Apply(void* target, const anim::AnimResult* result) const;
64 
65     //! @brief 対象を AnimResult に変換します。
66     //!
67     //! @param[out] result 出力の AnimResult です。
68     //! @param[in] source 変換元へのポインタです。
69     //!
70     //! :private
71     virtual void ConvertToAnimResult(anim::AnimResult* result, const void* source) const;
72 
73     //@}
74 
75 protected:
76     //----------------------------------------
77     //! @name 基本ブレンド処理
78     //@{
79 
80     //! @details :private
81     enum BasicBlendFlags
82     {
83         FLAG_ACCURATE_SCALE_SHIFT = 0,
84         FLAG_QUATERNION_ROTATE_SHIFT = 1,
85 
86         // 正確なスケールブレンドをするかどうかです。
87         FLAG_ACCURATE_SCALE = 0x1 << FLAG_ACCURATE_SCALE_SHIFT,
88 
89         // クォータニオンで回転をブレンドするかどうかです。オフなら行列の回転成分をブレンドします。
90         FLAG_QUATERNION_ROTATE = 0x1 << FLAG_QUATERNION_ROTATE_SHIFT
91     };
92 
93     //! @brief 標準的なスケールのブレンド処理を行います。
94     //!
95     //! @param[in,out] dst ブレンド処理結果です。
96     //! @param[in] src ブレンド処理の入力です。
97     //! @param[in] weight ブレンド処理の入力の重みです。
98     //!
99     //! :private
100     void BlendScaleStandard(
101         CalculatedTransform* dst,
102         const CalculatedTransform* src,
103         const float weight) const;
104 
105     //! @brief 正確なスケールのブレンド処理を行います。
106     //!
107     //! @param[in,out] dst ブレンド処理結果です。
108     //! @param[in] src ブレンド処理の入力です。
109     //! @param[in] weight ブレンド処理の入力の重みです。
110     //!
111     //! :private
112     void BlendScaleAccurate(
113         CalculatedTransform* dst,
114         const CalculatedTransform* src,
115         const float weight) const;
116 
117     //! @brief 正確なスケールブレンドのブレンド後の処理を行います。
118     //!
119     //! :private
120     //!
121     //! @param[in,out] transform トランスフォームです。
122     //!
123     //! @return 正しく処理できれば true を返します。
124     bool PostBlendAccurateScale(CalculatedTransform* transform) const;
125 
126     //! @brief 行列の回転のブレンド処理を行います。
127     //!
128     //! @param[in,out] dst ブレンド処理結果です。
129     //! @param[in] src ブレンド処理の入力です。
130     //! @param[in] weight ブレンド処理の入力の重みです。
131     //!
132     //! :private
133     void BlendRotateMatrix(
134         CalculatedTransform* dst,
135         const CalculatedTransform* src,
136         const float weight) const;
137 
138     //! @brief クォータニオンの回転のブレンド処理を行います。
139     //!
140     //! @param[in,out] dst ブレンド処理結果です。
141     //! @param[in] src ブレンド処理の入力です。
142     //! @param[in] weight ブレンド処理の入力の重みです。
143     //!
144     //! :private
145     void BlendRotateQuaternion(
146         CalculatedTransform* dst,
147         const CalculatedTransform* src,
148         const float weight) const;
149 
150     //! @brief 移動のブレンド処理を行います。
151     //!
152     //! @param[in,out] dst ブレンド処理結果です。
153     //! @param[in] src ブレンド処理の入力です。
154     //! @param[in] weight ブレンド処理の入力の重みです。
155     //!
156     //! :private
157     void BlendTranslate(
158         CalculatedTransform* dst,
159         const CalculatedTransform* src,
160         const float weight) const;
161 
162     //! @brief トランスフォームの上書き処理を行います。
163     //!
164     //! :private
165     //!
166     //! @param[in,out] dst ブレンド処理結果です。
167     //! @param[in] src ブレンド処理の入力です。
168     //! @param[in] blendFlags ブレンド処理のフラグです。
169     //!
170     //! @return すべての成分が上書きされたら true を返します。
171     bool OverrideTransform(
172         CalculatedTransform* dst,
173         const CalculatedTransform* src,
174         const bit32 blendFlags
175     ) const;
176 
177     //@}
178 };
179 
180 //---------------------------------------------------------------------------
181 //! @brief トランスフォームアニメーションの標準的なブレンドオペレーションのクラスです。
182 //! 回転行列の各成分をブレンドした後に、正規直交化します。
183 //---------------------------------------------------------------------------
184 class TransformAnimBlendOpStandard : public TransformAnimBlendOp
185 {
186 public:
187     //----------------------------------------
188     //! @name コンストラクタ/デストラクタ
189     //@{
190 
191     //! コンストラクタです。
TransformAnimBlendOpStandard()192     TransformAnimBlendOpStandard()
193     : TransformAnimBlendOp(true, true)
194     {}
195 
196     //! デストラクタです。
~TransformAnimBlendOpStandard()197     virtual ~TransformAnimBlendOpStandard() {}
198 
199     //@}
200 
201     //----------------------------------------
202     //! @name ブレンド
203     //@{
204 
205     //! @brief ブレンド処理を行います。
206     //!
207     //! @param[in,out] dst ブレンド処理結果です。
208     //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。
209     //! このブレンドオペレーションでは使用しません。
210     //! @param[in] src ブレンド処理の入力です。
211     //! @param[in] srcWeights ブレンド処理の入力の重みです。
212     //!
213     //! @return ブレンド処理のループを継続するなら true を返します。
214     //!
Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)215     virtual bool Blend(
216         anim::AnimResult* dst,
217         float* dstWeights,
218         const anim::AnimResult* src,
219         const float* srcWeights) const
220     {
221         (void)dstWeights;
222         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
223         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
224         BlendScaleStandard(dstX, srcX, srcWeights[0]);
225         BlendRotateMatrix (dstX, srcX, srcWeights[1]);
226         BlendTranslate    (dstX, srcX, srcWeights[2]);
227         return true;
228     }
229 
230     //! @brief ブレンド後の処理を行います。
231     //!
232     //! @param[in,out] result ブレンド処理結果です。
233     //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。
234     //! このブレンドオペレーションでは使用しません。
235     //!
236     //! @return 成功すれば true を返します。
237     //!
PostBlend(anim::AnimResult * result,const float * weights)238     virtual bool PostBlend(anim::AnimResult* result, const float* weights) const
239     {
240         (void)weights;
241         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result);
242         return dstX->NormalizeRotateMatrix();
243     }
244 
245     //! @brief 上書き処理を行います。
246     //!
247     //! @param[in,out] dst ブレンド処理結果です。
248     //! @param[in] src ブレンド処理の入力です。
249     //!
250     //! @return すべての成分が上書きされたら true を返します。
251     //!
Override(anim::AnimResult * dst,const anim::AnimResult * src)252     virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const
253     {
254         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
255         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
256         return OverrideTransform(dstX, srcX, 0);
257     }
258 
259     //@}
260 };
261 
262 //---------------------------------------------------------------------------
263 //! @brief トランスフォームアニメーションの正確なスケールブレンドに対応したブレンドオペレーションのクラスです。
264 //---------------------------------------------------------------------------
265 class TransformAnimBlendOpAccScale : public TransformAnimBlendOp
266 {
267 public:
268     //----------------------------------------
269     //! @name コンストラクタ/デストラクタ
270     //@{
271 
272     //! コンストラクタです。
TransformAnimBlendOpAccScale()273     TransformAnimBlendOpAccScale()
274     : TransformAnimBlendOp(true, true)
275     {}
276 
277     //! デストラクタです。
~TransformAnimBlendOpAccScale()278     virtual ~TransformAnimBlendOpAccScale() {}
279 
280     //@}
281 
282     //----------------------------------------
283     //! @name ブレンド
284     //@{
285 
286     //! @brief ブレンド処理を行います。
287     //!
288     //! @param[in,out] dst ブレンド処理結果です。
289     //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。
290     //! このブレンドオペレーションでは使用しません。
291     //! @param[in] src ブレンド処理の入力です。
292     //! @param[in] srcWeights ブレンド処理の入力の重みです。
293     //!
294     //! @return ブレンド処理のループを継続するなら true を返します。
295     //!
Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)296     virtual bool Blend(
297         anim::AnimResult* dst,
298         float* dstWeights,
299         const anim::AnimResult* src,
300         const float* srcWeights) const
301     {
302         (void)dstWeights;
303         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
304         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
305         BlendScaleAccurate(dstX, srcX, srcWeights[0]);
306         BlendRotateMatrix (dstX, srcX, srcWeights[1]);
307         BlendTranslate    (dstX, srcX, srcWeights[2]);
308         return true;
309     }
310 
311     //! @brief ブレンド後の処理を行います。
312     //!
313     //! @param[in,out] result ブレンド処理結果です。
314     //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。
315     //! このブレンドオペレーションでは使用しません。
316     //!
317     //! @return 成功すれば true を返します。
318     //!
PostBlend(anim::AnimResult * result,const float * weights)319     virtual bool PostBlend(anim::AnimResult* result, const float* weights) const
320     {
321         (void)weights;
322         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result);
323         const bool scaleRet = PostBlendAccurateScale(dstX);
324         return dstX->NormalizeRotateMatrix() && scaleRet;
325     }
326 
327     //! @brief 上書き処理を行います。
328     //!
329     //! @param[in,out] dst ブレンド処理結果です。
330     //! @param[in] src ブレンド処理の入力です。
331     //!
332     //! @return すべての成分が上書きされたら true を返します。
333     //!
Override(anim::AnimResult * dst,const anim::AnimResult * src)334     virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const
335     {
336         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
337         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
338         return OverrideTransform(dstX, srcX, FLAG_ACCURATE_SCALE);
339     }
340 
341     //@}
342 };
343 
344 //---------------------------------------------------------------------------
345 //! @brief トランスフォームアニメーションのクォータニオンによる回転ブレンドに対応したブレンドオペレーションのクラスです。
346 //---------------------------------------------------------------------------
347 class TransformAnimBlendOpQuat : public TransformAnimBlendOp
348 {
349 public:
350     //----------------------------------------
351     //! @name コンストラクタ/デストラクタ
352     //@{
353 
354     //! コンストラクタです。
TransformAnimBlendOpQuat()355     TransformAnimBlendOpQuat()
356     : TransformAnimBlendOp(true, true)
357     {}
358 
359     //! デストラクタです。
~TransformAnimBlendOpQuat()360     virtual ~TransformAnimBlendOpQuat() {}
361 
362     //@}
363 
364     //----------------------------------------
365     //! @name ブレンド
366     //@{
367 
368     //! @brief ブレンド処理を行います。
369     //!
370     //! @param[in,out] dst ブレンド処理結果です。
371     //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。
372     //! このブレンドオペレーションでは使用しません。
373     //! @param[in] src ブレンド処理の入力です。
374     //! @param[in] srcWeights ブレンド処理の入力の重みです。
375     //!
376     //! @return ブレンド処理のループを継続するなら true を返します。
377     //!
Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)378     virtual bool Blend(
379         anim::AnimResult* dst,
380         float* dstWeights,
381         const anim::AnimResult* src,
382         const float* srcWeights) const
383     {
384         (void)dstWeights;
385         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
386         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
387         BlendScaleStandard   (dstX, srcX, srcWeights[0]);
388         BlendRotateQuaternion(dstX, srcX, srcWeights[1]);
389         BlendTranslate       (dstX, srcX, srcWeights[2]);
390         return true;
391     }
392 
393     //! @brief ブレンド後の処理を行います。
394     //!
395     //! @param[in,out] result ブレンド処理結果です。
396     //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。
397     //! このブレンドオペレーションでは使用しません。
398     //!
399     //! @return 成功すれば true を返します。
400     //!
PostBlend(anim::AnimResult * result,const float * weights)401     virtual bool PostBlend(anim::AnimResult* result, const float* weights) const
402     {
403         (void)weights;
404         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result);
405         return dstX->QuaternionToRotateMatrix();
406     }
407 
408     //! @brief 上書き処理を行います。
409     //!
410     //! @param[in,out] dst ブレンド処理結果です。
411     //! @param[in] src ブレンド処理の入力です。
412     //!
413     //! @return すべての成分が上書きされたら true を返します。
414     //!
Override(anim::AnimResult * dst,const anim::AnimResult * src)415     virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const
416     {
417         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
418         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
419         return OverrideTransform(dstX, srcX, FLAG_QUATERNION_ROTATE);
420     }
421 
422     //@}
423 };
424 
425 //---------------------------------------------------------------------------
426 //! @brief トランスフォームアニメーションの正確なスケールブレンドとクォータニオンによる回転ブレンドに対応したブレンドオペレーションのクラスです。
427 //---------------------------------------------------------------------------
428 class TransformAnimBlendOpAccScaleQuat : public TransformAnimBlendOp
429 {
430 public:
431     //----------------------------------------
432     //! @name コンストラクタ/デストラクタ
433     //@{
434 
435     //! コンストラクタです。
TransformAnimBlendOpAccScaleQuat()436     TransformAnimBlendOpAccScaleQuat()
437     : TransformAnimBlendOp(true, true)
438     {}
439 
440     //! デストラクタです。
~TransformAnimBlendOpAccScaleQuat()441     virtual ~TransformAnimBlendOpAccScaleQuat() {}
442 
443     //@}
444 
445     //----------------------------------------
446     //! @name ブレンド
447     //@{
448 
449     //! @brief ブレンド処理を行います。
450     //!
451     //! @param[in,out] dst ブレンド処理結果です。
452     //! @param[in,out] dstWeights ブレンド処理結果の成分ごとの重みの累積値です。
453     //! このブレンドオペレーションでは使用しません。
454     //! @param[in] src ブレンド処理の入力です。
455     //! @param[in] srcWeights ブレンド処理の入力の重みです。
456     //!
457     //! @return ブレンド処理のループを継続するなら true を返します。
458     //!
Blend(anim::AnimResult * dst,float * dstWeights,const anim::AnimResult * src,const float * srcWeights)459     virtual bool Blend(
460         anim::AnimResult* dst,
461         float* dstWeights,
462         const anim::AnimResult* src,
463         const float* srcWeights) const
464     {
465         (void)dstWeights;
466         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
467         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
468         BlendScaleAccurate   (dstX, srcX, srcWeights[0]);
469         BlendRotateQuaternion(dstX, srcX, srcWeights[1]);
470         BlendTranslate       (dstX, srcX, srcWeights[2]);
471         return true;
472     }
473 
474     //! @brief ブレンド後の処理を行います。
475     //!
476     //! @param[in,out] result ブレンド処理結果です。
477     //! @param[in] weights ブレンド処理結果の成分ごとの重みの累積値です。
478     //! このブレンドオペレーションでは使用しません。
479     //!
480     //! @return 成功すれば true を返します。
481     //!
PostBlend(anim::AnimResult * result,const float * weights)482     virtual bool PostBlend(anim::AnimResult* result, const float* weights) const
483     {
484         (void)weights;
485         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(result);
486         const bool scaleRet = PostBlendAccurateScale(dstX);
487         return dstX->QuaternionToRotateMatrix() && scaleRet;
488     }
489 
490     //! @brief 上書き処理を行います。
491     //!
492     //! @param[in,out] dst ブレンド処理結果です。
493     //! @param[in] src ブレンド処理の入力です。
494     //!
495     //! @return すべての成分が上書きされたら true を返します。
496     //!
Override(anim::AnimResult * dst,const anim::AnimResult * src)497     virtual bool Override(anim::AnimResult* dst, const anim::AnimResult* src) const
498     {
499         CalculatedTransform* dstX = reinterpret_cast<CalculatedTransform*>(dst);
500         const CalculatedTransform* srcX = reinterpret_cast<const CalculatedTransform*>(src);
501         return OverrideTransform(dstX, srcX, FLAG_ACCURATE_SCALE | FLAG_QUATERNION_ROTATE);
502     }
503 
504     //@}
505 };
506 
507 //---------------------------------------------------------------------------
508 //! @brief トランスフォームアニメーションを評価するクラスです。
509 //!
510 //! アニメーションデータを保持し、ファンクションカーブの評価を行います。
511 //---------------------------------------------------------------------------
512 class TransformAnimEvaluator : public BaseAnimEvaluator
513 {
514 public:
515     NW_UT_RUNTIME_TYPEINFO;
516 
517     //----------------------------------------
518     //! @name 作成
519     //@{
520 
521     //! トランスフォームアニメーション評価を構築するクラスです。
522     class Builder
523     {
524     public:
525         //! コンストラクタです。
Builder()526         Builder()
527         : m_AnimData(NULL),
528           m_MaxMembers(64),
529           m_MaxAnimMembers(64),
530           m_AllocCache(false) {}
531 
532         //! アニメーションデータを設定します。
AnimData(const anim::ResAnim & animData)533         Builder& AnimData(const anim::ResAnim& animData) { m_AnimData = animData; return *this; }
534 
535         //! @brief アニメーション対象メンバの最大数を設定します。
536         //!
537         //! TransformAnimEvaluator::Bind に渡す AnimGroup の AnimGroup::GetMemberCount の値を設定してください。
538         //! 複数の AnimGroup に Bind する場合は、最大値を設定してください。
MaxMembers(int maxMembers)539         Builder& MaxMembers(int maxMembers)
540         {
541             NW_ASSERT(maxMembers > 0);
542             m_MaxMembers = maxMembers;
543             return *this;
544         }
545 
546         //! @brief 実際にアニメーションするメンバの最大数を設定します。
547         //!
548         //! AnimData() に渡す anim::res::ResAnim の anim::res::ResAnim::GetMemberAnimSetCount の値を設定してください。
549         //! TransformAnimEvaluator::ChangeAnim で複数の ResAnim を切り替える場合は、最大値を設定してください。
MaxAnimMembers(int maxAnimMembers)550         Builder& MaxAnimMembers(int maxAnimMembers)
551         {
552             NW_ASSERT(maxAnimMembers > 0);
553             m_MaxAnimMembers = maxAnimMembers;
554             return *this;
555         }
556 
557         //! キャッシュバッファを確保してキャッシュを有効にするかどうかを設定します。
AllocCache(bool allocCache)558         Builder& AllocCache(bool allocCache) { m_AllocCache = allocCache; return *this; }
559 
560         //! @brief 生成時に必要なメモリサイズを取得します。
561         //!
562         //! メモリサイズは Builder の設定によって変化します。
563         //! すべての設定が終わった後にこの関数を呼び出してください。
564         //!
565         size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
566         {
567             os::MemorySizeCalculator size(alignment);
568 
569             GetMemorySizeInternal(&size);
570 
571             return size.GetSizeWithPadding(alignment);
572         }
573 
574         //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)575         void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
576         {
577             os::MemorySizeCalculator& size = *pSize;
578 
579             size += sizeof(TransformAnimEvaluator);
580             BaseAnimEvaluator::GetMemorySizeForInitialize(pSize, m_MaxMembers, m_MaxAnimMembers);
581 
582             if (m_AllocCache)
583             {
584                 size += sizeof(CalculatedTransform) * m_MaxAnimMembers;
585             }
586         }
587 
588         //! @brief トランスフォームアニメーション評価を生成します。
589         //!
590         //! @param[in] allocator アロケータです。
591         //!
592         //! @return 生成されたトランスフォームアニメーション評価です。
593         //!
Create(os::IAllocator * allocator)594         TransformAnimEvaluator* Create(os::IAllocator* allocator)
595         {
596             void* buf = allocator->Alloc(sizeof(TransformAnimEvaluator));
597 
598             if (buf == NULL)
599             {
600                 return NULL;
601             }
602 
603             TransformAnimEvaluator* evaluator = new(buf) TransformAnimEvaluator(allocator);
604 
605             Result result = evaluator->Initialize(m_AnimData, m_MaxMembers, m_MaxAnimMembers, m_AllocCache);
606             NW_ASSERT(result.IsSuccess());
607 
608             return evaluator;
609         }
610 
611     private:
612         anim::ResAnim m_AnimData;
613         int m_MaxMembers;
614         int m_MaxAnimMembers;
615         bool m_AllocCache;
616     };
617 
618     //@}
619 
620     //----------------------------------------
621     //! @name 基本操作
622     //@{
623 
624     //! @brief  アニメーションを関連付けます。
625     //!
626     //!         Bind() よりも詳細なバインド結果を得ることができます。
627     //!
628     //!         アニメーションデータがないメンバには、この時点でバインドポーズをコピーします。
629     //!         そのため、この関数を呼び出した後からアニメーション評価を行うまでの間は
630     //!         スケルトンの姿勢が正しくない状態になりますのでご注意ください。
631     //!
632     //! @param[in] animGroup アニメーショングループです。
633     //!
634     //! @return バインドの結果を返します。
635     //!
636     //! @sa Bind
637     //! @sa BindResult
638     virtual Result TryBind(AnimGroup* animGroup);
639 
640     //! @brief アニメーションを変更します。
641     //!
642     //! 内部で Bind() を呼び出すため、スケルトンの姿勢が変化します。
643     //!
644     //! GetCacheBufferSizeNeeded() の値が変化しますので、
645     //! SetCacheBuffer() している場合はバッファの再設定が必要です。
646     //!
647     //! 内部で確保したキャッシュバッファは、自動的にサイズ変更されます。
648     //!
649     //! @sa Bind
650     //! @sa BaseAnimEvaluator::ChangeAnim
651     //! @param animData アニメーションデータです。
ChangeAnim(const nw::anim::ResAnim animData)652     virtual void ChangeAnim(const nw::anim::ResAnim animData)
653     {
654         // BaseAnimEvaluator::ChangeAnim()内でBind()が呼ばれ、
655         // そこでキャッシュを書き換えるので、キャッシュのResizeを先に行う
656         if (!m_IsCacheExternal && !m_CacheTransforms.Empty())
657         {
658             m_CacheTransforms.Resize(animData.GetMemberAnimSetCount());
659         }
660 
661         BaseAnimEvaluator::ChangeAnim(animData);
662     }
663 
664     //@}
665 
666     //----------------------------------------
667     //! @name 評価
668     //@{
669 
670     //! @brief メンバ単位でアニメーション結果を取得します。
671     //!
672     //! @param[out] target アニメーション結果を書き込む対象です。
673     //! @param[in] memberIdx メンバインデックスです。
674     //!
675     //! @return アニメーション結果を適用した場合は NULL でない値を返します。
676     //!
677     virtual const anim::AnimResult* GetResult(
678         void* target,
679         int memberIdx) const;
680 
681     //@}
682 
683     //----------------------------------------
684     //! @name 取得/設定
685     //@{
686 
687     //! スケールアニメを無効化しているかを取得します。
GetIsScaleDisabled()688     bool GetIsScaleDisabled() const { return m_IsScaleDisabled; }
689 
690     //! スケールアニメを無効化しているかを設定します。
SetIsScaleDisabled(bool isDisabled)691     void SetIsScaleDisabled(bool isDisabled) { m_IsScaleDisabled = isDisabled; }
692 
693     //! 回転アニメを無効化しているかを取得します。
GetIsRotateDisabled()694     bool GetIsRotateDisabled() const { return m_IsRotateDisabled; }
695 
696     //! 回転アニメを無効化しているかを設定します。
SetIsRotateDisabled(bool isDisabled)697     void SetIsRotateDisabled(bool isDisabled) { m_IsRotateDisabled = isDisabled; }
698 
699     //! 移動アニメを無効化しているかを取得します。
GetIsTranslateDisabled()700     bool GetIsTranslateDisabled() const { return m_IsTranslateDisabled; }
701 
702     //! 移動アニメを無効化しているかを設定します。
SetIsTranslateDisabled(bool isDisabled)703     void SetIsTranslateDisabled(bool isDisabled) { m_IsTranslateDisabled = isDisabled; }
704 
705     //! @brief メンバに関連付けられたアニメーションが存在するかどうかを取得します。
706     //!
707     //! @param[in] memberIdx メンバインデックスです。
708     //!
709     //! @return アニメーションが存在すれば true を返します。
710     //!
HasMemberAnim(int memberIdx)711     virtual bool HasMemberAnim(int memberIdx) const
712     {
713         NW_MINMAXLT_ASSERT(memberIdx, 0, m_BindIndexTable.Size());
714         if (m_AnimData.ptr() == NULL)
715         {
716             return (0 <= memberIdx && memberIdx < m_AnimGroup->GetMemberCount());
717         }
718         else
719         {
720             return m_BindIndexTable[memberIdx] != NotFoundIndex;
721         }
722     }
723 
724     //@}
725 
726     //----------------------------------------
727     //! @name キャッシュ
728     //@{
729 
730     //! アニメーション評価結果の内部キャッシュが古ければ更新します。
731     virtual void UpdateCache();
732 
733     //! キャッシュバッファに必要なサイズ(バイト数)を取得します。
GetCacheBufferSizeNeeded()734     virtual int GetCacheBufferSizeNeeded() const
735     {
736         return m_AnimData.GetMemberAnimSetCount() * sizeof(CalculatedTransform);
737     }
738 
739     //! キャッシュバッファを取得します。
GetCacheBuffer()740     virtual const void* GetCacheBuffer() const { return m_CacheTransforms.Elements(); }
741 
742     //! @brief キャッシュバッファを設定します。
743     //! この関数で指定したキャッシュバッファはデストラクタで開放されません。
744     //!
745     //! @param[in] buf キャッシュバッファ用のメモリの先頭アドレスです。
746     //! NULL の場合、キャッシュが無効になります。
747     //! @param[in] size キャッシュバッファのサイズ(バイト数)です。
748     //!
SetCacheBuffer(void * buf,int size)749     virtual void SetCacheBuffer(void* buf, int size)
750     {
751         if (buf != NULL)
752         {
753             NW_ASSERT(size >= GetCacheBufferSizeNeeded());
754             const int maxCalculatedTransforms = size / sizeof(CalculatedTransform);
755             m_CacheTransforms = ut::MoveArray<CalculatedTransform>(buf, maxCalculatedTransforms);
756             m_CacheTransforms.Resize(maxCalculatedTransforms);
757             m_IsCacheDirty = true;
758             m_IsCacheExternal = true;
759         }
760         else
761         {
762             m_CacheTransforms = ut::MoveArray<CalculatedTransform>();
763         }
764     }
765 
766     //@}
767 
768 protected:
769     //----------------------------------------
770     //! @name コンストラクタ/デストラクタ
771     //@{
772 
773     //! コンストラクタです。
774     //!
775     //! :private
TransformAnimEvaluator(os::IAllocator * allocator)776     TransformAnimEvaluator(
777         os::IAllocator* allocator)
778     : BaseAnimEvaluator(allocator),
779       m_IsScaleDisabled(false),
780       m_IsRotateDisabled(false),
781       m_IsTranslateDisabled(false)
782     {
783     }
784 
785     //! デストラクタです。
786     //!
787     //! :private
~TransformAnimEvaluator()788     virtual ~TransformAnimEvaluator() {}
789 
790     //@}
791 
792     //! @details :private
Initialize(const anim::ResAnim & animData,const int maxMembers,const int maxAnimMembers,bool allocCache)793     virtual Result Initialize(
794         const anim::ResAnim& animData,
795         const int maxMembers,
796         const int maxAnimMembers,
797         bool allocCache)
798     {
799         Result result = BaseAnimEvaluator::Initialize(animData, maxMembers, maxAnimMembers);
800         NW_ENSURE_AND_RETURN(result);
801 
802         if (allocCache)
803         {
804             void* memory = GetAllocator().Alloc(sizeof(CalculatedTransform) * maxAnimMembers);
805             if (memory == NULL)
806             {
807                 result |= Result::MASK_FAIL_BIT;
808             }
809             NW_ENSURE_AND_RETURN(result);
810 
811             m_CacheTransforms = ut::MoveArray<CalculatedTransform>(memory, maxAnimMembers, &GetAllocator());
812             m_CacheTransforms.Resize(animData.GetMemberAnimSetCount());
813         }
814 
815         return result;
816     }
817 
818     bool m_IsScaleDisabled; //!< @details :private
819     bool m_IsRotateDisabled; //!< @details :private
820     bool m_IsTranslateDisabled; //!< @details :private
821 
822     ut::MoveArray<CalculatedTransform> m_CacheTransforms; //!< @details :private
823 
824 private:
825     // アニメーションカーブが存在しないメンバを、OriginalValueで初期化します。
826     void ResetNoAnimMember(AnimGroup* animGroup, anim::ResAnim animData);
827 
828     const anim::AnimResult* GetResultFast(void* target, int memberIdx) const;
829     const anim::AnimResult* GetResultCommon(void* target, int memberIdx, bool writeNoAnimMember) const;
830 
831     // メンバアニメーションを評価します。
832     // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。
833     void EvaluateMemberAnim(
834         CalculatedTransform* result,
835         anim::ResTransformAnim transformAnim,
836         float frame,
837         const math::Transform3* originalTransform,
838         bool writeNoAnimMember) const;
839 
840     // ベイク済みのメンバアニメーションを評価します。
841     // @param[in] writeNoAnimMember trueなら、アニメーションのない要素にOriginalValueを上書きします。
842     void EvaluateMemberBakedAnim(
843         CalculatedTransform* result,
844         anim::ResBakedTransformAnim transformAnim,
845         float frame,
846         const math::Transform3* originalTransform,
847         bool writeNoAnimMember) const;
848 
849     void UpdateFlagsCommon(CalculatedTransform* transform) const;
850     void UpdateFlags(CalculatedTransform* transform) const;
851 
852     // CalculatedTransformのフラグを、Bakeされた情報をもとにして更新します。
853     void ApplyBakedFlags(CalculatedTransform* transform, bit32 flags) const;
854 
855     friend class AnimBinding;
856 };
857 
858 //---------------------------------------------------------------------------
859 //! @brief トランスフォームアニメーション評価結果を補間ブレンドするクラスです。
860 //!
861 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。
862 //!
863 //! 動作の詳細は、 AnimInterpolator をご覧ください。
864 //---------------------------------------------------------------------------
865 class TransformAnimInterpolator : public AnimInterpolator
866 {
867 public:
868     NW_UT_RUNTIME_TYPEINFO;
869 
870     //----------------------------------------
871     //! @name 作成
872     //@{
873 
874     //! @brief トランスフォームアニメーション補間を構築するクラスです。
875     //!
876     //! バージョン 1.0.1 以前の補間法に戻すためには、IsOldMethod か IgnoreNoAnimMember に true を指定してください。
877     //!
878     //! 1.0.1 以前の補間方法と現在の補間方法の違いの詳細については、アニメーションのドキュメント(高度な機能)を参照ください。
879     class Builder
880     {
881     public:
882         //! コンストラクタです。
Builder()883         Builder()
884         : m_MaxAnimObjects(2),
885           m_IgnoreNoAnimMember(false) {}
886 
887         //! 最大アニメーションオブジェクト数を設定します。
MaxAnimObjects(int maxAnimObjects)888         Builder& MaxAnimObjects(int maxAnimObjects)
889         {
890             NW_ASSERT(maxAnimObjects > 0);
891             m_MaxAnimObjects = maxAnimObjects;
892             return *this;
893         }
894 
895         //! @brief バージョン 1.0.1 以前の補間法に戻すかどうかを設定します。
896         //!
897         //! 1.0.1 以前の補間法は IgnoreNoAnimMember() に true を指定したときと同じであり、
898         //! この関数は IgnoreNoAnimMember() のエイリアスです。
899         //!
900         //! この設定はバージョン 1.3.0 以降で削除されます。
901         NW_DEPRECATED_FUNCTION_MSG(
902             Builder& IsOldMethod(bool isOldMethod),
903             "TransformAnimIntepolator::IsOldMethod() is deprecated. Use IgnoreNoAnimMember()")
904         {
905             return IgnoreNoAnimMember(isOldMethod);
906         }
907 
908         //! @brief アニメーションが存在しないメンバを無視するかどうかを設定します。
909         //!
910         //! デフォルトでは、アニメーションが存在しないメンバはバインド時の値がブレンドされます。
911         //! IgnoreNoAnimMember に true を設定すると、
912         //! 重みの正規化がメンバ毎に行なわれ、アニメーションが存在しないメンバは重み 0 としてブレンドされます。
913         //!
914         //! この挙動は バージョン 1.0.1 以前の補間法と同じです。
915         //!
IgnoreNoAnimMember(bool ignoreNoAnimMember)916         Builder& IgnoreNoAnimMember(bool ignoreNoAnimMember) { m_IgnoreNoAnimMember = ignoreNoAnimMember; return *this; }
917 
918         //! @brief 生成時に必要なメモリサイズを取得します。
919         //!
920         //! メモリサイズは Builder の設定によって変化します。
921         //! すべての設定が終わった後にこの関数を呼び出してください。
922         //!
923         size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
924         {
925             os::MemorySizeCalculator size(alignment);
926 
927             GetMemorySizeInternal(&size);
928 
929             return size.GetSizeWithPadding(alignment);
930         }
931 
932         //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)933         void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
934         {
935             os::MemorySizeCalculator& size = *pSize;
936 
937             size += sizeof(TransformAnimInterpolator);
938             TransformAnimInterpolator::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects);
939         }
940 
941         //! @brief トランスフォームアニメーション補間を生成します。
942         //!
943         //! @param[in] allocator アロケータです。
944         //!
945         //! @return 生成されたトランスフォームアニメーション補間です。
946         //!
Create(os::IAllocator * allocator)947         TransformAnimInterpolator* Create(os::IAllocator* allocator)
948         {
949             void* buf = allocator->Alloc(sizeof(TransformAnimInterpolator));
950 
951             if (buf == NULL)
952             {
953                 return NULL;
954             }
955 
956             TransformAnimInterpolator* interpolator = new(buf) TransformAnimInterpolator(allocator);
957 
958             Result result = interpolator->Initialize(m_MaxAnimObjects, m_IgnoreNoAnimMember);
959             NW_ASSERT(result.IsSuccess());
960 
961             return interpolator;
962         }
963 
964     private:
965         int m_MaxAnimObjects;
966         bool m_IgnoreNoAnimMember;
967     };
968 
969     //@}
970 
971     //----------------------------------------
972     //! @name 評価
973     //@{
974 
975     //! @brief メンバ単位でアニメーション結果を取得します。
976     //!
977     //! @param[out] target アニメーション結果を書き込む対象です。
978     //! @param[in] memberIdx メンバインデックスです。
979     //!
980     //! @return アニメーション結果を適用した場合は NULL でない値を返します。
981     //!
982     virtual const anim::AnimResult* GetResult(
983         void* target,
984         int memberIdx) const;
985 
986     //@}
987 
988 protected:
989     //----------------------------------------
990     //! @name コンストラクタ/デストラクタ
991     //@{
992 
993     //! コンストラクタです。
994     //!
995     //! :private
TransformAnimInterpolator(os::IAllocator * allocator)996     TransformAnimInterpolator(
997         os::IAllocator* allocator)
998     : AnimInterpolator(allocator)
999     {}
1000 
1001     //! デストラクタです。
1002     //!
1003     //! :private
~TransformAnimInterpolator()1004     virtual ~TransformAnimInterpolator() {}
1005 
1006     //@}
1007 };
1008 
1009 //---------------------------------------------------------------------------
1010 //! @details :private
1011 //! @brief トランスフォームアニメーション評価結果を加算ブレンドするクラスです。
1012 //!
1013 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。
1014 //---------------------------------------------------------------------------
1015 class TransformAnimAdder : public AnimAdder
1016 {
1017 public:
1018     NW_UT_RUNTIME_TYPEINFO;
1019 
1020     //----------------------------------------
1021     //! @name 作成
1022     //@{
1023 
1024     //! トランスフォームアニメーション加算を構築するクラスです。
1025     class Builder
1026     {
1027     public:
1028         //! コンストラクタです。
Builder()1029         Builder()
1030         : m_MaxAnimObjects(2) {}
1031 
1032         //! 最大アニメーションオブジェクト数を設定します。
MaxAnimObjects(int maxAnimObjects)1033         Builder& MaxAnimObjects(int maxAnimObjects)
1034         {
1035             NW_ASSERT(maxAnimObjects > 0);
1036             m_MaxAnimObjects = maxAnimObjects;
1037             return *this;
1038         }
1039 
1040         //! @brief 生成時に必要なメモリサイズを取得します。
1041         //!
1042         //! メモリサイズは Builder の設定によって変化します。
1043         //! すべての設定が終わった後にこの関数を呼び出してください。
1044         //!
1045         size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
1046         {
1047             os::MemorySizeCalculator size(alignment);
1048 
1049             GetMemorySizeInternal(&size);
1050 
1051             return size.GetSizeWithPadding(alignment);
1052         }
1053 
1054         //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1055         void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
1056         {
1057             os::MemorySizeCalculator& size = *pSize;
1058 
1059             size += sizeof(TransformAnimAdder);
1060             TransformAnimAdder::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects);
1061         }
1062 
1063         //! @brief トランスフォームアニメーション加算を生成します。
1064         //!
1065         //! @param[in] allocator アロケータです。
1066         //!
1067         //! @return 生成されたトランスフォームアニメーション加算です。
1068         //!
Create(os::IAllocator * allocator)1069         TransformAnimAdder* Create(os::IAllocator* allocator)
1070         {
1071             void* buf = allocator->Alloc(sizeof(TransformAnimAdder));
1072 
1073             if (buf == NULL)
1074             {
1075                 return NULL;
1076             }
1077 
1078             TransformAnimAdder* adder = new(buf) TransformAnimAdder(allocator);
1079 
1080             Result result = adder->Initialize(m_MaxAnimObjects);
1081             NW_ASSERT(result.IsSuccess());
1082 
1083             return adder;
1084         }
1085 
1086     private:
1087         int m_MaxAnimObjects;
1088     };
1089 
1090     //@}
1091 
1092     //----------------------------------------
1093     //! @name 評価
1094     //@{
1095 
1096     //! @brief メンバ単位でアニメーション結果を取得します。
1097     //!
1098     //! @param[out] target アニメーション結果を書き込む対象です。
1099     //! @param[in] memberIdx メンバインデックスです。
1100     //!
1101     //! @return アニメーション結果を適用した場合は NULL でない値を返します。
1102     //!
1103     virtual const anim::AnimResult* GetResult(
1104         void* target,
1105         int memberIdx) const;
1106 
1107     //@}
1108 
1109 protected:
1110     //----------------------------------------
1111     //! @name コンストラクタ/デストラクタ
1112     //@{
1113 
1114     //! コンストラクタです。
TransformAnimAdder(os::IAllocator * allocator)1115     TransformAnimAdder(
1116         os::IAllocator* allocator)
1117     : AnimAdder(allocator)
1118     {}
1119 
1120     //! デストラクタです。
~TransformAnimAdder()1121     virtual ~TransformAnimAdder() {}
1122 
1123     //@}
1124 };
1125 
1126 //---------------------------------------------------------------------------
1127 //! @brief トランスフォームアニメーション評価結果を上書きブレンドするクラスです。
1128 //!
1129 //! ブレンドは各メンバの移動・回転・スケール成分ごとに行われます。
1130 //!
1131 //! 動作の詳細は、 AnimOverrider をご覧ください。
1132 //---------------------------------------------------------------------------
1133 class TransformAnimOverrider : public AnimOverrider
1134 {
1135 public:
1136     NW_UT_RUNTIME_TYPEINFO;
1137 
1138     //----------------------------------------
1139     //! @name 作成
1140     //@{
1141 
1142     //! トランスフォームアニメーション上書きを構築するクラスです。
1143     class Builder
1144     {
1145     public:
1146         //! コンストラクタです。
Builder()1147         Builder()
1148         : m_MaxAnimObjects(2) {}
1149 
1150         //! 最大アニメーションオブジェクト数を設定します。
MaxAnimObjects(int maxAnimObjects)1151         Builder& MaxAnimObjects(int maxAnimObjects)
1152         {
1153             NW_ASSERT(maxAnimObjects > 0);
1154             m_MaxAnimObjects = maxAnimObjects;
1155             return *this;
1156         }
1157 
1158         //! @brief 生成時に必要なメモリサイズを取得します。
1159         //!
1160         //! メモリサイズは Builder の設定によって変化します。
1161         //! すべての設定が終わった後にこの関数を呼び出してください。
1162         //!
1163         size_t GetMemorySize(size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) const
1164         {
1165             os::MemorySizeCalculator size(alignment);
1166 
1167             GetMemorySizeInternal(&size);
1168 
1169             return size.GetSizeWithPadding(alignment);
1170         }
1171 
1172         //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize)1173         void GetMemorySizeInternal(os::MemorySizeCalculator* pSize) const
1174         {
1175             os::MemorySizeCalculator& size = *pSize;
1176 
1177             size += sizeof(TransformAnimOverrider);
1178             TransformAnimOverrider::GetMemorySizeForInitialize(pSize, m_MaxAnimObjects);
1179         }
1180 
1181         //! @brief トランスフォームアニメーション上書きを生成します。
1182         //!
1183         //! @param[in] allocator アロケータです。
1184         //!
1185         //! @return 生成されたトランスフォームアニメーション上書きです。
1186         //!
Create(os::IAllocator * allocator)1187         TransformAnimOverrider* Create(os::IAllocator* allocator)
1188         {
1189             void* buf = allocator->Alloc(sizeof(TransformAnimOverrider));
1190 
1191             if (buf == NULL)
1192             {
1193                 return NULL;
1194             }
1195 
1196             TransformAnimOverrider* overrider = new(buf) TransformAnimOverrider(allocator);
1197 
1198             Result result = overrider->Initialize(m_MaxAnimObjects);
1199             NW_ASSERT(result.IsSuccess());
1200 
1201             return overrider;
1202         }
1203 
1204     private:
1205         int m_MaxAnimObjects;
1206     };
1207 
1208     //@}
1209 
1210     //----------------------------------------
1211     //! @name 評価
1212     //@{
1213 
1214     //! @brief メンバ単位でアニメーション結果を取得します。
1215     //!
1216     //! @param[out] target アニメーション結果を書き込む対象です。
1217     //! @param[in] memberIdx メンバインデックスです。
1218     //!
1219     //! @return アニメーション結果を適用した場合は NULL でない値を返します。
1220     //!
1221     virtual const anim::AnimResult* GetResult(
1222         void* target,
1223         int memberIdx) const;
1224 
1225     //@}
1226 
1227 protected:
1228     //----------------------------------------
1229     //! @name コンストラクタ/デストラクタ
1230     //@{
1231 
1232     //! コンストラクタです。
1233     //!
1234     //! :private
TransformAnimOverrider(os::IAllocator * allocator)1235     TransformAnimOverrider(
1236         os::IAllocator* allocator)
1237     : AnimOverrider(allocator)
1238     {}
1239 
1240     //! デストラクタです。
1241     //!
1242     //! :private
~TransformAnimOverrider()1243     virtual ~TransformAnimOverrider() {}
1244 
1245     //@}
1246 };
1247 
1248 } // namespace gfx
1249 } // namespace nw
1250 
1251 #endif // NW_GFX_TRANSFORMANIM_H_
1252