openmohaa/code/skeletor/SkelMat4.h

393 lines
11 KiB
C
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
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:
2017-07-21 04:21:00 +02:00
void copy( const SkelMat4& );
2016-03-27 11:49:47 +02:00
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 ] )
{
2023-02-01 00:28:40 +01:00
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;
2016-03-27 11:49:47 +02:00
}
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__