Skip to content

Commit

Permalink
more test for the Quaternion class
Browse files Browse the repository at this point in the history
  • Loading branch information
jmacey committed Sep 29, 2023
1 parent 327f2e7 commit 07ef21f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 69 deletions.
10 changes: 3 additions & 7 deletions include/ngl/Quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,17 @@ class NGL_DLLEXPORT Quaternion
/// @brief set the current quaternion as a rotation around the X cartesian axis [1,0,0]
/// @param[in] _angle the angle of rotation around the x axis in degrees

void rotateX(Real _angle) noexcept;
static Quaternion rotateX(Real _angle) noexcept;

/// @brief set the current quaternion as a rotation around the Y cartesian axis [0,1,0]
/// @param[in] _angle the angle of rotation around the y axis in degrees

void rotateY(Real _angle) noexcept;
static Quaternion rotateY(Real _angle) noexcept;

/// @brief set the current quaternion as a rotation around the Z cartesian axis [0,0,1]
/// @param[in] _angle the angle of rotation around the Z axis in degrees

void rotateZ(Real _angle) noexcept;
static Quaternion rotateZ(Real _angle) noexcept;

/// @brief set the current quaternion as a rotation around the vector _axis
/// @brief[in] _axis the axis to rotate around (will be normalized)
Expand Down Expand Up @@ -301,10 +301,6 @@ class NGL_DLLEXPORT Quaternion

Mat4 toMat4() const noexcept;

/// @brief return the current quat as a 4x4 transform matrix transposed
/// @returns the quat as a matrix

Mat4 toMat4Transpose() const noexcept;

/// @brief the quaternion data for the scalar real part
Real m_s=1.0f;
Expand Down
89 changes: 28 additions & 61 deletions src/Quaternion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ Quaternion Quaternion::inverse() const noexcept

Real Quaternion::magnitude()const noexcept
{
return static_cast<Real>( sqrtf(m_s*m_s + m_x*m_x + m_y*m_y + m_z*m_z) );
return sqrtf(m_s*m_s + m_x*m_x + m_y*m_y + m_z*m_z);
}

bool Quaternion::operator == (const Quaternion& _q)const noexcept
Expand All @@ -202,12 +202,13 @@ bool Quaternion::operator == (const Quaternion& _q)const noexcept



Vec4 Quaternion::operator* (const Vec4 &_vec) const noexcept
Vec4 Quaternion::operator *(const Vec4 &_vec) const noexcept
{
Quaternion temp=-*this;
Quaternion point(0.0,_vec.m_x,_vec.m_y,_vec.m_z);
point = temp*point* *this;
return Vec4(point.m_x,point.m_y,point.m_z,1.0);

Vec4 qv(m_x,m_y,m_z);
Vec4 uv(qv.cross(_vec));
Vec4 uuv(qv.cross(uv));
return _vec + ((uv * m_s) + uuv) * 2.0f;
}

float Quaternion::dot(const Quaternion &_lhs)const noexcept
Expand All @@ -221,36 +222,40 @@ float Quaternion::dot(const Quaternion &_lhs, const Quaternion &_rhs) noexcept
}


void Quaternion::rotateX(Real _angle) noexcept
Quaternion Quaternion::rotateX(Real _angle) noexcept
{
Quaternion q;
_angle/=2.0f;
// q=[cos 1/2 theta, sin 1/2 theta V]
m_s=cosf(radians(_angle));
m_x=sinf(radians(_angle));
m_y=0.0f;
m_z=0.0f;
q.m_s=cosf(radians(_angle));
q.m_x=sinf(radians(_angle));
q.m_y=0.0f;
q.m_z=0.0f;
return q;
}

void Quaternion::rotateY(Real _angle) noexcept
Quaternion Quaternion::rotateY(Real _angle) noexcept
{
Quaternion q;
_angle/=2.0f;
// q=[cos 1/2 theta, sin 1/2 theta V]
m_s=cosf(radians(_angle));
m_x=0.0f;
m_y=sinf(radians(_angle));
m_z=0.0f;
q.m_s=cosf(radians(_angle));
q.m_x=0.0f;
q.m_y=sinf(radians(_angle));
q.m_z=0.0f;
return q;
}

void Quaternion::rotateZ(Real _angle) noexcept
Quaternion Quaternion::rotateZ(Real _angle) noexcept
{

Quaternion q;
_angle/=2.0f;
// q=[cos 1/2 theta, sin 1/2 theta V]
m_s=cosf(radians(_angle));
m_x=0.0f;
m_y=0.0f;
m_z=sinf(radians(_angle));

q.m_s=cosf(radians(_angle));
q.m_x=0.0f;
q.m_y=0.0f;
q.m_z=sinf(radians(_angle));
return q;
}

void Quaternion::fromAxisAngle(const Vec3& _axis, Real _angle) noexcept
Expand Down Expand Up @@ -389,44 +394,6 @@ Mat4 Quaternion::toMat4() const noexcept
return o;
}

