openmohaa/code/skeletor/SkelMat4.h

360 lines
10 KiB
C
Raw Permalink Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
2023-11-06 17:58:58 +01:00
Copyright (C) 2023 the OpenMoHAA team
2016-03-27 11:49:47 +02:00
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
2023-11-06 17:58:58 +01:00
#pragma once
2016-03-27 11:49:47 +02:00
#ifdef __cplusplus
class SkelQuat;
2023-11-06 17:58:58 +01:00
class SkelMat4
{
2016-03-27 11:49:47 +02:00
public:
2023-11-06 17:58:58 +01:00
float val[4][3];
2016-03-27 11:49:47 +02:00
protected:
2023-11-06 17:58:58 +01:00
void copy(const SkelMat4&);
2016-03-27 11:49:47 +02:00
public:
2023-11-06 17:58:58 +01:00
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);
2016-03-27 11:49:47 +02:00
};
2023-11-06 17:58:58 +01:00
inline SkelMat4::SkelMat4(const float mat[3][3])
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +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
}
2023-11-06 17:58:58 +01:00
inline SkelMat4::SkelMat4()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
MakeIdentity();
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::copy(const SkelMat4& m)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
MatrixCopy(*m.val, *val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::MakeIdentity()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
memset(val, 0, sizeof(val));
val[0][0] = 1.0f;
val[1][1] = 1.0f;
val[2][2] = 1.0f;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelVec3 *SkelMat4::XAxis()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (SkelVec3 *)&val[0];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelVec3 *SkelMat4::YAxis()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (SkelVec3 *)&val[1];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelVec3 *SkelMat4::ZAxis()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (SkelVec3 *)&val[2];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelVec3 *SkelMat4::XAxis() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (SkelVec3 *)&val[0];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelVec3 *SkelMat4::YAxis() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (SkelVec3 *)&val[1];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelVec3 *SkelMat4::ZAxis() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (SkelVec3 *)&val[2];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelMat4::operator float *()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return &val[0][0];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelMat4::operator float *() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (float *)&val[0][0];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline float *SkelMat4::operator[](int index)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return val[index];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline float *SkelMat4::operator[](int index) const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (float *)val[index];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline bool SkelMat4::IsOrthonormal() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
// FIXME: stub
return false;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline bool SkelMat4::IsValid() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
// FIXME: stub
return false;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::Sum(const SkelMat4& m1, const SkelMat4& m2)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
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]);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::Difference(const SkelMat4& m1, const SkelMat4& m2)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
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]);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::Multiply(const SkelMat4& m1, const SkelMat4& m2)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
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];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::InvertAxis(int a)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
val[a][0] = -val[a][0];
val[a][1] = -val[a][1];
val[a][2] = -val[a][2];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline float SkelMat4::Determinant(void)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
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]));
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::Inverse(void)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
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];
}
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::RotateBy(const SkelMat3& m)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
SkelMat4 temp = *this;
2016-03-27 11:49:47 +02:00
2023-11-06 17:58:58 +01:00
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];
2016-03-27 11:49:47 +02:00
2023-11-06 17:58:58 +01:00
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];
2016-03-27 11:49:47 +02:00
2023-11-06 17:58:58 +01:00
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];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::RotateByInverse(const SkelMat3& m)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
// FIXME: stub
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::TransposeRotOf(const SkelMat4& m)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
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];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelMat4::GetQuat(SkelQuat& quat)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
MatToQuat(val, (float *)&quat);
2016-03-27 11:49:47 +02:00
}
#else
typedef struct {
2023-11-06 17:58:58 +01:00
float val[4][3];
2016-03-27 11:49:47 +02:00
} SkelMat4;
#endif