1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     anim_ResAnimCurve.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_ANIM_RESANIMATIONCURVE_H_
19 #define NW_ANIM_RESANIMATIONCURVE_H_
20 
21 #include <nw/types.h>
22 
23 namespace nw {
24 namespace anim {
25 namespace res {
26 
27 namespace internal {
28     NW_INLINE f32
Round(f32 value)29     Round( f32 value )
30     {
31         return nn::math::FFloor(value + 0.5f);
32     }
33 
34     NW_INLINE f32
CastS9_10ToF32(s32 value)35     CastS9_10ToF32( s32 value )
36     {
37         return f32(value) * (1.f / 1024.f);
38     }
39 
40     NW_INLINE s32
CastF32ToS9_10(f32 value)41     CastF32ToS9_10( f32 value )
42     {
43         return s32(Round(value * 1024.f));
44     }
45 
46     NW_INLINE f32
CastS7_8ToF32(s32 value)47     CastS7_8ToF32( s32 value )
48     {
49         return f32(value) * (1.f / 256.f);
50     }
51 
52     NW_INLINE s32
CastF32ToS7_8(f32 value)53     CastF32ToS7_8( f32 value )
54     {
55         return s32(Round(value * 256.f));
56     }
57 
58     NW_INLINE f32
CastS10_5ToF32(s32 value)59     CastS10_5ToF32( s32 value )
60     {
61         return f32(value) * (1.f / 32.f);
62     }
63 
64     NW_INLINE s32
CastF32ToS10_5(f32 value)65     CastF32ToS10_5( f32 value )
66     {
67         return s32(Round(value * 32.f));
68     }
69 
70     NW_INLINE f32
CastS6_5ToF32(s32 value)71     CastS6_5ToF32( s32 value )
72     {
73         return f32(value) * (1.f / 32.f);
74     }
75 
76     NW_INLINE s32
CastF32ToS6_5(f32 value)77     CastF32ToS6_5( f32 value )
78     {
79         return s32(Round(value * 32.f));
80     }
81 } /* namespace internal */
82 
83 // TODO: 量子化のビット数は仮のものです。
84 
85 //! @details :private
86 struct ResFloatKeyFV64Data
87 {
88     ut::ResF32  m_Frame;
89     ut::ResF32  m_Value;
90 
GetFrameResFloatKeyFV64Data91     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFV64Data92     f32 GetFrameF32() const { return m_Frame; }
GetValueResFloatKeyFV64Data93     f32 GetValue()    const { return m_Value; }
94 };
95 
96 //! @details :private
97 struct ResFloatKeyFV32Data
98 {
99     ut::ResU32  m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset;
100 
GetFrameResFloatKeyFV32Data101     u32 GetFrame()    const { return m_FrameValue & 0x00000FFF; }
GetFrameF32ResFloatKeyFV32Data102     f32 GetFrameF32() const { return static_cast<f32>(this->GetFrame()); }
GetValueResFloatKeyFV32Data103     f32 GetValue()    const { return static_cast<f32>(m_FrameValue >> 12); }
104 };
105 
106 //! @details :private
107 struct ResFloatKeyFVSS128Data
108 {
109     ut::ResF32 m_Frame;
110     ut::ResF32 m_Value;
111     ut::ResF32 m_InSlope;
112     ut::ResF32 m_OutSlope;
113 
GetFrameResFloatKeyFVSS128Data114     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVSS128Data115     f32 GetFrameF32() const { return m_Frame; }
GetValueResFloatKeyFVSS128Data116     f32 GetValue()    const { return m_Value; }
GetInSlopeResFloatKeyFVSS128Data117     f32 GetInSlope()  const { return m_InSlope; }
GetOutSlopeResFloatKeyFVSS128Data118     f32 GetOutSlope() const { return m_OutSlope; }
119 };
120 
121 //! @details :private
122 struct ResFloatKeyFVSS64Data
123 {
124     ut::ResU32 m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset;
125     ut::ResS16 m_InSlope;    // fx7.8
126     ut::ResS16 m_OutSlope;   // fx7.8
127 
GetFrameResFloatKeyFVSS64Data128     u32 GetFrame()    const { return m_FrameValue & 0x00000FFF; }
GetFrameF32ResFloatKeyFVSS64Data129     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVSS64Data130     f32 GetValue()    const { return static_cast<f32>( m_FrameValue >> 12 ); }
GetInSlopeResFloatKeyFVSS64Data131     f32 GetInSlope()  const { return internal::CastS7_8ToF32(m_InSlope); }
GetOutSlopeResFloatKeyFVSS64Data132     f32 GetOutSlope() const { return internal::CastS7_8ToF32(m_OutSlope); }
133 };
134 
135 //! @details :private
136 struct ResFloatKeyFVSS48Data
137 {
138     ut::ResU8  m_FrameValue[3]; // u8 m_Frame; u16 m_Value * scale + offset;
139     ut::ResU8  m_InOutSlope[3]; // fx6.5 m_InSlope; fx6.5 m_OutSlope;
140 
GetFrameResFloatKeyFVSS48Data141     u32 GetFrame()    const { return m_FrameValue[0]; }
GetFrameF32ResFloatKeyFVSS48Data142     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVSS48Data143     f32 GetValue()    const { return static_cast<f32>( u16(m_FrameValue[1]) + (u16(m_FrameValue[2]) << 8) ); }
GetInSlopeResFloatKeyFVSS48Data144     f32 GetInSlope()  const { return internal::CastS6_5ToF32( s16(m_InOutSlope[0] + (s8(m_InOutSlope[1] << 4) << 4)) ); }
GetOutSlopeResFloatKeyFVSS48Data145     f32 GetOutSlope() const { return internal::CastS6_5ToF32( s16((s8(m_InOutSlope[2]) << 4) + (m_InOutSlope[1] >> 4)) ); }
146 };
147 
148 //! @details :private
149 struct ResFloatKeyFVS96Data
150 {
151     ut::ResF32 m_Frame;
152     ut::ResF32 m_Value;
153     ut::ResF32 m_Slope;
154 
GetFrameResFloatKeyFVS96Data155     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS96Data156     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVS96Data157     f32 GetValue()    const { return m_Value; }
GetSlopeResFloatKeyFVS96Data158     f32 GetSlope()    const { return m_Slope; }
159 };
160 
161 //! @details :private
162 struct ResFloatKeyFVS48Data
163 {
164     ut::ResU16 m_Frame; // fx10.5
165     ut::ResU16 m_Value; // m_Value * scale + offset
166     ut::ResS16 m_Slope; // fx7.8
167 
GetFrameResFloatKeyFVS48Data168     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS48Data169     f32 GetFrameF32() const { return internal::CastS10_5ToF32( m_Frame ); }
GetValueResFloatKeyFVS48Data170     f32 GetValue()    const { return static_cast<f32>( m_Value ); }
GetSlopeResFloatKeyFVS48Data171     f32 GetSlope()    const { return internal::CastS7_8ToF32(m_Slope); }
172 };
173 
174 //! @details :private
175 struct ResFloatKeyFVS32Data
176 {
177     ut::ResU8  m_Frame;         // u8
178     ut::ResU8  m_ValueSlope[3]; // u12 m_Value * scale + offset; fx6.5 m_Slope;
179 
GetFrameResFloatKeyFVS32Data180     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS32Data181     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVS32Data182     f32 GetValue()    const { return static_cast<f32>( u16(m_ValueSlope[0]) + (u16(m_ValueSlope[1] << 4) << 4) ); }
GetSlopeResFloatKeyFVS32Data183     f32 GetSlope()    const { return internal::CastS6_5ToF32((s8(m_ValueSlope[2]) << 4) + (m_ValueSlope[1] >> 4)); }
184 };
185 
186 //! @details :private
187 template <typename TKey>
188 struct ResKeysData
189 {
190     TKey m_KeyValue[1];  // 可変長配列にするとコンパイラが落ちるので、サイズ1にしておく。
191 };
192 
193 //! @details :private
194 template <typename TKey>
195 struct ResQuantizedKeysData
196 {
197     ut::ResF32  m_Scale; // Valueに適用する
198     ut::ResF32  m_Offset;
199     ut::ResF32  m_FrameScale; // Frameに適用する
200 
201     TKey    m_KeyValue[1];
202 };
203 
204 //! @details :private
205 struct ResFloatSegmentCVData
206 {
207     union
208     {
209         ResKeysData<f32>          cv32;
210         ResQuantizedKeysData<u16> cv16;
211         ResQuantizedKeysData<u8>  cv8;
212     };
213 };
214 
215 //! @details :private
216 struct ResFloatSegmentFVData
217 {
218     ut::ResU16 m_NumFrameValues;
219     u8     m_Padding_[2];
220 
221     ut::ResF32 m_InvDuration;
222 
223     union
224     {
225         ResKeysData<ResFloatKeyFVSS128Data>         fvss128;
226         ResQuantizedKeysData<ResFloatKeyFVSS64Data> fvss64;
227         ResQuantizedKeysData<ResFloatKeyFVSS48Data> fvss48;
228         ResKeysData<ResFloatKeyFVS96Data>           fvs96;
229         ResQuantizedKeysData<ResFloatKeyFVS48Data>  fvs48;
230         ResQuantizedKeysData<ResFloatKeyFVS32Data>  fvs32;
231         ResKeysData<ResFloatKeyFV64Data>            fv64;
232         ResQuantizedKeysData<ResFloatKeyFV32Data>   fv32;
233     };
234 };
235 
236 //! @details :private
237 struct ResFloatSegmentData
238 {
239     // セグメントカーブの特徴をフラグとして格納しています。
240     // FLAG_CONSTANT : このビットが1である場合には、このセグメントの
241     //                 アニメーション結果を定数として扱います。
242     //                 この時、FLAG_BAKED, FLAG_QUANTIZED, FLAG_INTERPORATE_MODE_MASK,
243     //                 FLAG_QUANTIZED_TYPE_MASK の設定は無効となります。
244     //
245     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
246     //                 コマ形式の場合には、FLAG_INTERPORATE_MODE_MASK の値は無視されます。
247     //
248     // FLAG_INTERPORATE_MODE_MASK : キーフレーム間の補間方式を設定します。
249     //
250     // FLAG_QUANTIZATION_TYPE_MASK    : 量子化の方式を設定します。
251     //
252     enum Flag
253     {
254         FLAG_CONSTANT               = (0x1 << 0),
255         FLAG_BAKED                  = (0x1 << 1),
256 
257         FLAG_INTERPORATE_MODE_SHIFT  = 2,
258         FLAG_QUANTIZATION_TYPE_SHIFT = 5,
259 
260         FLAG_INTERPORATE_MODE_MASK  = (0x7 << FLAG_INTERPORATE_MODE_SHIFT),
261         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
262     };
263 
264     enum InterporateMode
265     {
266         INTERPORATE_MODE_STEP    = 0,
267         INTERPORATE_MODE_LINEAR  = 1,
268         INTERPORATE_MODE_UNIFIED_HERMITE = 2,
269         INTERPORATE_MODE_HERMITE = 3
270     };
271 
272     enum QuantizeType
273     {
274         QUANTIZATION_TYPE_FVSS128 = 0,
275         QUANTIZATION_TYPE_FVSS64  = 1,
276         QUANTIZATION_TYPE_FVSS48  = 2,
277 
278         QUANTIZATION_TYPE_FVS96   = 3,
279         QUANTIZATION_TYPE_FVS48   = 4,
280         QUANTIZATION_TYPE_FVS32   = 5,
281 
282         QUANTIZATION_TYPE_FV64    = 6,
283         QUANTIZATION_TYPE_FV32    = 7,
284 
285         QUANTIZATION_TYPE_CV32   = 0,
286         QUANTIZATION_TYPE_CV16   = 1,
287         QUANTIZATION_TYPE_CV8    = 2
288     };
289 
290     ut::ResF32  m_StartFrame;
291     ut::ResF32  m_EndFrame;
292     ut::ResU32  m_Flags;
293 
294     union
295     {
296         ut::ResF32            constantValue;
297         ResFloatSegmentFVData fv;
298         ResFloatSegmentCVData cv;
299     };
300 };
301 
302 //! @details :private
303 struct ResAnimCurveData
304 {
305     enum RepeatMethod
306     {
307         METHOD_NONE,
308         METHOD_REPEAT,
309         METHOD_MIRROR,
310         METHOD_NUM
311     };
312 
313     ut::ResF32   m_StartFrame;
314     ut::ResF32   m_EndFrame;
315     ut::ResU8    m_InRepeatMethod;
316     ut::ResU8    m_OutRepeatMethod;
317     u8           m_Padding[2];
318 };
319 
320 //! @details :private
321 struct ResFloatCurveData : public ResAnimCurveData
322 {
323     // セグメントフロートカーブの特徴をフラグとして格納しています。
324     // FLAG_COMPOSITE_CURVE : このカーブが複合カーブであることを示します。
325     //
326     enum Flag
327     {
328         FLAG_COMPOSITE_CURVE         = (0x1 << 0),
329         FLAG_SHIFT_MAX = 1
330     };
331 
332     ut::ResU32 m_Flags;
333 };
334 
335 //! @details :private
336 struct ResSegmentFloatCurveData : public ResFloatCurveData
337 {
338     // セグメントフロートカーブの特徴をフラグとして格納しています。
339     // FLAG_CONSTANT : このビットが1である場合には、このカーブの
340     //                 アニメーション結果を定数として扱います。
341     // FLAG_MONO_SEGMENT : このビットが1である場合には、単一セグメントで
342     //                     構成されるカーブとして扱います。
343     //
344     enum Flag
345     {
346         FLAG_CONSTANT       = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 0)),
347         FLAG_MONO_SEGMENT   = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 1))
348     };
349 
350     union
351     {
352         ut::ResF32 m_ConstantValue;
353         struct
354         {
355             ut::ResS32 m_NumSegments;
356             ut::Offset toSegments[1];
357         } segmentsTable;
358     };
359 };
360 
361 
362 //! @details :private
363 struct ResCompositeFloatCurveData : public ResFloatCurveData
364 {
365     ut::Offset   toLeftCurve;
366     ut::Offset   toRightCurve;
367     ut::Offset   toLeftBoolCurve;
368     ut::Offset   toRightBoolCurve;
369     ut::ResU8    m_CompositeMode;
370     u8           padding[3];
371 };
372 
373 
374 
375 //! @details :private
376 struct ResIntKeyFV64Data
377 {
378     ut::ResF32 m_Frame;
379     ut::ResS32 m_Value;
380 
GetFrameResIntKeyFV64Data381     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV64Data382     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV64Data383     s32 GetValue()    const { return m_Value; }
384 };
385 
386 //! @details :private
387 struct ResIntKeyFV32Data
388 {
389     ut::ResU16 m_Frame;
390     ut::ResS16 m_Value;
391 
GetFrameResIntKeyFV32Data392     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV32Data393     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV32Data394     s16 GetValue()    const { return m_Value; }
395 };
396 
397 //! @details :private
398 struct ResIntKeyFV16Data
399 {
400     ut::ResU8 m_Frame;
401     ut::ResS8 m_Value;
402 
GetFrameResIntKeyFV16Data403     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV16Data404     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV16Data405     s8  GetValue()    const { return m_Value; }
406 };
407 
408 //! @details :private
409 struct ResIntCurveFVData
410 {
411     ut::ResU16 m_NumFrameValues;
412     u8     m_Padding_[2];
413 
414     ut::ResF32 m_InvDuration;
415 
416     union
417     {
418         ResKeysData<ResIntKeyFV64Data> fv64;
419         ResKeysData<ResIntKeyFV32Data> fv32;
420         ResKeysData<ResIntKeyFV16Data> fv16;
421     };
422 };
423 
424 //! @details :private
425 struct ResIntCurveCVData
426 {
427     union
428     {
429         ResKeysData<ut::ResS32>     cv32;
430         ResKeysData<ut::ResS16>     cv16;
431         ResKeysData<ut::ResS8>      cv8;
432     };
433 };
434 
435 
436 //! @details :private
437 struct ResIntCurveData : public ResAnimCurveData
438 {
439     // Int カーブの特徴をフラグとして格納しています。
440     // FLAG_CONSTANT : このビットが1である場合には、アニメーション結果を定数値として扱います。
441     //                 この時、FLAG_BAKED は無視されます。
442     //
443     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
444     //
445     enum Flag
446     {
447         FLAG_CONSTANT       = (0x1 << 0),
448         FLAG_BAKED          = (0x1 << 2),
449 
450         FLAG_QUANTIZATION_TYPE_SHIFT = 3,
451         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
452     };
453 
454     enum QuantizeType
455     {
456         FLAG_QUANTIZATION_TYPE_FV64   = 0,
457         FLAG_QUANTIZATION_TYPE_FV32   = 1,
458         FLAG_QUANTIZATION_TYPE_FV16   = 2,
459 
460         FLAG_QUANTIZATION_TYPE_CV32   = 0,
461         FLAG_QUANTIZATION_TYPE_CV16   = 1,
462         FLAG_QUANTIZATION_TYPE_CV8    = 2
463     };
464 
465     ut::ResU32 m_Flags;
466 
467     union
468     {
469         ut::ResS32                  constantValue;
470         ResIntCurveFVData           fv;
471         ResIntCurveCVData           cv;
472     };
473 };
474 
475 
476 //! @details :private
477 struct ResBoolCurveData : public ResAnimCurveData
478 {
479     // Bool カーブの特徴をフラグとして格納しています。
480     // FLAG_CONSTANT : このビットが1である場合には、FLAG_CONSTANT_VALUE を
481     //                 定数値の結果として扱います。
482     //                 この時、FLAG_BAKED は無視されます。
483     //
484     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
485     //                 コマ形式の場合は、1byte に 8フレーム分の bool 値が
486     //                 格納されています。
487     //
488     enum Flag
489     {
490         FLAG_CONSTANT       = (0x1 << 0),
491         FLAG_CONSTANT_VALUE = (0x1 << 1),
492         FLAG_BAKED          = (0x1 << 2),
493 
494         FLAG_QUANTIZATION_TYPE_SHIFT = 3,
495         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
496     };
497 
498     enum QuantizeType
499     {
500         FLAG_QUANTIZATION_TYPE_FV64   = 0,
501         FLAG_QUANTIZATION_TYPE_FV32   = 1,
502         FLAG_QUANTIZATION_TYPE_FV16   = 2
503     };
504 
505     ut::ResU32 m_Flags;
506 
507     union
508     {
509         ResKeysData<ut::ResU8>      cv;
510         ResIntCurveFVData           fv;
511     };
512 };
513 
514 //! @details :private
515 //! ベイクされたアニメーション専用のクラスです。
516 template <typename Type>
517 struct ResBakedCurveData : public ResAnimCurveData
518 {
519     // カーブの特徴をフラグとして格納しています。
520     // FLAG_CONSTANT : このビットが 1 である場合には、アニメーション結果を定数値として扱います。
521     enum Flag
522     {
523         FLAG_CONSTANT = (0x1 << 0)
524     };
525 
526     // TODO: 量子化対応
527     ut::ResU32 m_Flags;
528 
529     struct FrameValue
530     {
531         Type cv;
532         ut::ResU32 flag;
533     };
534     ResKeysData<FrameValue> frames;
535 };
536 
537 //! @details :private
538 //! フルベイクアニメーション専用のクラスです。
539 struct ResFullBakedCurveData : public ResAnimCurveData
540 {
541     ResKeysData<ut::ResMtx34_> frames;
542 };
543 
544 // ベイクされたアニメ用の型名を定義します。
545 typedef ResBakedCurveData<ut::ResVec3_> ResVector3CurveData; //!< @details :private
546 typedef ResBakedCurveData<ut::ResVec4> ResVector4CurveData; //!< @details :private
547 
548 f32  CalcFloatCurve( const ResFloatCurveData* pCurve, f32 frame ); //!< @details :private
549 bool CalcBoolCurve( const ResBoolCurveData* pCurve, f32 frame ); //!< @details :private
550 s32  CalcIntCurve( const ResIntCurveData* pCurve, f32 frame ); //!< @details :private
551 
552 void CalcVector3Curve( math::VEC3* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private
553 
554 void CalcTranslateCurve( math::MTX34* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private
555 void CalcRotateCurve( math::MTX34* result, bit32* flags, const ResVector4CurveData* pCurve, f32 frame ); //!< @details :private
556 
557 void CalcTransformCurve( math::MTX34* result, const ResFullBakedCurveData* pCurve, f32 frame ); //!< @details :private
558 
559 } /* namespace res */
560 } /* namespace anim */
561 } /* namespace nw */
562 
563 #endif /* NW_ANIM_RESANIMATIONCURVE_H_ */
564