Skip to content

Commit

Permalink
Created RotationOrder
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardodoria committed Dec 6, 2024
1 parent 081851c commit 1d0acef
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 16 deletions.
153 changes: 146 additions & 7 deletions engine/core/math/Quaternion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ Quaternion::Quaternion( float* const r )
}

Quaternion::Quaternion(const float xAngle, const float yAngle, const float zAngle){
this->fromEulerAngles(xAngle, yAngle, zAngle);
this->fromEulerAngles(xAngle, yAngle, zAngle, RotationOrder::ZYX);
}

Quaternion::Quaternion(const float xAngle, const float yAngle, const float zAngle, RotationOrder order){
this->fromEulerAngles(xAngle, yAngle, zAngle, order);
}

Quaternion::Quaternion(const Vector3* akAxis){
Expand Down Expand Up @@ -163,14 +167,33 @@ void Quaternion::swap(Quaternion& other){
std::swap(z, other.z);
}

void Quaternion::fromEulerAngles(const float xAngle, const float yAngle, const float zAngle){
void Quaternion::fromEulerAngles(const float xAngle, const float yAngle, const float zAngle, RotationOrder order){
Quaternion qx, qy, qz;

qx.fromAngleAxis(xAngle, Vector3(1,0,0));
qy.fromAngleAxis(yAngle, Vector3(0,1,0));
qz.fromAngleAxis(zAngle, Vector3(0,0,1));

*this = (qz * (qy * qx)); //order ZYX
switch (order) {
case RotationOrder::XYZ:
*this = qx * (qy * qz);
break;
case RotationOrder::XZY:
*this = qx * (qz * qy);
break;
case RotationOrder::YXZ:
*this = qy * (qx * qz);
break;
case RotationOrder::YZX:
*this = qy * (qz * qx);
break;
case RotationOrder::ZXY:
*this = qz * (qx * qy);
break;
case RotationOrder::ZYX:
*this = qz * (qy * qx);
break;
}
}

void Quaternion::fromAxes (const Vector3* akAxis){
Expand Down Expand Up @@ -312,11 +335,127 @@ void Quaternion::fromAngleAxis (const float angle, const Vector3& rkAxis){
z = fSin*rkAxis.z;
}

Vector3 Quaternion::getEulerAngles() const{
Quaternion q = *this;
q.normalize();
Vector3 Quaternion::getEulerAngles(RotationOrder order) const{
Vector3 eulerAngles;

switch (order) {
case RotationOrder::XYZ: {
// Roll (X-axis rotation)
float sinr_cosp = 2 * (w * x + y * z);
float cosr_cosp = 1 - 2 * (x * x + y * y);
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);

// Pitch (Y-axis rotation)
float sinp = 2 * (w * y - z * x);
if (fabs(sinp) >= 1) // Handle gimbal lock
eulerAngles.y = copysign(M_PI / 2, sinp);
else
eulerAngles.y = asin(sinp);

// Yaw (Z-axis rotation)
float siny_cosp = 2 * (w * z + x * y);
float cosy_cosp = 1 - 2 * (y * y + z * z);
eulerAngles.z = atan2(siny_cosp, cosy_cosp);
break;
}
case RotationOrder::XZY: {
// Roll (X-axis rotation)
float sinr_cosp = 2 * (w * x + y * z);
float cosr_cosp = 1 - 2 * (x * x + z * z);
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);

// Yaw (Z-axis rotation)
float siny = 2 * (w * z - x * y);
if (fabs(siny) >= 1) // Handle gimbal lock
eulerAngles.z = copysign(M_PI / 2, siny);
else
eulerAngles.z = asin(siny);

// Pitch (Y-axis rotation)
float sinp_cosp = 2 * (w * y + z * x);
float cosp_cosp = 1 - 2 * (y * y + z * z);
eulerAngles.y = atan2(sinp_cosp, cosp_cosp);
break;
}
case RotationOrder::YXZ: {
// Yaw (Y-axis rotation)
float siny_cosp = 2 * (w * y + x * z);
float cosy_cosp = 1 - 2 * (y * y + z * z);
eulerAngles.y = atan2(siny_cosp, cosy_cosp);

// Roll (X-axis rotation)
float sinr = 2 * (w * x - y * z);
if (fabs(sinr) >= 1) // Handle gimbal lock
eulerAngles.x = copysign(M_PI / 2, sinr);
else
eulerAngles.x = asin(sinr);

// Pitch (Z-axis rotation)
float sinp_cosp = 2 * (w * z + x * y);
float cosp_cosp = 1 - 2 * (z * z + x * x);
eulerAngles.z = atan2(sinp_cosp, cosp_cosp);
break;
}
case RotationOrder::YZX: {
// Pitch (Z-axis rotation)
float sinp = 2 * (w * z - x * y);
if (fabs(sinp) >= 1) // Handle gimbal lock
eulerAngles.z = copysign(M_PI / 2, sinp);
else
eulerAngles.z = asin(sinp);

// Yaw (Y-axis rotation)
float siny_cosp = 2 * (w * y + z * x);
float cosy_cosp = 1 - 2 * (y * y + z * z);
eulerAngles.y = atan2(siny_cosp, cosy_cosp);

// Roll (X-axis rotation)
float sinr_cosp = 2 * (w * x + y * z);
float cosr_cosp = 1 - 2 * (x * x + z * z);
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);
break;
}
case RotationOrder::ZXY: {
// Roll (X-axis rotation)
float sinr = 2 * (w * x - y * z);
if (fabs(sinr) >= 1) // Handle gimbal lock
eulerAngles.x = copysign(M_PI / 2, sinr);
else
eulerAngles.x = asin(sinr);

// Pitch (Y-axis rotation)
float sinp_cosp = 2 * (w * y + z * x);
float cosp_cosp = 1 - 2 * (y * y + x * x);
eulerAngles.y = atan2(sinp_cosp, cosp_cosp);

// Yaw (Z-axis rotation)
float siny_cosp = 2 * (w * z + x * y);
float cosy_cosp = 1 - 2 * (z * z + y * y);
eulerAngles.z = atan2(siny_cosp, cosy_cosp);
break;
}
case RotationOrder::ZYX: {
// Yaw (Z-axis rotation)
float siny_cosp = 2 * (w * z + x * y);
float cosy_cosp = 1 - 2 * (y * y + z * z);
eulerAngles.z = atan2(siny_cosp, cosy_cosp);

// Pitch (Y-axis rotation)
float sinp = 2 * (w * y - z * x);
if (fabs(sinp) >= 1) // Handle gimbal lock
eulerAngles.y = copysign(M_PI / 2, sinp);
else
eulerAngles.y = asin(sinp);

// Roll (X-axis rotation)
float sinr_cosp = 2 * (w * x + y * z);
float cosr_cosp = 1 - 2 * (x * x + y * y);
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);
break;
}
}

return Vector3(q.getPitch(), q.getYaw(), q.getRoll());
return Vector3(Angle::radToDefault(eulerAngles.x), Angle::radToDefault(eulerAngles.y), Angle::radToDefault(eulerAngles.z));
}

