/* =========================================================================== 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