Switched CQuaternion from XYZW to WXYZ, added new conversion functions (Quats->Eulers, Degs<->Rads)

This commit is contained in:
parax0 2015-08-20 22:18:13 -04:00
parent 3542759c74
commit f0cb6169ae
4 changed files with 48 additions and 15 deletions

View File

@ -1,21 +1,22 @@
#include "CQuaternion.h" #include "CQuaternion.h"
#include <cmath> #include <cmath>
#include <math.h> #include <math.h>
#include <Common/Math.h>
CQuaternion::CQuaternion() CQuaternion::CQuaternion()
{ {
x = 0; w = 0.f;
y = 0; x = 0.f;
z = 0; y = 0.f;
w = 0; z = 0.f;
} }
CQuaternion::CQuaternion(float _x, float _y, float _z, float _w) CQuaternion::CQuaternion(float _w, float _x, float _y, float _z)
{ {
w = _w;
x = _x; x = _x;
y = _y; y = _y;
z = _z; z = _z;
w = _w;
} }
CVector3f CQuaternion::XAxis() CVector3f CQuaternion::XAxis()
@ -40,12 +41,25 @@ CQuaternion CQuaternion::Inverse()
if (fNorm > 0.f) if (fNorm > 0.f)
{ {
float fInvNorm = 1.f / fNorm; float fInvNorm = 1.f / fNorm;
return CQuaternion(-x * fInvNorm, -y * fInvNorm, -z * fInvNorm, w * fInvNorm); return CQuaternion( w * fInvNorm, -x * fInvNorm, -y * fInvNorm, -z * fInvNorm);
} }
else else
return CQuaternion::skZero; return CQuaternion::skZero;
} }
CVector3f CQuaternion::ToEuler()
{
// There is more than one way to do this conversion, based on rotation order.
// But since we only care about the rotation order used in Retro games, which is consistent,
// we can just have a single conversion function. Handy!
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
float ex = atan2f(2 * (w*x + y*z), 1 - (2 * (Math::Pow(x,2) + Math::Pow(y,2))));
float ey = asinf(2 * (w*y - z*x));
float ez = atan2f(2 * (w*z + x*y), 1 - (2 * (Math::Pow(y,2) + Math::Pow(z,2))));
return CVector3f(Math::RadiansToDegrees(ex), Math::RadiansToDegrees(ey), Math::RadiansToDegrees(ez));
}
// ************ OPERATORS ************ // ************ OPERATORS ************
CVector3f CQuaternion::operator*(const CVector3f& vec) const CVector3f CQuaternion::operator*(const CVector3f& vec) const
{ {
@ -62,10 +76,10 @@ CVector3f CQuaternion::operator*(const CVector3f& vec) const
CQuaternion CQuaternion::operator*(const CQuaternion& other) const CQuaternion CQuaternion::operator*(const CQuaternion& other) const
{ {
CQuaternion out; CQuaternion out;
out.w = (-x * other.x) - (y * other.y) - (z * other.z) + (w * other.w);
out.x = ( x * other.w) + (y * other.z) - (z * other.y) + (w * other.x); out.x = ( x * other.w) + (y * other.z) - (z * other.y) + (w * other.x);
out.y = (-x * other.z) + (y * other.w) + (z * other.x) + (w * other.y); out.y = (-x * other.z) + (y * other.w) + (z * other.x) + (w * other.y);
out.z = ( x * other.y) - (y * other.x) + (z * other.w) + (w * other.z); out.z = ( x * other.y) - (y * other.x) + (z * other.w) + (w * other.z);
out.w = (-x * other.x) - (y * other.y) - (z * other.z) + (w * other.w);
return out; return out;
} }
@ -113,16 +127,16 @@ CQuaternion CQuaternion::FromAxisAngle(float angle, CVector3f axis)
{ {
CQuaternion quat; CQuaternion quat;
axis = axis.Normalized(); axis = axis.Normalized();
angle = angle * 3.14159265358979323846f / 180; angle = Math::DegreesToRadians(angle);
float sa = sin(angle / 2); float sa = sinf(angle / 2);
quat.w = cosf(angle / 2);
quat.x = axis.x * sa; quat.x = axis.x * sa;
quat.y = axis.y * sa; quat.y = axis.y * sa;
quat.z = axis.z * sa; quat.z = axis.z * sa;
quat.w = cos(angle / 2);
return quat; return quat;
} }
CQuaternion CQuaternion::skIdentity = CQuaternion(0.f, 0.f, 0.f, 1.f); CQuaternion CQuaternion::skIdentity = CQuaternion(1.f, 0.f, 0.f, 0.f);
CQuaternion CQuaternion::skZero = CQuaternion(0.f, 0.f, 0.f, 0.f); CQuaternion CQuaternion::skZero = CQuaternion(0.f, 0.f, 0.f, 0.f);

View File

@ -6,15 +6,16 @@
class CQuaternion class CQuaternion
{ {
public: public:
float x, y, z, w; float w, x, y, z;
CQuaternion(); CQuaternion();
CQuaternion(float _x, float _y, float _z, float _w); CQuaternion(float _w, float _x, float _y, float _z);
CVector3f XAxis(); CVector3f XAxis();
CVector3f YAxis(); CVector3f YAxis();
CVector3f ZAxis(); CVector3f ZAxis();
CQuaternion Inverse(); CQuaternion Inverse();
CVector3f ToEuler();
// Operators // Operators
CVector3f operator*(const CVector3f& vec) const; CVector3f operator*(const CVector3f& vec) const;

View File

@ -20,6 +20,16 @@ float Distance(const CVector3f& A, const CVector3f& B)
Pow(B.z - A.z, 2.f) ); Pow(B.z - A.z, 2.f) );
} }
float DegreesToRadians(float deg)
{
return deg * skPi / 180.f;
}
float RadiansToDegrees(float rad)
{
return rad * 180.f / skPi;
}
std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane) std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane)
{ {
// Code based on ray/plane intersect code from Ogre // Code based on ray/plane intersect code from Ogre

View File

@ -17,6 +17,10 @@ float Pow(float Base, float Exponent);
float Distance(const CVector3f& A, const CVector3f& B); float Distance(const CVector3f& A, const CVector3f& B);
float DegreesToRadians(float deg);
float RadiansToDegrees(float rad);
std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane); std::pair<bool,float> RayPlaneIntersecton(const CRay& ray, const CPlane& plane);
std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box); std::pair<bool,float> RayBoxIntersection(const CRay& Ray, const CAABox& Box);
@ -27,6 +31,10 @@ std::pair<bool,float> RayLineIntersection(const CRay& ray, const CVector3f& poin
std::pair<bool,float> RayTriangleIntersection(const CRay& Ray, const CVector3f& PointA, std::pair<bool,float> RayTriangleIntersection(const CRay& Ray, const CVector3f& PointA,
const CVector3f& PointB, const CVector3f& PointC, const CVector3f& PointB, const CVector3f& PointC,
bool AllowBackfaces = false); bool AllowBackfaces = false);
// Constants
static const float skPi = 3.14159265358979323846f;
static const float skHalfPi = skPi / 2.f;
} }
#endif // MATH #endif // MATH