1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     anim_ResAnimCurve.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: 19698 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_ANIM_RESANIMATIONCURVE_H_
17 #define NW_ANIM_RESANIMATIONCURVE_H_
18 
19 #include <nw/types.h>
20 
21 namespace nw {
22 namespace anim {
23 namespace res {
24 
25 namespace internal {
26     NW_INLINE f32
CastS9_10ToF32(s32 value)27     CastS9_10ToF32( s32 value )
28     {
29         return f32(value) * (1.f / 1024.f);
30     }
31 
32     NW_INLINE s32
CastF32ToS9_10(f32 value)33     CastF32ToS9_10( f32 value )
34     {
35         return s32(value * 1024.f);
36     }
37 
38     NW_INLINE f32
CastS7_8ToF32(s32 value)39     CastS7_8ToF32( s32 value )
40     {
41         return f32(value) * (1.f / 256.f);
42     }
43 
44     NW_INLINE s32
CastF32ToS7_8(f32 value)45     CastF32ToS7_8( f32 value )
46     {
47         return s32(value * 256.f);
48     }
49 
50     NW_INLINE f32
CastS10_5ToF32(s32 value)51     CastS10_5ToF32( s32 value )
52     {
53         return f32(value) * (1.f / 32.f);
54     }
55 
56     NW_INLINE s32
CastF32ToS10_5(f32 value)57     CastF32ToS10_5( f32 value )
58     {
59         return s32(value * 32.f);
60     }
61 
62     NW_INLINE f32
CastS6_5ToF32(s32 value)63     CastS6_5ToF32( s32 value )
64     {
65         return f32(value) * (1.f / 32.f);
66     }
67 
68     NW_INLINE s32
CastF32ToS6_5(f32 value)69     CastF32ToS6_5( f32 value )
70     {
71         return s32(value * 32.f);
72     }
73 } /* namespace internal */
74 
75 // TODO: 量子化のビット数は仮のものです。
76 
77 //! @details :private
78 struct ResFloatKeyFV64Data
79 {
80     ut::ResF32  m_Frame;
81     ut::ResF32  m_Value;
82 
GetFrameResFloatKeyFV64Data83     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFV64Data84     f32 GetFrameF32() const { return m_Frame; }
GetValueResFloatKeyFV64Data85     f32 GetValue()    const { return m_Value; }
86 };
87 
88 //! @details :private
89 struct ResFloatKeyFV32Data
90 {
91     ut::ResU32  m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset;
92 
GetFrameResFloatKeyFV32Data93     u32 GetFrame()    const { return m_FrameValue & 0x00000FFF; }
GetFrameF32ResFloatKeyFV32Data94     f32 GetFrameF32() const { return static_cast<f32>(this->GetFrame()); }
GetValueResFloatKeyFV32Data95     f32 GetValue()    const { return static_cast<f32>(m_FrameValue >> 12); }
96 };
97 
98 //! @details :private
99 struct ResFloatKeyFVSS128Data
100 {
101     ut::ResF32 m_Frame;
102     ut::ResF32 m_Value;
103     ut::ResF32 m_InSlope;
104     ut::ResF32 m_OutSlope;
105 
GetFrameResFloatKeyFVSS128Data106     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVSS128Data107     f32 GetFrameF32() const { return m_Frame; }
GetValueResFloatKeyFVSS128Data108     f32 GetValue()    const { return m_Value; }
GetInSlopeResFloatKeyFVSS128Data109     f32 GetInSlope()  const { return m_InSlope; }
GetOutSlopeResFloatKeyFVSS128Data110     f32 GetOutSlope() const { return m_OutSlope; }
111 };
112 
113 //! @details :private
114 struct ResFloatKeyFVSS64Data
115 {
116     ut::ResU32 m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset;
117     ut::ResS16 m_InSlope;    // fx7.8
118     ut::ResS16 m_OutSlope;   // fx7.8
119 
GetFrameResFloatKeyFVSS64Data120     u32 GetFrame()    const { return m_FrameValue & 0x00000FFF; }
GetFrameF32ResFloatKeyFVSS64Data121     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVSS64Data122     f32 GetValue()    const { return static_cast<f32>( m_FrameValue >> 12 ); }
GetInSlopeResFloatKeyFVSS64Data123     f32 GetInSlope()  const { return internal::CastS7_8ToF32(m_InSlope); }
GetOutSlopeResFloatKeyFVSS64Data124     f32 GetOutSlope() const { return internal::CastS7_8ToF32(m_OutSlope); }
125 };
126 
127 //! @details :private
128 struct ResFloatKeyFVSS48Data
129 {
130     ut::ResU8  m_FrameValue[3]; // u8 m_Frame; u16 m_Value * scale + offset;
131     ut::ResU8  m_InOutSlope[3]; // fx6.5 m_InSlope; fx6.5 m_OutSlope;
132 
GetFrameResFloatKeyFVSS48Data133     u32 GetFrame()    const { return m_FrameValue[0]; }
GetFrameF32ResFloatKeyFVSS48Data134     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVSS48Data135     f32 GetValue()    const { return static_cast<f32>( u16(m_FrameValue[1]) + (u16(m_FrameValue[2]) << 8) ); }
GetInSlopeResFloatKeyFVSS48Data136     f32 GetInSlope()  const { return internal::CastS6_5ToF32( s16(m_InOutSlope[0] + (s8(m_InOutSlope[1] << 4) << 4)) ); }
GetOutSlopeResFloatKeyFVSS48Data137     f32 GetOutSlope() const { return internal::CastS6_5ToF32( s16((s8(m_InOutSlope[2]) << 4) + (m_InOutSlope[1] >> 4)) ); }
138 };
139 
140 //! @details :private
141 struct ResFloatKeyFVS96Data
142 {
143     ut::ResF32 m_Frame;
144     ut::ResF32 m_Value;
145     ut::ResF32 m_Slope;
146 
GetFrameResFloatKeyFVS96Data147     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS96Data148     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVS96Data149     f32 GetValue()    const { return m_Value; }
GetSlopeResFloatKeyFVS96Data150     f32 GetSlope()    const { return m_Slope; }
151 };
152 
153 //! @details :private
154 struct ResFloatKeyFVS48Data
155 {
156     ut::ResU16 m_Frame; // fx10.5
157     ut::ResU16 m_Value; // m_Value * scale + offset
158     ut::ResS16 m_Slope; // fx7.8
159 
GetFrameResFloatKeyFVS48Data160     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS48Data161     f32 GetFrameF32() const { return internal::CastS10_5ToF32( m_Frame ); }
GetValueResFloatKeyFVS48Data162     f32 GetValue()    const { return static_cast<f32>( m_Value ); }
GetSlopeResFloatKeyFVS48Data163     f32 GetSlope()    const { return internal::CastS7_8ToF32(m_Slope); }
164 };
165 
166 //! @details :private
167 struct ResFloatKeyFVS32Data
168 {
169     ut::ResU8  m_Frame;         // u8
170     ut::ResU8  m_ValueSlope[3]; // u12 m_Value * scale + offset; fx6.5 m_Slope;
171 
GetFrameResFloatKeyFVS32Data172     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS32Data173     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVS32Data174     f32 GetValue()    const { return static_cast<f32>( u16(m_ValueSlope[0]) + (u16(m_ValueSlope[1] << 4) << 4) ); }
GetSlopeResFloatKeyFVS32Data175     f32 GetSlope()    const { return internal::CastS6_5ToF32((s8(m_ValueSlope[2]) << 4) + (m_ValueSlope[1] >> 4)); }
176 };
177 
178 //! @details :private
179 template <typename TKey>
180 struct ResKeysData
181 {
182     TKey m_KeyValue[1];  // 可変長配列にするとコンパイラが落ちるので、サイズ1にしておく。
183 };
184 
185 //! @details :private
186 template <typename TKey>
187 struct ResQuantizedKeysData
188 {
189     ut::ResF32  m_Scale;
190     ut::ResF32  m_Offset;
191 
192     TKey    m_KeyValue[1];
193 };
194 
195 //! @details :private
196 struct ResFloatSegmentCVData
197 {
198     union
199     {
200         ResKeysData<f32>          cv32;
201         ResQuantizedKeysData<u16> cv16;
202         ResQuantizedKeysData<u8>  cv8;
203     };
204 };
205 
206 //! @details :private
207 struct ResFloatSegmentFVData
208 {
209     ut::ResU16 m_NumFrameValues;
210     u8     m_Padding_[2];
211 
212     ut::ResF32 m_InvDuration;
213 
214     union
215     {
216         ResKeysData<ResFloatKeyFVSS128Data>         fvss128;
217         ResQuantizedKeysData<ResFloatKeyFVSS64Data> fvss64;
218         ResQuantizedKeysData<ResFloatKeyFVSS48Data> fvss48;
219         ResKeysData<ResFloatKeyFVS96Data>           fvs96;
220         ResQuantizedKeysData<ResFloatKeyFVS48Data>  fvs48;
221         ResQuantizedKeysData<ResFloatKeyFVS32Data>  fvs32;
222         ResKeysData<ResFloatKeyFV64Data>            fv64;
223         ResQuantizedKeysData<ResFloatKeyFV32Data>   fv32;
224     };
225 };
226 
227 //! @details :private
228 struct ResFloatSegmentData
229 {
230     // セグメントカーブの特徴をフラグとして格納しています。
231     // FLAG_CONSTANT : このビットが1である場合には、このセグメントの
232     //                 アニメーション結果を定数として扱います。
233     //                 この時、FLAG_BAKED, FLAG_QUANTIZED, FLAG_INTERPORATE_MODE_MASK,
234     //                 FLAG_QUANTIZED_TYPE_MASK の設定は無効となります。
235     //
236     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
237     //                 コマ形式の場合には、FLAG_INTERPORATE_MODE_MASK の値は無視されます。
238     //
239     // FLAG_INTERPORATE_MODE_MASK : キーフレーム間の補間方式を設定します。
240     //
241     // FLAG_QUANTIZATION_TYPE_MASK    : 量子化の方式を設定します。
242     //
243     enum Flag
244     {
245         FLAG_CONSTANT               = (0x1 << 0),
246         FLAG_BAKED                  = (0x1 << 1),
247 
248         FLAG_INTERPORATE_MODE_SHIFT  = 2,
249         FLAG_QUANTIZATION_TYPE_SHIFT = 5,
250 
251         FLAG_INTERPORATE_MODE_MASK  = (0x7 << FLAG_INTERPORATE_MODE_SHIFT),
252         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
253     };
254 
255     enum InterporateMode
256     {
257         INTERPORATE_MODE_STEP    = 0,
258         INTERPORATE_MODE_LINEAR  = 1,
259         INTERPORATE_MODE_UNIFIED_HERMITE = 2,
260         INTERPORATE_MODE_HERMITE = 3
261     };
262 
263     enum QuantizeType
264     {
265         QUANTIZATION_TYPE_FVSS128 = 0,
266         QUANTIZATION_TYPE_FVSS64  = 1,
267         QUANTIZATION_TYPE_FVSS48  = 2,
268 
269         QUANTIZATION_TYPE_FVS96   = 3,
270         QUANTIZATION_TYPE_FVS48   = 4,
271         QUANTIZATION_TYPE_FVS32   = 5,
272 
273         QUANTIZATION_TYPE_FV64    = 6,
274         QUANTIZATION_TYPE_FV32    = 7,
275 
276         QUANTIZATION_TYPE_CV32   = 0,
277         QUANTIZATION_TYPE_CV16   = 1,
278         QUANTIZATION_TYPE_CV8    = 2
279     };
280 
281     ut::ResF32  m_StartFrame;
282     ut::ResF32  m_EndFrame;
283     ut::ResU32  m_Flags;
284 
285     union
286     {
287         ut::ResF32            constantValue;
288         ResFloatSegmentFVData fv;
289         ResFloatSegmentCVData cv;
290     };
291 };
292 
293 //! @details :private
294 struct ResAnimCurveData
295 {
296     enum RepeatMethod
297     {
298         METHOD_NONE,
299         METHOD_REPEAT,
300         METHOD_MIRROR,
301         METHOD_RELATIVE,
302         METHOD_NUM
303     };
304 
305     ut::ResF32   m_StartFrame;
306     ut::ResF32   m_EndFrame;
307     ut::ResU8    m_InRepeatMethod;
308     ut::ResU8    m_OutRepeatMethod;
309     u8           m_Padding[2];
310 };
311 
312 //! @details :private
313 struct ResFloatCurveData : public ResAnimCurveData
314 {
315     // セグメントフロートカーブの特徴をフラグとして格納しています。
316     // FLAG_COMPOSITE_CURVE : このカーブが複合カーブであることを示します。
317     //
318     enum Flag
319     {
320         FLAG_COMPOSITE_CURVE         = (0x1 << 0),
321         FLAG_SHIFT_MAX = 1
322     };
323 
324     ut::ResU32 m_Flags;
325 };
326 
327 //! @details :private
328 struct ResSegmentFloatCurveData : public ResFloatCurveData
329 {
330     // セグメントフロートカーブの特徴をフラグとして格納しています。
331     // FLAG_CONSTANT : このビットが1である場合には、このカーブの
332     //                 アニメーション結果を定数として扱います。
333     // FLAG_MONO_SEGMENT : このビットが1である場合には、単一セグメントで
334     //                     構成されるカーブとして扱います。
335     //
336     enum Flag
337     {
338         FLAG_CONSTANT       = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 0)),
339         FLAG_MONO_SEGMENT   = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 1))
340     };
341 
342     union
343     {
344         ut::ResF32 m_ConstantValue;
345         struct
346         {
347             ut::ResS32 m_NumSegments;
348             ut::Offset toSegments[1];
349         } segmentsTable;
350     };
351 };
352 
353 
354 //! @details :private
355 struct ResCompositeFloatCurveData : public ResFloatCurveData
356 {
357     ut::Offset   toLeftCurve;
358     ut::Offset   toRightCurve;
359     ut::Offset   toLeftBoolCurve;
360     ut::Offset   toRightBoolCurve;
361     ut::ResU8    m_CompositeMode;
362     u8           padding[3];
363 };
364 
365 
366 
367 //! @details :private
368 struct ResIntKeyFV64Data
369 {
370     ut::ResF32 m_Frame;
371     ut::ResS32 m_Value;
372 
GetFrameResIntKeyFV64Data373     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV64Data374     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV64Data375     s32 GetValue()    const { return m_Value; }
376 };
377 
378 //! @details :private
379 struct ResIntKeyFV32Data
380 {
381     ut::ResU16 m_Frame;
382     ut::ResS16 m_Value;
383 
GetFrameResIntKeyFV32Data384     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV32Data385     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV32Data386     s16 GetValue()    const { return m_Value; }
387 };
388 
389 //! @details :private
390 struct ResIntKeyFV16Data
391 {
392     ut::ResU8 m_Frame;
393     ut::ResS8 m_Value;
394 
GetFrameResIntKeyFV16Data395     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV16Data396     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV16Data397     s8  GetValue()    const { return m_Value; }
398 };
399 
400 //! @details :private
401 struct ResIntCurveFVData
402 {
403     ut::ResU16 m_NumFrameValues;
404     u8     m_Padding_[2];
405 
406     ut::ResF32 m_InvDuration;
407 
408     union
409     {
410         ResKeysData<ResIntKeyFV64Data> fv64;
411         ResKeysData<ResIntKeyFV32Data> fv32;
412         ResKeysData<ResIntKeyFV16Data> fv16;
413     };
414 };
415 
416 //! @details :private
417 struct ResIntCurveCVData
418 {
419     union
420     {
421         ResKeysData<ut::ResS32>     cv32;
422         ResKeysData<ut::ResS16>     cv16;
423         ResKeysData<ut::ResS8>      cv8;
424     };
425 };
426 
427 
428 //! @details :private
429 struct ResIntCurveData : public ResAnimCurveData
430 {
431     // Int カーブの特徴をフラグとして格納しています。
432     // FLAG_CONSTANT : このビットが1である場合には、アニメーション結果を定数値として扱います。
433     //                 この時、FLAG_BAKED は無視されます。
434     //
435     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
436     //
437     enum Flag
438     {
439         FLAG_CONSTANT       = (0x1 << 0),
440         FLAG_BAKED          = (0x1 << 2),
441 
442         FLAG_QUANTIZATION_TYPE_SHIFT = 3,
443         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
444     };
445 
446     enum QuantizeType
447     {
448         FLAG_QUANTIZATION_TYPE_FV64   = 0,
449         FLAG_QUANTIZATION_TYPE_FV32   = 1,
450         FLAG_QUANTIZATION_TYPE_FV16   = 2,
451 
452         FLAG_QUANTIZATION_TYPE_CV32   = 0,
453         FLAG_QUANTIZATION_TYPE_CV16   = 1,
454         FLAG_QUANTIZATION_TYPE_CV8    = 2
455     };
456 
457     ut::ResU32 m_Flags;
458 
459     union
460     {
461         ut::ResS32                  constantValue;
462         ResIntCurveFVData           fv;
463         ResIntCurveCVData           cv;
464     };
465 };
466 
467 
468 //! @details :private
469 struct ResBoolCurveData : public ResAnimCurveData
470 {
471     // Bool カーブの特徴をフラグとして格納しています。
472     // FLAG_CONSTANT : このビットが1である場合には、FLAG_CONSTANT_VALUE を
473     //                 定数値の結果として扱います。
474     //                 この時、FLAG_BAKED は無視されます。
475     //
476     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
477     //                 コマ形式の場合は、1byte に 8フレーム分の bool 値が
478     //                 格納されています。
479     //
480     enum Flag
481     {
482         FLAG_CONSTANT       = (0x1 << 0),
483         FLAG_CONSTANT_VALUE = (0x1 << 1),
484         FLAG_BAKED          = (0x1 << 2),
485 
486         FLAG_QUANTIZATION_TYPE_SHIFT = 3,
487         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
488     };
489 
490     enum QuantizeType
491     {
492         FLAG_QUANTIZATION_TYPE_FV64   = 0,
493         FLAG_QUANTIZATION_TYPE_FV32   = 1,
494         FLAG_QUANTIZATION_TYPE_FV16   = 2
495     };
496 
497     ut::ResU32 m_Flags;
498 
499     union
500     {
501         ResKeysData<ut::ResU8>      cv;
502         ResIntCurveFVData           fv;
503     };
504 };
505 
506 //! @details :private
507 //! ベイクされたアニメーション専用のクラスです。
508 template <typename Type>
509 struct ResBakedCurveData : public ResAnimCurveData
510 {
511     // カーブの特徴をフラグとして格納しています。
512     // FLAG_CONSTANT : このビットが 1 である場合には、アニメーション結果を定数値として扱います。
513     enum Flag
514     {
515         FLAG_CONSTANT = (0x1 << 0)
516     };
517 
518     // TODO: 量子化対応
519     ut::ResU32 m_Flags;
520 
521     struct FrameValue
522     {
523         Type cv;
524         ut::ResU32 flag;
525     };
526     ResKeysData<FrameValue> frames;
527 };
528 
529 // ベイクされたアニメ用の型名を定義します。
530 typedef ResBakedCurveData<ut::ResVec3_> ResVector3CurveData; //!< @details :private
531 typedef ResBakedCurveData<ut::ResVec4> ResVector4CurveData; //!< @details :private
532 
533 f32  CalcFloatCurve( const ResFloatCurveData* pCurve, f32 frame ); //!< @details :private
534 bool CalcBoolCurve( const ResBoolCurveData* pCurve, f32 frame ); //!< @details :private
535 s32  CalcIntCurve( const ResIntCurveData* pCurve, f32 frame ); //!< @details :private
536 
537 void CalcVector3Curve( math::VEC3* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private
538 
539 void CalcTranslateCurve( math::MTX34* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private
540 void CalcRotateCurve( math::MTX34* result, bit32* flags, const ResVector4CurveData* pCurve, f32 frame ); //!< @details :private
541 
542 } /* namespace res */
543 } /* namespace anim */
544 } /* namespace nw */
545 
546 #endif /* NW_ANIM_RESANIMATIONCURVE_H_ */
547