OGLplus (0.52.0) a C++ wrapper for OpenGL

quaternion.hpp
Go to the documentation of this file.
1 
12 #pragma once
13 #ifndef OGLPLUS_MATH_QUATERNION_1310291021_HPP
14 #define OGLPLUS_MATH_QUATERNION_1310291021_HPP
15 
16 #include <oglplus/math/angle.hpp>
17 #include <oglplus/math/vector.hpp>
18 #include <oglplus/math/slerp.hpp>
19 
20 namespace oglplus {
21 
22 template <typename T>
23 class Quaternion;
24 
25 template <typename T>
27 
28 #if OGLPLUS_DOCUMENTATION_ONLY || defined(GL_FLOAT)
29 
35 #endif
36 
37 #if OGLPLUS_DOCUMENTATION_ONLY || defined(GL_DOUBLE)
38 
44 #endif
45 
47 
50 template <typename T>
51 class Quaternion
52 {
53 private:
54  T _a, _x, _y, _z;
55 public:
57  Quaternion(T a, T x, T y, T z)
58  : _a(a)
59  , _x(x)
60  , _y(y)
61  , _z(z)
62  { }
63 
66  {
67  axis.Normalize();
68  angle /= T(2);
69  T sx = Sin(angle);
70  _a = Cos(angle);
71  _x = sx*axis.x();
72  _y = sx*axis.y();
73  _z = sx*axis.z();
74  }
75 
77  Quaternion(T real, const Vector<T, 3>& imag)
78  : _a(real)
79  , _x(imag.x())
80  , _y(imag.y())
81  , _z(imag.z())
82  { }
83 
85  T Real(void) const
86  {
87  return _a;
88  }
89 
91  Vector<T, 3> Imag(void) const
92  {
93  return Vector<T, 3>(_x, _y, _z);
94  }
95 
96  T At(std::size_t index) const
97  {
98  assert(index < 4);
99  if(index == 0) return _a;
100  if(index == 1) return _x;
101  if(index == 2) return _y;
102  if(index == 3) return _z;
103  return T(0);
104  }
105 
106 #if OGLPLUS_DOCUMENTATION_ONLY
107  friend T Dot(const Quaternion& q1, const Quaternion& q2);
108 #endif
109 
110  static T DotProduct(const Quaternion& q1, const Quaternion& q2)
111  {
112  return q1._a*q2._a + q1._x*q2._x + q1._y*q2._y + q1._z*q2._z;
113  }
114 
116  T Magnitude(void) const
117  {
118  return std::sqrt(DotProduct(*this, *this));
119  }
120 
122 
126  bool IsUnit(T eps = T(0)) const
127  {
128  return std::abs(DotProduct(*this, *this) - T(1)) <= eps;
129  }
130 
132 
136  bool IsNormal(T eps = T(0)) const
137  {
138  return IsUnit(eps);
139  }
140 
142  bool IsDegenerate(T eps = T(0)) const
143  {
144  return DotProduct(*this, *this) <= eps;
145  }
146 
148 
153  {
154  T im = Magnitude();
155  assert(im != T(0));
156  im = T(1)/im;
157  _a *= im;
158  _x *= im;
159  _y *= im;
160  _z *= im;
161  return *this;
162  }
163 
165  friend bool Equal(const Quaternion& q1, const Quaternion& q2)
166  {
167  return (q1._a == q2._a) &&
168  (q1._x == q2._x) &&
169  (q1._y == q2._y) &&
170  (q1._z == q2._z);
171  }
172 
174  friend bool Close(const Quaternion& q1, const Quaternion& q2, T eps)
175  {
176  for(std::size_t i=0; i!=4; ++i)
177  {
178  T u = q1.At(i);
179  T v = q2.At(i);
180  T d = std::abs(u-v);
181  bool ca = d <= std::abs(u)*eps;
182  bool cb = d <= std::abs(v)*eps;
183  if(!ca && !cb) return false;
184  }
185  return true;
186  }
187 
189  friend bool operator == (const Quaternion& q1, const Quaternion& q2)
190  {
191  return Equal(q1, q2);
192  }
193 
195  friend bool operator != (const Quaternion& q1, const Quaternion& q2)
196  {
197  return !Equal(q1, q2);
198  }
199 
200 #if OGLPLUS_DOCUMENTATION_ONLY
201  friend Quaternion Conjugate(const Quaternion& q1);
203 #endif
204 
205  static Quaternion Conjugate(const Quaternion& q1)
206  {
207  return Quaternion(q1._a,-q1._x,-q1._y,-q1._z);
208  }
209 
212  {
213  return Conjugate(q1);
214  }
215 
216 #if OGLPLUS_DOCUMENTATION_ONLY
217  friend Quaternion Inverse(const Quaternion& q1);
219 #endif
220 
221  static Quaternion Inverse(const Quaternion& q1)
222  {
223  T id = DotProduct(q1, q1);
224  assert(id != T(0));
225  id *= T(1)/id;
226  return Quaternion(
227  +q1._a*id,
228  -q1._x*id,
229  -q1._y*id,
230  -q1._z*id
231  );
232  }
233 
234 #if OGLPLUS_DOCUMENTATION_ONLY
235  friend Quaternion Add(const Quaternion& q1, const Quaternion& q2);
237 #endif
238 
239  static Quaternion Added(const Quaternion& q1, const Quaternion& q2)
240  {
241  return Quaternion(
242  q1._a+q2._a,
243  q1._x+q2._x,
244  q1._y+q2._y,
245  q1._z+q2._z
246  );
247  }
248 
250  friend Quaternion operator + (const Quaternion& q1, const Quaternion& q2)
251  {
252  return Added(q1, q2);
253  }
254 
255 #if OGLPLUS_DOCUMENTATION_ONLY
256  friend Quaternion Multiply(const Quaternion& q1, const Quaternion& q2);
258 #endif
259 
260  static Quaternion Multiplied(const Quaternion& q1, const Quaternion& q2)
261  {
262  return Quaternion(
263  q1._a*q2._a - q1._x*q2._x - q1._y*q2._y - q1._z*q2._z,
264  q1._a*q2._x + q1._x*q2._a + q1._y*q2._z - q1._z*q2._y,
265  q1._a*q2._y - q1._x*q2._z + q1._y*q2._a + q1._z*q2._x,
266  q1._a*q2._z + q1._x*q2._y - q1._y*q2._x + q1._z*q2._a
267  );
268  }
269 
271  friend Quaternion operator * (const Quaternion& q1, const Quaternion& q2)
272  {
273  return Multiplied(q1, q2);
274  }
275 
276  static Quaternion Multiplied(const Quaternion& q1, T t)
277  {
278  return Quaternion(q1._a*t, q1._x*t, q1._y*t, q1._z*t);
279  }
280 
282  friend Quaternion operator * (const Quaternion& q1, T t)
283  {
284  return Multiplied(q1, t);
285  }
286 
288  friend Quaternion operator * (T t, const Quaternion& q1)
289  {
290  return Multiplied(q1, t);
291  }
292 
293 #if OGLPLUS_DOCUMENTATION_ONLY
294 
298  friend Vector<T, 3> Rotate(const Quaternion& q, const Vector<T, 3>& v);
299 #endif
300 
301  static Vector<T, 3> RotateVector(
302  const Quaternion& q,
303  const Vector<T, 3>& v
304  )
305  {
306  return (q*Quaternion(T(0), v)*Conjugate(q)).Imag();
307  }
308 };
309 
310 template <typename T>
311 inline T Dot(const Quaternion<T>& q1, const Quaternion<T>& q2)
312 {
313  return Quaternion<T>::DotProduct(q1, q2);
314 }
315 
316 template <typename T>
317 inline T Magnitude(const Quaternion<T>& q1)
318 {
319  return q1.Magnitude();
320 }
321 
322 template <typename T>
323 inline Quaternion<T> Conjugate(const Quaternion<T>& q1)
324 {
325  return Quaternion<T>::Conjugate(q1);
326 }
327 
328 template <typename T>
329 inline Quaternion<T> Inverse(const Quaternion<T>& q1)
330 {
331  return Quaternion<T>::Inverse(q1);
332 }
333 
334 template <typename T>
335 inline Quaternion<T> Add(const Quaternion<T>& q1, const Quaternion<T>& q2)
336 {
337  return Quaternion<T>::Added(q1, q2);
338 }
339 
340 template <typename T>
341 inline Quaternion<T> Multiply(const Quaternion<T>& q1, const Quaternion<T>& q2)
342 {
343  return Quaternion<T>::Multiplied(q1, q2);
344 }
345 
346 template <typename T>
347 inline Vector<T, 3> Rotate(const Quaternion<T>& q, const Vector<T, 3>& v)
348 {
349  return Quaternion<T>::RotateVector(q, v);
350 }
351 
353 
358 template <typename T>
359 class QuaternionSLERP
360  : public BaseSLERP<Quaternion<T>, T>
361 {
362 public:
364 
368  const Quaternion<T>& q1,
369  const Quaternion<T>& q2,
370  T eps = 0.001
371  ): BaseSLERP<Quaternion<T>, T>(q1, q2, eps)
372  { }
373 };
374 
375 } // namespace oglplus
376 
377 #endif // include guard
friend Quaternion operator+(const Quaternion &q1, const Quaternion &q2)
Addition operator.
Definition: quaternion.hpp:250
Template class for quaternions.
Definition: fwd.hpp:59
bool IsUnit(T eps=T(0)) const
Returns true if the quaternion has unit Magnitude.
Definition: quaternion.hpp:126
Quaternion(Vector< T, 3 > axis, Angle< T > angle)
Construct a Quaternion from an axis and an angle.
Definition: quaternion.hpp:65
Vector< T, 3 > Rotate(const Quaternion< T > &q, const Vector< T, 3 > &v)
Definition: quaternion.hpp:347
Class implementing planar angle-related functionality.
Definition: fwd.hpp:24
Definition: vector.hpp:14
Functor template for quaternion spherical-linear interpolation.
Definition: quaternion.hpp:26
Quaternion(T a, T x, T y, T z)
Constructs a quaternion.
Definition: quaternion.hpp:57
friend bool operator==(const Quaternion &q1, const Quaternion &q2)
Equality comparison.
Definition: quaternion.hpp:189
friend bool Close(const Quaternion &q1, const Quaternion &q2, T eps)
Near-equality comparison.
Definition: quaternion.hpp:174
Quaternion< GLfloat > Quatf
Float quaternion.
Definition: quaternion.hpp:26
A template for spherical-linear interpolation.
bool IsDegenerate(T eps=T(0)) const
Returns true if the quaternion has zero Magnitude.
Definition: quaternion.hpp:142
friend bool operator!=(const Quaternion &q1, const Quaternion &q2)
Non-equality comparison.
Definition: quaternion.hpp:195
Vector< T, 3 > Imag(void) const
Returns the imaginary vector part of the quaternion.
Definition: quaternion.hpp:91
Quaternion< GLdouble > Quatd
Double-precision quaternion.
Definition: quaternion.hpp:42
friend Quaternion Add(const Quaternion &q1, const Quaternion &q2)
Quaternion addition.
Definition: quaternion.hpp:335
Quaternion & Normalize(void)
Normalizes this quaternion.
Definition: quaternion.hpp:152
void Normalize(void)
Normalizes this vector.
Definition: vector.hpp:326
T Magnitude(void) const
Returns the magnitude of the quaternion.
Definition: quaternion.hpp:116
QuaternionSLERP(const Quaternion< T > &q1, const Quaternion< T > &q2, T eps=0.001)
Constructs a SLERP functor from two unit quaternions.
Definition: quaternion.hpp:367
friend Quaternion Multiply(const Quaternion &q1, const Quaternion &q2)
Quaternion multiplication.
Definition: quaternion.hpp:341
friend Quaternion Conjugate(const Quaternion &q1)
Conjugate quaternion.
Definition: quaternion.hpp:323
Angle utility class.
friend bool Equal(const Quaternion &q1, const Quaternion &q2)
Equality comparison.
Definition: quaternion.hpp:165
friend Vector< T, 3 > Rotate(const Quaternion &q, const Vector< T, 3 > &v)
Rotate a vector by this quaternion.
Definition: quaternion.hpp:347
friend Quaternion Inverse(const Quaternion &q1)
Inverse quaternion.
Definition: quaternion.hpp:329
Base template for spherical-linear interpolation functors.
Definition: slerp.hpp:28
Quaternion(T real, const Vector< T, 3 > &imag)
Construct q Quaternion from the real and imag parts.
Definition: quaternion.hpp:77
friend Quaternion operator~(const Quaternion &q1)
Conjugation.
Definition: quaternion.hpp:211
friend Quaternion operator*(const Quaternion &q1, const Quaternion &q2)
Multiplication operator.
Definition: quaternion.hpp:271
bool IsNormal(T eps=T(0)) const
Synonym for IsUnit.
Definition: quaternion.hpp:136
A vector class.
T Real(void) const
Returns the real scalar part of the quaternion.
Definition: quaternion.hpp:85

Copyright © 2010-2014 Matúš Chochlík, University of Žilina, Žilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Mon Sep 22 2014 by Doxygen (version 1.8.6).