Mat4 Quaternion::toMat4Transpose() const noexcept
{
// written by Rob Bateman
// sacrafice a few bytes to pre-calculate some values
Real xx = m_x * m_x;
Real xy = m_x * m_y;
Real xz = m_x * m_z;
Real xs = m_x * m_s;
Real yy = m_y * m_y;
Real yz = m_y * m_z;
Real ys = m_y * m_s;
Real zz = m_z * m_z;
Real zs = m_z * m_s;
Mat4 o;
o.m_openGL[0] = 1.0f - 2.0f * (yy+zz);
o.m_openGL[4] = 2.0f * (xy+zs);
o.m_openGL[8] = 2.0f * (xz-ys);
o.m_openGL[12] = 0.0f;

// [4] -> [7]
o.m_openGL[1] = 2.0f * (xy-zs);
o.m_openGL[5] = 1.0f - 2.0f * (xx+zz);
o.m_openGL[9] = 2.0f * (yz+xs);
o.m_openGL[13] = 0.0f;

// [8] -> [11]
o.m_openGL[2] = 2.0f * (xz+ys);
o.m_openGL[6] = 2.0f * (yz-xs);
o.m_openGL[10]= 1.0f - 2.0f * (xx+yy);
o.m_openGL[14] = 0.0f;

// [12] -> [15]
o.m_openGL[3] = 0.0f;
o.m_openGL[7] = 0.0f;
o.m_openGL[11] = 0.0f;
o.m_openGL[15] = 1.0f;
return o;
}



Expand Down
67 changes: 66 additions & 1 deletion tests/QuaternionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <glm/gtx/string_cast.hpp>
#include <gtest/gtest.h>
#include <ngl/Mat4.h>
#include <ngl/Vec4.h>
#include <ngl/NGLStream.h>
#include <ngl/Quaternion.h>
#include <ngl/Types.h>
Expand Down Expand Up @@ -43,14 +44,29 @@ TEST(Quaternion, UserCtor)

TEST(Quaternion, fromMat4)
{
ngl::Mat4 tx = ngl::Mat4::rotateX(45.0f);
auto tx = ngl::Mat4::rotateX(45.0f);

ngl::Quaternion test(tx);
ASSERT_NEAR(test.m_s, 0.92388f, 0.001f);
ASSERT_NEAR(test.m_x, 0.382683f, 0.001f);
ASSERT_NEAR(test.m_y, 0.0f, 0.001f);
ASSERT_NEAR(test.m_z, 0.0f, 0.001f);

auto ty=ngl::Mat4::rotateY(45.0f);
ngl::Quaternion testy(ty);
ASSERT_NEAR(testy.m_s, 0.92388f, 0.001f);
ASSERT_NEAR(testy.m_x, 0.0f, 0.001f);
ASSERT_NEAR(testy.m_y, 0.382683f, 0.001f);
ASSERT_NEAR(testy.m_z, 0.0f, 0.001f);

auto tz=ngl::Mat4::rotateZ(45.0f);
ngl::Quaternion testz(tz);
ASSERT_NEAR(testz.m_s, 0.92388f, 0.001f);
ASSERT_NEAR(testz.m_x, 0.0f, 0.001f);
ASSERT_NEAR(testz.m_y, 0.0f, 0.001f);
ASSERT_NEAR(testz.m_z, 0.382683f, 0.001f);


glm::mat4 gtx = glm::rotate(glm::mat4(1.0f), glm::radians(45.0f), glm::vec3(1, 0, 0));

glm::quat gtest = glm::quat_cast(gtx);
Expand Down Expand Up @@ -316,6 +332,7 @@ TEST(Quaternion, toMat4)
}
}


TEST(Quaternion, SLERP)
{

Expand Down Expand Up @@ -345,3 +362,51 @@ TEST(Quaternion, SLERP)
}
}


TEST(Quaternion,timesEqualFloat)
{
auto a=ngl::Quaternion(0.2f,0.1f,0.3f,0.5f);
a*=2.0f;
EXPECT_FLOAT_EQ(a.m_s,0.4f);
EXPECT_FLOAT_EQ(a.m_x,0.2f);
EXPECT_FLOAT_EQ(a.m_y,0.6f);
EXPECT_FLOAT_EQ(a.m_z,1.0f);
}

TEST(Quaternion,magantude)
{
auto a=ngl::Quaternion(0.2f,0.1f,0.3f,0.5f);
EXPECT_FLOAT_EQ(a.magnitude(),0.6244998f);
}

TEST(Quaternion,multVec4)
{
auto a=ngl::Quaternion(0.2f,0.1f,0.3f,0.5f);
auto b=ngl::Vec4(1.0f,2.0f,3.0f,1.0f);
auto c=a*b;

glm::quat ga(0.2f,0.1f,0.3f,0.5f);
glm::vec4 gb(1.0f,2.0f,3.0f,1.0f);
auto gc=ga*gb;

EXPECT_FLOAT_EQ(c.m_x,gc.x);
EXPECT_FLOAT_EQ(c.m_y,gc.y);
EXPECT_FLOAT_EQ(c.m_z,gc.z);
EXPECT_FLOAT_EQ(c.m_w,gc.w);
}

TEST(Quaternion,rotations)
{
auto tx=ngl::Quaternion::rotateX(45.0f);
auto mx=ngl::Mat4::rotateX(45.0f);
EXPECT_TRUE(tx.toMat4()==mx);

auto ty=ngl::Quaternion::rotateY(25.0f);
auto my=ngl::Mat4::rotateY(25.0f);
EXPECT_TRUE(ty.toMat4()==my);

auto tz=ngl::Quaternion::rotateZ(77.0f);
auto mz=ngl::Mat4::rotateZ(77.0f);
EXPECT_TRUE(tz.toMat4()==mz);

}

0 comments on commit 07ef21f

Please sign in to comment.