/*---------------------------------------------------------------------------* Project: NintendoWare File: anim_ResAnimCurve.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 19698 $ *---------------------------------------------------------------------------*/ #ifndef NW_ANIM_RESANIMATIONCURVE_H_ #define NW_ANIM_RESANIMATIONCURVE_H_ #include namespace nw { namespace anim { namespace res { namespace internal { NW_INLINE f32 CastS9_10ToF32( s32 value ) { return f32(value) * (1.f / 1024.f); } NW_INLINE s32 CastF32ToS9_10( f32 value ) { return s32(value * 1024.f); } NW_INLINE f32 CastS7_8ToF32( s32 value ) { return f32(value) * (1.f / 256.f); } NW_INLINE s32 CastF32ToS7_8( f32 value ) { return s32(value * 256.f); } NW_INLINE f32 CastS10_5ToF32( s32 value ) { return f32(value) * (1.f / 32.f); } NW_INLINE s32 CastF32ToS10_5( f32 value ) { return s32(value * 32.f); } NW_INLINE f32 CastS6_5ToF32( s32 value ) { return f32(value) * (1.f / 32.f); } NW_INLINE s32 CastF32ToS6_5( f32 value ) { return s32(value * 32.f); } } /* namespace internal */ // TODO: 量子化のビット数は仮のものです。 //! @details :private struct ResFloatKeyFV64Data { ut::ResF32 m_Frame; ut::ResF32 m_Value; f32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return m_Frame; } f32 GetValue() const { return m_Value; } }; //! @details :private struct ResFloatKeyFV32Data { ut::ResU32 m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset; u32 GetFrame() const { return m_FrameValue & 0x00000FFF; } f32 GetFrameF32() const { return static_cast(this->GetFrame()); } f32 GetValue() const { return static_cast(m_FrameValue >> 12); } }; //! @details :private struct ResFloatKeyFVSS128Data { ut::ResF32 m_Frame; ut::ResF32 m_Value; ut::ResF32 m_InSlope; ut::ResF32 m_OutSlope; f32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return m_Frame; } f32 GetValue() const { return m_Value; } f32 GetInSlope() const { return m_InSlope; } f32 GetOutSlope() const { return m_OutSlope; } }; //! @details :private struct ResFloatKeyFVSS64Data { ut::ResU32 m_FrameValue; // u12 m_Frame; u20 m_Value * scale + offset; ut::ResS16 m_InSlope; // fx7.8 ut::ResS16 m_OutSlope; // fx7.8 u32 GetFrame() const { return m_FrameValue & 0x00000FFF; } f32 GetFrameF32() const { return static_cast( this->GetFrame() ); } f32 GetValue() const { return static_cast( m_FrameValue >> 12 ); } f32 GetInSlope() const { return internal::CastS7_8ToF32(m_InSlope); } f32 GetOutSlope() const { return internal::CastS7_8ToF32(m_OutSlope); } }; //! @details :private struct ResFloatKeyFVSS48Data { ut::ResU8 m_FrameValue[3]; // u8 m_Frame; u16 m_Value * scale + offset; ut::ResU8 m_InOutSlope[3]; // fx6.5 m_InSlope; fx6.5 m_OutSlope; u32 GetFrame() const { return m_FrameValue[0]; } f32 GetFrameF32() const { return static_cast( this->GetFrame() ); } f32 GetValue() const { return static_cast( u16(m_FrameValue[1]) + (u16(m_FrameValue[2]) << 8) ); } f32 GetInSlope() const { return internal::CastS6_5ToF32( s16(m_InOutSlope[0] + (s8(m_InOutSlope[1] << 4) << 4)) ); } f32 GetOutSlope() const { return internal::CastS6_5ToF32( s16((s8(m_InOutSlope[2]) << 4) + (m_InOutSlope[1] >> 4)) ); } }; //! @details :private struct ResFloatKeyFVS96Data { ut::ResF32 m_Frame; ut::ResF32 m_Value; ut::ResF32 m_Slope; f32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return static_cast( this->GetFrame() ); } f32 GetValue() const { return m_Value; } f32 GetSlope() const { return m_Slope; } }; //! @details :private struct ResFloatKeyFVS48Data { ut::ResU16 m_Frame; // fx10.5 ut::ResU16 m_Value; // m_Value * scale + offset ut::ResS16 m_Slope; // fx7.8 u32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return internal::CastS10_5ToF32( m_Frame ); } f32 GetValue() const { return static_cast( m_Value ); } f32 GetSlope() const { return internal::CastS7_8ToF32(m_Slope); } }; //! @details :private struct ResFloatKeyFVS32Data { ut::ResU8 m_Frame; // u8 ut::ResU8 m_ValueSlope[3]; // u12 m_Value * scale + offset; fx6.5 m_Slope; u32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return static_cast( this->GetFrame() ); } f32 GetValue() const { return static_cast( u16(m_ValueSlope[0]) + (u16(m_ValueSlope[1] << 4) << 4) ); } f32 GetSlope() const { return internal::CastS6_5ToF32((s8(m_ValueSlope[2]) << 4) + (m_ValueSlope[1] >> 4)); } }; //! @details :private template struct ResKeysData { TKey m_KeyValue[1]; // 可変長配列にするとコンパイラが落ちるので、サイズ1にしておく。 }; //! @details :private template struct ResQuantizedKeysData { ut::ResF32 m_Scale; ut::ResF32 m_Offset; TKey m_KeyValue[1]; }; //! @details :private struct ResFloatSegmentCVData { union { ResKeysData cv32; ResQuantizedKeysData cv16; ResQuantizedKeysData cv8; }; }; //! @details :private struct ResFloatSegmentFVData { ut::ResU16 m_NumFrameValues; u8 m_Padding_[2]; ut::ResF32 m_InvDuration; union { ResKeysData fvss128; ResQuantizedKeysData fvss64; ResQuantizedKeysData fvss48; ResKeysData fvs96; ResQuantizedKeysData fvs48; ResQuantizedKeysData fvs32; ResKeysData fv64; ResQuantizedKeysData fv32; }; }; //! @details :private struct ResFloatSegmentData { // セグメントカーブの特徴をフラグとして格納しています。 // FLAG_CONSTANT : このビットが1である場合には、このセグメントの // アニメーション結果を定数として扱います。 // この時、FLAG_BAKED, FLAG_QUANTIZED, FLAG_INTERPORATE_MODE_MASK, // FLAG_QUANTIZED_TYPE_MASK の設定は無効となります。 // // FLAG_BAKED : アニメーションデータをコマ形式として扱います。 // コマ形式の場合には、FLAG_INTERPORATE_MODE_MASK の値は無視されます。 // // FLAG_INTERPORATE_MODE_MASK : キーフレーム間の補間方式を設定します。 // // FLAG_QUANTIZATION_TYPE_MASK : 量子化の方式を設定します。 // enum Flag { FLAG_CONSTANT = (0x1 << 0), FLAG_BAKED = (0x1 << 1), FLAG_INTERPORATE_MODE_SHIFT = 2, FLAG_QUANTIZATION_TYPE_SHIFT = 5, FLAG_INTERPORATE_MODE_MASK = (0x7 << FLAG_INTERPORATE_MODE_SHIFT), FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT) }; enum InterporateMode { INTERPORATE_MODE_STEP = 0, INTERPORATE_MODE_LINEAR = 1, INTERPORATE_MODE_UNIFIED_HERMITE = 2, INTERPORATE_MODE_HERMITE = 3 }; enum QuantizeType { QUANTIZATION_TYPE_FVSS128 = 0, QUANTIZATION_TYPE_FVSS64 = 1, QUANTIZATION_TYPE_FVSS48 = 2, QUANTIZATION_TYPE_FVS96 = 3, QUANTIZATION_TYPE_FVS48 = 4, QUANTIZATION_TYPE_FVS32 = 5, QUANTIZATION_TYPE_FV64 = 6, QUANTIZATION_TYPE_FV32 = 7, QUANTIZATION_TYPE_CV32 = 0, QUANTIZATION_TYPE_CV16 = 1, QUANTIZATION_TYPE_CV8 = 2 }; ut::ResF32 m_StartFrame; ut::ResF32 m_EndFrame; ut::ResU32 m_Flags; union { ut::ResF32 constantValue; ResFloatSegmentFVData fv; ResFloatSegmentCVData cv; }; }; //! @details :private struct ResAnimCurveData { enum RepeatMethod { METHOD_NONE, METHOD_REPEAT, METHOD_MIRROR, METHOD_RELATIVE, METHOD_NUM }; ut::ResF32 m_StartFrame; ut::ResF32 m_EndFrame; ut::ResU8 m_InRepeatMethod; ut::ResU8 m_OutRepeatMethod; u8 m_Padding[2]; }; //! @details :private struct ResFloatCurveData : public ResAnimCurveData { // セグメントフロートカーブの特徴をフラグとして格納しています。 // FLAG_COMPOSITE_CURVE : このカーブが複合カーブであることを示します。 // enum Flag { FLAG_COMPOSITE_CURVE = (0x1 << 0), FLAG_SHIFT_MAX = 1 }; ut::ResU32 m_Flags; }; //! @details :private struct ResSegmentFloatCurveData : public ResFloatCurveData { // セグメントフロートカーブの特徴をフラグとして格納しています。 // FLAG_CONSTANT : このビットが1である場合には、このカーブの // アニメーション結果を定数として扱います。 // FLAG_MONO_SEGMENT : このビットが1である場合には、単一セグメントで // 構成されるカーブとして扱います。 // enum Flag { FLAG_CONSTANT = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 0)), FLAG_MONO_SEGMENT = (0x1 << (ResFloatCurveData::FLAG_SHIFT_MAX + 1)) }; union { ut::ResF32 m_ConstantValue; struct { ut::ResS32 m_NumSegments; ut::Offset toSegments[1]; } segmentsTable; }; }; //! @details :private struct ResCompositeFloatCurveData : public ResFloatCurveData { ut::Offset toLeftCurve; ut::Offset toRightCurve; ut::Offset toLeftBoolCurve; ut::Offset toRightBoolCurve; ut::ResU8 m_CompositeMode; u8 padding[3]; }; //! @details :private struct ResIntKeyFV64Data { ut::ResF32 m_Frame; ut::ResS32 m_Value; f32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return static_cast( this->GetFrame() ); } s32 GetValue() const { return m_Value; } }; //! @details :private struct ResIntKeyFV32Data { ut::ResU16 m_Frame; ut::ResS16 m_Value; u32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return static_cast( this->GetFrame() ); } s16 GetValue() const { return m_Value; } }; //! @details :private struct ResIntKeyFV16Data { ut::ResU8 m_Frame; ut::ResS8 m_Value; u32 GetFrame() const { return m_Frame; } f32 GetFrameF32() const { return static_cast( this->GetFrame() ); } s8 GetValue() const { return m_Value; } }; //! @details :private struct ResIntCurveFVData { ut::ResU16 m_NumFrameValues; u8 m_Padding_[2]; ut::ResF32 m_InvDuration; union { ResKeysData fv64; ResKeysData fv32; ResKeysData fv16; }; }; //! @details :private struct ResIntCurveCVData { union { ResKeysData cv32; ResKeysData cv16; ResKeysData cv8; }; }; //! @details :private struct ResIntCurveData : public ResAnimCurveData { // Int カーブの特徴をフラグとして格納しています。 // FLAG_CONSTANT : このビットが1である場合には、アニメーション結果を定数値として扱います。 // この時、FLAG_BAKED は無視されます。 // // FLAG_BAKED : アニメーションデータをコマ形式として扱います。 // enum Flag { FLAG_CONSTANT = (0x1 << 0), FLAG_BAKED = (0x1 << 2), FLAG_QUANTIZATION_TYPE_SHIFT = 3, FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT) }; enum QuantizeType { FLAG_QUANTIZATION_TYPE_FV64 = 0, FLAG_QUANTIZATION_TYPE_FV32 = 1, FLAG_QUANTIZATION_TYPE_FV16 = 2, FLAG_QUANTIZATION_TYPE_CV32 = 0, FLAG_QUANTIZATION_TYPE_CV16 = 1, FLAG_QUANTIZATION_TYPE_CV8 = 2 }; ut::ResU32 m_Flags; union { ut::ResS32 constantValue; ResIntCurveFVData fv; ResIntCurveCVData cv; }; }; //! @details :private struct ResBoolCurveData : public ResAnimCurveData { // Bool カーブの特徴をフラグとして格納しています。 // FLAG_CONSTANT : このビットが1である場合には、FLAG_CONSTANT_VALUE を // 定数値の結果として扱います。 // この時、FLAG_BAKED は無視されます。 // // FLAG_BAKED : アニメーションデータをコマ形式として扱います。 // コマ形式の場合は、1byte に 8フレーム分の bool 値が // 格納されています。 // enum Flag { FLAG_CONSTANT = (0x1 << 0), FLAG_CONSTANT_VALUE = (0x1 << 1), FLAG_BAKED = (0x1 << 2), FLAG_QUANTIZATION_TYPE_SHIFT = 3, FLAG_QUANTIZATION_TYPE_MASK = (0x7 << FLAG_QUANTIZATION_TYPE_SHIFT) }; enum QuantizeType { FLAG_QUANTIZATION_TYPE_FV64 = 0, FLAG_QUANTIZATION_TYPE_FV32 = 1, FLAG_QUANTIZATION_TYPE_FV16 = 2 }; ut::ResU32 m_Flags; union { ResKeysData cv; ResIntCurveFVData fv; }; }; //! @details :private //! ベイクされたアニメーション専用のクラスです。 template struct ResBakedCurveData : public ResAnimCurveData { // カーブの特徴をフラグとして格納しています。 // FLAG_CONSTANT : このビットが 1 である場合には、アニメーション結果を定数値として扱います。 enum Flag { FLAG_CONSTANT = (0x1 << 0) }; // TODO: 量子化対応 ut::ResU32 m_Flags; struct FrameValue { Type cv; ut::ResU32 flag; }; ResKeysData frames; }; // ベイクされたアニメ用の型名を定義します。 typedef ResBakedCurveData ResVector3CurveData; //!< @details :private typedef ResBakedCurveData ResVector4CurveData; //!< @details :private f32 CalcFloatCurve( const ResFloatCurveData* pCurve, f32 frame ); //!< @details :private bool CalcBoolCurve( const ResBoolCurveData* pCurve, f32 frame ); //!< @details :private s32 CalcIntCurve( const ResIntCurveData* pCurve, f32 frame ); //!< @details :private void CalcVector3Curve( math::VEC3* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private void CalcTranslateCurve( math::MTX34* result, bit32* flags, const ResVector3CurveData* pCurve, f32 frame ); //!< @details :private void CalcRotateCurve( math::MTX34* result, bit32* flags, const ResVector4CurveData* pCurve, f32 frame ); //!< @details :private } /* namespace res */ } /* namespace anim */ } /* namespace nw */ #endif /* NW_ANIM_RESANIMATIONCURVE_H_ */