1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     anim_ResAnimCurve.cpp
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: 19698 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "../precompiled.h"
17 
18 #include <nw/anim/res/anim_ResAnimCurve.h>
19 #include <nw/anim/res/anim_ResAnim.h>
20 #include <nw/anim/res/anim_ResAnimGroup.h>
21 
22 #include <cmath>
23 #include <nw/math/math_Arithmetic.h>
24 
25 namespace nw {
26 namespace anim {
27 namespace res {
28 
29 namespace {
30 
31     /*!--------------------------------------------------------------------------*
32       @brief        キー形式毎の特性の定義です。
33      *---------------------------------------------------------------------------*/
34     template <typename T>
35     class ResAnimTraits;
36 
37     template <>
38     class ResAnimTraits<ResFloatKeyFV64Data>
39     {
40     public:
41         typedef ResFloatKeyFV64Data KeyType;
42         typedef f32                 FrameType;
43 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)44         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
45             { return &(pSegment->fv64.m_KeyValue[ keyIdx ]); }
46 
QuantizedFrame(f32 frame)47         static FrameType QuantizedFrame( f32 frame ) { return frame; }
GetFrame(const KeyType * pKey)48         static FrameType GetFrame( const KeyType* pKey ) { return pKey->GetFrame(); }
GetFrameF32(const KeyType * pKey)49         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->GetFrameF32(); }
GetValue(const ResFloatSegmentFVData *,const KeyType * pKey)50         static f32       GetValue( const ResFloatSegmentFVData*, const KeyType* pKey ) { return pKey->GetValue(); }
51     };
52 
53     template <>
54     class ResAnimTraits<ResFloatKeyFV32Data>
55     {
56     public:
57         typedef ResFloatKeyFV32Data KeyType;
58         typedef u32                 FrameType;
59 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)60         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
61             { return &(pSegment->fv32.m_KeyValue[ keyIdx ]); }
62 
QuantizedFrame(f32 frame)63         static FrameType QuantizedFrame( f32 frame ) { return u32(frame); }
GetFrame(const KeyType * pKey)64         static FrameType GetFrame( const KeyType* pKey ) { return pKey->GetFrame(); }
GetFrameF32(const KeyType * pKey)65         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->GetFrameF32(); }
GetValue(const ResFloatSegmentFVData * pSegment,const KeyType * pKey)66         static f32       GetValue( const ResFloatSegmentFVData* pSegment, const KeyType* pKey )
67             {
68                 f32 value = pKey->GetValue();
69                 return value * pSegment->fv32.m_Scale + pSegment->fv32.m_Offset;
70             }
71     };
72 
73     template <>
74     class ResAnimTraits<ResFloatKeyFVSS128Data>
75     {
76     public:
77         typedef ResFloatKeyFVSS128Data KeyType;
78         typedef f32                    FrameType;
79 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)80         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
81             { return &(pSegment->fvss128.m_KeyValue[ keyIdx ]); }
82 
QuantizedFrame(f32 frame)83         static FrameType QuantizedFrame( f32 frame ) { return frame; }
GetFrame(const KeyType * pKey)84         static FrameType GetFrame( const KeyType* pKey ) { return pKey->m_Frame; }
GetFrameF32(const KeyType * pKey)85         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->m_Frame; }
GetValue(const ResFloatSegmentFVData *,const KeyType * pKey)86         static f32       GetValue( const ResFloatSegmentFVData*, const KeyType* pKey ) { return pKey->m_Value; }
GetInSlope(const KeyType * pKey)87         static f32       GetInSlope( const KeyType* pKey ) { return pKey->m_InSlope; }
GetOutSlope(const KeyType * pKey)88         static f32       GetOutSlope( const KeyType* pKey ) { return pKey->m_OutSlope; }
89     };
90 
91     template <>
92     class ResAnimTraits<ResFloatKeyFVSS64Data>
93     {
94     public:
95         typedef ResFloatKeyFVSS64Data KeyType;
96         typedef u32                   FrameType;
97 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)98         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
99             { return &(pSegment->fvss64.m_KeyValue[ keyIdx ]); }
100 
QuantizedFrame(f32 frame)101         static FrameType QuantizedFrame( f32 frame ) { return u32(frame); }
GetFrame(const KeyType * pKey)102         static FrameType GetFrame( const KeyType* pKey ) { return (pKey->m_FrameValue & 0x00000FFF); }
GetFrameF32(const KeyType * pKey)103         static f32       GetFrameF32( const KeyType* pKey ) { return f32( GetFrame(pKey) ); }
GetValue(const ResFloatSegmentFVData * pSegment,const KeyType * pKey)104         static f32       GetValue( const ResFloatSegmentFVData* pSegment, const KeyType* pKey )
105             {
106                 f32 value = pKey->GetValue();
107                 return value * pSegment->fvss64.m_Scale + pSegment->fvss64.m_Offset;
108             }
GetInSlope(const KeyType * pKey)109         static f32       GetInSlope( const KeyType* pKey ) { return pKey->GetInSlope(); }
GetOutSlope(const KeyType * pKey)110         static f32       GetOutSlope( const KeyType* pKey ) { return pKey->GetOutSlope(); }
111     };
112 
113     template <>
114     class ResAnimTraits<ResFloatKeyFVSS48Data>
115     {
116     public:
117         typedef ResFloatKeyFVSS48Data KeyType;
118         typedef u32                  FrameType;
119 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)120         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
121             { return &(pSegment->fvss48.m_KeyValue[ keyIdx ]); }
122 
QuantizedFrame(f32 frame)123         static FrameType QuantizedFrame( f32 frame ) { return u32(frame); }
GetFrame(const KeyType * pKey)124         static FrameType GetFrame( const KeyType* pKey ) { return pKey->GetFrame(); }
GetFrameF32(const KeyType * pKey)125         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->GetFrameF32(); }
GetValue(const ResFloatSegmentFVData * pSegment,const KeyType * pKey)126         static f32       GetValue( const ResFloatSegmentFVData* pSegment, const KeyType* pKey )
127             {
128                 f32 value = pKey->GetValue();
129                 return value * pSegment->fvss48.m_Scale + pSegment->fvss48.m_Offset;
130             }
GetInSlope(const KeyType * pKey)131         static f32       GetInSlope( const KeyType* pKey ) { return pKey->GetInSlope(); }
GetOutSlope(const KeyType * pKey)132         static f32       GetOutSlope( const KeyType* pKey ) { return pKey->GetOutSlope(); }
133     };
134 
135 
136     template <>
137     class ResAnimTraits<ResFloatKeyFVS96Data>
138     {
139     public:
140         typedef ResFloatKeyFVS96Data KeyType;
141         typedef f32                  FrameType;
142 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)143         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
144             { return &(pSegment->fvs96.m_KeyValue[ keyIdx ]); }
145 
QuantizedFrame(f32 frame)146         static FrameType QuantizedFrame( f32 frame ) { return frame; }
GetFrame(const KeyType * pKey)147         static FrameType GetFrame( const KeyType* pKey ) { return pKey->GetFrame(); }
GetFrameF32(const KeyType * pKey)148         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->GetFrameF32(); }
GetValue(const ResFloatSegmentFVData *,const KeyType * pKey)149         static f32       GetValue( const ResFloatSegmentFVData*, const KeyType* pKey ) { return pKey->GetValue(); }
GetSlope(const KeyType * pKey)150         static f32       GetSlope( const KeyType* pKey ) { return pKey->GetSlope(); }
151     };
152 
153     template <>
154     class ResAnimTraits<ResFloatKeyFVS48Data>
155     {
156     public:
157         typedef ResFloatKeyFVS48Data  KeyType;
158         typedef u32                   FrameType;
159 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)160         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
161             { return &(pSegment->fvs48.m_KeyValue[ keyIdx ]); }
162 
QuantizedFrame(f32 frame)163         static FrameType QuantizedFrame( f32 frame ) { return internal::CastF32ToS10_5(frame); }
GetFrame(const KeyType * pKey)164         static FrameType GetFrame( const KeyType* pKey ) { return pKey->GetFrame(); }
GetFrameF32(const KeyType * pKey)165         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->GetFrameF32(); }
GetValue(const ResFloatSegmentFVData * pSegment,const KeyType * pKey)166         static f32       GetValue( const ResFloatSegmentFVData* pSegment, const KeyType* pKey )
167             {
168                 f32 value = pKey->GetValue();
169                 return value * pSegment->fvs48.m_Scale + pSegment->fvs48.m_Offset;
170             }
GetSlope(const KeyType * pKey)171         static f32       GetSlope( const KeyType* pKey ) { return pKey->GetSlope(); }
172     };
173 
174     template <>
175     class ResAnimTraits<ResFloatKeyFVS32Data>
176     {
177     public:
178         typedef ResFloatKeyFVS32Data KeyType;
179         typedef u32                  FrameType;
180 
GetKey(const ResFloatSegmentFVData * pSegment,uint keyIdx)181         static const KeyType*   GetKey( const ResFloatSegmentFVData* pSegment, uint keyIdx )
182             { return &(pSegment->fvs32.m_KeyValue[ keyIdx ]); }
183 
QuantizedFrame(f32 frame)184         static FrameType QuantizedFrame( f32 frame ) { return u32(frame); }
GetFrame(const KeyType * pKey)185         static FrameType GetFrame( const KeyType* pKey ) { return pKey->m_Frame; }
GetFrameF32(const KeyType * pKey)186         static f32       GetFrameF32( const KeyType* pKey ) { return f32( GetFrame( pKey ) ); }
GetValue(const ResFloatSegmentFVData * pSegment,const KeyType * pKey)187         static f32       GetValue( const ResFloatSegmentFVData* pSegment, const KeyType* pKey )
188             {
189                 f32 value = f32(pKey->m_ValueSlope[0] + ((pKey->m_ValueSlope[1] & 0x0F) << 8) );
190                 return value * pSegment->fvs32.m_Scale + pSegment->fvs32.m_Offset;
191             }
GetSlope(const KeyType * pKey)192         static f32       GetSlope( const KeyType* pKey ) { return pKey->GetSlope(); }
193     };
194 
195 
196     template <>
197     class ResAnimTraits<ResIntKeyFV64Data>
198     {
199     public:
200         typedef ResIntKeyFV64Data KeyType;
201         typedef f32               FrameType;
202 
GetKey(const ResIntCurveFVData * pCurve,uint keyIdx)203         static const KeyType*   GetKey( const ResIntCurveFVData* pCurve, uint keyIdx )
204             { return &(pCurve->fv64.m_KeyValue[ keyIdx ]); }
205 
QuantizedFrame(f32 frame)206         static FrameType QuantizedFrame( f32 frame ) { return frame; }
GetFrame(const KeyType * pKey)207         static FrameType GetFrame( const KeyType* pKey ) { return pKey->GetFrame(); }
GetFrameF32(const KeyType * pKey)208         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->GetFrameF32(); }
GetValue(const ResIntCurveFVData *,const KeyType * pKey)209         static s32       GetValue( const ResIntCurveFVData*, const KeyType* pKey ) { return pKey->GetValue(); }
210     };
211 
212     template <>
213     class ResAnimTraits<ResIntKeyFV32Data>
214     {
215     public:
216         typedef ResIntKeyFV32Data KeyType;
217         typedef u32               FrameType;
218 
GetKey(const ResIntCurveFVData * pCurve,uint keyIdx)219         static const KeyType*   GetKey( const ResIntCurveFVData* pCurve, uint keyIdx )
220             { return &(pCurve->fv32.m_KeyValue[ keyIdx ]); }
221 
QuantizedFrame(f32 frame)222         static FrameType QuantizedFrame( f32 frame ) { return u32(frame); }
GetFrame(const KeyType * pKey)223         static FrameType GetFrame( const KeyType* pKey ) { return pKey->GetFrame(); }
GetFrameF32(const KeyType * pKey)224         static f32       GetFrameF32( const KeyType* pKey ) { return pKey->GetFrameF32(); }
GetValue(const ResIntCurveFVData *,const KeyType * pKey)225         static s32       GetValue( const ResIntCurveFVData* /*pCurve*/, const KeyType* pKey )
226             {
227                 return pKey->GetValue();
228             }
229     };
230 
231 
232     template <>
233     class ResAnimTraits<ResIntKeyFV16Data>
234     {
235     public:
236         typedef ResIntKeyFV16Data KeyType;
237         typedef u32               FrameType;
238 
GetKey(const ResIntCurveFVData * pCurve,uint keyIdx)239         static const KeyType*   GetKey( const ResIntCurveFVData* pCurve, uint keyIdx )
240             { return &(pCurve->fv16.m_KeyValue[ keyIdx ]); }
241 
QuantizedFrame(f32 frame)242         static FrameType QuantizedFrame( f32 frame ) { return u32(frame); }
GetFrame(const KeyType * pKey)243         static FrameType GetFrame( const KeyType* pKey ) { return u32(pKey->m_Frame); }
GetFrameF32(const KeyType * pKey)244         static f32       GetFrameF32( const KeyType* pKey ) { return f32( GetFrame( pKey ) ); }
GetValue(const ResIntCurveFVData *,const KeyType * pKey)245         static s32       GetValue( const ResIntCurveFVData* /*pCurve*/, const KeyType* pKey )
246             {
247                 return s32(pKey->m_Value);
248             }
249     };
250 
251     typedef f32 (*NormalizeFrameFunc)( f32 frame, f32 startFrame, f32 endFrame );
252 
253     f32
NormalizeFrameNonePre_(f32 frame,f32 startFrame,f32)254     NormalizeFrameNonePre_( f32 frame, f32 startFrame, f32 /* endFrame */ )
255     {
256         return (frame < startFrame) ? startFrame : frame;
257     }
258 
259     f32
NormalizeFrameNonePost_(f32 frame,f32,f32 endFrame)260     NormalizeFrameNonePost_( f32 frame, f32 /*startFrame*/, f32 endFrame )
261     {
262         return (frame > endFrame) ? endFrame : frame;
263     }
264 
265     f32
NormalizeFrameRepeatPre_(f32 frame,f32 startFrame,f32 endFrame)266     NormalizeFrameRepeatPre_( f32 frame, f32 startFrame, f32 endFrame )
267     {
268         f32 duration = endFrame - startFrame;
269 
270         s32 cnt = static_cast<s32>(std::floor( (frame - startFrame) / duration ));
271         frame -= cnt * duration;
272 
273         return frame;
274     }
275 
276     f32
NormalizeFrameRepeatPost_(f32 frame,f32 startFrame,f32 endFrame)277     NormalizeFrameRepeatPost_( f32 frame, f32 startFrame, f32 endFrame )
278     {
279         f32 duration = endFrame - startFrame;
280 
281         s32 cnt = static_cast<s32>(std::floor( (frame - startFrame) / duration ));
282         frame -= cnt * duration;
283 
284         return frame;
285     }
286 
287     f32
NormalizeFrameMirrorPre_(f32 frame,f32 startFrame,f32 endFrame)288     NormalizeFrameMirrorPre_( f32 frame, f32 startFrame, f32 endFrame )
289     {
290         bool needsReverse = false;
291         f32 duration = endFrame - startFrame;
292 
293         s32 cnt = static_cast<s32>(std::floor( (frame - startFrame) / duration ));
294         frame -= cnt * duration;
295         needsReverse = (cnt & 1)? true : false;
296 
297         return needsReverse ? startFrame + endFrame - frame : frame;
298     }
299 
300     f32
NormalizeFrameMirrorPost_(f32 frame,f32 startFrame,f32 endFrame)301     NormalizeFrameMirrorPost_( f32 frame, f32 startFrame, f32 endFrame )
302     {
303         bool needsReverse = false;
304         f32 duration = endFrame - startFrame;
305 
306         s32 cnt = static_cast<s32>(std::floor( (frame - startFrame) / duration ));
307         frame -= cnt * duration;
308         needsReverse = (cnt & 1)? true : false;
309 
310         return needsReverse ? startFrame + endFrame - frame : frame;
311     }
312 
313     /*!--------------------------------------------------------------------------*
314       @brief        フレームを正規化します。
315 
316       @param[in]    frame   正規化するフレームです。
317       @param[in]    pCurve  アニメーションデータへのポインタです。
318 
319       @return
320      *---------------------------------------------------------------------------*/
NormalizeFrame_(f32 frame,const ResAnimCurveData * pCurve)321     f32 NormalizeFrame_( f32 frame, const ResAnimCurveData* pCurve )
322     {
323         static const NormalizeFrameFunc preRepeatMethod[] =
324         {
325             NormalizeFrameNonePre_,
326             NormalizeFrameRepeatPre_,
327             NormalizeFrameMirrorPre_,
328             NormalizeFrameRepeatPre_
329         };
330 
331         static const NormalizeFrameFunc postRepeatMethod[] =
332         {
333             NormalizeFrameNonePost_,
334             NormalizeFrameRepeatPost_,
335             NormalizeFrameMirrorPost_,
336             NormalizeFrameRepeatPost_
337         };
338 
339         NW_ASSERT( pCurve->m_InRepeatMethod < ResAnimCurveData::METHOD_NUM );
340         NW_ASSERT( pCurve->m_OutRepeatMethod < ResAnimCurveData::METHOD_NUM );
341 
342         if ( frame < pCurve->m_StartFrame )
343         {
344             return preRepeatMethod[ pCurve->m_InRepeatMethod ]( frame, pCurve->m_StartFrame, pCurve->m_EndFrame );
345         }
346 
347         // リピート時に、EndFrame と等しいフレームは、StartFrame と同じものとして扱うので、
348         // 終端の判定のみ if の判定条件にイコールを入れている。
349         if ( frame >= pCurve->m_EndFrame )
350         {
351             return postRepeatMethod[ pCurve->m_OutRepeatMethod ]( frame, pCurve->m_StartFrame, pCurve->m_EndFrame );
352         }
353 
354         return frame;
355     }
356 
357     /*!--------------------------------------------------------------------------*
358       @brief        指定されたフレーム以下の最大のキーフレームを検索して返します。
359 
360       @param[in]    pSegment キーを検索するセグメントです。
361       @param[in]    frame    キーを検索するフレーム数です。
362 
363       @return       キーフレームです。
364      *---------------------------------------------------------------------------*/
365     template <typename Traits, typename Segment>
366     const typename Traits::KeyType*
GetKeyFV_(const Segment * pSegment,f32 frame)367     GetKeyFV_( const Segment* pSegment, f32 frame )
368     {
369         typename Traits::FrameType quantizedFrame = Traits::QuantizedFrame( frame );
370 
371         // 先頭のキー以前の場合は特別扱い
372         // 先頭のフレームに複数のキーがある場合、それ以前のフレームでは最初のキーを選択する
373         const typename Traits::KeyType* pFirstKey = Traits::GetKey(pSegment, 0);
374         if ( quantizedFrame <= Traits::GetFrame( pFirstKey ) )
375         {
376             return pFirstKey;
377         }
378 
379         // 末尾のキーを超える場合は特別扱い
380         const typename Traits::KeyType* pLastKey = Traits::GetKey(pSegment, pSegment->m_NumFrameValues - 1);
381         if ( Traits::GetFrame( pLastKey ) <= quantizedFrame )
382         {
383             return pLastKey;
384         }
385 
386         // キーが等幅で打たれていると仮定して、キーの位置を推測する。
387         uint keyIdx = static_cast<uint>( frame * pSegment->m_InvDuration * (pSegment->m_NumFrameValues - 1) );
388         NW_ASSERT( keyIdx <= pSegment->m_NumFrameValues - 1U );
389 
390         const typename Traits::KeyType* pKey = Traits::GetKey(pSegment, keyIdx);
391 
392         // 推測位置から線形探索
393         if ( quantizedFrame < Traits::GetFrame( pKey ) )
394         {
395             do
396             {
397                 NW_ASSERT( Traits::GetKey(pSegment, 0) < pKey );
398                 --pKey;
399             } while ( quantizedFrame < Traits::GetFrame( pKey ) );
400         }
401         else
402         {
403             do
404             {
405                 NW_ASSERT( pKey < Traits::GetKey(pSegment, pSegment->m_NumFrameValues - 1) );
406                 ++pKey;
407             } while ( Traits::GetFrame( pKey ) <= quantizedFrame );
408 
409             // ここにきた時点で1つ通り過ぎている
410             NW_ASSERT( Traits::GetKey(pSegment, 0) < pKey );
411             --pKey;
412         }
413 
414         return pKey;
415     }
416 
417     /*!--------------------------------------------------------------------------*
418       @brief        指定されたフレームに相当するセグメントを返します。
419 
420       @param[in]    pCurve  セグメントを検索するセグメントカーブです。
421       @param[in]    frame   セグメントを検索するフレーム数です。
422 
423       @return       カーブの中から対象となるセグメントを検索します。
424      *---------------------------------------------------------------------------*/
425     NW_INLINE const ResFloatSegmentData*
GetFloatSegment_(const ResSegmentFloatCurveData * pCurve,f32 frame)426     GetFloatSegment_( const ResSegmentFloatCurveData* pCurve, f32 frame )
427     {
428         NW_NULL_ASSERT( pCurve );
429         NW_ASSERT( pCurve->m_StartFrame <= frame && frame <= pCurve->m_EndFrame );
430 
431         // 単一セグメントである場合は唯一のセグメントを返します。
432         if ( pCurve->m_Flags & ResSegmentFloatCurveData::FLAG_MONO_SEGMENT )
433         {
434             return reinterpret_cast<const ResFloatSegmentData*>( pCurve->segmentsTable.toSegments[0].to_ptr() );
435         }
436 
437         s32 segmentCount = pCurve->segmentsTable.m_NumSegments;
438 
439         NW_ASSERT( segmentCount > 0 );
440 
441         const ut::Offset* pOffsetTable = &(pCurve->segmentsTable.toSegments[0]);
442 
443         for ( const ut::Offset* pOffset = pOffsetTable; pOffset < pOffsetTable + segmentCount; ++pOffset )
444         {
445             const ResFloatSegmentData* pSegment = reinterpret_cast<const ResFloatSegmentData*>( pOffset->to_ptr() );
446 
447             if ( pSegment->m_EndFrame > frame )
448             {
449                 return pSegment;
450             }
451         }
452 
453         return reinterpret_cast<const ResFloatSegmentData*>( pOffsetTable[ segmentCount - 1 ].to_ptr() );
454     }
455 
456     template <typename Traits>
457     const typename Traits::KeyType*
GetFloatKeyFV_(const ResFloatSegmentFVData * pSegment,f32 frame)458     GetFloatKeyFV_( const ResFloatSegmentFVData* pSegment, f32 frame )
459     {
460         return GetKeyFV_<Traits, ResFloatSegmentFVData>( pSegment, frame );
461     }
462 
463 
464     template <typename Traits>
465     f32
CalcStepFloatSegmentFV_(const ResFloatSegmentFVData * pSegment,f32 frame)466     CalcStepFloatSegmentFV_( const ResFloatSegmentFVData* pSegment, f32 frame )
467     {
468         const typename Traits::KeyType* pKey = GetFloatKeyFV_<Traits>( pSegment, frame );
469 
470         return Traits::GetValue( pSegment, pKey );
471     }
472 
473 
474     template <typename Traits>
475     f32
CalcLinearFloatSegmentFV_(const ResFloatSegmentFVData * pSegment,f32 frame)476     CalcLinearFloatSegmentFV_( const ResFloatSegmentFVData* pSegment, f32 frame )
477     {
478         const typename Traits::KeyType* pKey = GetFloatKeyFV_<Traits>( pSegment, frame );
479 
480         f32 keyFrame = Traits::GetFrameF32( pKey );
481 
482         if ( keyFrame == frame )
483         {
484             return Traits::GetValue( pSegment, pKey );
485         }
486 
487         const typename Traits::KeyType* pNextKey = pKey + 1;
488 
489         f32 nextKeyFrame = Traits::GetFrameF32( pNextKey );
490         f32 rate = (frame - keyFrame) / (nextKeyFrame - keyFrame);
491 
492         return Traits::GetValue( pSegment, pKey ) * (1.0f - rate)
493                + Traits::GetValue( pSegment, pNextKey ) * rate;
494     }
495 
496     template <typename Traits>
497     f32
CalcHermiteFloatSegmentFVSS_(const ResFloatSegmentFVData * pSegment,f32 frame)498     CalcHermiteFloatSegmentFVSS_( const ResFloatSegmentFVData* pSegment, f32 frame )
499     {
500         const typename Traits::KeyType* pKey = GetFloatKeyFV_<Traits>( pSegment, frame );
501 
502         f32 keyFrame = Traits::GetFrameF32( pKey );
503 
504         if ( keyFrame == frame )
505         {
506             return Traits::GetValue( pSegment, pKey );
507         }
508 
509         const typename Traits::KeyType* pNextKey = pKey + 1;
510 
511         f32 p  = frame - keyFrame;
512         f32 d  = Traits::GetFrameF32( pNextKey ) - keyFrame;
513         f32 v0 = Traits::GetValue( pSegment, pKey );
514         f32 v1 = Traits::GetValue( pSegment, pNextKey );
515         f32 t0 = Traits::GetOutSlope( pKey );
516         f32 t1 = Traits::GetInSlope( pNextKey );
517 
518         return nw::math::Hermite( v0, t0, v1, t1, p, d );
519     }
520 
521     template <typename Traits>
522     f32
CalcHermiteFloatSegmentFVS_(const ResFloatSegmentFVData * pSegment,f32 frame)523     CalcHermiteFloatSegmentFVS_( const ResFloatSegmentFVData* pSegment, f32 frame )
524     {
525         const typename Traits::KeyType* pKey = GetFloatKeyFV_<Traits>( pSegment, frame );
526 
527         // UNDONE: 同じフレームにキーが複数存在する場合の対処が必要。
528 
529         f32 keyFrame = Traits::GetFrameF32( pKey );
530 
531         if ( keyFrame == frame )
532         {
533             return Traits::GetValue( pSegment, pKey );
534         }
535 
536         const typename Traits::KeyType* pNextKey = pKey + 1;
537 
538         f32 p  = frame - keyFrame;
539         f32 d  = Traits::GetFrameF32( pNextKey ) - keyFrame;
540         f32 v0 = Traits::GetValue( pSegment, pKey );
541         f32 v1 = Traits::GetValue( pSegment, pNextKey );
542         f32 t0 = Traits::GetSlope( pKey );
543         f32 t1 = Traits::GetSlope( pNextKey );
544 
545         return nw::math::Hermite( v0, t0, v1, t1, p, d );
546     }
547 
548     typedef f32 (*CalcFloatSegmentFVFunc)( const ResFloatSegmentFVData* pSegment, f32 frame );
549 
550     static CalcFloatSegmentFVFunc s_CalcFloatSegmentFVTable[][8] =
551     {
552         {
553             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVSS128Data> >,
554             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVSS64Data> >,
555             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVSS48Data> >,
556             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVS96Data> >,
557             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVS48Data> >,
558             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVS32Data> >,
559             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFV64Data> >,
560             CalcStepFloatSegmentFV_< ResAnimTraits<ResFloatKeyFV32Data> >,
561         },
562         {
563             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVSS128Data> >,
564             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVSS64Data> >,
565             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVSS48Data> >,
566             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVS96Data> >,
567             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVS48Data> >,
568             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFVS32Data> >,
569             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFV64Data> >,
570             CalcLinearFloatSegmentFV_< ResAnimTraits<ResFloatKeyFV32Data> >,
571         },
572         {
573             CalcHermiteFloatSegmentFVSS_< ResAnimTraits<ResFloatKeyFVSS128Data> >,
574             CalcHermiteFloatSegmentFVSS_< ResAnimTraits<ResFloatKeyFVSS64Data> >,
575             CalcHermiteFloatSegmentFVSS_< ResAnimTraits<ResFloatKeyFVSS48Data> >,
576             CalcHermiteFloatSegmentFVS_< ResAnimTraits<ResFloatKeyFVS96Data> >,
577             CalcHermiteFloatSegmentFVS_< ResAnimTraits<ResFloatKeyFVS48Data> >,
578             CalcHermiteFloatSegmentFVS_< ResAnimTraits<ResFloatKeyFVS32Data> >,
579             NULL,
580             NULL,
581         }
582     };
583 
584 
585     template <typename Traits>
586     const typename Traits::KeyType*
GetIntKeyFV_(const ResIntCurveFVData * pCurve,f32 frame)587     GetIntKeyFV_( const ResIntCurveFVData* pCurve, f32 frame )
588     {
589         return GetKeyFV_<Traits, ResIntCurveFVData>( pCurve, frame );
590     }
591 
592 
593     template <typename Traits>
594     s32
CalcIntCurveFV_(const ResIntCurveFVData * pCurve,f32 frame)595     CalcIntCurveFV_( const ResIntCurveFVData* pCurve, f32 frame )
596     {
597         const typename Traits::KeyType* pKey = GetIntKeyFV_<Traits>( pCurve, frame );
598 
599         return Traits::GetValue( pCurve, pKey );
600     }
601 
602     typedef s32 (*CalcIntCurveFVFunc)( const ResIntCurveFVData* pCurve, f32 frame );
603 
604     static CalcIntCurveFVFunc s_CalcIntCurveFVTable[] =
605     {
606         CalcIntCurveFV_< ResAnimTraits<ResIntKeyFV64Data> >,
607         CalcIntCurveFV_< ResAnimTraits<ResIntKeyFV32Data> >,
608         CalcIntCurveFV_< ResAnimTraits<ResIntKeyFV16Data> >,
609     };
610 
611 
612     NW_INLINE f32
CalcFloatSegment_(const ResFloatSegmentData * pSegment,f32 frame)613     CalcFloatSegment_( const ResFloatSegmentData* pSegment, f32 frame )
614     {
615         NW_NULL_ASSERT( pSegment );
616         NW_ASSERT( pSegment->m_StartFrame <= frame && frame <= pSegment->m_EndFrame );
617         NW_ASSERT(!(pSegment->m_Flags & ResFloatSegmentData::FLAG_BAKED));
618 
619         if ( pSegment->m_Flags & ResFloatSegmentData::FLAG_CONSTANT )
620         {
621             return pSegment->constantValue;
622         }
623 
624         u32 quantizeType = (pSegment->m_Flags & ResFloatSegmentData::FLAG_QUANTIZATION_TYPE_MASK) >>
625             ResFloatSegmentData::FLAG_QUANTIZATION_TYPE_SHIFT;
626 
627         u32 interporateMode = (pSegment->m_Flags & ResFloatSegmentData::FLAG_INTERPORATE_MODE_MASK) >>
628                                   ResFloatSegmentData::FLAG_INTERPORATE_MODE_SHIFT;
629 
630         return s_CalcFloatSegmentFVTable[ interporateMode ][ quantizeType ]( &(pSegment->fv), frame - pSegment->m_StartFrame );
631     }
632 
633 
634     NW_INLINE f32
CalcSegmentFloatCurve_(const ResSegmentFloatCurveData * pCurve,f32 frame)635     CalcSegmentFloatCurve_( const ResSegmentFloatCurveData* pCurve, f32 frame )
636     {
637         NW_NULL_ASSERT( pCurve );
638         NW_ASSERT( pCurve->m_StartFrame <= frame && frame <= pCurve->m_EndFrame );
639 
640         if ( pCurve->m_Flags & ResSegmentFloatCurveData::FLAG_CONSTANT )
641         {
642             return pCurve->m_ConstantValue;
643         }
644 
645         const ResFloatSegmentData* pSegment = GetFloatSegment_( pCurve, frame );
646 
647         if ( frame < pSegment->m_StartFrame )
648         {
649             // 量子化の影響で、セグメント間に隙間があいてしまうことがあるため
650             frame = pSegment->m_StartFrame;
651         }
652 
653         return CalcFloatSegment_( pSegment, frame );
654     }
655 
656 
657     NW_INLINE f32
CalcCompositeFloatCurve_(const ResCompositeFloatCurveData * pCurve,f32 frame)658     CalcCompositeFloatCurve_( const ResCompositeFloatCurveData* pCurve, f32 frame )
659     {
660         const ResFloatCurveData* pLeftCurve =
661             reinterpret_cast<const ResFloatCurveData*>( pCurve->toLeftCurve.to_ptr() );
662         const ResFloatCurveData* pRightCurve =
663             reinterpret_cast<const ResFloatCurveData*>( pCurve->toRightCurve.to_ptr() );
664 
665         f32 leftValue  = CalcFloatCurve( pLeftCurve, frame );
666         f32 rightValue = CalcFloatCurve( pRightCurve, frame );
667 
668         // UNDONE: CompositeCurve には未対応。 bool curve の乗算をしていない。
669 
670         return leftValue + rightValue;
671     }
672 
673 
674 
675     bool
CalcBoolCurveCV_(const ResBoolCurveData * pCurve,f32 frame)676     CalcBoolCurveCV_( const ResBoolCurveData* pCurve, f32 frame )
677     {
678         NW_ASSERT( pCurve->m_StartFrame <= frame && frame <= pCurve->m_EndFrame );
679 
680         float frameOffset = frame - pCurve->m_StartFrame;
681 
682         // EndFrameが小数の場合に、PostInfinityを正しく計算する
683         if (frame == pCurve->m_EndFrame)
684         {
685             frameOffset = math::FCeil(frameOffset);
686         }
687 
688         u32 index = u32(frameOffset) / 8;
689         u32 shift = u32(frameOffset) % 8;
690 
691         return ( (pCurve->cv.m_KeyValue[ index ] >> shift) & 0x1) != 0;
692     }
693 
694 
695     void
CalcVector3CurveCV_(math::VEC3 * result,bit32 * flags,const ResVector3CurveData * pCurve,f32 frame)696     CalcVector3CurveCV_( math::VEC3* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame )
697     {
698         u32 index = u32(frame);
699         f32 remainder = frame - index;
700         const ResVector3CurveData::FrameValue& frameValue = pCurve->frames.m_KeyValue[index];
701 
702         if ( remainder == 0 )
703         {
704             // 整数フレーム
705             *result = frameValue.cv;
706             *flags |= frameValue.flag;
707         }
708         else
709         {
710             // 小数フレーム
711             f32 nextFrame = NormalizeFrame_( frame + 1.0f, pCurve );
712             u32 nextIndex = u32(nextFrame);
713             const ResVector3CurveData::FrameValue& nextFrameValue = pCurve->frames.m_KeyValue[nextIndex];
714 
715             VEC3Lerp(
716                 result,
717                 static_cast<const math::VEC3*>(&frameValue.cv),
718                 static_cast<const math::VEC3*>(&nextFrameValue.cv),
719                 remainder );
720 
721             // 補間の両端でフラグが立っているなら、補間後も立っているはず
722             // 両端で立たず、2点の間のどこかで立つことはありうるが、その1フレームだけ軽くなってもメリットは薄そう
723             // それより、平均的な処理負荷を下げるためシンプルな実装にする
724             *flags |= (frameValue.flag & nextFrameValue.flag);
725         }
726     }
727 
728     void
CalcRotateCurveCV_(math::MTX34 * result,bit32 * flags,const ResVector4CurveData * pCurve,f32 frame)729     CalcRotateCurveCV_( math::MTX34* result, bit32* flags, const ResVector4CurveData* pCurve, f32 frame )
730     {
731         u32 index = u32(frame);
732         f32 remainder = frame - index;
733         const ResVector4CurveData::FrameValue& frameValue = pCurve->frames.m_KeyValue[index];
734 
735         math::MTX34 mtx;
736 
737         if ( remainder == 0 )
738         {
739             // 整数フレーム
740 
741             // クォータニオンを用意
742             math::QUAT quaternion(frameValue.cv);
743             // クォータニオンから回転行列を生成する
744             math::QUATToMTX34(&mtx, &quaternion);
745 
746             *flags |= frameValue.flag;
747         }
748         else
749         {
750             // 小数フレーム
751             f32 nextFrame = NormalizeFrame_( frame + 1.0f, pCurve );
752             u32 nextIndex = u32(nextFrame);
753             const ResVector4CurveData::FrameValue& nextFrameValue = pCurve->frames.m_KeyValue[nextIndex];
754 
755             // クォータニオンを用意
756             math::QUAT lerpResult;
757             math::QUAT q1(frameValue.cv);
758             math::QUAT q2(nextFrameValue.cv);
759 
760             // 補間してから回転行列を生成する
761             math::QUATLerp(&lerpResult, &q1, &q2, remainder);
762             math::QUATToMTX34(&mtx, &lerpResult);
763 
764             // 意図はCalcVector3CurveCV_のコメントを参照
765             *flags |= (frameValue.flag & nextFrameValue.flag);
766         }
767 
768         // Mtx34の4列目はTranslateの値が入るので、
769         // Rotateのカーブ評価であるこの関数ではあえて上書きを行わない。
770         result->f._00 = mtx.f._00;
771         result->f._01 = mtx.f._01;
772         result->f._02 = mtx.f._02;
773         //result->f._03 = 0.0f;
774         result->f._10 = mtx.f._10;
775         result->f._11 = mtx.f._11;
776         result->f._12 = mtx.f._12;
777         //result->f._13 = 0.0f;
778         result->f._20 = mtx.f._20;
779         result->f._21 = mtx.f._21;
780         result->f._22 = mtx.f._22;
781         //result->f._23 = 0.0f;
782     }
783 
784 
CalcTranslateCurveCV_(math::MTX34 * result,bit32 * flags,const ResVector3CurveData * pCurve,f32 frame)785     void CalcTranslateCurveCV_( math::MTX34* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame )
786     {
787         u32 index = u32(frame);
788         f32 remainder = frame - index;
789         const ResVector3CurveData::FrameValue& frameValue = pCurve->frames.m_KeyValue[index];
790 
791         if ( remainder == 0 )
792         {
793             // 整数フレーム
794             result->f._03 = frameValue.cv.x;
795             result->f._13 = frameValue.cv.y;
796             result->f._23 = frameValue.cv.z;
797 
798             *flags |= frameValue.flag;
799         }
800         else
801         {
802             // 小数フレーム
803             f32 nextFrame = NormalizeFrame_( frame + 1.0f, pCurve );
804             u32 nextIndex = u32(nextFrame);
805             const ResVector3CurveData::FrameValue& nextFrameValue = pCurve->frames.m_KeyValue[nextIndex];
806 
807             math::VEC3 v;
808             VEC3Lerp(
809                 &v,
810                 static_cast<const math::VEC3*>(&frameValue.cv),
811                 static_cast<const math::VEC3*>(&nextFrameValue.cv),
812                 remainder );
813 
814             result->f._03 = v.x;
815             result->f._13 = v.y;
816             result->f._23 = v.z;
817 
818             // 意図はCalcVector3CurveCV_のコメントを参照
819             *flags |= (frameValue.flag & nextFrameValue.flag);
820         }
821     }
822 } // namespace
823 
824 f32
CalcFloatCurve(const ResFloatCurveData * pCurve,f32 frame)825 CalcFloatCurve( const ResFloatCurveData* pCurve, f32 frame )
826 {
827     NW_NULL_ASSERT( pCurve );
828 
829     frame = NormalizeFrame_( frame, pCurve );
830 
831     if ( pCurve->m_Flags & ResFloatCurveData::FLAG_COMPOSITE_CURVE )
832     {
833         return CalcCompositeFloatCurve_( reinterpret_cast<const ResCompositeFloatCurveData*>( pCurve ), frame );
834     }
835     else
836     {
837         return CalcSegmentFloatCurve_( reinterpret_cast<const ResSegmentFloatCurveData*>( pCurve ), frame );
838     }
839 }
840 
841 
842 s32
CalcIntCurve(const ResIntCurveData * pCurve,f32 frame)843 CalcIntCurve( const ResIntCurveData* pCurve, f32 frame )
844 {
845     NW_NULL_ASSERT( pCurve );
846     NW_ASSERT(!(pCurve->m_Flags & ResIntCurveData::FLAG_BAKED));
847 
848     frame = NormalizeFrame_( frame, pCurve );
849 
850     if ( pCurve->m_Flags & ResIntCurveData::FLAG_CONSTANT )
851     {
852         return pCurve->constantValue;
853     }
854 
855     u32 quantizedType = (pCurve->m_Flags & ResIntCurveData::FLAG_QUANTIZATION_TYPE_MASK) >>
856                         ResIntCurveData::FLAG_QUANTIZATION_TYPE_SHIFT;
857 
858     return s_CalcIntCurveFVTable[ quantizedType ]( &(pCurve->fv), frame );
859 }
860 
861 
862 bool
CalcBoolCurve(const ResBoolCurveData * pCurve,f32 frame)863 CalcBoolCurve( const ResBoolCurveData* pCurve, f32 frame )
864 {
865     NW_NULL_ASSERT( pCurve );
866 
867     frame = NormalizeFrame_( frame, pCurve );
868 
869     if ( pCurve->m_Flags & ResBoolCurveData::FLAG_CONSTANT )
870     {
871         return ((pCurve->m_Flags & ResBoolCurveData::FLAG_CONSTANT_VALUE) != 0);
872     }
873 
874     if ( pCurve->m_Flags & ResBoolCurveData::FLAG_BAKED )
875     {
876         return CalcBoolCurveCV_( pCurve, frame );
877     }
878     else
879     {
880         u32 quantizedType = (pCurve->m_Flags & ResBoolCurveData::FLAG_QUANTIZATION_TYPE_MASK) >>
881                             ResBoolCurveData::FLAG_QUANTIZATION_TYPE_SHIFT;
882 
883         return  (s_CalcIntCurveFVTable[ quantizedType ]( &(pCurve->fv), frame ) != 0);
884     }
885 }
886 
887 
888 void
CalcVector3Curve(math::VEC3 * result,bit32 * flags,const ResVector3CurveData * pCurve,f32 frame)889 CalcVector3Curve( math::VEC3* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame )
890 {
891     NW_NULL_ASSERT( pCurve );
892 
893     if ( pCurve->m_Flags & ResVector3CurveData::FLAG_CONSTANT )
894     {
895         // コンスタントの場合は最初のフレームの値を使用する
896         frame = pCurve->m_StartFrame;
897     }
898     else
899     {
900         frame = NormalizeFrame_( frame, pCurve );
901     }
902 
903     // TODO: 量子化対応
904     CalcVector3CurveCV_( result, flags, pCurve, frame );
905 }
906 
907 
908 /*!--------------------------------------------------------------------------*
909   @brief ベイクされたRotateのカーブ評価です。カーブはVector4ですが、書き込み先はMtx34です。
910  *---------------------------------------------------------------------------*/
CalcRotateCurve(math::MTX34 * result,bit32 * flags,const ResVector4CurveData * pCurve,f32 frame)911 void CalcRotateCurve(math::MTX34* result, bit32* flags, const ResVector4CurveData* pCurve, f32 frame)
912 {
913     NW_NULL_ASSERT( pCurve );
914 
915     frame = NormalizeFrame_( frame, pCurve );
916 
917     if ( pCurve->m_Flags & ResVector4CurveData::FLAG_CONSTANT )
918     {
919         // コンスタントの場合は最初のフレームの値を使用する
920         frame = pCurve->m_StartFrame;
921     }
922 
923     // TODO: 量子化対応
924     CalcRotateCurveCV_( result, flags, pCurve, frame );
925 }
926 
927 
928 /*!--------------------------------------------------------------------------*
929   @brief ベイクされたTranslateのカーブ評価です。カーブはVector3ですが、書き込み先はMtx34です。
930  *---------------------------------------------------------------------------*/
CalcTranslateCurve(math::MTX34 * result,bit32 * flags,const ResVector3CurveData * pCurve,f32 frame)931 void CalcTranslateCurve(math::MTX34* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame)
932 {
933     NW_NULL_ASSERT( pCurve );
934 
935     if ( pCurve->m_Flags & ResVector3CurveData::FLAG_CONSTANT )
936     {
937         // コンスタントの場合は最初のフレームの値を使用する
938         frame = pCurve->m_StartFrame;
939     }
940     else
941     {
942         frame = NormalizeFrame_( frame, pCurve );
943     }
944 
945     // TODO: 量子化対応
946     CalcTranslateCurveCV_( result, flags, pCurve, frame );
947 }
948 
949 } /* namespace res */
950 } /* namespace anim */
951 } /* namespace nw */
952 
953