/* =========================================================================== Copyright (C) 2015 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenMoHAA source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // SkelMat4.h : Skeletor #ifndef __SKELMAT4_H__ #define __SKELMAT4_H__ #ifdef __cplusplus class SkelQuat; class SkelMat4 { public: float val[ 4 ][ 3 ]; protected: void copy( const SkelMat4& ); public: void MakeIdentity(); void MakeTranslate( float, float, float ); void MakeXRotation( float ); void MakeYRotation( float ); void MakeZRotation( float ); SkelMat4( const float mat[ 3 ][ 3 ] ); SkelMat4(); SkelVec3 *XAxis(); SkelVec3 *YAxis(); SkelVec3 *ZAxis(); SkelVec3 *XAxis() const; SkelVec3 *YAxis() const; SkelVec3 *ZAxis() const; operator float *( ); operator float *( ) const; bool IsOrthonormal() const; bool IsValid() const; float *operator[]( int index ); float *operator[]( int index ) const; int CompareExact( const SkelMat4& skel ) const; void Sum( const SkelMat4& m1, const SkelMat4& m2 ); void Difference( const SkelMat4& m1, const SkelMat4& m2 ); void Multiply( const SkelMat4& m1, const SkelMat4& m2 ); void InvertAxis( int ); void RotateBy( const SkelMat3& m ); void RotateByInverse( const SkelMat3& m ); void RotateXAxis( float x ); void RotateYAxis( float y ); void RotateZAxis( float z ); void RotateXAxis( float, float ); void RotateYAxis( float, float ); void RotateZAxis( float, float ); void MoveOnXAxis( float x ); void MoveOnYAxis( float y ); void MoveOnZAxis( float z ); void TransformVector( float * ) const; void TransposeRot(); void TransposeOf( const SkelMat4& m ); void TransposeRotOf( const SkelMat4& m ); void InverseRotOf( const SkelMat4& m ); float Determinant( void ); void Inverse( void ); void GetRotationMatrix( float( *)[ 3 ] ) const; void GetRotationMatrix( float( *)[ 4 ] ) const; void ReplacePos( const float * ); void ReplaceRot( const SkelMat3& m ); void ReplaceRot( const SkelMat4& m ); void GetPos( float *pos ) const; void GetScale( float *scale ) const; void DeltaPos( const SkelMat4& m, float *delta ) const; void RotateYaw( float, float ); void GetQuat( SkelQuat& quat ); }; inline SkelMat4::SkelMat4( const float mat[ 3 ][ 3 ] ) { VectorCopy(mat[0], val[0]); VectorCopy(mat[1], val[1]); VectorCopy(mat[2], val[2]); val[3][0] = 0.0f; val[3][1] = 0.0f; val[3][2] = 0.0f; } inline SkelMat4::SkelMat4() { MakeIdentity(); } inline void SkelMat4::copy( const SkelMat4& m ) { MatrixCopy( *m.val, *val ); } inline void SkelMat4::MakeIdentity() { memset( val, 0, sizeof( val ) ); val[ 0 ][ 0 ] = 1.0f; val[ 1 ][ 1 ] = 1.0f; val[ 2 ][ 2 ] = 1.0f; } inline SkelVec3 *SkelMat4::XAxis() { return ( SkelVec3 * )&val[ 0 ]; } inline SkelVec3 *SkelMat4::YAxis() { return ( SkelVec3 * )&val[ 1 ]; } inline SkelVec3 *SkelMat4::ZAxis() { return ( SkelVec3 * )&val[ 2 ]; } inline SkelVec3 *SkelMat4::XAxis() const { return ( SkelVec3 * )&val[ 0 ]; } inline SkelVec3 *SkelMat4::YAxis() const { return ( SkelVec3 * )&val[ 1 ]; } inline SkelVec3 *SkelMat4::ZAxis() const { return ( SkelVec3 * )&val[ 2 ]; } inline SkelMat4::operator float *( ) { return &val[ 0 ][ 0 ]; } inline SkelMat4::operator float *( ) const { return ( float * )&val[ 0 ][ 0 ]; } inline float *SkelMat4::operator[]( int index ) { return val[ index ]; } inline float *SkelMat4::operator[]( int index ) const { return ( float * )val[ index ]; } inline bool SkelMat4::IsOrthonormal() const { // FIXME: stub return false; } inline bool SkelMat4::IsValid() const { // FIXME: stub return false; } inline void SkelMat4::Sum( const SkelMat4& m1, const SkelMat4& m2 ) { VectorAdd( m1.val[ 0 ], m2.val[ 0 ], val[ 0 ] ); VectorAdd( m1.val[ 1 ], m2.val[ 1 ], val[ 1 ] ); VectorAdd( m1.val[ 2 ], m2.val[ 2 ], val[ 2 ] ); } inline void SkelMat4::Difference( const SkelMat4& m1, const SkelMat4& m2 ) { VectorSubtract( m1.val[ 0 ], m2.val[ 0 ], val[ 0 ] ); VectorSubtract( m1.val[ 1 ], m2.val[ 1 ], val[ 1 ] ); VectorSubtract( m1.val[ 2 ], m2.val[ 2 ], val[ 2 ] ); } inline void SkelMat4::Multiply( const SkelMat4& m1, const SkelMat4& m2 ) { val[ 0 ][ 0 ] = m1[ 0 ][ 0 ] * m2[ 0 ][ 0 ] + m1[ 0 ][ 1 ] * m2[ 1 ][ 0 ] + m1[ 0 ][ 2 ] * m2[ 2 ][ 0 ]; val[ 1 ][ 0 ] = m1[ 1 ][ 0 ] * m2[ 0 ][ 0 ] + m1[ 1 ][ 1 ] * m2[ 1 ][ 0 ] + m1[ 1 ][ 2 ] * m2[ 2 ][ 0 ]; val[ 2 ][ 0 ] = m1[ 2 ][ 0 ] * m2[ 0 ][ 0 ] + m1[ 2 ][ 1 ] * m2[ 1 ][ 0 ] + m1[ 2 ][ 2 ] * m2[ 2 ][ 0 ]; val[ 3 ][ 0 ] = m1[ 3 ][ 0 ] * m2[ 0 ][ 0 ] + m1[ 3 ][ 1 ] * m2[ 1 ][ 0 ] + m1[ 3 ][ 2 ] * m2[ 2 ][ 0 ] + m2[ 3 ][ 0 ]; val[ 0 ][ 1 ] = m1[ 0 ][ 0 ] * m2[ 0 ][ 1 ] + m1[ 0 ][ 1 ] * m2[ 1 ][ 1 ] + m1[ 0 ][ 2 ] * m2[ 2 ][ 1 ]; val[ 1 ][ 1 ] = m1[ 1 ][ 0 ] * m2[ 0 ][ 1 ] + m1[ 1 ][ 1 ] * m2[ 1 ][ 1 ] + m1[ 1 ][ 2 ] * m2[ 2 ][ 1 ]; val[ 2 ][ 1 ] = m1[ 2 ][ 0 ] * m2[ 0 ][ 1 ] + m1[ 2 ][ 1 ] * m2[ 1 ][ 1 ] + m1[ 2 ][ 2 ] * m2[ 2 ][ 1 ]; val[ 3 ][ 1 ] = m1[ 3 ][ 0 ] * m2[ 0 ][ 1 ] + m1[ 3 ][ 1 ] * m2[ 1 ][ 1 ] + m1[ 3 ][ 2 ] * m2[ 2 ][ 1 ] + m2[ 3 ][ 1 ]; val[ 0 ][ 2 ] = m1[ 0 ][ 0 ] * m2[ 0 ][ 2 ] + m1[ 0 ][ 1 ] * m2[ 1 ][ 2 ] + m1[ 0 ][ 2 ] * m2[ 2 ][ 2 ]; val[ 1 ][ 2 ] = m1[ 1 ][ 0 ] * m2[ 0 ][ 2 ] + m1[ 1 ][ 1 ] * m2[ 1 ][ 2 ] + m1[ 1 ][ 2 ] * m2[ 2 ][ 2 ]; val[ 2 ][ 2 ] = m1[ 2 ][ 0 ] * m2[ 0 ][ 2 ] + m1[ 2 ][ 1 ] * m2[ 1 ][ 2 ] + m1[ 2 ][ 2 ] * m2[ 2 ][ 2 ]; val[ 3 ][ 2 ] = m1[ 3 ][ 0 ] * m2[ 0 ][ 2 ] + m1[ 3 ][ 1 ] * m2[ 1 ][ 2 ] + m1[ 3 ][ 2 ] * m2[ 2 ][ 2 ] + m2[ 3 ][ 2 ]; } inline void SkelMat4::InvertAxis( int a ) { val[ a ][ 0 ] = -val[ a ][ 0 ]; val[ a ][ 1 ] = -val[ a ][ 1 ]; val[ a ][ 2 ] = -val[ a ][ 2 ]; } inline float SkelMat4::Determinant( void ) { float mat4x4[ 4 ][ 4 ]; mat4x4[ 0 ][ 0 ] = val[ 0 ][ 0 ]; mat4x4[ 0 ][ 1 ] = val[ 0 ][ 1 ]; mat4x4[ 0 ][ 2 ] = val[ 0 ][ 2 ]; mat4x4[ 0 ][ 3 ] = 0; mat4x4[ 1 ][ 0 ] = val[ 1 ][ 0 ]; mat4x4[ 1 ][ 1 ] = val[ 1 ][ 1 ]; mat4x4[ 1 ][ 2 ] = val[ 1 ][ 2 ]; mat4x4[ 1 ][ 3 ] = 0; mat4x4[ 2 ][ 0 ] = val[ 2 ][ 0 ]; mat4x4[ 2 ][ 1 ] = val[ 2 ][ 1 ]; mat4x4[ 2 ][ 2 ] = val[ 2 ][ 2 ]; mat4x4[ 2 ][ 3 ] = 0; mat4x4[ 3 ][ 0 ] = val[ 3 ][ 0 ]; mat4x4[ 3 ][ 1 ] = val[ 3 ][ 1 ]; mat4x4[ 3 ][ 2 ] = val[ 3 ][ 2 ]; mat4x4[ 3 ][ 3 ] = 1; return mat4x4[ 0 ][ 0 ] * ( mat4x4[ 1 ][ 1 ] * ( mat4x4[ 2 ][ 2 ] * mat4x4[ 3 ][ 3 ] - mat4x4[ 2 ][ 3 ] * mat4x4[ 3 ][ 2 ] ) - mat4x4[ 2 ][ 1 ] * ( mat4x4[ 1 ][ 2 ] * mat4x4[ 3 ][ 3 ] - mat4x4[ 1 ][ 3 ] * mat4x4[ 3 ][ 2 ] ) + mat4x4[ 3 ][ 1 ] * ( mat4x4[ 1 ][ 2 ] * mat4x4[ 2 ][ 3 ] - mat4x4[ 1 ][ 3 ] * mat4x4[ 2 ][ 2 ] ) ) - mat4x4[ 1 ][ 0 ] * ( mat4x4[ 0 ][ 1 ] * ( mat4x4[ 2 ][ 2 ] * mat4x4[ 3 ][ 3 ] - mat4x4[ 2 ][ 3 ] * mat4x4[ 3 ][ 2 ] ) - mat4x4[ 2 ][ 1 ] * ( mat4x4[ 0 ][ 2 ] * mat4x4[ 3 ][ 3 ] - mat4x4[ 0 ][ 3 ] * mat4x4[ 3 ][ 2 ] ) + mat4x4[ 3 ][ 1 ] * ( mat4x4[ 0 ][ 2 ] * mat4x4[ 2 ][ 3 ] - mat4x4[ 0 ][ 3 ] * mat4x4[ 2 ][ 2 ] ) ) + mat4x4[ 2 ][ 0 ] * ( mat4x4[ 0 ][ 1 ] * ( mat4x4[ 1 ][ 2 ] * mat4x4[ 3 ][ 3 ] - mat4x4[ 1 ][ 3 ] * mat4x4[ 3 ][ 2 ] ) - mat4x4[ 1 ][ 1 ] * ( mat4x4[ 0 ][ 2 ] * mat4x4[ 3 ][ 3 ] - mat4x4[ 0 ][ 3 ] * mat4x4[ 3 ][ 2 ] ) + mat4x4[ 3 ][ 1 ] * ( mat4x4[ 0 ][ 2 ] * mat4x4[ 1 ][ 3 ] - mat4x4[ 0 ][ 3 ] * mat4x4[ 1 ][ 2 ] ) ) - mat4x4[ 3 ][ 0 ] * ( mat4x4[ 0 ][ 1 ] * ( mat4x4[ 1 ][ 2 ] * mat4x4[ 2 ][ 3 ] - mat4x4[ 1 ][ 3 ] * mat4x4[ 2 ][ 2 ] ) - mat4x4[ 1 ][ 1 ] * ( mat4x4[ 0 ][ 2 ] * mat4x4[ 2 ][ 3 ] - mat4x4[ 0 ][ 3 ] * mat4x4[ 2 ][ 2 ] ) + mat4x4[ 2 ][ 1 ] * ( mat4x4[ 0 ][ 2 ] * mat4x4[ 1 ][ 3 ] - mat4x4[ 0 ][ 3 ] * mat4x4[ 1 ][ 2 ] ) ); } inline void SkelMat4::Inverse( void ) { float mat4x4[ 4 ][ 4 ]; float outmat4x4[ 4 ][ 4 ]; const float Det = Determinant(); mat4x4[ 0 ][ 0 ] = val[ 0 ][ 0 ]; mat4x4[ 0 ][ 1 ] = val[ 0 ][ 1 ]; mat4x4[ 0 ][ 2 ] = val[ 0 ][ 2 ]; mat4x4[ 0 ][ 3 ] = 0; mat4x4[ 1 ][ 0 ] = val[ 1 ][ 0 ]; mat4x4[ 1 ][ 1 ] = val[ 1 ][ 1 ]; mat4x4[ 1 ][ 2 ] = val[ 1 ][ 2 ]; mat4x4[ 1 ][ 3 ] = 0; mat4x4[ 2 ][ 0 ] = val[ 2 ][ 0 ]; mat4x4[ 2 ][ 1 ] = val[ 2 ][ 1 ]; mat4x4[ 2 ][ 2 ] = val[ 2 ][ 2 ]; mat4x4[ 2 ][ 3 ] = 0; mat4x4[ 3 ][ 0 ] = val[ 3 ][ 0 ]; mat4x4[ 3 ][ 1 ] = val[ 3 ][ 1 ]; mat4x4[ 3 ][ 2 ] = val[ 3 ][ 2 ]; mat4x4[ 3 ][ 3 ] = 1; if( Det == 0.0f ) { MakeIdentity(); } else { VectorMatrixInverse( outmat4x4, mat4x4 ); val[ 0 ][ 0 ] = outmat4x4[ 0 ][ 0 ]; val[ 0 ][ 1 ] = outmat4x4[ 0 ][ 1 ]; val[ 0 ][ 2 ] = outmat4x4[ 0 ][ 2 ]; val[ 1 ][ 0 ] = outmat4x4[ 1 ][ 0 ]; val[ 1 ][ 1 ] = outmat4x4[ 1 ][ 1 ]; val[ 1 ][ 2 ] = outmat4x4[ 1 ][ 2 ]; val[ 2 ][ 0 ] = outmat4x4[ 2 ][ 0 ]; val[ 2 ][ 1 ] = outmat4x4[ 2 ][ 1 ]; val[ 2 ][ 2 ] = outmat4x4[ 2 ][ 2 ]; val[ 3 ][ 0 ] = outmat4x4[ 3 ][ 0 ]; val[ 3 ][ 1 ] = outmat4x4[ 3 ][ 1 ]; val[ 3 ][ 2 ] = outmat4x4[ 3 ][ 2 ]; } } inline void SkelMat4::RotateBy( const SkelMat3& m ) { SkelMat4 temp = *this; val[ 0 ][ 0 ] = temp[ 0 ][ 0 ] * m[ 0 ][ 0 ] + temp[ 0 ][ 1 ] * m[ 1 ][ 0 ] + temp[ 0 ][ 2 ] * m[ 2 ][ 0 ]; val[ 0 ][ 1 ] = temp[ 0 ][ 0 ] * m[ 0 ][ 1 ] + temp[ 0 ][ 1 ] * m[ 1 ][ 1 ] + temp[ 0 ][ 2 ] * m[ 2 ][ 1 ]; val[ 0 ][ 2 ] = temp[ 0 ][ 0 ] * m[ 0 ][ 2 ] + temp[ 0 ][ 1 ] * m[ 1 ][ 2 ] + temp[ 0 ][ 2 ] * m[ 2 ][ 2 ]; val[ 1 ][ 0 ] = temp[ 1 ][ 0 ] * m[ 0 ][ 0 ] + temp[ 1 ][ 1 ] * m[ 1 ][ 0 ] + temp[ 1 ][ 2 ] * m[ 2 ][ 0 ]; val[ 1 ][ 1 ] = temp[ 1 ][ 0 ] * m[ 0 ][ 1 ] + temp[ 1 ][ 1 ] * m[ 1 ][ 1 ] + temp[ 1 ][ 2 ] * m[ 2 ][ 1 ]; val[ 1 ][ 2 ] = temp[ 1 ][ 0 ] * m[ 0 ][ 2 ] + temp[ 1 ][ 1 ] * m[ 1 ][ 2 ] + temp[ 1 ][ 2 ] * m[ 2 ][ 2 ]; val[ 2 ][ 0 ] = temp[ 2 ][ 0 ] * m[ 0 ][ 0 ] + temp[ 2 ][ 1 ] * m[ 1 ][ 0 ] + temp[ 2 ][ 2 ] * m[ 2 ][ 0 ]; val[ 2 ][ 1 ] = temp[ 2 ][ 0 ] * m[ 0 ][ 1 ] + temp[ 2 ][ 1 ] * m[ 1 ][ 1 ] + temp[ 2 ][ 2 ] * m[ 2 ][ 1 ]; val[ 2 ][ 2 ] = temp[ 2 ][ 0 ] * m[ 0 ][ 2 ] + temp[ 2 ][ 1 ] * m[ 1 ][ 2 ] + temp[ 2 ][ 2 ] * m[ 2 ][ 2 ]; } inline void SkelMat4::RotateByInverse( const SkelMat3& m ) { // FIXME: stub } inline void SkelMat4::TransposeRotOf( const SkelMat4& m ) { val[ 0 ][ 0 ] = m.val[ 0 ][ 0 ]; val[ 0 ][ 1 ] = m.val[ 1 ][ 0 ]; val[ 0 ][ 2 ] = m.val[ 2 ][ 0 ]; val[ 1 ][ 0 ] = m.val[ 0 ][ 1 ]; val[ 1 ][ 1 ] = m.val[ 1 ][ 1 ]; val[ 1 ][ 2 ] = m.val[ 2 ][ 1 ]; val[ 2 ][ 0 ] = m.val[ 0 ][ 2 ]; val[ 2 ][ 1 ] = m.val[ 1 ][ 2 ]; val[ 2 ][ 2 ] = m.val[ 2 ][ 2 ]; } inline void SkelMat4::GetQuat( SkelQuat& quat ) { MatToQuat( val, ( float * )&quat ); } #else typedef struct { float val[ 4 ][ 3 ]; } SkelMat4; #endif #endif // __SKELMAT4_H__