openmohaa/code/skeletor/SkelQuat.h

288 lines
5.6 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
===========================================================================
*/
// SkelQuat.h : Skeletor Quat
2023-11-06 17:58:58 +01:00
#pragma once
2016-03-27 11:49:47 +02:00
#ifdef __cplusplus
2023-11-06 17:58:58 +01:00
# include "SkelVec3.h"
# include "SkelVec4.h"
# include "SkelMat3.h"
# include "SkelMat4.h"
2023-02-01 00:28:40 +01:00
2023-11-06 17:58:58 +01:00
class SkelQuat
{
2016-03-27 11:49:47 +02:00
public:
2023-11-06 17:58:58 +01:00
union {
float val[4];
struct {
float x;
float y;
float z;
float w;
};
};
SkelQuat();
SkelQuat(SkelVec3 vec);
SkelQuat(SkelMat3 mat3);
SkelQuat(SkelMat4 mat4);
SkelQuat(float x, float y, float z, float w);
SkelQuat(float *quat);
SkelQuat(const float *quat);
SkelQuat(float w, const SkelVec3 *vec);
float& operator[](int index);
float operator[](int index) const;
operator float *();
operator float *() const;
void Set(float x, float y, float z, float w);
void Set(SkelVec4 vec4);
void Set(float *quat);
void SetAngle(float a);
void SetAxis(SkelVec3 vec);
void Invert();
float Length() const;
float LengthSquared() const;
void Normalize();
void GetMat3(SkelMat3& mat3) const;
void GetMat4(SkelMat4& mat4) const;
void GetEulerAngles(float *angles) const;
bool IsUnit() const;
void MakeIdentity();
bool IsIdentity();
bool IsValid() const;
2016-03-27 11:49:47 +02:00
};
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
QuatClear(val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat(SkelVec3 vec)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
EulerToQuat(vec.val, val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat(SkelMat3 mat3)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
MatToQuat(mat3.val, val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat(SkelMat4 mat4)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
MatToQuat(mat4.val, val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat(float x, float y, float z, float w)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
Set(x, y, z, w);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat(float *quat)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
val[0] = quat[0];
val[1] = quat[1];
val[2] = quat[2];
val[3] = quat[3];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat(const float *quat)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
val[0] = quat[0];
val[1] = quat[1];
val[2] = quat[2];
val[3] = quat[3];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::SkelQuat(float w, const SkelVec3 *vec)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
val[0] = vec->x;
val[1] = vec->y;
val[2] = vec->z;
val[3] = w;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::Set(float x, float y, float z, float w)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
this->x = x;
this->y = y;
this->z = z;
this->w = w;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::Set(SkelVec4 vec4)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
val[0] = vec4.val[0];
val[1] = vec4.val[1];
val[2] = vec4.val[2];
val[3] = vec4.val[3];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::Set(float *quat)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
val[0] = quat[0];
val[1] = quat[1];
val[2] = quat[2];
val[3] = quat[3];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::SetAngle(float a)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
SkelVec3 vec;
vec.y = a;
EulerToQuat(vec.val, val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::SetAxis(SkelVec3 vec)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
EulerToQuat(vec.val, val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::Invert()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
QuatInverse(val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline float SkelQuat::Length() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (float)sqrt(val[0] * val[0] + val[1] * val[1] + val[2] * val[2] + val[3] * val[3]);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline float SkelQuat::LengthSquared() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return val[0] * val[0] + val[1] * val[1] + val[2] * val[2] + val[3] * val[3];
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::Normalize()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
VectorNormalize(val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::GetMat3(SkelMat3& mat3) const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
QuatToMat(val, mat3.val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::GetMat4(SkelMat4& mat4) const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
QuatToMat(val, mat4.val);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void SkelQuat::GetEulerAngles(float *angles) const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
QuatToAngles(val, angles);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline bool SkelQuat::IsUnit() 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 SkelQuat::MakeIdentity()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
x = 0.0f;
y = 0.0f;
z = 0.0f;
w = 1.0f;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline bool SkelQuat::IsIdentity()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 1.0f);
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline bool SkelQuat::IsValid() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
// FIXME: stub
return true;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline void Slerp(SkelQuat& from, SkelQuat& to, float t, SkelQuat *out)
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
static_assert(sizeof(float) == sizeof(int), "Float must be the same size as Int");
float f;
float f2;
f = from.x * to.x + from.y * to.y + from.z * to.z + from.w * to.w;
f2 = 1.0 - t;
// little hack because I don't know how can this operation be converted to float...
*(int *)&f = (*(int *)&f & 0x80000000) ^ *(int *)&f2;
out->x = to.x * t + from.x * f;
out->y = to.y * t + from.y * f;
out->z = to.z * t + from.z * f;
out->w = to.w * t + from.w * f;
f = 1.0 / out->Length();
out->x = out->x * f;
out->y = out->y * f;
out->z = out->z * f;
out->w = out->w * f;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::operator float *()
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return val;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline SkelQuat::operator float *() const
2016-03-27 11:49:47 +02:00
{
2023-11-06 17:58:58 +01:00
return (float *)val;
2016-03-27 11:49:47 +02:00
}
2023-11-06 17:58:58 +01:00
inline float& SkelQuat::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 SkelQuat::operator[](int index) const
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
}
#else
typedef struct {
2023-11-06 17:58:58 +01:00
union {
float val[4];
struct {
float x;
float y;
float z;
float w;
};
};
2016-03-27 11:49:47 +02:00
} SkelQuat;
#endif