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
Round(f32 value)27     Round( f32 value )
28     {
29         return nn::math::FFloor(value + 0.5f);
30     }
31 
32     NW_INLINE f32
CastS9_10ToF32(s32 value)33     CastS9_10ToF32( s32 value )
34     {
35         return f32(value) * (1.f / 1024.f);
36     }
37 
38     NW_INLINE s32
CastF32ToS9_10(f32 value)39     CastF32ToS9_10( f32 value )
40     {
41         return s32(Round(value * 1024.f));
42     }
43 
44     NW_INLINE f32
CastS7_8ToF32(s32 value)45     CastS7_8ToF32( s32 value )
46     {
47         return f32(value) * (1.f / 256.f);
48     }
49 
50     NW_INLINE s32
CastF32ToS7_8(f32 value)51     CastF32ToS7_8( f32 value )
52     {
53         return s32(Round(value * 256.f));
54     }
55 
56     NW_INLINE f32
CastS10_5ToF32(s32 value)57     CastS10_5ToF32( s32 value )
58     {
59         return f32(value) * (1.f / 32.f);
60     }
61 
62     NW_INLINE s32
CastF32ToS10_5(f32 value)63     CastF32ToS10_5( f32 value )
64     {
65         return s32(Round(value * 32.f));
66     }
67 
68     NW_INLINE f32
CastS6_5ToF32(s32 value)69     CastS6_5ToF32( s32 value )
70     {
71         return f32(value) * (1.f / 32.f);
72     }
73 
74     NW_INLINE s32
CastF32ToS6_5(f32 value)75     CastF32ToS6_5( f32 value )
76     {
77         return s32(Round(value * 32.f));
78     }
79 } /* namespace internal */
80 
81 // TODO: 量子化のビット数は仮のものです。
82 
83 //! @details :private
84 struct ResFloatKeyFV64Data
85 {
86     ut::ResF32  m_Frame;
87     ut::ResF32  m_Value;
88 
GetFrameResFloatKeyFV64Data89     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFV64Data90     f32 GetFrameF32() const { return m_Frame; }
GetValueResFloatKeyFV64Data91     f32 GetValue()    const { return m_Value; }
92 };
93 
94 //! @details :private
95 struct ResFloatKeyFV32Data
96 {
97     ut::ResU32  m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset;
98 
GetFrameResFloatKeyFV32Data99     u32 GetFrame()    const { return m_FrameValue & 0x00000FFF; }
GetFrameF32ResFloatKeyFV32Data100     f32 GetFrameF32() const { return static_cast<f32>(this->GetFrame()); }
GetValueResFloatKeyFV32Data101     f32 GetValue()    const { return static_cast<f32>(m_FrameValue >> 12); }
102 };
103 
104 //! @details :private
105 struct ResFloatKeyFVSS128Data
106 {
107     ut::ResF32 m_Frame;
108     ut::ResF32 m_Value;
109     ut::ResF32 m_InSlope;
110     ut::ResF32 m_OutSlope;
111 
GetFrameResFloatKeyFVSS128Data112     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVSS128Data113     f32 GetFrameF32() const { return m_Frame; }
GetValueResFloatKeyFVSS128Data114     f32 GetValue()    const { return m_Value; }
GetInSlopeResFloatKeyFVSS128Data115     f32 GetInSlope()  const { return m_InSlope; }
GetOutSlopeResFloatKeyFVSS128Data116     f32 GetOutSlope() const { return m_OutSlope; }
117 };
118 
119 //! @details :private
120 struct ResFloatKeyFVSS64Data
121 {
122     ut::ResU32 m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset;
123     ut::ResS16 m_InSlope;    // fx7.8
124     ut::ResS16 m_OutSlope;   // fx7.8
125 
GetFrameResFloatKeyFVSS64Data126     u32 GetFrame()    const { return m_FrameValue & 0x00000FFF; }
GetFrameF32ResFloatKeyFVSS64Data127     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVSS64Data128     f32 GetValue()    const { return static_cast<f32>( m_FrameValue >> 12 ); }
GetInSlopeResFloatKeyFVSS64Data129     f32 GetInSlope()  const { return internal::CastS7_8ToF32(m_InSlope); }
GetOutSlopeResFloatKeyFVSS64Data130     f32 GetOutSlope() const { return internal::CastS7_8ToF32(m_OutSlope); }
131 };
132 
133 //! @details :private
134 struct ResFloatKeyFVSS48Data
135 {
136     ut::ResU8  m_FrameValue[3]; // u8 m_Frame; u16 m_Value * scale + offset;
137     ut::ResU8  m_InOutSlope[3]; // fx6.5 m_InSlope; fx6.5 m_OutSlope;
138 
GetFrameResFloatKeyFVSS48Data139     u32 GetFrame()    const { return m_FrameValue[0]; }
GetFrameF32ResFloatKeyFVSS48Data140     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVSS48Data141     f32 GetValue()    const { return static_cast<f32>( u16(m_FrameValue[1]) + (u16(m_FrameValue[2]) << 8) ); }
GetInSlopeResFloatKeyFVSS48Data142     f32 GetInSlope()  const { return internal::CastS6_5ToF32( s16(m_InOutSlope[0] + (s8(m_InOutSlope[1] << 4) << 4)) ); }
GetOutSlopeResFloatKeyFVSS48Data143     f32 GetOutSlope() const { return internal::CastS6_5ToF32( s16((s8(m_InOutSlope[2]) << 4) + (m_InOutSlope[1] >> 4)) ); }
144 };
145 
146 //! @details :private
147 struct ResFloatKeyFVS96Data
148 {
149     ut::ResF32 m_Frame;
150     ut::ResF32 m_Value;
151     ut::ResF32 m_Slope;
152 
GetFrameResFloatKeyFVS96Data153     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS96Data154     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVS96Data155     f32 GetValue()    const { return m_Value; }
GetSlopeResFloatKeyFVS96Data156     f32 GetSlope()    const { return m_Slope; }
157 };
158 
159 //! @details :private
160 struct ResFloatKeyFVS48Data
161 {
162     ut::ResU16 m_Frame; // fx10.5
163     ut::ResU16 m_Value; // m_Value * scale + offset
164     ut::ResS16 m_Slope; // fx7.8
165 
GetFrameResFloatKeyFVS48Data166     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS48Data167     f32 GetFrameF32() const { return internal::CastS10_5ToF32( m_Frame ); }
GetValueResFloatKeyFVS48Data168     f32 GetValue()    const { return static_cast<f32>( m_Value ); }
GetSlopeResFloatKeyFVS48Data169     f32 GetSlope()    const { return internal::CastS7_8ToF32(m_Slope); }
170 };
171 
172 //! @details :private
173 struct ResFloatKeyFVS32Data
174 {
175     ut::ResU8  m_Frame;         // u8
176     ut::ResU8  m_ValueSlope[3]; // u12 m_Value * scale + offset; fx6.5 m_Slope;
177 
GetFrameResFloatKeyFVS32Data178     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResFloatKeyFVS32Data179     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResFloatKeyFVS32Data180     f32 GetValue()    const { return static_cast<f32>( u16(m_ValueSlope[0]) + (u16(m_ValueSlope[1] << 4) << 4) ); }
GetSlopeResFloatKeyFVS32Data181     f32 GetSlope()    const { return internal::CastS6_5ToF32((s8(m_ValueSlope[2]) << 4) + (m_ValueSlope[1] >> 4)); }
182 };
183 
184 //! @details :private
185 template <typename TKey>
186 struct ResKeysData
187 {
188     TKey m_KeyValue[1];  // 可変長配列にするとコンパイラが落ちるので、サイズ1にしておく。
189 };
190 
191 //! @details :private
192 template <typename TKey>
193 struct ResQuantizedKeysData
194 {
195     ut::ResF32  m_Scale; // Valueに適用する
196     ut::ResF32  m_Offset;
197     ut::ResF32  m_FrameScale; // Frameに適用する
198     ut::ResF32  m_FrameOffset;
199 
200     TKey    m_KeyValue[1];
201 };
202 
203 //! @details :private
204 struct ResFloatSegmentCVData
205 {
206     union
207     {
208         ResKeysData<f32>          cv32;
209         ResQuantizedKeysData<u16> cv16;
210         ResQuantizedKeysData<u8>  cv8;
211     };
212 };
213 
214 //! @details :private
215 struct ResFloatSegmentFVData
216 {
217     ut::ResU16 m_NumFrameValues;
218     u8     m_Padding_[2];
219 
220     ut::ResF32 m_InvDuration;
221 
222     union
223     {
224         ResKeysData<ResFloatKeyFVSS128Data>         fvss128;
225         ResQuantizedKeysData<ResFloatKeyFVSS64Data> fvss64;
226         ResQuantizedKeysData<ResFloatKeyFVSS48Data> fvss48;
227         ResKeysData<ResFloatKeyFVS96Data>           fvs96;
228         ResQuantizedKeysData<ResFloatKeyFVS48Data>  fvs48;
229         ResQuantizedKeysData<ResFloatKeyFVS32Data>  fvs32;
230         ResKeysData<ResFloatKeyFV64Data>            fv64;
231         ResQuantizedKeysData<ResFloatKeyFV32Data>   fv32;
232     };
233 };
234 
235 //! @details :private
236 struct ResFloatSegmentData
237 {
238     // セグメントカーブの特徴をフラグとして格納しています。
239     // FLAG_CONSTANT : このビットが1である場合には、このセグメントの
240     //                 アニメーション結果を定数として扱います。
241     //                 この時、FLAG_BAKED, FLAG_QUANTIZED, FLAG_INTERPORATE_MODE_MASK,
242     //                 FLAG_QUANTIZED_TYPE_MASK の設定は無効となります。
243     //
244     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
245     //                 コマ形式の場合には、FLAG_INTERPORATE_MODE_MASK の値は無視されます。
246     //
247     // FLAG_INTERPORATE_MODE_MASK : キーフレーム間の補間方式を設定します。
248     //
249     // FLAG_QUANTIZATION_TYPE_MASK    : 量子化の方式を設定します。
250     //
251     enum Flag
252     {
253         FLAG_CONSTANT               = (0x1 << 0),
254         FLAG_BAKED                  = (0x1 << 1),
255 
256         FLAG_INTERPORATE_MODE_SHIFT  = 2,
257         FLAG_QUANTIZATION_TYPE_SHIFT = 5,
258 
259         FLAG_INTERPORATE_MODE_MASK  = (0x7 << FLAG_INTERPORATE_MODE_SHIFT),
260         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
261     };
262 
263     enum InterporateMode
264     {
265         INTERPORATE_MODE_STEP    = 0,
266         INTERPORATE_MODE_LINEAR  = 1,
267         INTERPORATE_MODE_UNIFIED_HERMITE = 2,
268         INTERPORATE_MODE_HERMITE = 3
269     };
270 
271     enum QuantizeType
272     {
273         QUANTIZATION_TYPE_FVSS128 = 0,
274         QUANTIZATION_TYPE_FVSS64  = 1,
275         QUANTIZATION_TYPE_FVSS48  = 2,
276 
277         QUANTIZATION_TYPE_FVS96   = 3,
278         QUANTIZATION_TYPE_FVS48   = 4,
279         QUANTIZATION_TYPE_FVS32   = 5,
280 
281         QUANTIZATION_TYPE_FV64    = 6,
282         QUANTIZATION_TYPE_FV32    = 7,
283 
284         QUANTIZATION_TYPE_CV32   = 0,
285         QUANTIZATION_TYPE_CV16   = 1,
286         QUANTIZATION_TYPE_CV8    = 2
287     };
288 
289     ut::ResF32  m_StartFrame;
290     ut::ResF32  m_EndFrame;
291     ut::ResU32  m_Flags;
292 
293     union
294     {
295         ut::ResF32            constantValue;
296         ResFloatSegmentFVData fv;
297         ResFloatSegmentCVData cv;
298     };
299 };
300 
301 //! @details :private
302 struct ResAnimCurveData
303 {
304     enum RepeatMethod
305     {
306         METHOD_NONE,
307         METHOD_REPEAT,
308         METHOD_MIRROR,
309         METHOD_NUM
310     };
311 
312     ut::ResF32   m_StartFrame;
313     ut::ResF32   m_EndFrame;
314     ut::ResU8    m_InRepeatMethod;
315     ut::ResU8    m_OutRepeatMethod;
316     u8           m_Padding[2];
317 };
318 
319 //! @details :private
320 struct ResFloatCurveData : public ResAnimCurveData
321 {
322     // セグメントフロートカーブの特徴をフラグとして格納しています。
323     // FLAG_COMPOSITE_CURVE : このカーブが複合カーブであることを示します。
324     //
325     enum Flag
326     {
327         FLAG_COMPOSITE_CURVE         = (0x1 << 0),
328         FLAG_SHIFT_MAX = 1
329     };
330 
331     ut::ResU32 m_Flags;
332 };
333 
334 //! @details :private
335 struct ResSegmentFloatCurveData : public ResFloatCurveData
336 {
337     // セグメントフロートカーブの特徴をフラグとして格納しています。
338     // FLAG_CONSTANT : このビットが1である場合には、このカーブの
339     //                 アニメーション結果を定数として扱います。
340     // FLAG_MONO_SEGMENT : このビットが1である場合には、単一セグメントで
341     //                     構成されるカーブとして扱います。
342     //
343     enum Flag
344     {
345         FLAG_CONSTANT       = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 0)),
346         FLAG_MONO_SEGMENT   = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 1))
347     };
348 
349     union
350     {
351         ut::ResF32 m_ConstantValue;
352         struct
353         {
354             ut::ResS32 m_NumSegments;
355             ut::Offset toSegments[1];
356         } segmentsTable;
357     };
358 };
359 
360 
361 //! @details :private
362 struct ResCompositeFloatCurveData : public ResFloatCurveData
363 {
364     ut::Offset   toLeftCurve;
365     ut::Offset   toRightCurve;
366     ut::Offset   toLeftBoolCurve;
367     ut::Offset   toRightBoolCurve;
368     ut::ResU8    m_CompositeMode;
369     u8           padding[3];
370 };
371 
372 
373 
374 //! @details :private
375 struct ResIntKeyFV64Data
376 {
377     ut::ResF32 m_Frame;
378     ut::ResS32 m_Value;
379 
GetFrameResIntKeyFV64Data380     f32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV64Data381     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV64Data382     s32 GetValue()    const { return m_Value; }
383 };
384 
385 //! @details :private
386 struct ResIntKeyFV32Data
387 {
388     ut::ResU16 m_Frame;
389     ut::ResS16 m_Value;
390 
GetFrameResIntKeyFV32Data391     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV32Data392     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV32Data393     s16 GetValue()    const { return m_Value; }
394 };
395 
396 //! @details :private
397 struct ResIntKeyFV16Data
398 {
399     ut::ResU8 m_Frame;
400     ut::ResS8 m_Value;
401 
GetFrameResIntKeyFV16Data402     u32 GetFrame()    const { return m_Frame; }
GetFrameF32ResIntKeyFV16Data403     f32 GetFrameF32() const { return static_cast<f32>( this->GetFrame() ); }
GetValueResIntKeyFV16Data404     s8  GetValue()    const { return m_Value; }
405 };
406 
407 //! @details :private
408 struct ResIntCurveFVData
409 {
410     ut::ResU16 m_NumFrameValues;
411     u8     m_Padding_[2];
412 
413     ut::ResF32 m_InvDuration;
414 
415     union
416     {
417         ResKeysData<ResIntKeyFV64Data> fv64;
418         ResKeysData<ResIntKeyFV32Data> fv32;
419         ResKeysData<ResIntKeyFV16Data> fv16;
420     };
421 };
422 
423 //! @details :private
424 struct ResIntCurveCVData
425 {
426     union
427     {
428         ResKeysData<ut::ResS32>     cv32;
429         ResKeysData<ut::ResS16>     cv16;
430         ResKeysData<ut::ResS8>      cv8;
431     };
432 };
433 
434 
435 //! @details :private
436 struct ResIntCurveData : public ResAnimCurveData
437 {
438     // Int カーブの特徴をフラグとして格納しています。
439     // FLAG_CONSTANT : このビットが1である場合には、アニメーション結果を定数値として扱います。
440     //                 この時、FLAG_BAKED は無視されます。
441     //
442     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
443     //
444     enum Flag
445     {
446         FLAG_CONSTANT       = (0x1 << 0),
447         FLAG_BAKED          = (0x1 << 2),
448 
449         FLAG_QUANTIZATION_TYPE_SHIFT = 3,
450         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
451     };
452 
453     enum QuantizeType
454     {
455         FLAG_QUANTIZATION_TYPE_FV64   = 0,
456         FLAG_QUANTIZATION_TYPE_FV32   = 1,
457         FLAG_QUANTIZATION_TYPE_FV16   = 2,
458 
459         FLAG_QUANTIZATION_TYPE_CV32   = 0,
460         FLAG_QUANTIZATION_TYPE_CV16   = 1,
461         FLAG_QUANTIZATION_TYPE_CV8    = 2
462     };
463 
464     ut::ResU32 m_Flags;
465 
466     union
467     {
468         ut::ResS32                  constantValue;
469         ResIntCurveFVData           fv;
470         ResIntCurveCVData           cv;
471     };
472 };
473 
474 
475 //! @details :private
476 struct ResBoolCurveData : public ResAnimCurveData
477 {
478     // Bool カーブの特徴をフラグとして格納しています。
479     // FLAG_CONSTANT : このビットが1である場合には、FLAG_CONSTANT_VALUE を
480     //                 定数値の結果として扱います。
481     //                 この時、FLAG_BAKED は無視されます。
482     //
483     // FLAG_BAKED    : アニメーションデータをコマ形式として扱います。
484     //                 コマ形式の場合は、1byte に 8フレーム分の bool 値が
485     //                 格納されています。
486     //
487     enum Flag
488     {
489         FLAG_CONSTANT       = (0x1 << 0),
490         FLAG_CONSTANT_VALUE = (0x1 << 1),
491         FLAG_BAKED          = (0x1 << 2),
492 
493         FLAG_QUANTIZATION_TYPE_SHIFT = 3,
494         FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT)
495     };
496 
497     enum QuantizeType
498     {
499         FLAG_QUANTIZATION_TYPE_FV64   = 0,
500         FLAG_QUANTIZATION_TYPE_FV32   = 1,
501         FLAG_QUANTIZATION_TYPE_FV16   = 2
502     };
503 
504     ut::ResU32 m_Flags;
505 
506     union
507     {
508         ResKeysData<ut::ResU8>      cv;
509         ResIntCurveFVData           fv;
510     };
511 };
512 
513 //! @details :private
514 //! ベイクされたアニメーション専用のクラスです。
515 template <typename Type>
516 struct ResBakedCurveData : public ResAnimCurveData
517 {
518     // カーブの特徴をフラグとして格納しています。
519     // FLAG_CONSTANT : このビットが 1 である場合には、アニメーション結果を定数値として扱います。
520     enum Flag
521     {
522         FLAG_CONSTANT = (0x1 << 0)
523     };
524 
525     // TODO: 量子化対応
526     ut::ResU32 m_Flags;
527 
528     struct FrameValue
529     {
530         Type cv;
531         ut::ResU32 flag;
532     };
533     ResKeysData<FrameValue> frames;
534 };
535 
536 //! @details :private
537 //! フルベイクアニメーション専用のクラスです。
538 struct ResFullBakedCurveData : public ResAnimCurveData
539 {
540     ResKeysData<ut::ResMtx34_> frames;
541 };
542 
543 // ベイクされたアニメ用の型名を定義します。
544 typedef ResBakedCurveData<ut::ResVec3_> ResVector3CurveData; //!< @details :private
545 typedef ResBakedCurveData<ut::ResVec4> ResVector4CurveData; //!< @details :private
546 
547 f32  CalcFloatCurve( const ResFloatCurveData* pCurve, f32 frame ); //!< @details :private
548 bool CalcBoolCurve( const ResBoolCurveData* pCurve, f32 frame ); //!< @details :private
549 s32  CalcIntCurve( const ResIntCurveData* pCurve, f32 frame ); //!< @details :private
550 
551 void CalcVector3Curve( math::VEC3* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private
552 
553 void CalcTranslateCurve( math::MTX34* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private
554 void CalcRotateCurve( math::MTX34* result, bit32* flags, const ResVector4CurveData* pCurve, f32 frame ); //!< @details :private
555 
556 void CalcTransformCurve( math::MTX34* result, const ResFullBakedCurveData* pCurve, f32 frame ); //!< @details :private
557 
558 } /* namespace res */
559 } /* namespace anim */
560 } /* namespace nw */
561 
562 #endif /* NW_ANIM_RESANIMATIONCURVE_H_ */
563