TDME2  1.9.200
Quaternion.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <array>
4 
5 #include <tdme/tdme.h>
6 #include <tdme/math/fwd-tdme.h>
7 #include <tdme/math/Math.h>
8 #include <tdme/math/Matrix4x4.h>
9 #include <tdme/math/Vector3.h>
10 #include <tdme/utilities/Float.h>
11 
12 using std::array;
13 
14 using tdme::math::Math;
18 
19 /**
20  * Quaternion class representing quaternion mathematical structure and operations with x, y, z, w components
21  * @author Andreas Drewke
22  */
24 {
25  // see http://db-in.com/blog/2011/04/cameras-on-opengl-es-2-x/
26 private:
27  array<float, 4> data { 0.0f, 0.0f, 0.0f, 0.0f };
28 
29 public:
30  /**
31  * Public constructor
32  */
33  inline Quaternion() {
34  }
35 
36  /**
37  * Public constructor
38  * @param x x component
39  * @param y y component
40  * @param z z component
41  * @param w w component
42  */
43  inline Quaternion(float x, float y, float z, float w) {
44  data[0] = x;
45  data[1] = y;
46  data[2] = z;
47  data[3] = w;
48  }
49 
50  /**
51  * Public constructor
52  * @param vector3 vector3 as array
53  * @param w w component
54  */
55  inline Quaternion(const array<float, 3>& vector3, float w) {
56  data[0] = vector3[0];
57  data[1] = vector3[1];
58  data[2] = vector3[2];
59  data[3] = w;
60  }
61 
62  /**
63  * Public constructor
64  * @param vector3 vector3
65  * @param w w component
66  */
67  inline Quaternion(const Vector3& vector3, float w) {
68  data[0] = vector3.data[0];
69  data[1] = vector3.data[1];
70  data[2] = vector3.data[2];
71  data[3] = w;
72  }
73 
74  /**
75  * Public constructor
76  * @param quaternion quaternion as array
77  */
78  inline Quaternion(const array<float, 4>& quaternion) {
79  data = quaternion;
80  }
81 
82  /**
83  * Public constructor
84  * @param quaternion Quaternion
85  */
86  inline Quaternion(const Quaternion& quaternion) {
87  data = quaternion.data;
88  }
89 
90  /**
91  * Sets this quaternion by its components
92  * @param x x component
93  * @param y y component
94  * @param z z component
95  * @param w w component
96  * @return this quaternion
97  */
98  inline Quaternion& set(float x, float y, float z, float w) {
99  data[0] = x;
100  data[1] = y;
101  data[2] = z;
102  data[3] = w;
103  return *this;
104  }
105 
106  /**
107  * Sets this quaternion by vector3 by array and w component
108  * @param vector3 vector3 as array
109  * @param w w component
110  * @return this quaternion
111  */
112  inline Quaternion& set(const array<float, 3>& vector3, float w) {
113  data[0] = vector3[0];
114  data[1] = vector3[1];
115  data[2] = vector3[2];
116  data[3] = w;
117  return *this;
118  }
119 
120  /**
121  * Sets this quaternion by vector3 and w component
122  * @param vector3 vector3
123  * @param w w component
124  * @return this quaternion
125  */
126  inline Quaternion& set(const Vector3& vector3, float w) {
127  data[0] = vector3.data[0];
128  data[1] = vector3.data[1];
129  data[2] = vector3.data[2];
130  data[3] = w;
131  return *this;
132  }
133 
134  /**
135  * Sets this quaternion by array
136  * @param quaternion quaternion as array
137  * @return this quaternion
138  */
139  inline Quaternion& set(const array<float, 4>& quaternion) {
140  data = quaternion;
141  return *this;
142  }
143 
144  /**
145  * Sets this quaternion by given quaternion
146  * @param quaternion quaternion
147  * @return this quaternion
148  */
149  inline Quaternion& set(const Quaternion& quaternion) {
150  data = quaternion.data;
151  return *this;
152  }
153 
154  /**
155  * @return x component
156  */
157  inline float getX() const {
158  return data[0];
159  }
160 
161  /**
162  * Sets x component
163  * @param x x component
164  * @return this quaternion
165  */
166  inline Quaternion& setX(float x) {
167  data[0] = x;
168  return *this;
169  }
170 
171  /**
172  * @return y component
173  */
174  inline float getY() const {
175  return data[1];
176  }
177 
178  /**
179  * Sets y component
180  * @param y y component
181  * @return this quaternion
182  */
183  inline Quaternion& setY(float y) {
184  data[1] = y;
185  return *this;
186  }
187 
188  /**
189  * @return z component
190  */
191  inline float getZ() const {
192  return data[2];
193  }
194 
195  /**
196  * Sets z component
197  * @param z z component
198  * @return this quaternion
199  */
200  inline Quaternion& setZ(float z) {
201  data[2] = z;
202  return *this;
203  }
204 
205  /**
206  * @return w component
207  */
208  inline float getW() const {
209  return data[3];
210  }
211 
212  /**
213  * Sets w component
214  * @param w w component
215  * @return this quaternion
216  */
217  inline Quaternion& setW(float w) {
218  data[3] = w;
219  return *this;
220  }
221 
222  /**
223  * Creates identity quaternion
224  * @return this quaternion
225  */
226  inline Quaternion& identity() {
227  data[0] = 0.0f;
228  data[1] = 0.0f;
229  data[2] = 0.0f;
230  data[3] = 1.0f;
231  return *this;
232  }
233 
234  /**
235  * Adds quaternion
236  * @param quaternion quaternion
237  * @return this quaternion
238  */
239  inline Quaternion& add(const Quaternion& quaternion) {
240  data[0] += quaternion.data[0];
241  data[1] += quaternion.data[1];
242  data[2] += quaternion.data[2];
243  data[3] += quaternion.data[3];
244  return *this;
245  }
246 
247  /**
248  * Subtracts quaternion
249  * @param quaternion quaternion
250  * @return this quaternion
251  */
252  inline Quaternion& sub(const Quaternion& quaternion) {
253  data[0] -= quaternion.data[0];
254  data[1] -= quaternion.data[1];
255  data[2] -= quaternion.data[2];
256  data[3] -= quaternion.data[3];
257  return *this;
258  }
259 
260  /**
261  * Scales by scalar
262  * @param scalar scalar
263  * @return this quaternion
264  */
265  inline Quaternion& scale(float scalar) {
266  data[0] *= scalar;
267  data[1] *= scalar;
268  data[2] *= scalar;
269  data[3] *= scalar;
270  return *this;
271  }
272 
273  /**
274  * Multiplies this quaternion with given quaternion
275  * @param quaternion quaternion
276  * @return this quaternion
277  */
278  inline Quaternion& multiply(const Quaternion quaternion) {
279  array<float, 4> _data;
280  _data[0] = data[3] * quaternion.data[0] + data[0] * quaternion.data[3] + data[1] * quaternion.data[2] - data[2] * quaternion.data[1];
281  _data[1] = data[3] * quaternion.data[1] - data[0] * quaternion.data[2] + data[1] * quaternion.data[3] + data[2] * quaternion.data[0];
282  _data[2] = data[3] * quaternion.data[2] + data[0] * quaternion.data[1] - data[1] * quaternion.data[0] + data[2] * quaternion.data[3];
283  _data[3] = data[3] * quaternion.data[3] - data[0] * quaternion.data[0] - data[1] * quaternion.data[1] - data[2] * quaternion.data[2];
284  data = _data;
285  return *this;
286  }
287 
288  /**
289  * Multiplies this quaternion with vector3
290  * @param vector3 vector3
291  * @return vector3
292  */
293  inline Vector3 multiply(const Vector3& vector3) const {
294  // t = 2 * cross(quaternion.xyz, vector3)
295  Vector3 quaternion(data[0], data[1], data[2]);
296  auto t = Vector3::computeCrossProduct(quaternion, vector3).scale(2.0f);
297  // vector3' = vector3 + quaternion.w * t + cross(quaternion.xyz, t)
298  auto qxt = Vector3::computeCrossProduct(quaternion, t);
299  //
300  Vector3 result;
301  result.set(vector3);
302  result.add(qxt);
303  result.add(t.scale(data[3]));
304  return result;
305  }
306 
307  /**
308  * Compares this quaternion with given quaternion
309  * @param quaternion quaternion
310  * @return equality
311  */
312  inline bool equals(const Quaternion& quaternion) const {
313  return equals(quaternion, Math::EPSILON);
314  }
315 
316  /**
317  * Compares this quaternion with given quaternion
318  * @param quaternion quaternion
319  * @param tolerance tolerance per component(x, y, z, w)
320  * @return equality
321  */
322  inline bool equals(const Quaternion& quaternion, float tolerance) const {
323  return (this == &quaternion) ||
324  (
325  Math::abs(data[0] - quaternion.data[0]) < tolerance &&
326  Math::abs(data[1] - quaternion.data[1]) < tolerance &&
327  Math::abs(data[2] - quaternion.data[2]) < tolerance &&
328  Math::abs(data[3] - quaternion.data[3]) < tolerance
329  );
330  }
331 
332  /**
333  * Inverts this quaternion
334  * @return this quaternion
335  */
336  inline Quaternion& invert() {
337  data[0] *= -1.0f;
338  data[1] *= -1.0f;
339  data[2] *= -1.0f;
340  return *this;
341  }
342 
343  /**
344  * Normalizes this quaternion
345  */
346  inline Quaternion& normalize() {
347  auto magnitude = Math::sqrt(data[0] * data[0] + data[1] * data[1] + data[2] * data[2] + data[3] * data[3]);
348  data[0] = data[0] / magnitude;
349  data[1] = data[1] / magnitude;
350  data[2] = data[2] / magnitude;
351  data[3] = data[3] / magnitude;
352  return *this;
353  }
354 
355  /**
356  * Creates rotation quaternion
357  * @param axis axis
358  * @param angle angle
359  * @return this quaternion
360  */
361  inline Quaternion& rotate(const Vector3& axis, float angle) {
362  // converts the angle in degrees to radians
363  auto radians = angle * Math::PI / 180.0f;
364  // finds the sin and cosin for the half angle
365  auto sin = Math::sin(radians * 0.5);
366  auto cos = Math::cos(radians * 0.5);
367  // formula to construct a new Quaternion based on direction and angle
368  data[0] = axis.data[0] * sin;
369  data[1] = axis.data[1] * sin;
370  data[2] = axis.data[2] * sin;
371  data[3] = cos;
372  return *this;
373  }
374 
375  /**
376  * Computes a rotation matrix4x4 from this quaternion
377  * @return rotation matrix
378  */
379  inline Matrix4x4 computeMatrix() const {
380  return Matrix4x4(
381  1.0f - 2.0f * (data[1] * data[1] + data[2] * data[2]),
382  2.0f * (data[0] * data[1] + data[2] * data[3]),
383  2.0f * (data[0] * data[2] - data[1] * data[3]),
384  0.0f,
385  2.0f * (data[0] * data[1] - data[2] * data[3]),
386  1.0f - 2.0f * (data[0] * data[0] + data[2] * data[2]),
387  2.0f * (data[2] * data[1] + data[0] * data[3]),
388  0.0f,
389  2.0f * (data[0] * data[2] + data[1] * data[3]),
390  2.0f * (data[1] * data[2] - data[0] * data[3]),
391  1.0f - 2.0f * (data[0] * data[0] + data[1] * data[1]),
392  0.0f,
393  0.0f,
394  0.0f,
395  0.0f,
396  1.0f
397  );
398  }
399 
400  /**
401  * Compute Euler angles
402  * @return Euler angles
403  */
404  inline Vector3 computeEulerAngles() const {
405  // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
406  // https://math.stackexchange.com/questions/2975109/how-to-convert-euler-angles-to-quaternions-and-get-the-same-euler-angles-back-fr
407  Vector3 euler;
408  // roll (x-axis rotation)
409  auto t0 = 2.0f * (data[3] * data[0] + data[1] * data[2]);
410  auto t1 = 1.0f - 2.0f * (data[0] * data[0] + data[1] * data[1]);
411  euler[0] = Math::atan2(t0, t1) / Math::DEG2RAD;
412  // pitch (y-axis rotation)
413  auto t2 = Math::clamp(2.0f * (data[3] * data[1] - data[2] * data[0]), -1.0f, 1.0f);
414  euler[1] = Math::asin(t2) / Math::DEG2RAD;
415  // yaw (z-axis rotation)
416  auto t3 = 2.0f * (data[3] * data[2] + data[0] * data[1]);
417  auto t4 = 1.0f - 2.0f * (data[1] * data[1] + data[2] * data[2]);
418  euler[2] = Math::atan2(t3, t4) / Math::DEG2RAD;
419  //
420  return euler;
421  }
422 
423  /**
424  * Clones this quaternion
425  * @return new cloned quaternion
426  */
427  inline Quaternion clone() const {
428  return Quaternion(*this);
429  }
430 
431  /**
432  * @return quaternion as array
433  */
434  inline const array<float, 4>& getArray() const {
435  return data;
436  }
437 
438  /**
439  * Array access operator
440  * @param i index
441  * @return quaternion component
442  */
443  inline float& operator[](int i) {
444  return data[i];
445  }
446 
447  /**
448  * Const array access operator
449  * @param i index
450  * @return quaternion component
451  */
452  inline const float& operator[](int i) const {
453  return data[i];
454  }
455 
456  /**
457  * Operator + quaternion
458  * @param quaternion quaternion
459  * @return new quaternion (this + quaternion)
460  */
461  inline Quaternion operator +(const Quaternion& quaternion) const {
462  auto r = this->clone().add(quaternion);
463  return r;
464  }
465 
466  /**
467  * Operator - quaternion
468  * @param quaternion quaternion
469  * @return new quaternion (this - quaternion)
470  */
471  inline Quaternion operator -(const Quaternion& quaternion) const {
472  auto r = this->clone().sub(quaternion);
473  return r;
474  }
475 
476  /**
477  * Operator * scalar
478  * @param scalar scalar
479  * @return new quaternion (this * scalar)
480  */
481  inline Quaternion operator *(const float scalar) const {
482  auto r = this->clone().scale(scalar);
483  return r;
484  }
485 
486  /**
487  * Operator * quaternion
488  * @param scalar scalar
489  * @return new quaternion (this * quaternion)
490  */
491  inline Quaternion operator *(const Quaternion& quaternion) const {
492  auto r = this->clone().multiply(quaternion);
493  return r;
494  }
495 
496  /**
497  * Operator * vector3
498  * @param vector3 vector3
499  * @return new vector3 (this * vector3)
500  */
501  inline Vector3 operator *(const Vector3& vector3) const {
502  return this->multiply(vector3);
503  }
504 
505  /**
506  * Operator / scalar
507  * @param scalar scalar
508  * @return new quaternion (this / scalar)
509  */
510  inline Quaternion operator /(const float scalar) const {
511  auto r = this->clone().scale(1.0f / scalar);
512  return r;
513  }
514 
515  /**
516  * Operator / quaternion
517  * @param quaternion quaternion
518  * @return new quaternion (this / quaternion)
519  */
520  inline Quaternion operator /(const Quaternion& quaternion) const {
521  auto qInverted = Quaternion(1.0f / quaternion[0], 1.0f / quaternion[1], 1.0f / quaternion[2], 1.0f / quaternion[3]);
522  auto r = this->clone().multiply(qInverted);
523  return r;
524  }
525 
526  /**
527  * Operator += quaternion
528  * @param quaternion quaternion
529  * @return this quaternion
530  */
531  inline Quaternion& operator +=(const Quaternion& quaternion) {
532  return this->add(quaternion);
533  }
534 
535  /**
536  * Operator -= quaternion
537  * @param quaternion quaternion
538  * @return this quaternion
539  */
540  inline Quaternion& operator -=(const Quaternion& quaternion) {
541  return this->sub(quaternion);
542  }
543 
544  /**
545  * Operator *= quaternion
546  * @param quaternion quaternion
547  * @return this quaternion
548  */
549  inline Quaternion& operator *=(const Quaternion& quaternion) {
550  return this->multiply(quaternion);
551  }
552 
553  /**
554  * Operator /= quaternion
555  * @param quaternion quaternion
556  * @return this quaternion
557  */
558  inline Quaternion& operator /=(const Quaternion& quaternion) {
559  auto qInverted = Quaternion(1.0f / quaternion[0], 1.0f / quaternion[1], 1.0f / quaternion[2], 1.0f / quaternion[3]);
560  return this->multiply(qInverted);
561  }
562 
563  /**
564  * Equality comparison operator
565  * @param quaternion quaternion
566  * @return equality
567  */
568  inline bool operator ==(const Quaternion& quaternion) const {
569  return this->equals(quaternion);
570  }
571 
572  /**
573  * Non equality comparison operator
574  * @param quaternion quaternion
575  * @return non equality
576  */
577  inline bool operator !=(const Quaternion& quaternion) const {
578  return this->equals(quaternion) == false;
579  }
580 
581 };
Standard math functions.
Definition: Math.h:19
static float sqrt(float value)
Returns the square root of given value.
Definition: Math.h:192
static float sin(float x)
Returns the sine of x.
Definition: Math.h:183
static float cos(float x)
Returns the cosine of x.
Definition: Math.h:118
static constexpr float EPSILON
Definition: Math.h:22
static auto abs(auto value)
Returns absolute value.
Definition: Math.h:63
static float asin(float x)
Returns the arc sine of x.
Definition: Math.h:81
static float atan2(float y, float x)
Returns the angle from the conversion of rectangular coordinates to polar coordinates.
Definition: Math.h:100
static constexpr float PI
Definition: Math.h:21
static constexpr float DEG2RAD
Definition: Math.h:23
static auto clamp(auto value, auto min, auto max)
Clamps a value to min or max value.
Definition: Math.h:33
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
Quaternion class representing quaternion mathematical structure and operations with x,...
Definition: Quaternion.h:24
Quaternion operator*(const float scalar) const
Operator * scalar.
Definition: Quaternion.h:481
float getY() const
Definition: Quaternion.h:174
Quaternion(const Quaternion &quaternion)
Public constructor.
Definition: Quaternion.h:86
const float & operator[](int i) const
Const array access operator.
Definition: Quaternion.h:452
Quaternion & identity()
Creates identity quaternion.
Definition: Quaternion.h:226
Vector3 multiply(const Vector3 &vector3) const
Multiplies this quaternion with vector3.
Definition: Quaternion.h:293
float getX() const
Definition: Quaternion.h:157
float & operator[](int i)
Array access operator.
Definition: Quaternion.h:443
Quaternion(const Vector3 &vector3, float w)
Public constructor.
Definition: Quaternion.h:67
Quaternion & add(const Quaternion &quaternion)
Adds quaternion.
Definition: Quaternion.h:239
Quaternion & scale(float scalar)
Scales by scalar.
Definition: Quaternion.h:265
float getZ() const
Definition: Quaternion.h:191
Vector3 computeEulerAngles() const
Compute Euler angles.
Definition: Quaternion.h:404
Quaternion & operator+=(const Quaternion &quaternion)
Operator += quaternion.
Definition: Quaternion.h:531
Quaternion operator+(const Quaternion &quaternion) const
Operator + quaternion.
Definition: Quaternion.h:461
Quaternion & operator/=(const Quaternion &quaternion)
Operator /= quaternion.
Definition: Quaternion.h:558
Quaternion operator-(const Quaternion &quaternion) const
Operator - quaternion.
Definition: Quaternion.h:471
Matrix4x4 computeMatrix() const
Computes a rotation matrix4x4 from this quaternion.
Definition: Quaternion.h:379
Quaternion(const array< float, 4 > &quaternion)
Public constructor.
Definition: Quaternion.h:78
Quaternion(float x, float y, float z, float w)
Public constructor.
Definition: Quaternion.h:43
bool operator==(const Quaternion &quaternion) const
Equality comparison operator.
Definition: Quaternion.h:568
Quaternion operator/(const float scalar) const
Operator / scalar.
Definition: Quaternion.h:510
Quaternion & operator*=(const Quaternion &quaternion)
Operator *= quaternion.
Definition: Quaternion.h:549
Quaternion()
Public constructor.
Definition: Quaternion.h:33
bool operator!=(const Quaternion &quaternion) const
Non equality comparison operator.
Definition: Quaternion.h:577
Quaternion & set(const Vector3 &vector3, float w)
Sets this quaternion by vector3 and w component.
Definition: Quaternion.h:126
Quaternion & multiply(const Quaternion quaternion)
Multiplies this quaternion with given quaternion.
Definition: Quaternion.h:278
float getW() const
Definition: Quaternion.h:208
Quaternion & rotate(const Vector3 &axis, float angle)
Creates rotation quaternion.
Definition: Quaternion.h:361
Quaternion & sub(const Quaternion &quaternion)
Subtracts quaternion.
Definition: Quaternion.h:252
Quaternion & setY(float y)
Sets y component.
Definition: Quaternion.h:183
Quaternion & setW(float w)
Sets w component.
Definition: Quaternion.h:217
Quaternion & setZ(float z)
Sets z component.
Definition: Quaternion.h:200
Quaternion & invert()
Inverts this quaternion.
Definition: Quaternion.h:336
Quaternion & set(const array< float, 4 > &quaternion)
Sets this quaternion by array.
Definition: Quaternion.h:139
array< float, 4 > data
Definition: Quaternion.h:27
Quaternion clone() const
Clones this quaternion.
Definition: Quaternion.h:427
Quaternion & set(const array< float, 3 > &vector3, float w)
Sets this quaternion by vector3 by array and w component.
Definition: Quaternion.h:112
Quaternion & operator-=(const Quaternion &quaternion)
Operator -= quaternion.
Definition: Quaternion.h:540
const array< float, 4 > & getArray() const
Definition: Quaternion.h:434
bool equals(const Quaternion &quaternion) const
Compares this quaternion with given quaternion.
Definition: Quaternion.h:312
Quaternion & normalize()
Normalizes this quaternion.
Definition: Quaternion.h:346
Quaternion & set(float x, float y, float z, float w)
Sets this quaternion by its components.
Definition: Quaternion.h:98
bool equals(const Quaternion &quaternion, float tolerance) const
Compares this quaternion with given quaternion.
Definition: Quaternion.h:322
Quaternion & set(const Quaternion &quaternion)
Sets this quaternion by given quaternion.
Definition: Quaternion.h:149
Quaternion(const array< float, 3 > &vector3, float w)
Public constructor.
Definition: Quaternion.h:55
Quaternion & setX(float x)
Sets x component.
Definition: Quaternion.h:166
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
static Vector3 computeCrossProduct(const Vector3 &a, const Vector3 &b)
Computes the cross product of a and b.
Definition: Vector3.h:263
Vector3 & add(float scalar)
Adds a scalar.
Definition: Vector3.h:153
Vector3 & scale(float scalar)
Scales by scalar.
Definition: Vector3.h:201
Vector3 & set(float x, float y, float z)
Sets this vector3 by its components.
Definition: Vector3.h:70
array< float, 3 > data
Definition: Vector3.h:26
Float class.
Definition: Float.h:27