mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 13:47:58 +03:00
359 lines
10 KiB
C++
359 lines
10 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2023 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
|
|
|
|
#pragma once
|
|
|
|
#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
|