Skip to content

Commit 1d0acef

Browse files
committed
Created RotationOrder
1 parent 081851c commit 1d0acef

File tree

4 files changed

+170
-16
lines changed

4 files changed

+170
-16
lines changed

engine/core/math/Quaternion.cpp

Lines changed: 146 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ Quaternion::Quaternion( float* const r )
2727
}
2828

2929
Quaternion::Quaternion(const float xAngle, const float yAngle, const float zAngle){
30-
this->fromEulerAngles(xAngle, yAngle, zAngle);
30+
this->fromEulerAngles(xAngle, yAngle, zAngle, RotationOrder::ZYX);
31+
}
32+
33+
Quaternion::Quaternion(const float xAngle, const float yAngle, const float zAngle, RotationOrder order){
34+
this->fromEulerAngles(xAngle, yAngle, zAngle, order);
3135
}
3236

3337
Quaternion::Quaternion(const Vector3* akAxis){
@@ -163,14 +167,33 @@ void Quaternion::swap(Quaternion& other){
163167
std::swap(z, other.z);
164168
}
165169

166-
void Quaternion::fromEulerAngles(const float xAngle, const float yAngle, const float zAngle){
170+
void Quaternion::fromEulerAngles(const float xAngle, const float yAngle, const float zAngle, RotationOrder order){
167171
Quaternion qx, qy, qz;
168172

169173
qx.fromAngleAxis(xAngle, Vector3(1,0,0));
170174
qy.fromAngleAxis(yAngle, Vector3(0,1,0));
171175
qz.fromAngleAxis(zAngle, Vector3(0,0,1));
172176

173-
*this = (qz * (qy * qx)); //order ZYX
177+
switch (order) {
178+
case RotationOrder::XYZ:
179+
*this = qx * (qy * qz);
180+
break;
181+
case RotationOrder::XZY:
182+
*this = qx * (qz * qy);
183+
break;
184+
case RotationOrder::YXZ:
185+
*this = qy * (qx * qz);
186+
break;
187+
case RotationOrder::YZX:
188+
*this = qy * (qz * qx);
189+
break;
190+
case RotationOrder::ZXY:
191+
*this = qz * (qx * qy);
192+
break;
193+
case RotationOrder::ZYX:
194+
*this = qz * (qy * qx);
195+
break;
196+
}
174197
}
175198

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

315-
Vector3 Quaternion::getEulerAngles() const{
316-
Quaternion q = *this;
317-
q.normalize();
338+
Vector3 Quaternion::getEulerAngles(RotationOrder order) const{
339+
Vector3 eulerAngles;
340+
341+
switch (order) {
342+
case RotationOrder::XYZ: {
343+
// Roll (X-axis rotation)
344+
float sinr_cosp = 2 * (w * x + y * z);
345+
float cosr_cosp = 1 - 2 * (x * x + y * y);
346+
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);
347+
348+
// Pitch (Y-axis rotation)
349+
float sinp = 2 * (w * y - z * x);
350+
if (fabs(sinp) >= 1) // Handle gimbal lock
351+
eulerAngles.y = copysign(M_PI / 2, sinp);
352+
else
353+
eulerAngles.y = asin(sinp);
354+
355+
// Yaw (Z-axis rotation)
356+
float siny_cosp = 2 * (w * z + x * y);
357+
float cosy_cosp = 1 - 2 * (y * y + z * z);
358+
eulerAngles.z = atan2(siny_cosp, cosy_cosp);
359+
break;
360+
}
361+
case RotationOrder::XZY: {
362+
// Roll (X-axis rotation)
363+
float sinr_cosp = 2 * (w * x + y * z);
364+
float cosr_cosp = 1 - 2 * (x * x + z * z);
365+
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);
366+
367+
// Yaw (Z-axis rotation)
368+
float siny = 2 * (w * z - x * y);
369+
if (fabs(siny) >= 1) // Handle gimbal lock
370+
eulerAngles.z = copysign(M_PI / 2, siny);
371+
else
372+
eulerAngles.z = asin(siny);
373+
374+
// Pitch (Y-axis rotation)
375+
float sinp_cosp = 2 * (w * y + z * x);
376+
float cosp_cosp = 1 - 2 * (y * y + z * z);
377+
eulerAngles.y = atan2(sinp_cosp, cosp_cosp);
378+
break;
379+
}
380+
case RotationOrder::YXZ: {
381+
// Yaw (Y-axis rotation)
382+
float siny_cosp = 2 * (w * y + x * z);
383+
float cosy_cosp = 1 - 2 * (y * y + z * z);
384+
eulerAngles.y = atan2(siny_cosp, cosy_cosp);
385+
386+
// Roll (X-axis rotation)
387+
float sinr = 2 * (w * x - y * z);
388+
if (fabs(sinr) >= 1) // Handle gimbal lock
389+
eulerAngles.x = copysign(M_PI / 2, sinr);
390+
else
391+
eulerAngles.x = asin(sinr);
392+
393+
// Pitch (Z-axis rotation)
394+
float sinp_cosp = 2 * (w * z + x * y);
395+
float cosp_cosp = 1 - 2 * (z * z + x * x);
396+
eulerAngles.z = atan2(sinp_cosp, cosp_cosp);
397+
break;
398+
}
399+
case RotationOrder::YZX: {
400+
// Pitch (Z-axis rotation)
401+
float sinp = 2 * (w * z - x * y);
402+
if (fabs(sinp) >= 1) // Handle gimbal lock
403+
eulerAngles.z = copysign(M_PI / 2, sinp);
404+
else
405+
eulerAngles.z = asin(sinp);
406+
407+
// Yaw (Y-axis rotation)
408+
float siny_cosp = 2 * (w * y + z * x);
409+
float cosy_cosp = 1 - 2 * (y * y + z * z);
410+
eulerAngles.y = atan2(siny_cosp, cosy_cosp);
411+
412+
// Roll (X-axis rotation)
413+
float sinr_cosp = 2 * (w * x + y * z);
414+
float cosr_cosp = 1 - 2 * (x * x + z * z);
415+
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);
416+
break;
417+
}
418+
case RotationOrder::ZXY: {
419+
// Roll (X-axis rotation)
420+
float sinr = 2 * (w * x - y * z);
421+
if (fabs(sinr) >= 1) // Handle gimbal lock
422+
eulerAngles.x = copysign(M_PI / 2, sinr);
423+
else
424+
eulerAngles.x = asin(sinr);
425+
426+
// Pitch (Y-axis rotation)
427+
float sinp_cosp = 2 * (w * y + z * x);
428+
float cosp_cosp = 1 - 2 * (y * y + x * x);
429+
eulerAngles.y = atan2(sinp_cosp, cosp_cosp);
430+
431+
// Yaw (Z-axis rotation)
432+
float siny_cosp = 2 * (w * z + x * y);
433+
float cosy_cosp = 1 - 2 * (z * z + y * y);
434+
eulerAngles.z = atan2(siny_cosp, cosy_cosp);
435+
break;
436+
}
437+
case RotationOrder::ZYX: {
438+
// Yaw (Z-axis rotation)
439+
float siny_cosp = 2 * (w * z + x * y);
440+
float cosy_cosp = 1 - 2 * (y * y + z * z);
441+
eulerAngles.z = atan2(siny_cosp, cosy_cosp);
442+
443+
// Pitch (Y-axis rotation)
444+
float sinp = 2 * (w * y - z * x);
445+
if (fabs(sinp) >= 1) // Handle gimbal lock
446+
eulerAngles.y = copysign(M_PI / 2, sinp);
447+
else
448+
eulerAngles.y = asin(sinp);
449+
450+
// Roll (X-axis rotation)
451+
float sinr_cosp = 2 * (w * x + y * z);
452+
float cosr_cosp = 1 - 2 * (x * x + y * y);
453+
eulerAngles.x = atan2(sinr_cosp, cosr_cosp);
454+
break;
455+
}
456+
}
318457

319-
return Vector3(q.getPitch(), q.getYaw(), q.getRoll());
458+
return Vector3(Angle::radToDefault(eulerAngles.x), Angle::radToDefault(eulerAngles.y), Angle::radToDefault(eulerAngles.z));
320459
}
321460