Vector3 Quaternion::xAxis(void) const{
Expand Down
15 changes: 12 additions & 3 deletions engine/core/math/Quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ Supernova::Quaternion operator * (float fScalar, const Supernova::Quaternion& rk

namespace Supernova {

enum class RotationOrder{
XYZ,
XZY,
YXZ,
YZX,
ZXY,
ZYX
};

class Quaternion {
public:

Expand All @@ -20,6 +29,7 @@ namespace Supernova {
Quaternion( const float fW, const float fX, const float fY, const float fZ );
explicit Quaternion( float* const r );
Quaternion(const float xAngle, const float yAngle, const float zAngle);
Quaternion(const float xAngle, const float yAngle, const float zAngle, RotationOrder order);
Quaternion(const Vector3* akAxis);
Quaternion(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis);
Quaternion(const float angle, const Vector3& rkAxis);
Expand Down Expand Up @@ -51,7 +61,7 @@ namespace Supernova {

void swap(Quaternion& other);

void fromEulerAngles(const float xAngle, const float yAngle, const float zAngle);
void fromEulerAngles(const float xAngle, const float yAngle, const float zAngle, RotationOrder order);
void fromAxes (const Vector3* akAxis);
void fromAxes (const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis);
Quaternion& fromRotationMatrix (const Matrix3& kRot);
Expand All @@ -60,8 +70,7 @@ namespace Supernova {
void fromAngle (const float angle);
void fromAngleAxis (const float angle, const Vector3& rkAxis);

Vector3 getEulerAngles() const;

Vector3 getEulerAngles(RotationOrder order) const;
Vector3 xAxis(void) const;
Vector3 yAxis(void) const;
Vector3 zAxis(void) const;
Expand Down
2 changes: 2 additions & 0 deletions engine/core/script/LuaBridgeAddon.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ namespace luabridge
template<> struct Stack<AdMobRating> : EnumWrapper<AdMobRating>{};
template<> struct Stack<CursorType> : EnumWrapper<CursorType>{};

template<> struct Stack<RotationOrder> : EnumWrapper<RotationOrder>{};

template<> struct Stack<FogType> : EnumWrapper<FogType>{};
template<> struct Stack<CameraType> : EnumWrapper<CameraType>{};
template<> struct Stack<FrustumPlane> : EnumWrapper<FrustumPlane>{};
Expand Down
16 changes: 10 additions & 6 deletions engine/core/script/binding/MathClassesLua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@ namespace luabridge
void LuaBinding::registerMathClasses(lua_State *L){
#ifndef DISABLE_LUA_BINDINGS

static const Vector2 ZERO;
static const Vector2 UNIT_X;
static const Vector2 UNIT_Y;
static const Vector2 NEGATIVE_UNIT_X;
static const Vector2 NEGATIVE_UNIT_Y;
static const Vector2 UNIT_SCALE;
luabridge::getGlobalNamespace(L)
.beginNamespace("RotationOrder")
.addVariable("XYZ", RotationOrder::XYZ)
.addVariable("XZY", RotationOrder::XZY)
.addVariable("YXZ", RotationOrder::YXZ)
.addVariable("YZX", RotationOrder::YZX)
.addVariable("ZXY", RotationOrder::ZXY)
.addVariable("ZYX", RotationOrder::ZYX)
.endNamespace();

luabridge::getGlobalNamespace(L)
.beginClass<Vector2>("Vector2")
Expand Down Expand Up @@ -289,6 +292,7 @@ void LuaBinding::registerMathClasses(lua_State *L){
void(),
void(const float, const float, const float, const float),
void(const float, const float, const float),
void(const float, const float, const float, RotationOrder),
void(const Vector3*),
void(const Vector3&, const Vector3&, const Vector3&),
void(const float, const Vector3&),
Expand Down

0 comments on commit 1d0acef

Please sign in to comment.