Monado OpenXR Runtime
utility_northstar.h
1 // Copyright 2020, Hesham Wahba.
2 // Copyright 2020, Nova King.
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #pragma once
6 
7 #include <math.h>
8 using namespace std;
9 
10 // min set of functions needed
11 const float LP_PI = 3.14159265f; // float error, will be 3.141592741f.
12 const float kEpsilon = 0.00001f;
13 
14 
15 // Min Port of a Vector3 class for the deformation rendering system.
16 class Vector3
17 {
18 public:
19  inline Vector3(const Vector3 &in)
20  {
21  x = in.x;
22  y = in.y;
23  z = in.z;
24  };
25 
26  inline Vector3()
27  {
28  x = 0.f;
29  y = 0.f;
30  z = 0.f;
31  };
32 
33  inline Vector3(float _x, float _y, float _z)
34  {
35  x = _x;
36  y = _y;
37  z = _z;
38  };
39 
40  inline Vector3(float _x, float _y)
41  {
42  x = _x;
43  y = _y;
44  z = 0.f;
45  };
46 
47  constexpr Vector3 &
48  operator=(const Vector3 &lhr)
49  {
50  this->x = lhr.x;
51  this->y = lhr.y;
52  this->z = lhr.z;
53  return *this;
54  }
55 
56  inline static Vector3
57  Up()
58  {
59  return Vector3(0.f, 1.f, 0.f);
60  };
61  inline static Vector3
62  Down()
63  {
64  return Vector3(0.f, -1.f, 0.f);
65  };
66  inline static Vector3
67  Left()
68  {
69  return Vector3(-1.f, 0.f, 0.f);
70  };
71  inline static Vector3
72  Right()
73  {
74  return Vector3(1.f, 0.f, 0.f);
75  };
76  inline static Vector3
77  Forward()
78  {
79  return Vector3(0.f, 0.f, 1.f);
80  };
81  inline static Vector3
82  Backward()
83  {
84  return Vector3(0.f, 0.f, -1.f);
85  };
86 
87  inline Vector3
88  operator-(Vector3 &rhs)
89  {
90  Vector3 ret;
91  ret.x = (x - rhs.x);
92  ret.y = (y - rhs.y);
93  ret.z = (z - rhs.z);
94  return ret;
95  }
96 
97  inline Vector3
98  operator-()
99  {
100  return Vector3(-x, -y, -z);
101  }
102 
103  inline Vector3
104  operator+(const Vector3 &rhs)
105  {
106  Vector3 ret;
107  ret.x = (x + rhs.x);
108  ret.y = (y + rhs.y);
109  ret.z = (z + rhs.z);
110  return ret;
111  }
112 
113  inline Vector3 &
114  operator+=(const Vector3 &v)
115  {
116  this->x += v.x;
117  this->y += v.y;
118  this->z += v.z;
119  return *this;
120  }
121 
122  inline Vector3
123  operator/(const float &d)
124  {
125  Vector3 *ret = new Vector3();
126  ret->x = (x / d);
127  ret->y = (y / d);
128  ret->z = (z / d);
129  return *ret;
130  }
131 
132  inline Vector3 operator*(const float &d)
133  {
134  Vector3 ret;
135  ret.x = (x * d);
136  ret.y = (y * d);
137  ret.z = (z * d);
138  return ret;
139  }
140 
141  inline Vector3
142  Inverse()
143  {
144  Vector3 ret;
145  ret.x = -x;
146  ret.y = -y;
147  ret.z = -z;
148  return ret;
149  }
150 
151  inline float static Dot(Vector3 lhs, Vector3 rhs)
152  {
153  float result =
154  (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z);
155  return result;
156  }
157 
158  inline float
159  Dot(Vector3 rhs)
160  {
161  float result = (x * rhs.x) + (y * rhs.y) + (z * rhs.z);
162  return result;
163  }
164 
165  inline static float
166  Angle(Vector3 v0, Vector3 v1)
167  {
168  Vector3 dir0 = v0.Normalized();
169  Vector3 dir1 = v1.Normalized();
170 
171  float dot = dir0.Dot(dir1);
172  dot = (dot < -1.f ? -1.f : (dot > 1.f ? 1.f : dot));
173 
174  float angle = acos(dot);
175 
176  return angle;
177  }
178 
179  inline float
180  sqrMagnitude()
181  {
182  return x * x + y * y + z * z;
183  }
184 
185  inline float
186  Magnitude()
187  {
188  return sqrt(x * x + y * y + z * z);
189  }
190 
191  inline static Vector3
192  Zero()
193  {
194  Vector3 ret;
195  ret.x = 0.f;
196  ret.y = 0.f;
197  ret.z = 0.f;
198  return ret;
199  }
200 
201  inline static Vector3
202  One()
203  {
204  Vector3 ret;
205  ret.x = 1.f;
206  ret.y = 1.f;
207  ret.z = 1.f;
208  return ret;
209  }
210 
211  inline static Vector3
212  Reflect(Vector3 inDirection, Vector3 inNormal)
213  {
214  return inNormal * -2.F * Dot(inNormal, inDirection) +
215  inDirection;
216  }
217 
218  inline void
219  Normalize()
220  {
221  float mag = Magnitude();
222  if (mag > kEpsilon) {
223  x = x / mag;
224  y = y / mag;
225  z = z / mag;
226  } else {
227  x = 0.f;
228  y = 0.f;
229  z = 0.f;
230  }
231  }
232 
233  inline Vector3
234  Normalized()
235  {
236  Vector3 ret;
237  float mag = Magnitude();
238  if (mag > kEpsilon) {
239  ret.x = x / mag;
240  ret.y = y / mag;
241  ret.z = z / mag;
242  } else {
243  ret.x = 0.f;
244  ret.y = 0.f;
245  ret.z = 0.f;
246  }
247  return ret;
248  }
249 
250 
251  inline void
252  rotate(Vector3 axis, float radians)
253  {
254  float cos_theta = cosf(radians);
255  float sin_theta = sinf(radians);
256 
257  x = (x * cos_theta) + (Vector3::Cross(axis) * sin_theta).x +
258  (axis.x * Vector3::Dot(axis, *this)) * (1 - cos_theta);
259 
260  y = (y * cos_theta) + (Vector3::Cross(axis) * sin_theta).y +
261  (axis.y * Vector3::Dot(axis, *this)) * (1 - cos_theta);
262 
263  z = (z * cos_theta) + (Vector3::Cross(axis) * sin_theta).z +
264  (axis.z * Vector3::Dot(axis, *this)) * (1 - cos_theta);
265  }
266 
267  inline Vector3
268  Cross(const Vector3 in)
269  {
270  Vector3 ret;
271  ret.x = y * in.z - z * in.y;
272  ret.y = z * in.x - x * in.z;
273  ret.z = x * in.y - y * in.x;
274  return ret;
275  }
276 
277  float x;
278  float y;
279  float z;
280 };
281 
282 // Min Port of a Vector2 class for the deformation rendering system.
283 class Vector2
284 {
285 public:
286  inline Vector2()
287  {
288  x = 0.f;
289  y = 0.f;
290  };
291 
292  inline Vector2(const Vector2 &in)
293  {
294  x = in.x;
295  y = in.y;
296  }
297 
298  inline Vector2(float _x, float _y)
299  {
300  x = _x;
301  y = _y;
302  };
303 
304  constexpr Vector2 &
305  operator=(const Vector2 &lhr)
306  {
307  this->x = lhr.x;
308  this->y = lhr.y;
309  return *this;
310  }
311 
312  inline static Vector2
313  zero()
314  {
315  Vector2 ret;
316  ret.x = 0.f;
317  ret.y = 0.f;
318  return ret;
319  }
320 
321  inline static Vector2
322  One()
323  {
324  Vector2 ret;
325  ret.x = 1.f;
326  ret.y = 1.f;
327  return ret;
328  }
329 
330  inline Vector2
331  operator/(const float &d)
332  {
333  Vector2 ret;
334  ret.x = (x / d);
335  ret.y = (y / d);
336  return ret;
337  }
338 
339  inline Vector2 operator*(const float &d)
340  {
341  Vector2 ret;
342  ret.x = (x * d);
343  ret.y = (y * d);
344  return ret;
345  }
346  inline Vector2
347  operator-(const Vector2 &rhs)
348  {
349  Vector2 ret;
350  ret.x = (x - rhs.x);
351  ret.y = (y - rhs.y);
352  return ret;
353  }
354 
355  inline Vector2
356  operator+(const Vector2 &rhs)
357  {
358  Vector2 ret;
359  ret.x = (x + rhs.x);
360  ret.y = (y + rhs.y);
361  return ret;
362  }
363 
364  float x;
365  float y;
366 };
367 
369 {
370 public:
371  inline Matrix4x4()
372  {
373  m00 = 0.0f;
374  m01 = 0.0f;
375  m02 = 0.0f;
376  m03 = 0.0f;
377  m10 = 0.0f;
378  m11 = 0.0f;
379  m12 = 0.0f;
380  m13 = 0.0f;
381  m20 = 0.0f;
382  m21 = 0.0f;
383  m22 = 0.0f;
384  m23 = 0.0f;
385  m30 = 0.0f;
386  m31 = 0.0f;
387  m32 = 0.0f;
388  m33 = 0.0f;
389  };
390 
391  inline Matrix4x4(const Matrix4x4 &_in)
392  {
393  m00 = _in.m00;
394  m01 = _in.m01;
395  m02 = _in.m02;
396  m03 = _in.m03;
397  m10 = _in.m10;
398  m11 = _in.m11;
399  m12 = _in.m12;
400  m13 = _in.m13;
401  m20 = _in.m20;
402  m21 = _in.m21;
403  m22 = _in.m22;
404  m23 = _in.m23;
405  m30 = _in.m30;
406  m31 = _in.m31;
407  m32 = _in.m32;
408  m33 = _in.m33;
409  };
410 
411  inline Matrix4x4(float in00,
412  float in01,
413  float in02,
414  float in03,
415  float in10,
416  float in11,
417  float in12,
418  float in13,
419  float in20,
420  float in21,
421  float in22,
422  float in23,
423  float in30,
424  float in31,
425  float in32,
426  float in33)
427  {
428  m00 = in00;
429  m01 = in01;
430  m02 = in02;
431  m03 = in03;
432  m10 = in10;
433  m11 = in11;
434  m12 = in12;
435  m13 = in13;
436  m20 = in20;
437  m21 = in21;
438  m22 = in22;
439  m23 = in23;
440  m30 = in30;
441  m31 = in31;
442  m32 = in32;
443  m33 = in33;
444  };
445 
446  constexpr Matrix4x4 &
447  operator=(const Matrix4x4 &lhr)
448  {
449  this->m00 = lhr.m00;
450  this->m01 = lhr.m01;
451  this->m02 = lhr.m02;
452  this->m03 = lhr.m03;
453  this->m10 = lhr.m10;
454  this->m11 = lhr.m11;
455  this->m12 = lhr.m12;
456  this->m13 = lhr.m13;
457  this->m20 = lhr.m20;
458  this->m21 = lhr.m21;
459  this->m22 = lhr.m22;
460  this->m23 = lhr.m23;
461  this->m30 = lhr.m30;
462  this->m31 = lhr.m31;
463  this->m32 = lhr.m32;
464  this->m33 = lhr.m33;
465  return *this;
466  };
467 
468  inline static Matrix4x4
469  Identity()
470  {
471  Matrix4x4 m;
472  m.m00 = 1;
473  m.m01 = 0;
474  m.m02 = 0;
475  m.m03 = 0;
476  m.m10 = 0;
477  m.m11 = 1;
478  m.m12 = 0;
479  m.m13 = 0;
480  m.m20 = 0;
481  m.m21 = 0;
482  m.m22 = 1;
483  m.m23 = 0;
484  m.m30 = 0;
485  m.m31 = 0;
486  m.m32 = 0;
487  m.m33 = 1;
488  return m;
489  }
490 
491  // Returns a 3x3 rotation matrix (padded to a Matrix4x4).
492  inline static Matrix4x4
493  RotationAlign(Vector3 fromDir, Vector3 toDir)
494  {
495  const Vector3 v = fromDir.Cross(toDir);
496  const float c = fromDir.Dot(toDir);
497  const float k = 1.0f / (1.0f + c);
498 
499  return Matrix4x4(v.x * v.x * k + c, v.y * v.x * k - v.z,
500  v.z * v.x * k + v.y, 0.f, v.x * v.y * k + v.z,
501  v.y * v.y * k + c, v.z * v.y * k - v.x, 0.f,
502  v.x * v.z * k - v.y, v.y * v.z * k + v.x,
503  v.z * v.z * k + c, 0.f, 0.f, 0.f, 0.f, 1.f);
504  }
505 
506  inline Matrix4x4 operator*(const Matrix4x4 &_in)
507  {
508  Matrix4x4 ret;
509  ret.m00 = (m00 * _in.m00) + (m01 * _in.m10) + (m02 * _in.m20) +
510  (m03 * _in.m30);
511  ret.m01 = (m00 * _in.m01) + (m01 * _in.m11) + (m02 * _in.m21) +
512  (m03 * _in.m31);
513  ret.m02 = (m00 * _in.m02) + (m01 * _in.m12) + (m02 * _in.m22) +
514  (m03 * _in.m32);
515  ret.m03 = (m00 * _in.m03) + (m01 * _in.m13) + (m02 * _in.m23) +
516  (m03 * _in.m33);
517 
518 
519  ret.m10 = (m10 * _in.m00) + (m11 * _in.m10) + (m12 * _in.m20) +
520  (m13 * _in.m30);
521  ret.m11 = (m10 * _in.m01) + (m11 * _in.m11) + (m12 * _in.m21) +
522  (m13 * _in.m31);
523  ret.m12 = (m10 * _in.m02) + (m11 * _in.m12) + (m12 * _in.m22) +
524  (m13 * _in.m32);
525  ret.m13 = (m10 * _in.m03) + (m11 * _in.m13) + (m12 * _in.m23) +
526  (m13 * _in.m33);
527 
528 
529  ret.m20 = (m20 * _in.m00) + (m21 * _in.m10) + (m22 * _in.m20) +
530  (m23 * _in.m30);
531  ret.m21 = (m20 * _in.m01) + (m21 * _in.m11) + (m22 * _in.m21) +
532  (m23 * _in.m31);
533  ret.m22 = (m20 * _in.m02) + (m21 * _in.m12) + (m22 * _in.m22) +
534  (m23 * _in.m32);
535  ret.m23 = (m20 * _in.m03) + (m21 * _in.m13) + (m22 * _in.m23) +
536  (m23 * _in.m33);
537 
538  ret.m30 = (m30 * _in.m00) + (m31 * _in.m10) + (m32 * _in.m20) +
539  (m33 * _in.m30);
540  ret.m31 = (m30 * _in.m01) + (m31 * _in.m11) + (m32 * _in.m21) +
541  (m33 * _in.m31);
542  ret.m32 = (m30 * _in.m02) + (m31 * _in.m12) + (m32 * _in.m22) +
543  (m33 * _in.m32);
544  ret.m33 = (m30 * _in.m03) + (m31 * _in.m13) + (m32 * _in.m23) +
545  (m33 * _in.m33);
546 
547  return ret;
548  }
549 
550  inline Vector3
551  MultiplyPoint(Vector3 point)
552  {
553  Vector3 res;
554  float w;
555  res.x = m00 * point.x + m01 * point.y + m02 * point.z + m03;
556  res.y = m10 * point.x + m11 * point.y + m12 * point.z + m13;
557  res.z = m20 * point.x + m21 * point.y + m22 * point.z + m23;
558 
559  w = m30 * point.x + m31 * point.y + m32 * point.z + m33;
560 
561  w = 1.f / w;
562  res.x *= w;
563  res.y *= w;
564  res.z *= w;
565  return res;
566  }
567 
568  inline static Matrix4x4
569  Translate(Vector3 vector)
570  {
571  Matrix4x4 m;
572  m.m00 = 1.f;
573  m.m01 = 0.f;
574  m.m02 = 0.f;
575  m.m03 = vector.x;
576  m.m10 = 0.f;
577  m.m11 = 1.f;
578  m.m12 = 0.f;
579  m.m13 = vector.y;
580  m.m20 = 0.f;
581  m.m21 = 0.f;
582  m.m22 = 1.f;
583  m.m23 = vector.z;
584  m.m30 = 0.f;
585  m.m31 = 0.f;
586  m.m32 = 0.f;
587  m.m33 = 1.f;
588  return m;
589  }
590 
591  inline Vector3
592  MultiplyVector(Vector3 vector)
593  {
594  Vector3 res;
595  res.x = m00 * vector.x + m01 * vector.y + m02 * vector.z;
596  res.y = m10 * vector.x + m11 * vector.y + m12 * vector.z;
597  res.z = m20 * vector.x + m21 * vector.y + m22 * vector.z;
598  return res;
599  }
600 
601  inline Vector3
602  MultiplyPoint3x4(Vector3 point)
603  {
604  Vector3 res;
605  res.x = m00 * point.x + m01 * point.y + m02 * point.z + m03;
606  res.y = m10 * point.x + m11 * point.y + m12 * point.z + m13;
607  res.z = m20 * point.x + m21 * point.y + m22 * point.z + m23;
608  return res;
609  }
610 
611  inline Matrix4x4
612  Transpose()
613  {
614  Matrix4x4 r;
615  r.m00 = m00;
616  r.m01 = m10;
617  r.m02 = m20;
618  r.m03 = m30;
619  r.m10 = m01;
620  r.m11 = m11;
621  r.m12 = m21;
622  r.m13 = m31;
623  r.m20 = m02;
624  r.m21 = m12;
625  r.m22 = m22;
626  r.m23 = m32;
627  r.m30 = m03;
628  r.m31 = m13;
629  r.m32 = m23;
630  r.m33 = m33;
631  return r;
632  }
633 
634  inline Matrix4x4
635  Inverse()
636  {
637  float A2323 = m22 * m33 - m23 * m32;
638  float A1323 = m21 * m33 - m23 * m31;
639  float A1223 = m21 * m32 - m22 * m31;
640  float A0323 = m20 * m33 - m23 * m30;
641  float A0223 = m20 * m32 - m22 * m30;
642  float A0123 = m20 * m31 - m21 * m30;
643  float A2313 = m12 * m33 - m13 * m32;
644  float A1313 = m11 * m33 - m13 * m31;
645  float A1213 = m11 * m32 - m12 * m31;
646  float A2312 = m12 * m23 - m13 * m22;
647  float A1312 = m11 * m23 - m13 * m21;
648  float A1212 = m11 * m22 - m12 * m21;
649  float A0313 = m10 * m33 - m13 * m30;
650  float A0213 = m10 * m32 - m12 * m30;
651  float A0312 = m10 * m23 - m13 * m20;
652  float A0212 = m10 * m22 - m12 * m20;
653  float A0113 = m10 * m31 - m11 * m30;
654  float A0112 = m10 * m21 - m11 * m20;
655 
656  float det = m00 * (m11 * A2323 - m12 * A1323 + m13 * A1223) -
657  m01 * (m10 * A2323 - m12 * A0323 + m13 * A0223) +
658  m02 * (m10 * A1323 - m11 * A0323 + m13 * A0123) -
659  m03 * (m10 * A1223 - m11 * A0223 + m12 * A0123);
660  det = 1 / det;
661 
662  return Matrix4x4(
663  det * (m11 * A2323 - m12 * A1323 + m13 * A1223),
664  det * -(m01 * A2323 - m02 * A1323 + m03 * A1223),
665  det * (m01 * A2313 - m02 * A1313 + m03 * A1213),
666  det * -(m01 * A2312 - m02 * A1312 + m03 * A1212),
667  det * -(m10 * A2323 - m12 * A0323 + m13 * A0223),
668  det * (m00 * A2323 - m02 * A0323 + m03 * A0223),
669  det * -(m00 * A2313 - m02 * A0313 + m03 * A0213),
670  det * (m00 * A2312 - m02 * A0312 + m03 * A0212),
671  det * (m10 * A1323 - m11 * A0323 + m13 * A0123),
672  det * -(m00 * A1323 - m01 * A0323 + m03 * A0123),
673  det * (m00 * A1313 - m01 * A0313 + m03 * A0113),
674  det * -(m00 * A1312 - m01 * A0312 + m03 * A0112),
675  det * -(m10 * A1223 - m11 * A0223 + m12 * A0123),
676  det * (m00 * A1223 - m01 * A0223 + m02 * A0123),
677  det * -(m00 * A1213 - m01 * A0213 + m02 * A0113),
678  det * (m00 * A1212 - m01 * A0212 + m02 * A0112));
679  }
680 
681  float m00;
682  float m01;
683  float m02;
684  float m03;
685 
686  float m10;
687  float m11;
688  float m12;
689  float m13;
690 
691  float m20;
692  float m21;
693  float m22;
694  float m23;
695 
696  float m30;
697  float m31;
698  float m32;
699  float m33;
700 };
701 
702 // Vector4 min port to get code working...
703 class Vector4
704 {
705 public:
706  inline Vector4()
707  {
708  x = 0.f;
709  y = 0.f;
710  z = 0.f;
711  w = 0.f;
712  }
713 
714  inline Vector4(const Vector4 &in)
715  {
716  x = in.x;
717  y = in.y;
718  z = in.z;
719  w = in.w;
720  }
721 
722  constexpr Vector4 &
723  operator=(const Vector4 &lhr)
724  {
725  this->x = lhr.x;
726  this->y = lhr.y;
727  this->z = lhr.z;
728  this->w = lhr.w;
729  return *this;
730  }
731 
732  inline Matrix4x4
733  ComposeProjection()
734  {
735  const float zNear = 0.07f;
736  const float zFar = 1000.f;
737 
738  float fLeft = x;
739  float fRight = y;
740  float fTop = z;
741  float fBottom = w;
742 
743  float idx = 1.0f / (fRight - fLeft);
744  float idy = 1.0f / (fBottom - fTop);
745  // float idz = 1.0f / (zFar - zNear);
746  float sx = fRight + fLeft;
747  float sy = fBottom + fTop;
748 
749  float c = -(zFar + zNear) / (zFar - zNear);
750  float d = -(2.0F * zFar * zNear) / (zFar - zNear);
751 
752  Matrix4x4 m;
753  m.m00 = 2.f * idx;
754  m.m01 = 0.f;
755  m.m02 = sx * idx;
756  m.m03 = 0.f;
757  m.m10 = 0.f;
758  m.m11 = 2.f * idy;
759  m.m12 = sy * idy;
760  m.m13 = 0.f;
761  m.m20 = 0.f;
762  m.m21 = 0.f;
763  m.m22 = c;
764  m.m23 = d;
765  m.m30 = 0.f;
766  m.m31 = 0.f;
767  m.m32 = -1.0f;
768  m.m33 = 0.f;
769 
770  return m;
771  }
772 
773  float x;
774  float y;
775  float z;
776  float w;
777 };
778 
779 class Ray
780 {
781 public:
782  inline Ray(Vector3 origin, Vector3 direction)
783  {
784  m_Origin = origin;
785  direction.Normalize();
786  m_Direction.x = direction.x;
787  m_Direction.y = direction.y;
788  m_Direction.z = direction.z;
789  }
790 
791  inline Vector3
792  GetPoint(float distance)
793  {
794  return m_Origin + m_Direction * distance;
795  }
796 
797  Vector3 m_Origin;
798  Vector3 m_Direction;
799 };
800 
802 {
803 public:
804  inline Quaternion()
805  {
806  x = 0.f;
807  y = 0.f;
808  z = 0.f;
809  w = 1.f;
810  };
811 
812  inline Quaternion(float _x, float _y, float _z, float _w)
813  {
814  x = _x;
815  y = _y;
816  z = _z;
817  w = _w;
818  };
819 
820  inline Quaternion(const Quaternion &_in)
821  {
822  x = _in.x;
823  y = _in.y;
824  z = _in.z;
825  w = _in.w;
826  };
827 
828  constexpr Quaternion &
829  operator=(const Quaternion &lhr)
830  {
831  this->x = lhr.x;
832  this->y = lhr.y;
833  this->z = lhr.z;
834  this->w = lhr.w;
835  return *this;
836  }
837 
838  inline static Quaternion
839  Identity()
840  {
841  return Quaternion(0, 0, 0, 1);
842  }
843 
844  inline Quaternion
845  conjugate()
846  {
847  return Quaternion(-x, -y, -z, w);
848  }
849 
850  inline float
851  norm()
852  {
853  return sqrt((x * x) + (y * y) + (z * z) + (w * w));
854  }
855 
856  inline Quaternion
857  scale(float s)
858  {
859  return Quaternion(w * s, x * s, y * s, z * s);
860  }
861 
862  inline Quaternion
863  Inverse()
864  {
865  return conjugate() / norm();
866  }
867 
868  inline Vector3
869  Right()
870  {
871  return *this * Vector3::Right();
872  }
873 
874  inline Vector3
875  Up()
876  {
877  return *this * Vector3::Up();
878  }
879 
880  inline Vector3
881  Forward()
882  {
883  return *this * Vector3::Forward();
884  }
885 
886  inline static void
887  ToEulerAngle(const Quaternion &q, float &roll, float &pitch, float &yaw)
888  {
889  float sinr = +2.0f * (q.w * q.x + q.y * q.z);
890  float cosr = +1.0f - 2.0f * (q.x * q.x + q.y * q.y);
891  roll = atan2f(sinr, cosr);
892 
893  float sinp = +2.0f * (q.w * q.y - q.z * q.x);
894  if (fabs(sinp) >= 1.f) {
895  pitch = copysignf(LP_PI / 2.f, sinp);
896  } else {
897  pitch = asinf(sinp);
898  }
899 
900  float siny = +2.0f * (q.w * q.z + q.x * q.y);
901  float cosy = +1.0f - 2.0f * (q.y * q.y + q.z * q.z);
902  yaw = atan2f(siny, cosy);
903  }
904 
905  inline static Vector3
906  ToEulerAngles(const Quaternion &in)
907  {
908  Vector3 euler;
909  const static float PI_OVER_2 = LP_PI * 0.5f;
910  const static float EPSILON = 1e-10f;
911  float sqw, sqx, sqy, sqz;
912 
913  // quick conversion to Euler angles to give tilt to user
914  sqw = in.w * in.w;
915  sqx = in.x * in.x;
916  sqy = in.y * in.y;
917  sqz = in.z * in.z;
918 
919  euler.y = asinf(2.0f * (in.w * in.y - in.x * in.z));
920  if (PI_OVER_2 - fabs(euler.y) > EPSILON) {
921  euler.z = atan2f(2.0f * (in.x * in.y + in.w * in.z),
922  sqx - sqy - sqz + sqw);
923  euler.x = atan2f(2.0f * (in.w * in.x + in.y * in.z),
924  sqw - sqx - sqy + sqz);
925  } else {
926  // compute heading from local 'down' vector
927  euler.z = atan2f(2.f * in.y * in.z - 2.f * in.x * in.w,
928  2.f * in.x * in.z + 2.f * in.y * in.w);
929  euler.x = 0.0f;
930 
931  // If facing down, reverse yaw
932  if (euler.y < 0.f) {
933  euler.z = LP_PI - euler.z;
934  }
935  }
936  return euler;
937  }
938 
939  inline Vector3 operator*(Vector3 vec)
940  {
941  float num = x * 2.f;
942  float num2 = y * 2.f;
943  float num3 = z * 2.f;
944  float num4 = x * num;
945  float num5 = y * num2;
946  float num6 = z * num3;
947  float num7 = x * num2;
948  float num8 = x * num3;
949  float num9 = y * num3;
950  float num10 = w * num;
951  float num11 = w * num2;
952  float num12 = w * num3;
953  Vector3 result;
954  result.x = (1.f - (num5 + num6)) * vec.x +
955  (num7 - num12) * vec.y + (num8 + num11) * vec.z;
956  result.y = (num7 + num12) * vec.x +
957  (1.f - (num4 + num6)) * vec.y +
958  (num9 - num10) * vec.z;
959  result.z = (num8 - num11) * vec.x + (num9 + num10) * vec.y +
960  (1.f - (num4 + num5)) * vec.z;
961  return result;
962  }
963 
964  inline static Quaternion
965  Euler(const Vector3 &euler)
966  {
967  float c1 = cos(euler.z * 0.5f);
968  float c2 = cos(euler.y * 0.5f);
969  float c3 = cos(euler.x * 0.5f);
970  float s1 = sin(euler.z * 0.5f);
971  float s2 = sin(euler.y * 0.5f);
972  float s3 = sin(euler.x * 0.5f);
973 
974  Quaternion ret;
975  ret.x = c1 * c2 * s3 - s1 * s2 * c3;
976  ret.y = c1 * s2 * c3 + s1 * c2 * s3;
977  ret.z = s1 * c2 * c3 - c1 * s2 * s3;
978  ret.w = c1 * c2 * c3 + s1 * s2 * s3;
979 
980  return ret;
981  }
982 
983 
984  Matrix4x4
985  ToMatrix4x4()
986  {
987  float qw = w;
988  float qx = x;
989  float qy = y;
990  float qz = z;
991 
992  const float n =
993  1.0f / sqrt(qx * qx + qy * qy + qz * qz + qw * qw);
994  qx *= n;
995  qy *= n;
996  qz *= n;
997  qw *= n;
998 
999  return Matrix4x4(1.0f - 2.0f * qy * qy - 2.0f * qz * qz,
1000  2.0f * qx * qy - 2.0f * qz * qw,
1001  2.0f * qx * qz + 2.0f * qy * qw, 0.0f,
1002  2.0f * qx * qy + 2.0f * qz * qw,
1003  1.0f - 2.0f * qx * qx - 2.0f * qz * qz,
1004  2.0f * qy * qz - 2.0f * qx * qw, 0.0f,
1005  2.0f * qx * qz - 2.0f * qy * qw,
1006  2.0f * qy * qz + 2.0f * qx * qw,
1007  1.0f - 2.0f * qx * qx - 2.0f * qy * qy, 0.0f,
1008  0.0f, 0.0f, 0.0f, 1.0f);
1009  }
1010 
1011  inline Quaternion operator*(const Quaternion &q)
1012  {
1013  return Quaternion(y * q.z - z * q.y + x * q.w + w * q.x,
1014  z * q.x - x * q.z + y * q.w + w * q.y,
1015  x * q.y - y * q.x + z * q.w + w * q.z,
1016  w * q.w - x * q.x - y * q.y - z * q.z);
1017  }
1018 
1019  Quaternion
1020  operator/(const float div)
1021  {
1022  return Quaternion(x / div, y / div, z / div, w / div);
1023  }
1024 
1025  inline static Quaternion
1026  AxisAngle(Vector3 axis, float angle)
1027  {
1028  float halfAngle = angle * .5f;
1029  float s = (float)sin(halfAngle);
1030  Quaternion q;
1031  q.x = axis.x * s;
1032  q.y = axis.y * s;
1033  q.z = axis.z * s;
1034  q.w = (float)cos(halfAngle);
1035  return q;
1036  }
1037 
1038  inline static Quaternion
1039  LookAt(Vector3 sourcePoint, Vector3 destPoint)
1040  {
1041  Vector3 forwardVector = (destPoint - sourcePoint).Normalized();
1042 
1043  float dot = Vector3::Dot(Vector3::Forward(), forwardVector);
1044 
1045  if (fabs(dot - (-1.0f)) < 0.000001f) {
1046  return Quaternion(Vector3::Up().x, Vector3::Up().y,
1047  Vector3::Up().z, 3.1415926535897932f);
1048  }
1049  if (fabs(dot - (1.0f)) < 0.000001f) {
1050  return Quaternion();
1051  }
1052 
1053  float rotAngle = cos(dot);
1054  Vector3 rotAxis = Vector3::Forward().Cross(forwardVector);
1055  rotAxis = rotAxis.Normalized();
1056  return AxisAngle(rotAxis, rotAngle);
1057  }
1058 
1059  inline static Quaternion
1060  QuaternionLookRotation(Vector3 forward, Vector3 Up)
1061  {
1062 
1063  Vector3 vector1 = forward.Normalized();
1064  Vector3 vector2 = (Up.Cross(vector1)).Normalized();
1065  Vector3 vector3 = vector1.Cross(vector2);
1066 
1067  float m00 = vector2.x;
1068  float m01 = vector2.y;
1069  float m02 = vector2.z;
1070  float m10 = vector3.x;
1071  float m11 = vector3.y;
1072  float m12 = vector3.z;
1073  float m20 = vector1.x;
1074  float m21 = vector1.y;
1075  float m22 = vector1.z;
1076 
1077  float num8 = (m00 + m11) + m22;
1078  Quaternion quaternion;
1079  if (num8 > 0.f) {
1080  float num = (float)sqrtf(num8 + 1.f);
1081  quaternion.w = num * 0.5f;
1082  num = 0.5f / num;
1083  quaternion.x = (m12 - m21) * num;
1084  quaternion.y = (m20 - m02) * num;
1085  quaternion.z = (m01 - m10) * num;
1086  return quaternion;
1087  }
1088 
1089  if ((m00 >= m11) && (m00 >= m22)) {
1090  float num7 = (float)sqrtf(((1.f + m00) - m11) - m22);
1091  float num4 = 0.5f / num7;
1092  quaternion.x = 0.5f * num7;
1093  quaternion.y = (m01 + m10) * num4;
1094  quaternion.z = (m02 + m20) * num4;
1095  quaternion.w = (m12 - m21) * num4;
1096  return quaternion;
1097  }
1098 
1099  if (m11 > m22) {
1100  float num6 = (float)sqrtf(((1.f + m11) - m00) - m22);
1101  float num3 = 0.5f / num6;
1102  quaternion.x = (m10 + m01) * num3;
1103  quaternion.y = 0.5f * num6;
1104  quaternion.z = (m21 + m12) * num3;
1105  quaternion.w = (m20 - m02) * num3;
1106  return quaternion;
1107  }
1108 
1109  float num5 = (float)sqrtf(((1.f + m22) - m00) - m11);
1110  float num2 = 0.5f / num5;
1111  quaternion.x = (m20 + m02) * num2;
1112  quaternion.y = (m21 + m12) * num2;
1113  quaternion.z = 0.5f * num5;
1114  quaternion.w = (m01 - m10) * num2;
1115  return quaternion;
1116  }
1117 
1118 
1119  inline float
1120  SIGN(float x)
1121  {
1122  return (x >= 0.0f) ? +1.0f : -1.0f;
1123  }
1124 
1125  inline float
1126  NORM(float a, float b, float c, float d)
1127  {
1128  return sqrt(a * a + b * b + c * c + d * d);
1129  }
1130 
1131  inline static Quaternion
1132  FromMatrix(const Matrix4x4 m)
1133  {
1134  float tr = m.m00 + m.m11 + m.m22;
1135  float qx, qy, qz, qw;
1136 
1137  if (tr > 0) {
1138  float S = sqrtf(tr + 1.f) * 2.f;
1139  qw = 0.25f * S;
1140  qx = (m.m21 - m.m12) / S;
1141  qy = (m.m02 - m.m20) / S;
1142  qz = (m.m10 - m.m01) / S;
1143  } else if ((m.m00 > m.m11) && (m.m00 > m.m22)) {
1144  float S = sqrtf(1.f + m.m00 - m.m11 - m.m22) * 2.f;
1145  qw = (m.m21 - m.m12) / S;
1146  qx = 0.25f * S;
1147  qy = (m.m01 + m.m10) / S;
1148  qz = (m.m02 + m.m20) / S;
1149  } else if (m.m11 > m.m22) {
1150  float S = sqrtf(1.f + m.m11 - m.m00 - m.m22) * 2.f;
1151  qw = (m.m02 - m.m20) / S;
1152  qx = (m.m01 + m.m10) / S;
1153  qy = 0.25f * S;
1154  qz = (m.m12 + m.m21) / S;
1155  } else {
1156  float S = sqrtf(1.f + m.m22 - m.m00 - m.m11) * 2.f;
1157  qw = (m.m10 - m.m01) / S;
1158  qx = (m.m02 + m.m20) / S;
1159  qy = (m.m12 + m.m21) / S;
1160  qz = 0.25f * S;
1161  }
1162 
1163  return Quaternion(qx, qy, qz, qw);
1164  }
1165 
1166  //// quaternion = [w, x, y, z]'
1167  // void mRot2Quat(const Matrix4x4 m) {
1168  // float r11 = m.m00;
1169  // float r12 = m.m01;
1170  // float r13 = m.m02;
1171  // float r21 = m.m10;
1172  // float r22 = m.m11;
1173  // float r23 = m.m12;
1174  // float r31 = m.m20;
1175  // float r32 = m.m21;
1176  // float r33 = m.m22;
1177  // float w = (r11 + r22 + r33 + 1.0f) / 4.0f;
1178  // float x = (r11 - r22 - r33 + 1.0f) / 4.0f;
1179  // float y = (-r11 + r22 - r33 + 1.0f) / 4.0f;
1180  // float z = (-r11 - r22 + r33 + 1.0f) / 4.0f;
1181  // if (w < 0.0f) {
1182  // w = 0.0f;
1183  // }
1184  // if (x < 0.0f) {
1185  // x = 0.0f;
1186  // }
1187  // if (y < 0.0f) {
1188  // y = 0.0f;
1189  // }
1190  // if (z < 0.0f) {
1191  // z = 0.0f;
1192  // }
1193  // w = sqrt(w);
1194  // x = sqrt(x);
1195  // y = sqrt(y);
1196  // z = sqrt(z);
1197  // if (w >= x && w >= y && w >= z) {
1198  // w *= +1.0f;
1199  // x *= SIGN(r32 - r23);
1200  // y *= SIGN(r13 - r31);
1201  // z *= SIGN(r21 - r12);
1202  // }
1203  // else if (x >= w && x >= y && x >= z) {
1204  // w *= SIGN(r32 - r23);
1205  // x *= +1.0f;
1206  // y *= SIGN(r21 + r12);
1207  // z *= SIGN(r13 + r31);
1208  // }
1209  // else if (y >= w && y >= x && y >= z) {
1210  // w *= SIGN(r13 - r31);
1211  // x *= SIGN(r21 + r12);
1212  // y *= +1.0f;
1213  // z *= SIGN(r32 + r23);
1214  // }
1215  // else if (z >= w && z >= x && z >= y) {
1216  // w *= SIGN(r21 - r12);
1217  // x *= SIGN(r31 + r13);
1218  // y *= SIGN(r32 + r23);
1219  // z *= +1.0f;
1220  // }
1221  // else {
1222  // //printf("coding error\n");
1223  // }
1224  // float r = NORM(w, x, w, z);
1225  // w /= r;
1226  // x /= r;
1227  // y /= r;
1228  // z /= r;
1229  //}
1230 
1231  inline static Quaternion
1232  FromToRotation(Vector3 dir0, Vector3 dir1)
1233  {
1234  Vector3 axis = dir0.Cross(dir1).Normalized();
1235  float angle = Vector3::Angle(dir0, dir1);
1236  return Quaternion::AxisAngle(axis, angle);
1237  }
1238 
1239  float x;
1240  float y;
1241  float z;
1242  float w;
1243 };
1244 
1245 // A position and rotation. You can multiply two poses; this acts like
1246 // Matrix4x4 multiplication, but Poses always have unit scale.
1247 class Pose
1248 {
1249 public:
1250  Vector3 position;
1251  Quaternion rotation;
1252 
1253  Pose(Vector3 pos)
1254  {
1255  position = pos;
1256  rotation = Quaternion::Identity();
1257  }
1258  Pose(Quaternion rot)
1259  {
1260  position = Vector3::Zero();
1261  rotation = rot;
1262  }
1263  Pose(Vector3 pos, Quaternion rot)
1264  {
1265  position = pos;
1266  rotation = rot;
1267  }
1268 
1269  inline static Pose
1270  Identity()
1271  {
1272  return Pose(Vector3::Zero(), Quaternion::Identity());
1273  }
1274 
1275  inline Pose
1276  Inverse()
1277  {
1278  Quaternion invQ = rotation.Inverse();
1279  return Pose(invQ * -position, invQ);
1280  }
1281 
1282  inline Matrix4x4
1283  Matrix()
1284  {
1285  return Matrix4x4::Translate(position) * rotation.ToMatrix4x4();
1286  }
1287 
1288  inline Pose operator*(Pose rhs)
1289  {
1290  return Pose(position + (rotation * rhs.position),
1291  rotation * rhs.rotation);
1292  }
1293 
1294  inline Pose operator*(Vector3 rhs)
1295  {
1296  return Pose(position + rotation * rhs, rotation);
1297  }
1298 
1299  inline static Pose
1300  FromMatrix(Matrix4x4 m)
1301  {
1302  return Pose(Vector3(m.m03, m.m13, m.m23),
1303  Quaternion::FromMatrix(m));
1304  }
1305 };
Definition: utility_northstar.h:801
Definition: utility_northstar.h:368
STL namespace.
Definition: utility_northstar.h:283
Definition: utility_northstar.h:779
Definition: utility_northstar.h:703
Definition: utility_northstar.h:1247
Definition: utility_northstar.h:16