CUGL 1.3
Cornell University Game Library
CUQuaternion.h
1 //
2 // CUQuaternion.h
3 // Cornell University Game Library (CUGL)
4 //
5 // This module provides support for a quaternion, which is a way of representing
6 // rotations in 3d sapce.. It has support for basic arithmetic, as well as
7 // as the standard quaternion interpolations.
8 //
9 // Because math objects are intended to be on the stack, we do not provide
10 // any shared pointer support in this class.
11 //
12 // This module is based on an original file from GamePlay3D: http://gameplay3d.org.
13 // It has been modified to support the CUGL framework.
14 //
15 // CUGL MIT License:
16 // This software is provided 'as-is', without any express or implied
17 // warranty. In no event will the authors be held liable for any damages
18 // arising from the use of this software.
19 //
20 // Permission is granted to anyone to use this software for any purpose,
21 // including commercial applications, and to alter it and redistribute it
22 // freely, subject to the following restrictions:
23 //
24 // 1. The origin of this software must not be misrepresented; you must not
25 // claim that you wrote the original software. If you use this software
26 // in a product, an acknowledgment in the product documentation would be
27 // appreciated but is not required.
28 //
29 // 2. Altered source versions must be plainly marked as such, and must not
30 // be misrepresented as being the original software.
31 //
32 // 3. This notice may not be removed or altered from any source distribution.
33 //
34 // Author: Walker White
35 // Version: 6/5/16
36 #ifndef __CU_QUATERNION_H__
37 #define __CU_QUATERNION_H__
38 
39 #include <math.h>
40 #include "CUVec3.h"
41 #include "CUMathBase.h"
42 
43 namespace cugl {
44 
45 // Forward declarations
46 class Mat4;
47 
97 class Quaternion {
98 
99 #pragma mark Values
100 public:
101 #if defined CU_MATH_VECTOR_SSE
102  union {
103  struct {
105  float x;
107  float y;
109  float z;
111  float w;
112  };
113  __m128 v;
114  };
115 #elif defined CU_MATH_VECTOR_NEON64
116  union {
117  struct {
119  float x;
121  float y;
123  float z;
125  float w;
126  };
127  float32x4_t v;
128  };
129 #else
130 
131  float x;
133  float y;
135  float z;
137  float w;
138 #endif
139 
141  static const Quaternion ZERO;
143  static const Quaternion IDENTITY;
144 
145 
146 #pragma mark -
147 #pragma mark Constructors
148 public:
152  Quaternion() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
153 
162  Quaternion(float x, float y, float z, float w) {
163  #if defined CU_MATH_VECTOR_SSE
164  v = _mm_set_ps(w, z, y, x);
165  #elif defined CU_MATH_VECTOR_NEON64
166  v = {x, y, z, w};
167  #else
168  this->x = x; this->y = y; this->z = z; this->w = w;
169  #endif
170  }
171 
179  Quaternion(float* array);
180 
187  Quaternion(const Vec3& axis, float angle);
188 
189 
190 #pragma mark -
191 #pragma mark Static Constructors
192 
202  static Quaternion* createFromRotationMatrix(const Mat4& m, Quaternion* dst);
203 
215  static Quaternion* createFromAxisAngle(const Vec3& axis, float angle, Quaternion* dst);
216 
217 
218 #pragma mark -
219 #pragma mark Setters
220 
229  Quaternion& operator=(const float* array) {
230  return set(array);
231  }
232 
243  Quaternion& set(float x, float y, float z, float w) {
244  #if defined CU_MATH_VECTOR_SSE
245  v = _mm_set_ps(w, z, y, x);
246  #elif defined CU_MATH_VECTOR_NEON64
247  v = {x, y, z, w};
248  #else
249  this->x = x; this->y = y; this->z = z; this->w = w;
250  #endif
251  return *this;
252  }
253 
263  Quaternion& set(const float* array);
264 
273  Quaternion& set(const Vec3& axis, float angle);
274 
282  Quaternion& set(const Quaternion& q) {
283  #if defined CU_MATH_VECTOR_SSE || defined CU_MATH_VECTOR_NEON64
284  v = q.v;
285  #else
286  x = q.x; y = q.y; z = q.z; w = q.w;
287  #endif
288  return *this;
289  }
290 
297  #if defined CU_MATH_VECTOR_SSE
298  v = _mm_setzero_ps();
299  v[3] = 1.0f;
300  #elif defined CU_MATH_VECTOR_NEON64
301  v = vmovq_n_f32(0.0f);
302  v[3] = 1.0f;
303  #else
304  x = y = z = 0; w = 1;
305  #endif
306  return *this;
307  }
308 
315  #if defined CU_MATH_VECTOR_SSE
316  v = _mm_setzero_ps();
317  #elif defined CU_MATH_VECTOR_NEON64
318  v = vmovq_n_f32(0.0f);
319  #else
320  x = y = z = w = 0;
321  #endif
322  return *this;
323  }
324 
325 
326 #pragma mark -
327 #pragma mark Static Arithmetic
328 
337  static Quaternion* add(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
338 
348  static Quaternion* subtract(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
349 
361  static Quaternion* multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
362 
375  static Quaternion* divide(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
376 
386  static Quaternion* scale(const Quaternion& q1, float s, Quaternion* dst);
387 
396  static Quaternion* conjugate(const Quaternion& quat, Quaternion* dst);
397 
414  static Quaternion* invert(const Quaternion& quat, Quaternion* dst);
415 
427  static Quaternion* normalize(const Quaternion& quat, Quaternion* dst);
428 
437  static Quaternion* negate(const Quaternion& quat, Quaternion* dst);
438 
447  static float dot(const Quaternion& q1, const Quaternion& q2);
448 
449 
450 #pragma mark -
451 #pragma mark Arithmetic
452 
459  Quaternion& add(const Quaternion& q) {
460  #if defined CU_MATH_VECTOR_SSE
461  v = _mm_add_ps(v,q.v);
462  #elif defined CU_MATH_VECTOR_NEON64
463  v = vaddq_f32(v,q.v);
464  #else
465  x += q.x; y += q.y; z += q.z; w += q.w;
466  #endif
467  return *this;
468  }
469 
478  #if defined CU_MATH_VECTOR_SSE
479  v = _mm_sub_ps(v,q.v);
480  #elif defined CU_MATH_VECTOR_NEON64
481  v = vsubq_f32(v,q.v);
482  #else
483  x -= q.x; y -= q.y; z -= q.z; w -= q.w;
484  #endif
485  return *this;
486  }
487 
496  return *(multiply(*this,q,this));
497  }
498 
499 
510  return *(divide(*this,q,this));
511  }
512 
513 
521  Quaternion& scale(float s) {
522  #if defined CU_MATH_VECTOR_SSE
523  v = _mm_mul_ps(v,_mm_set1_ps(s));
524  #elif defined CU_MATH_VECTOR_NEON64
525  v = vmulq_n_f32(v,(float32_t)s);
526  #else
527  x *= s; y *= s; z *= s; w *= s;
528  #endif
529  return *this;
530  }
531 
538  #if defined CU_MATH_VECTOR_SSE
539  float tmp = w;
540  v = _mm_sub_ps(_mm_setzero_ps(), v);
541  w = tmp;
542  #elif defined CU_MATH_VECTOR_NEON64
543  float tmp = w;
544  v = vnegq_f32(v);
545  w = tmp;
546  #else
547  x = -x; y = -y; z = -z;
548  #endif
549  return *this;
550  }
551 
558  Quaternion result;
559  return *(conjugate(*this,&result));
560  }
561 
576  return *(invert(*this,this));
577  }
578 
593  Quaternion result;
594  return *(invert(*this,&result));
595  }
596 
606  return *(normalize(*this,this));
607  }
608 
620  Quaternion result;
621  return *(normalize(*this,&result));
622  }
623 
630  #if defined CU_MATH_VECTOR_SSE
631  v = _mm_sub_ps(_mm_setzero_ps(), v);
632  #elif defined CU_MATH_VECTOR_NEON64
633  v = vsubq_f32(vmovq_n_f32(0.0f), v);
634  #else
635  x = -x; y = -y; z = -z; w = -w;
636  #endif
637  return *this;
638  }
639 
648  Quaternion result;
649  return *(negate(*this,&result));
650  }
651 
659  float dot(const Quaternion& q) const {
660  return dot(*this,q);
661  }
662 
663 
664 
665 #pragma mark -
666 #pragma mark Operators
667 
675  return add(q);
676  }
677 
686  return subtract(q);
687  }
688 
696  Quaternion& operator*=(float s) {
697  return scale(s);
698  }
699 
710  return *(multiply(*this,q,this));
711  }
712 
720  Quaternion& operator/=(float s) {
721  return *(scale(*this,1.0f/s,this));
722  }
723 
736  return *(divide(*this,q,this));
737  }
738 
748  const Quaternion operator+(const Quaternion& q) const {
749  Quaternion result;
750  return *(add(*this,q,&result));
751  }
752 
762  const Quaternion operator-(const Quaternion& q) const {
763  Quaternion result;
764  return *(subtract(*this,q,&result));
765  }
766 
774  const Quaternion operator-() const {
775  Quaternion result;
776  return *(negate(*this,&result));
777  }
778 
788  const Quaternion operator*(float s) const {
789  Quaternion result;
790  return *(scale(*this,s,&result));
791  }
792 
804  const Quaternion operator*(const Quaternion& q) const {
805  Quaternion result;
806  return *(multiply(*this,q,&result));
807  }
808 
818  const Quaternion operator/(float s) const {
819  Quaternion result;
820  return *(scale(*this,1.0f/s,&result));
821  }
822 
836  const Quaternion operator/(const Quaternion& q) const {
837  Quaternion result;
838  return *(divide(*this,q,&result));
839  }
840 
841 
842 #pragma mark -
843 #pragma mark Comparisons
844 
854  bool operator==(const Quaternion& q) const;
855 
866  bool operator!=(const Quaternion& q) const;
867 
879  bool equals(const Quaternion& q, float variance=CU_MATH_EPSILON) const;
880 
881 #pragma mark -
882 #pragma mark Linear Attributes
883 
890  float norm() const {
891  return sqrt(normSquared());
892  }
893 
906  float normSquared() const {
907  return dot(*this);
908  }
909 
918  bool isZero() const;
919 
929  bool isNearZero(float variance=CU_MATH_EPSILON) const {
930  return equals(ZERO,variance);
931  }
932 
938  bool isIdentity() const;
939 
949  bool isNearIdentity(float variance=CU_MATH_EPSILON) const {
950  return equals(IDENTITY,variance);
951  }
952 
960  bool isUnit(float variance=CU_MATH_EPSILON) const {
961  float dot = norm()-1.0f;
962  return fabsf(dot) <= variance;
963  }
964 
974  float toAxisAngle(Vec3* e) const;
975 
976 
977 #pragma mark -
978 #pragma mark Static Interpolation
979 
995  static Quaternion* lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
996 
1017  static Quaternion* slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
1018 
1039  static Quaternion* nlerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
1040 
1052  static Vec3* rotate(const Vec3& v, const Quaternion& quat, Vec3* dst);
1053 
1054 
1055 #pragma mark -
1056 #pragma mark Interpolation
1057 
1071  Quaternion& lerp(const Quaternion& q, float t) {
1072  return *(lerp(*this,q,t,this));
1073  }
1074 
1093  Quaternion& slerp(const Quaternion& q, float t) {
1094  return *(slerp(*this,q,t,this));
1095  }
1096 
1115  Quaternion& nlerp(const Quaternion& q, float t) {
1116  return *(slerp(*this,q,t,this));
1117  }
1118 
1135  Quaternion getLerp(const Quaternion& q, float t) {
1136  Quaternion result;
1137  return *(lerp(*this,q,t,&result));
1138  }
1139 
1160  Quaternion getSlerp(const Quaternion& q, float t) {
1161  Quaternion result;
1162  return *(slerp(*this,q,t,&result));
1163  }
1164 
1185  Quaternion getNlerp(const Quaternion& q, float t) {
1186  Quaternion result;
1187  return *(nlerp(*this,q,t,&result));
1188  }
1189 
1198  Vec3 getRotation(const Vec3& v) {
1199  Vec3 result;
1200  return *(rotate(v,*this,&result));
1201  }
1202 
1203 #pragma mark -
1204 #pragma mark Conversion Methods
1205 public:
1216  std::string toString(bool verbose = false) const;
1217 
1219  operator std::string() const { return toString(); }
1220 
1222  operator Vec4() const;
1223 
1229  explicit Quaternion(const Vec4& vector);
1230 
1238  Quaternion& operator= (const Vec4& vector) {
1239  return set(vector);
1240  }
1241 
1249  Quaternion& set(const Vec4& vector);
1250 
1257  operator Mat4() const;
1258 
1268  explicit Quaternion(const Mat4& m);
1269 
1282  return set(m);
1283  }
1284 
1296  Quaternion& set(const Mat4& m);
1297 
1298 };
1299 
1312 inline Vec3& operator*=(Vec3& v, const Quaternion& quat) {
1313  return *(Quaternion::rotate(v,quat,&v));
1314 }
1315 
1328 inline const Vec3 operator*(const Vec3& v, const Quaternion& quat) {
1329  Vec3 result;
1330  return *(Quaternion::rotate(v,quat,&result));
1331 }
1332 
1342 inline const Quaternion operator*(float s, const Quaternion& quat) {
1343  Quaternion result;
1344  return *(Quaternion::scale(quat,s,&result));
1345 }
1346 
1347 
1348 }
1349 
1350 #endif /* __CU_QUATERNION_H__ */
cugl::Quaternion::dot
float dot(const Quaternion &q) const
Definition: CUQuaternion.h:659
cugl::Quaternion::operator!=
bool operator!=(const Quaternion &q) const
cugl::Quaternion::negate
Quaternion & negate()
Definition: CUQuaternion.h:629
cugl::Quaternion::add
Quaternion & add(const Quaternion &q)
Definition: CUQuaternion.h:459
cugl::Quaternion::getNormalization
Quaternion getNormalization() const
Definition: CUQuaternion.h:619
cugl::Quaternion::slerp
Quaternion & slerp(const Quaternion &q, float t)
Definition: CUQuaternion.h:1093
cugl::Quaternion::lerp
static Quaternion * lerp(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst)
cugl::Quaternion::nlerp
static Quaternion * nlerp(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst)
cugl::Vec4
Definition: CUVec4.h:64
cugl::Quaternion::equals
bool equals(const Quaternion &q, float variance=CU_MATH_EPSILON) const
cugl::Quaternion::Quaternion
Quaternion()
Definition: CUQuaternion.h:152
cugl::Quaternion::isIdentity
bool isIdentity() const
cugl::Quaternion::subtract
static Quaternion * subtract(const Quaternion &q1, const Quaternion &q2, Quaternion *dst)
cugl::Quaternion::operator/
const Quaternion operator/(const Quaternion &q) const
Definition: CUQuaternion.h:836
cugl::Quaternion::getLerp
Quaternion getLerp(const Quaternion &q, float t)
Definition: CUQuaternion.h:1135
cugl::Quaternion::scale
Quaternion & scale(float s)
Definition: CUQuaternion.h:521
cugl::Quaternion::getNegation
Quaternion getNegation() const
Definition: CUQuaternion.h:647
cugl::Quaternion::operator==
bool operator==(const Quaternion &q) const
cugl::Quaternion::operator/=
Quaternion & operator/=(float s)
Definition: CUQuaternion.h:720
cugl::Quaternion::divide
static Quaternion * divide(const Quaternion &q1, const Quaternion &q2, Quaternion *dst)
cugl::Quaternion::norm
float norm() const
Definition: CUQuaternion.h:890
cugl::Quaternion::operator*=
Quaternion & operator*=(const Quaternion &q)
Definition: CUQuaternion.h:709
cugl::Quaternion::setIdentity
Quaternion & setIdentity()
Definition: CUQuaternion.h:296
cugl::Quaternion::createFromRotationMatrix
static Quaternion * createFromRotationMatrix(const Mat4 &m, Quaternion *dst)
cugl::Quaternion::getSlerp
Quaternion getSlerp(const Quaternion &q, float t)
Definition: CUQuaternion.h:1160
cugl::Quaternion::w
float w
Definition: CUQuaternion.h:137
cugl::Quaternion::set
Quaternion & set(const Quaternion &q)
Definition: CUQuaternion.h:282
cugl::Quaternion::divide
Quaternion & divide(const Quaternion &q)
Definition: CUQuaternion.h:509
cugl::Quaternion::isNearIdentity
bool isNearIdentity(float variance=CU_MATH_EPSILON) const
Definition: CUQuaternion.h:949
cugl::Quaternion::y
float y
Definition: CUQuaternion.h:133
cugl::Mat4
Definition: CUMat4.h:83
cugl::Quaternion::operator/=
Quaternion & operator/=(const Quaternion &q)
Definition: CUQuaternion.h:735
cugl::Quaternion::operator+=
Quaternion & operator+=(const Quaternion &q)
Definition: CUQuaternion.h:674
cugl::Quaternion::operator*
const Quaternion operator*(float s) const
Definition: CUQuaternion.h:788
cugl::Quaternion::isNearZero
bool isNearZero(float variance=CU_MATH_EPSILON) const
Definition: CUQuaternion.h:929
cugl::Quaternion::ZERO
static const Quaternion ZERO
Definition: CUQuaternion.h:141
cugl::Quaternion::isZero
bool isZero() const
cugl::Quaternion::operator-
const Quaternion operator-(const Quaternion &q) const
Definition: CUQuaternion.h:762
cugl::Quaternion::operator*=
Quaternion & operator*=(float s)
Definition: CUQuaternion.h:696
cugl::Quaternion::IDENTITY
static const Quaternion IDENTITY
Definition: CUQuaternion.h:143
cugl::Quaternion::operator-
const Quaternion operator-() const
Definition: CUQuaternion.h:774
cugl::Quaternion::slerp
static Quaternion * slerp(const Quaternion &q1, const Quaternion &q2, float t, Quaternion *dst)
cugl::Quaternion::z
float z
Definition: CUQuaternion.h:135
cugl::Quaternion::multiply
static Quaternion * multiply(const Quaternion &q1, const Quaternion &q2, Quaternion *dst)
cugl::Quaternion::getRotation
Vec3 getRotation(const Vec3 &v)
Definition: CUQuaternion.h:1198
cugl::Quaternion::operator+
const Quaternion operator+(const Quaternion &q) const
Definition: CUQuaternion.h:748
cugl::Quaternion::invert
Quaternion & invert()
Definition: CUQuaternion.h:575
cugl::Quaternion::getNlerp
Quaternion getNlerp(const Quaternion &q, float t)
Definition: CUQuaternion.h:1185
cugl::Quaternion::normalize
Quaternion & normalize()
Definition: CUQuaternion.h:605
cugl::Quaternion::lerp
Quaternion & lerp(const Quaternion &q, float t)
Definition: CUQuaternion.h:1071
cugl::Quaternion::toAxisAngle
float toAxisAngle(Vec3 *e) const
cugl::Quaternion::nlerp
Quaternion & nlerp(const Quaternion &q, float t)
Definition: CUQuaternion.h:1115
cugl::Quaternion::operator/
const Quaternion operator/(float s) const
Definition: CUQuaternion.h:818
cugl::Quaternion::subtract
Quaternion & subtract(const Quaternion &q)
Definition: CUQuaternion.h:477
cugl::Quaternion::multiply
Quaternion & multiply(const Quaternion &q)
Definition: CUQuaternion.h:495
cugl::Quaternion::createFromAxisAngle
static Quaternion * createFromAxisAngle(const Vec3 &axis, float angle, Quaternion *dst)
cugl::Quaternion::x
float x
Definition: CUQuaternion.h:131
cugl::Quaternion::Quaternion
Quaternion(float x, float y, float z, float w)
Definition: CUQuaternion.h:162
cugl::Quaternion
Definition: CUQuaternion.h:97
cugl::Quaternion::dot
static float dot(const Quaternion &q1, const Quaternion &q2)
cugl::Quaternion::setZero
Quaternion & setZero()
Definition: CUQuaternion.h:314
cugl::Quaternion::rotate
static Vec3 * rotate(const Vec3 &v, const Quaternion &quat, Vec3 *dst)
cugl::Quaternion::normSquared
float normSquared() const
Definition: CUQuaternion.h:906
cugl::Quaternion::operator=
Quaternion & operator=(const float *array)
Definition: CUQuaternion.h:229
cugl::Quaternion::toString
std::string toString(bool verbose=false) const
cugl::Vec3
Definition: CUVec3.h:61
cugl::Quaternion::conjugate
Quaternion & conjugate()
Definition: CUQuaternion.h:537
cugl::Quaternion::getConjugate
Quaternion getConjugate() const
Definition: CUQuaternion.h:557
cugl::Quaternion::operator-=
Quaternion & operator-=(const Quaternion &q)
Definition: CUQuaternion.h:685
cugl::Quaternion::add
static Quaternion * add(const Quaternion &q1, const Quaternion &q2, Quaternion *dst)
cugl::Quaternion::set
Quaternion & set(float x, float y, float z, float w)
Definition: CUQuaternion.h:243
cugl::Quaternion::operator*
const Quaternion operator*(const Quaternion &q) const
Definition: CUQuaternion.h:804
cugl::Quaternion::isUnit
bool isUnit(float variance=CU_MATH_EPSILON) const
Definition: CUQuaternion.h:960
cugl::Quaternion::getInverse
Quaternion getInverse() const
Definition: CUQuaternion.h:592
cugl::Quaternion::scale
static Quaternion * scale(const Quaternion &q1, float s, Quaternion *dst)