322461
Vector3 Quaternion::xAxis(void) const{

engine/core/math/Quaternion.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ Supernova::Quaternion operator * (float fScalar, const Supernova::Quaternion& rk
99

1010
namespace Supernova {
1111

12+
enum class RotationOrder{
13+
XYZ,
14+
XZY,
15+
YXZ,
16+
YZX,
17+
ZXY,
18+
ZYX
19+
};
20+
1221
class Quaternion {
1322
public:
1423

@@ -20,6 +29,7 @@ namespace Supernova {
2029
Quaternion( const float fW, const float fX, const float fY, const float fZ );
2130
explicit Quaternion( float* const r );
2231
Quaternion(const float xAngle, const float yAngle, const float zAngle);
32+
Quaternion(const float xAngle, const float yAngle, const float zAngle, RotationOrder order);
2333
Quaternion(const Vector3* akAxis);
2434
Quaternion(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis);
2535
Quaternion(const float angle, const Vector3& rkAxis);
@@ -51,7 +61,7 @@ namespace Supernova {
5161

5262
void swap(Quaternion& other);
5363

54-
void fromEulerAngles(const float xAngle, const float yAngle, const float zAngle);
64+
void fromEulerAngles(const float xAngle, const float yAngle, const float zAngle, RotationOrder order);
5565
void fromAxes (const Vector3* akAxis);
5666
void fromAxes (const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis);
5767
Quaternion& fromRotationMatrix (const Matrix3& kRot);
@@ -60,8 +70,7 @@ namespace Supernova {
6070
void fromAngle (const float angle);
6171
void fromAngleAxis (const float angle, const Vector3& rkAxis);
6272

63-
Vector3 getEulerAngles() const;
64-
73+
Vector3 getEulerAngles(RotationOrder order) const;
6574
Vector3 xAxis(void) const;
6675
Vector3 yAxis(void) const;
6776
Vector3 zAxis(void) const;

engine/core/script/LuaBridgeAddon.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ namespace luabridge
5252
template<> struct Stack<AdMobRating> : EnumWrapper<AdMobRating>{};
5353
template<> struct Stack<CursorType> : EnumWrapper<CursorType>{};
5454

55+
template<> struct Stack<RotationOrder> : EnumWrapper<RotationOrder>{};
56+
5557
template<> struct Stack<FogType> : EnumWrapper<FogType>{};
5658
template<> struct Stack<CameraType> : EnumWrapper<CameraType>{};
5759
template<> struct Stack<FrustumPlane> : EnumWrapper<FrustumPlane>{};

engine/core/script/binding/MathClassesLua.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@ namespace luabridge
3535
void LuaBinding::registerMathClasses(lua_State *L){
3636
#ifndef DISABLE_LUA_BINDINGS
3737

38-
static const Vector2 ZERO;
39-
static const Vector2 UNIT_X;
40-
static const Vector2 UNIT_Y;
41-
static const Vector2 NEGATIVE_UNIT_X;
42-
static const Vector2 NEGATIVE_UNIT_Y;
43-
static const Vector2 UNIT_SCALE;
38+
luabridge::getGlobalNamespace(L)
39+
.beginNamespace("RotationOrder")
40+
.addVariable("XYZ", RotationOrder::XYZ)
41+
.addVariable("XZY", RotationOrder::XZY)
42+
.addVariable("YXZ", RotationOrder::YXZ)
43+
.addVariable("YZX", RotationOrder::YZX)
44+
.addVariable("ZXY", RotationOrder::ZXY)
45+
.addVariable("ZYX", RotationOrder::ZYX)
46+
.endNamespace();
4447

4548
luabridge::getGlobalNamespace(L)
4649
.beginClass<Vector2>("Vector2")
@@ -289,6 +292,7 @@ void LuaBinding::registerMathClasses(lua_State *L){
289292
void(),
290293
void(const float, const float, const float, const float),
291294
void(const float, const float, const float),
295+
void(const float, const float, const float, RotationOrder),
292296
void(const Vector3*),
293297
void(const Vector3&, const Vector3&, const Vector3&),
294298
void(const float, const Vector3&),

0 commit comments

Comments
 (0)