Diligent Engine API Reference
BasicMath.h
1 /* Copyright 2015-2018 Egor Yusov
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
12  *
13  * In no event and under no legal theory, whether in tort (including negligence),
14  * contract, or otherwise, unless required by applicable law (such as deliberate
15  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
16  * liable for any damages, including any direct, indirect, special, incidental,
17  * or consequential damages of any character arising as a result of this License or
18  * out of the use or inability to use the software (including but not limited to damages
19  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
20  * all other commercial damages or losses), even if such Contributor has been advised
21  * of the possibility of such damages.
22  */
23 
30 
31 #pragma once
32 
33 #include "DebugUtilities.h"
34 
35 #define _USE_MATH_DEFINES
36 #include <math.h>
37 
38 #include "HashUtils.h"
39 
40 // Common Constants
41 
42 #define PI_F 3.1415927f
43 
44 // Template Vector & Matrix Classes
45 template <class T> struct Matrix4x4;
46 template <class T> struct Vector4;
47 
48 template <class T> struct Vector2
49 {
50  union
51  {
52  struct
53  {
54  T x;
55  T y;
56  };
57  struct
58  {
59  T r;
60  T g;
61  };
62  struct
63  {
64  T u;
65  T v;
66  };
67  };
68 
69 
70  Vector2 operator-(const Vector2<T> &right)const
71  {
72  return Vector2(x - right.x, y - right.y);
73  }
74 
75  Vector2& operator-=(const Vector2<T> &right)
76  {
77  x -= right.x;
78  y -= right.y;
79  return *this;
80  }
81 
82  Vector2 operator-()const
83  {
84  return Vector2(-x, -y);
85  }
86 
87  Vector2 operator+(const Vector2<T> &right)const
88  {
89  return Vector2(x + right.x, y + right.y);
90  }
91 
92  Vector2& operator+=(const Vector2<T> &right)
93  {
94  x += right.x;
95  y += right.y;
96  return *this;
97  }
98 
99  Vector2 operator*(T s)const
100  {
101  return Vector2(x * s, y * s);
102  }
103 
104  Vector2 operator*(const Vector2 &right)const
105  {
106  return Vector2(x * right.x, y * right.y);
107  }
108 
109  Vector2& operator*=( const Vector2 &right)
110  {
111  x *= right.x;
112  y *= right.y;
113  return *this;
114  }
115 
116  Vector2& operator*=( T s)
117  {
118  x *= s;
119  y *= s;
120  return *this;
121  }
122 
123  Vector2 operator/(const Vector2 &right)const
124  {
125  return Vector2(x / right.x, y / right.y);
126  }
127 
128  Vector2& operator/=( const Vector2 &right)
129  {
130  x /= right.x;
131  y /= right.y;
132  return *this;
133  }
134 
135  Vector2 operator/(T s)const
136  {
137  return Vector2(x / s, y / s);
138  }
139 
140  Vector2& operator/=( T s)
141  {
142  x /= s;
143  y /= s;
144  return *this;
145  }
146 
147  bool operator == (const Vector2 &right)const
148  {
149  return x == right.x && y == right.y;
150  }
151 
152  bool operator != (const Vector2 &right)const
153  {
154  return !(*this == right);
155  }
156 
157  Vector2 operator < ( const Vector2 &right )const
158  {
159  return Vector2(x < right.x ? static_cast<T>(1) : static_cast<T>(0),
160  y < right.y ? static_cast<T>(1) : static_cast<T>(0));
161  }
162 
163  Vector2 operator > ( const Vector2 &right )const
164  {
165  return Vector2(x > right.x ? static_cast<T>(1) : static_cast<T>(0),
166  y > right.y ? static_cast<T>(1) : static_cast<T>(0));
167  }
168 
169  Vector2 operator <= ( const Vector2 &right )const
170  {
171  return Vector2(x <= right.x ? static_cast<T>(1) : static_cast<T>(0),
172  y <= right.y ? static_cast<T>(1) : static_cast<T>(0));
173  }
174 
175  Vector2 operator >= ( const Vector2 &right )const
176  {
177  return Vector2(x >= right.x ? static_cast<T>(1) : static_cast<T>(0),
178  y >= right.y ? static_cast<T>(1) : static_cast<T>(0));
179  }
180 
181  T& operator[](size_t index)
182  {
183  return reinterpret_cast<T*>(this)[index];
184  }
185 
186  const T& operator[](size_t index)const
187  {
188  return reinterpret_cast<const T*>(this)[index];
189  }
190 
191  explicit
192  Vector2(T _x = 0, T _y = 0) : x(_x), y(_y) { }
193 };
194 
195 template <class T>
196 Vector2<T> operator*(T s, const Vector2<T> &a)
197 {
198  return a * s;
199 }
200 
201 
202 template <class T> struct Vector3
203 {
204  union
205  {
206  struct
207  {
208  T x;
209  T y;
210  T z;
211  };
212  struct
213  {
214  T r;
215  T g;
216  T b;
217  };
218  struct
219  {
220  T u;
221  T v;
222  T w;
223  };
224  };
225 
226 
227  Vector3 operator-( const Vector3 &right )const
228  {
229  return Vector3(x - right.x, y - right.y, z - right.z);
230  }
231 
232  Vector3 operator-()const
233  {
234  return Vector3(-x, -y, -z);
235  }
236 
237  Vector3& operator-=(const Vector3<T> &right)
238  {
239  x -= right.x;
240  y -= right.y;
241  z -= right.z;
242  return *this;
243  }
244 
245  Vector3 operator+( const Vector3 &right )const
246  {
247  return Vector3(x + right.x, y + right.y, z + right.z);
248  }
249 
250  Vector3& operator+=(const Vector3<T> &right)
251  {
252  x += right.x;
253  y += right.y;
254  z += right.z;
255  return *this;
256  }
257 
258  Vector3 operator*( T s )const
259  {
260  return Vector3(x * s, y * s, z * s);
261  }
262 
263  Vector3& operator*=( T s)
264  {
265  x *= s;
266  y *= s;
267  z *= s;
268  return *this;
269  }
270 
271  Vector3 operator*( const Vector3 &right )const
272  {
273  return Vector3(x * right.x, y * right.y, z * right.z);
274  }
275 
276  Vector3 operator* (const Matrix4x4<T>& m)const
277  {
278  Vector4<T> out4 = Vector4<T>(x, y, z, 1) * m;
279  return Vector3(out4.x / out4.w, out4.y / out4.w, out4.z / out4.w) ;
280  }
281 
282  Vector3& operator*=( const Vector3 &right)
283  {
284  x *= right.x;
285  y *= right.y;
286  z *= right.z;
287  return *this;
288  }
289 
290  Vector3 operator/ ( T s)const
291  {
292  return Vector3(x / s, y / s, z / s);
293  }
294 
295  Vector3& operator/=( T s)
296  {
297  x /= s;
298  y /= s;
299  z /= s;
300  return *this;
301  }
302 
303  Vector3 operator/( const Vector3 &right )const
304  {
305  return Vector3(x / right.x, y / right.y, z / right.z);
306  }
307 
308  Vector3& operator/=( const Vector3 &right)
309  {
310  x /= right.x;
311  y /= right.y;
312  z /= right.z;
313  return *this;
314  }
315 
316  bool operator == (const Vector3 &right)const
317  {
318  return x == right.x && y == right.y && z == right.z;
319  }
320 
321  bool operator != (const Vector3 &right)const
322  {
323  return !(*this == right);
324  }
325 
326  Vector3 operator < ( const Vector3 &right )const
327  {
328  return Vector3(x < right.x ? static_cast<T>(1) : static_cast<T>(0),
329  y < right.y ? static_cast<T>(1) : static_cast<T>(0),
330  z < right.z ? static_cast<T>(1) : static_cast<T>(0));
331  }
332 
333  Vector3 operator > ( const Vector3 &right )const
334  {
335  return Vector3(x > right.x ? static_cast<T>(1) : static_cast<T>(0),
336  y > right.y ? static_cast<T>(1) : static_cast<T>(0),
337  z > right.z ? static_cast<T>(1) : static_cast<T>(0));
338  }
339 
340  Vector3 operator <= ( const Vector3 &right )const
341  {
342  return Vector3(x <= right.x ? static_cast<T>(1) : static_cast<T>(0),
343  y <= right.y ? static_cast<T>(1) : static_cast<T>(0),
344  z <= right.z ? static_cast<T>(1) : static_cast<T>(0));
345  }
346 
347  Vector3 operator >= ( const Vector3 &right )const
348  {
349  return Vector3(x >= right.x ? static_cast<T>(1) : static_cast<T>(0),
350  y >= right.y ? static_cast<T>(1) : static_cast<T>(0),
351  z >= right.z ? static_cast<T>(1) : static_cast<T>(0));
352  }
353 
354  T& operator[](size_t index)
355  {
356  return reinterpret_cast<T*>(this)[index];
357  }
358 
359  const T& operator[](size_t index)const
360  {
361  return reinterpret_cast<const T*>(this)[index];
362  }
363 
364  explicit
365  Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z) { }
366 
367  operator Vector2<T>()const{return Vector2<T>(x,y);}
368 };
369 
370 template <class T>
371 Vector3<T> operator*(T s, const Vector3<T> &a)
372 {
373  return a * s;
374 }
375 
376 
377 template <class T> struct Vector4
378 {
379  union
380  {
381  struct
382  {
383  T x;
384  T y;
385  T z;
386  T w;
387  };
388  struct
389  {
390  T r;
391  T g;
392  T b;
393  T a;
394  };
395  };
396 
397  Vector4 operator-( const Vector4 &right)const
398  {
399  return Vector4(x - right.x, y - right.y, z - right.z, w - right.w);
400  }
401 
402  Vector4 operator-()const
403  {
404  return Vector4(-x, -y, -z, -w);
405  }
406 
407  Vector4& operator-=(const Vector4<T> &right)
408  {
409  x -= right.x;
410  y -= right.y;
411  z -= right.z;
412  w -= right.w;
413  return *this;
414  }
415 
416  Vector4 operator+( const Vector4 &right)const
417  {
418  return Vector4(x + right.x, y + right.y, z + right.z, w + right.w);
419  }
420 
421  Vector4& operator+=(const Vector4<T> &right)
422  {
423  x += right.x;
424  y += right.y;
425  z += right.z;
426  w += right.w;
427  return *this;
428  }
429 
430  Vector4 operator*( T s)const
431  {
432  return Vector4(x * s, y * s, z * s, w * s);
433  }
434 
435  Vector4& operator*=( T s)
436  {
437  x *= s;
438  y *= s;
439  z *= s;
440  w *= s;
441  return *this;
442  }
443 
444  Vector4 operator*( const Vector4 &right)const
445  {
446  return Vector4(x * right.x, y * right.y, z * right.z, w * right.w);
447  }
448 
449  Vector4& operator*=( const Vector4 &right)
450  {
451  x *= right.x;
452  y *= right.y;
453  z *= right.z;
454  w *= right.w;
455  return *this;
456  }
457 
458  Vector4 operator/( T s)const
459  {
460  return Vector4(x / s, y / s, z / s, w / s);
461  }
462 
463  Vector4& operator/=( T s)
464  {
465  x /= s;
466  y /= s;
467  z /= s;
468  w /= s;
469  return *this;
470  }
471 
472  Vector4 operator/( const Vector4 &right)const
473  {
474  return Vector4(x / right.x, y / right.y, z / right.z, w / right.w);
475  }
476 
477  Vector4& operator/=( const Vector4 &right)
478  {
479  x /= right.x;
480  y /= right.y;
481  z /= right.z;
482  w /= right.w;
483  return *this;
484  }
485 
486  bool operator == (const Vector4 &right)const
487  {
488  return x == right.x && y == right.y && z == right.z && w == right.w;
489  }
490 
491  bool operator != (const Vector4 &right)const
492  {
493  return !(*this == right);
494  }
495 
496  Vector4 operator*(const Matrix4x4<T>& m)const
497  {
498  Vector4 out;
499  out[0] = x * m[0][0] + y * m[1][0] + z * m[2][0] + w * m[3][0];
500  out[1] = x * m[0][1] + y * m[1][1] + z * m[2][1] + w * m[3][1];
501  out[2] = x * m[0][2] + y * m[1][2] + z * m[2][2] + w * m[3][2];
502  out[3] = x * m[0][3] + y * m[1][3] + z * m[2][3] + w * m[3][3];
503  return out;
504  }
505 
506  Vector4& operator = (const Vector3<T> &v3)
507  {
508  x = v3.x;
509  y = v3.y;
510  z = v3.z;
511  w = 1;
512  return *this;
513  }
514  Vector4& operator = (const Vector4 &) = default;
515 
516  Vector4 operator < ( const Vector4 &right )const
517  {
518  return Vector4(x < right.x ? static_cast<T>(1) : static_cast<T>(0),
519  y < right.y ? static_cast<T>(1) : static_cast<T>(0),
520  z < right.z ? static_cast<T>(1) : static_cast<T>(0),
521  w < right.w ? static_cast<T>(1) : static_cast<T>(0));
522  }
523 
524  Vector4 operator > ( const Vector4 &right )const
525  {
526  return Vector4(x > right.x ? static_cast<T>(1) : static_cast<T>(0),
527  y > right.y ? static_cast<T>(1) : static_cast<T>(0),
528  z > right.z ? static_cast<T>(1) : static_cast<T>(0),
529  w > right.w ? static_cast<T>(1) : static_cast<T>(0));
530  }
531 
532  Vector4 operator <= ( const Vector4 &right )const
533  {
534  return Vector4(x <= right.x ? static_cast<T>(1) : static_cast<T>(0),
535  y <= right.y ? static_cast<T>(1) : static_cast<T>(0),
536  z <= right.z ? static_cast<T>(1) : static_cast<T>(0),
537  w <= right.w ? static_cast<T>(1) : static_cast<T>(0));
538  }
539 
540  Vector4 operator >= ( const Vector4 &right )const
541  {
542  return Vector4(x >= right.x ? static_cast<T>(1) : static_cast<T>(0),
543  y >= right.y ? static_cast<T>(1) : static_cast<T>(0),
544  z >= right.z ? static_cast<T>(1) : static_cast<T>(0),
545  w >= right.w ? static_cast<T>(1) : static_cast<T>(0));
546  }
547 
548  T& operator[](size_t index)
549  {
550  return reinterpret_cast<T*>(this)[index];
551  }
552 
553  const T& operator[](size_t index)const
554  {
555  return reinterpret_cast<const T*>(this)[index];
556  }
557 
558  explicit
559  Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) : x(_x), y(_y), z(_z), w(_w) { }
560 };
561 
562 
563 template <class T>
564 Vector4<T> operator*(T s, const Vector4<T> &a)
565 {
566  return a * s;
567 }
568 
569 template <class T> struct Matrix3x3
570 {
571  union
572  {
573  struct
574  {
575  T _11; T _12; T _13;
576  T _21; T _22; T _23;
577  T _31; T _32; T _33;
578  };
579  struct
580  {
581  T _m00; T _m01; T _m02;
582  T _m10; T _m11; T _m12;
583  T _m20; T _m21; T _m22;
584  };
585  };
586 
587  explicit
588  Matrix3x3(T value = 0)
589  {
590  _11 = _12 = _13 =value;
591  _21 = _22 = _23 =value;
592  _31 = _32 = _33 =value;
593  }
594 
595  explicit
596  Matrix3x3(
597  T i11, T i12, T i13,
598  T i21, T i22, T i23,
599  T i31, T i32, T i33 )
600  {
601  _11 = i11; _12 = i12; _13 = i13;
602  _21 = i21; _22 = i22; _23 = i23;
603  _31 = i31; _32 = i32; _33 = i33;
604  }
605 
606  bool operator == (const Matrix3x3 &r)const
607  {
608  for( int i = 0; i < 3; ++i )
609  for( int j = 0; i < 3; ++i )
610  if( (*this)[i][j] != r[i][j] )
611  return false;
612 
613  return true;
614  }
615 
616  bool operator != (const Matrix3x3 &r)const
617  {
618  return !(*this == r);
619  }
620 
621  T* operator[](size_t index)
622  {
623  return &(reinterpret_cast<T*>(this)[index*3]);
624  }
625 
626  const T* operator[](size_t index)const
627  {
628  return &(reinterpret_cast<const T*>(this)[index*3]);
629  }
630 
631  Matrix3x3& operator *=(T s)
632  {
633  for( int i = 0; i < 9; ++i )
634  (reinterpret_cast<T*>(this))[i] *= s;
635 
636  return *this;
637  }
638 };
639 
640 template <class T> struct Matrix4x4
641 {
642  union
643  {
644  struct
645  {
646  T _11; T _12; T _13; T _14;
647  T _21; T _22; T _23; T _24;
648  T _31; T _32; T _33; T _34;
649  T _41; T _42; T _43; T _44;
650  };
651  struct
652  {
653  T _m00; T _m01; T _m02; T _m03;
654  T _m10; T _m11; T _m12; T _m13;
655  T _m20; T _m21; T _m22; T _m23;
656  T _m30; T _m31; T _m32; T _m33;
657  };
658  };
659 
660  explicit
661  Matrix4x4(T value = 0)
662  {
663  _11 = _12 = _13 = _14 = value;
664  _21 = _22 = _23 = _24 = value;
665  _31 = _32 = _33 = _34 = value;
666  _41 = _42 = _43 = _44 = value;
667  }
668 
669  explicit
670  Matrix4x4(
671  T i11, T i12, T i13, T i14,
672  T i21, T i22, T i23, T i24,
673  T i31, T i32, T i33, T i34,
674  T i41, T i42, T i43, T i44
675  )
676  {
677  _11 = i11; _12 = i12; _13 = i13; _14 = i14;
678  _21 = i21; _22 = i22; _23 = i23; _24 = i24;
679  _31 = i31; _32 = i32; _33 = i33; _34 = i34;
680  _41 = i41; _42 = i42; _43 = i43; _44 = i44;
681  }
682 
683  bool operator == (const Matrix4x4 &r)const
684  {
685  for( int i = 0; i < 4; ++i )
686  for( int j = 0; i < 4; ++i )
687  if( (*this)[i][j] != r[i][j] )
688  return false;
689 
690  return true;
691  }
692 
693  bool operator != (const Matrix4x4 &r)const
694  {
695  return !(*this == r);
696  }
697 
698  T* operator[](size_t index)
699  {
700  return &(reinterpret_cast<T*>(this)[index*4]);
701  }
702 
703  const T* operator[](size_t index)const
704  {
705  return &(reinterpret_cast<const T*>(this)[index*4]);
706  }
707 
708  Matrix4x4& operator *=(T s)
709  {
710  for( int i = 0; i < 16; ++i )
711  (reinterpret_cast<T*>(this))[i] *= s;
712 
713  return *this;
714  }
715 };
716 
717 // Template Vector Operations
718 
719 
720 template <class T>
721 T dot(const Vector2<T> &a, const Vector2<T> &b)
722 {
723  return a.x * b.x + a.y * b.y;
724 }
725 
726 template <class T>
727 T dot(const Vector3<T> &a, const Vector3<T> &b)
728 {
729  return a.x * b.x + a.y * b.y + a.z * b.z;
730 }
731 
732 template <class T>
733 T dot(const Vector4<T> &a, const Vector4<T> &b)
734 {
735  return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
736 }
737 
738 template <class VectorType>
739 auto length(const VectorType &a)->decltype(dot(a,a))
740 {
741  return sqrt( dot(a,a) );
742 }
743 
744 
745 template <class T>
746 Vector3<T> min(const Vector3<T> &a, const Vector3<T> &b)
747 {
748  return Vector3<T>( std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z) );
749 }
750 
751 template <class T>
752 Vector4<T> min(const Vector4<T> &a, const Vector4<T> &b)
753 {
754  return Vector4<T>( std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z), std::min(a.w, b.w) );
755 }
756 
757 template <class T>
758 Vector3<T> max(const Vector3<T> &a, const Vector3<T> &b)
759 {
760  return Vector3<T>( std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z) );
761 }
762 
763 template <class T>
764 Vector4<T> max(const Vector4<T> &a, const Vector4<T> &b)
765 {
766  return Vector4<T>( std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z), std::max(a.w, b.w) );
767 }
768 
769 template <class T>
770 Vector2<T> abs(const Vector2<T> &a)
771 {
772  // WARNING: abs() on gcc is for integers only!
773  return Vector2<T>( a.x < 0 ? -a.x : a.x,
774  a.y < 0 ? -a.y : a.y);
775 }
776 
777 template <class T>
778 Vector3<T> abs(const Vector3<T> &a)
779 {
780  // WARNING: abs() on gcc is for integers only!
781  return Vector3<T>( a.x < 0 ? -a.x : a.x,
782  a.y < 0 ? -a.y : a.y,
783  a.z < 0 ? -a.z : a.z);
784 }
785 
786 template <class T>
787 Vector4<T> abs(const Vector4<T> &a)
788 {
789  // WARNING: abs() on gcc is for integers only!
790  return Vector4<T>( a.x < 0 ? -a.x : a.x,
791  a.y < 0 ? -a.y : a.y,
792  a.z < 0 ? -a.z : a.z,
793  a.w < 0 ? -a.w : a.w);
794 }
795 
796 
797 template <class T>
798 Vector3<T> cross(const Vector3<T> &a, const Vector3<T> &b)
799 {
800  // | i j k |
801  // | a.x a.y a.z |
802  // | b.x b.y b.z |
803  return Vector3<T>((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x));
804 }
805 
806 template <class VectorType>
807 VectorType normalize(const VectorType &a)
808 {
809  auto len = length(a);
810  return a / len;
811 }
812 
813 
814 // Template Matrix Operations
815 
816 template <class T>
817 Matrix4x4<T> transposeMatrix(const Matrix4x4<T> &m)
818 {
819  return Matrix4x4<T>(
820  m._11, m._21, m._31, m._41,
821  m._12, m._22, m._32, m._42,
822  m._13, m._23, m._33, m._43,
823  m._14, m._24, m._34, m._44
824  );
825 }
826 
827 template <class T>
828 Matrix4x4<T> mul(const Matrix4x4<T> &m1, const Matrix4x4<T> &m2)
829 {
830  Matrix4x4<T> mOut;
831 
832  for (int i = 0; i < 4; i++)
833  {
834  for (int j = 0; j < 4; j++)
835  {
836  for (int k = 0; k < 4; k++)
837  {
838  mOut[i][j] += m1[i][k] * m2[k][j];
839  }
840  }
841  }
842 
843  return mOut;
844 }
845 
846 template <class T>
847 Matrix4x4<T> operator* (const Matrix4x4<T> &m1, const Matrix4x4<T> &m2)
848 {
849  return mul( m1, m2 );
850 }
851 
852 
853 
854 template <class T>
855 Matrix3x3<T> transposeMatrix(const Matrix3x3<T> &m)
856 {
857  return Matrix3x3<T>(
858  m._11, m._21, m._31,
859  m._12, m._22, m._32,
860  m._13, m._23, m._33
861  );
862 }
863 
864 template <class T>
865 Matrix3x3<T> mul(const Matrix3x3<T> &m1, const Matrix3x3<T> &m2)
866 {
867  Matrix3x3<T> mOut;
868 
869  for (int i = 0; i < 3; i++)
870  {
871  for (int j = 0; j < 3; j++)
872  {
873  for (int k = 0; k < 3; k++)
874  {
875  mOut[i][j] += m1[i][k] * m2[k][j];
876  }
877  }
878  }
879 
880  return mOut;
881 }
882 
883 template <class T>
884 Matrix3x3<T> operator* (const Matrix3x3<T> &m1, const Matrix3x3<T> &m2)
885 {
886  return mul( m1, m2 );
887 }
888 
889 // Common HLSL-compatible vector typedefs
890 
891 typedef unsigned int uint;
892 
893 typedef Vector2<float> float2;
894 typedef Vector3<float> float3;
895 typedef Vector4<float> float4;
896 
897 typedef Matrix4x4<float> float4x4;
898 typedef Matrix3x3<float> float3x3;
899 
900 // Standard Matrix Intializers
901 
902 inline float4x4 identityMatrix()
903 {
904  return float4x4(1, 0, 0, 0,
905  0, 1, 0, 0,
906  0, 0, 1, 0,
907  0, 0, 0, 1);
908 }
909 
910 inline float4x4 translationMatrix(float x, float y, float z)
911 {
912  return float4x4 (1, 0, 0, 0,
913  0, 1, 0, 0,
914  0, 0, 1, 0,
915  x, y, z, 1);
916 }
917 
918 inline float4x4 translationMatrix( const float3 &v )
919 {
920  return translationMatrix( v.x, v.y, v.z );
921 }
922 
923 
924 inline float4x4 scaleMatrix(float x, float y, float z)
925 {
926  return float4x4(x, 0, 0, 0,
927  0, y, 0, 0,
928  0, 0, z, 0,
929  0, 0, 0, 1);
930 }
931 
932 inline float4x4 rotationX(float angleInRadians)
933 {
934  float sinAngle = sinf(angleInRadians);
935  float cosAngle = cosf(angleInRadians);
936 
937  float4x4 mOut;
938 
939  mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f;
940  mOut._21 = 0.0f; mOut._22 = cosAngle; mOut._23 = -sinAngle; mOut._24 = 0.0f;
941  mOut._31 = 0.0f; mOut._32 = sinAngle; mOut._33 = cosAngle; mOut._34 = 0.0f;
942  mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
943 
944  return mOut;
945 }
946 
947 inline float4x4 rotationY(float angleInRadians)
948 {
949  float sinAngle = sinf(angleInRadians);
950  float cosAngle = cosf(angleInRadians);
951 
952  float4x4 mOut;
953 
954  mOut._11 = cosAngle; mOut._12 = 0.0f; mOut._13 = sinAngle; mOut._14 = 0.0f;
955  mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f;
956  mOut._31 = -sinAngle; mOut._32 = 0.0f; mOut._33 = cosAngle; mOut._34 = 0.0f;
957  mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
958 
959  return mOut;
960 }
961 
962 inline float4x4 rotationZ(float angleInRadians)
963 {
964  float sinAngle = sinf(angleInRadians);
965  float cosAngle = cosf(angleInRadians);
966 
967  float4x4 mOut;
968 
969  mOut._11 = cosAngle; mOut._12 = -sinAngle; mOut._13 = 0.0f; mOut._14 = 0.0f;
970  mOut._21 = sinAngle; mOut._22 = cosAngle; mOut._23 = 0.0f; mOut._24 = 0.0f;
971  mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f;
972  mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f;
973 
974  return mOut;
975 }
976 
977 // 3D Rotation matrix for an arbitrary axis specified by x, y and z
978 inline float4x4 rotationArbitrary(float3 axis, float degree)
979 {
980  UNSUPPORTED("This function is not tested, it might be incorrect");
981 
982  axis = normalize(axis);
983 
984  float angleInRadians = degree * (PI_F / 180.0f);
985 
986  float sinAngle = sinf(angleInRadians);
987  float cosAngle = cosf(angleInRadians);
988  float oneMinusCosAngle = 1 - cosAngle;
989 
990  float4x4 mOut;
991 
992  mOut._11 = 1.0f + oneMinusCosAngle * (axis.x * axis.x - 1.0f);
993  mOut._12 = axis.z * sinAngle + oneMinusCosAngle * axis.x * axis.y;
994  mOut._13 = -axis.y * sinAngle + oneMinusCosAngle * axis.x * axis.z;
995  mOut._41 = 0.0f;
996 
997  mOut._21 = -axis.z * sinAngle + oneMinusCosAngle * axis.y * axis.x;
998  mOut._22 = 1.0f + oneMinusCosAngle * (axis.y * axis.y - 1.0f);
999  mOut._23 = axis.x * sinAngle + oneMinusCosAngle * axis.y * axis.z;
1000  mOut._24 = 0.0f;
1001 
1002  mOut._31 = axis.y * sinAngle + oneMinusCosAngle * axis.z * axis.x;
1003  mOut._32 = -axis.x * sinAngle + oneMinusCosAngle * axis.z * axis.y;
1004  mOut._33 = 1.0f + oneMinusCosAngle * (axis.z * axis.z - 1.0f);
1005  mOut._34 = 0.0f;
1006 
1007  mOut._41 = 0.0f;
1008  mOut._42 = 0.0f;
1009  mOut._43 = 0.0f;
1010  mOut._44 = 1.0f;
1011 
1012  return mOut;
1013 }
1014 
1015 inline float4x4 ViewMatrixFromBasis( const float3 &f3X, const float3 &f3Y, const float3 &f3Z )
1016 {
1017  return float4x4( f3X.x, f3Y.x, f3Z.x, 0,
1018  f3X.y, f3Y.y, f3Z.y, 0,
1019  f3X.z, f3Y.z, f3Z.z, 0,
1020  0, 0, 0, 1);
1021 }
1022 
1023 inline void SetNearFarClipPlanes( float4x4 &ProjMatrix, float zNear, float zFar, bool bIsDirectX )
1024 {
1025  if( bIsDirectX )
1026  {
1027  ProjMatrix._33 = zFar / (zFar - zNear);
1028  ProjMatrix._43 = -zNear * zFar / (zFar - zNear);
1029  ProjMatrix._34 = 1;
1030  }
1031  else
1032  {
1033  // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
1034  // http://www.terathon.com/gdc07_lengyel.pdf
1035  // Note that OpenGL uses right-handed coordinate system, where
1036  // camera is looking in negative z direction:
1037  // OO
1038  // |__|<--------------------
1039  // -z +z
1040  // Consequently, OpenGL projection matrix given by these two
1041  // references inverts z axis.
1042 
1043  // We do not need to do this, because we use DX coordinate
1044  // system for the camera space. Thus we need to invert the
1045  // sign of the values in the third column in the matrix
1046  // from the references:
1047 
1048  ProjMatrix._33 = -(-(zFar + zNear) / (zFar - zNear));
1049  ProjMatrix._43 = -2.0f * zNear * zFar / (zFar - zNear);
1050  ProjMatrix._34 = -(-1);
1051  }
1052 }
1053 
1054 inline void GetNearFarPlaneFromProjMatrix( const float4x4 &ProjMatrix, float &zNear, float &zFar, bool bIsDirectX )
1055 {
1056  if( bIsDirectX )
1057  {
1058  zNear = -ProjMatrix._43 / ProjMatrix._33;
1059  zFar = ProjMatrix._33 / (ProjMatrix._33 - 1) * zNear;
1060  }
1061  else
1062  {
1063  zNear = ProjMatrix._43 / (-1.f - ProjMatrix._33);
1064  zFar = ProjMatrix._43 / (+1.f - ProjMatrix._33);
1065  }
1066 }
1067 
1068 inline float4x4 Projection(float fov, float aspectRatio, float zNear, float zFar, bool bIsDirectX) // Left-handed projection
1069 {
1070  float4x4 mOut;
1071  float yScale = 1.0f / tan(fov / 2.0f);
1072  float xScale = yScale / aspectRatio;
1073  mOut._11 = xScale;
1074  mOut._22 = yScale;
1075 
1076  SetNearFarClipPlanes( mOut, zNear, zFar, bIsDirectX );
1077 
1078  return mOut;
1079 }
1080 
1081 
1082 struct Quaternion
1083 {
1084  float q[4];
1085 };
1086 
1087 inline Quaternion RotationFromAxisAngle(const float3& axis, float angle)
1088 {
1089  Quaternion out;
1090  float norm = length(axis);
1091  float sina2 = sin(0.5f * angle);
1092  out.q[0] = sina2 * axis[0] / norm;
1093  out.q[1] = sina2 * axis[1] / norm;
1094  out.q[2] = sina2 * axis[2] / norm;
1095  out.q[3] = cos(0.5f * angle);
1096  return out;
1097 }
1098 
1099 inline void AxisAngleFromRotation(float3& outAxis, float& outAngle, const Quaternion& quat)
1100 {
1101  float sina2 = sqrt(quat.q[0]*quat.q[0] + quat.q[1]*quat.q[1] + quat.q[2]*quat.q[2]);
1102  outAngle = 2.0f * atan2(sina2, quat.q[3]);
1103  float r = (sina2 > 0) ? (1.0f / sina2) : 0;
1104  outAxis[0] = r * quat.q[0];
1105  outAxis[1] = r * quat.q[1];
1106  outAxis[2] = r * quat.q[2];
1107 }
1108 
1109 inline float4x4 QuaternionToMatrix(const Quaternion& quat)
1110 {
1111  float4x4 out;
1112  float yy2 = 2.0f * quat.q[1] * quat.q[1];
1113  float xy2 = 2.0f * quat.q[0] * quat.q[1];
1114  float xz2 = 2.0f * quat.q[0] * quat.q[2];
1115  float yz2 = 2.0f * quat.q[1] * quat.q[2];
1116  float zz2 = 2.0f * quat.q[2] * quat.q[2];
1117  float wz2 = 2.0f * quat.q[3] * quat.q[2];
1118  float wy2 = 2.0f * quat.q[3] * quat.q[1];
1119  float wx2 = 2.0f * quat.q[3] * quat.q[0];
1120  float xx2 = 2.0f * quat.q[0] * quat.q[0];
1121  out[0][0] = - yy2 - zz2 + 1.0f;
1122  out[0][1] = xy2 + wz2;
1123  out[0][2] = xz2 - wy2;
1124  out[0][3] = 0;
1125  out[1][0] = xy2 - wz2;
1126  out[1][1] = - xx2 - zz2 + 1.0f;
1127  out[1][2] = yz2 + wx2;
1128  out[1][3] = 0;
1129  out[2][0] = xz2 + wy2;
1130  out[2][1] = yz2 - wx2;
1131  out[2][2] = - xx2 - yy2 + 1.0f;
1132  out[2][3] = 0;
1133  out[3][0] = out[3][1] = out[3][2] = 0;
1134  out[3][3] = 1;
1135  return out;
1136 }
1137 
1138 inline float determinant( const float3x3& m )
1139 {
1140  float det = 0.f;
1141  det += m._11 * (m._22*m._33 - m._32*m._23);
1142  det -= m._12 * (m._21*m._33 - m._31*m._23);
1143  det += m._13 * (m._21*m._32 - m._31*m._22);
1144  return det;
1145 }
1146 
1147 
1148 inline float determinant( const float4x4& m )
1149 {
1150  float det = 0.f;
1151 
1152  det += m._11 * determinant(
1153  float3x3 ( m._22,m._23,m._24,
1154  m._32,m._33,m._34,
1155  m._42,m._43,m._44) );
1156 
1157  det -= m._12 * determinant(
1158  float3x3( m._21,m._23,m._24,
1159  m._31,m._33,m._34,
1160  m._41,m._43,m._44) );
1161 
1162  det += m._13 * determinant(
1163  float3x3( m._21,m._22,m._24,
1164  m._31,m._32,m._34,
1165  m._41,m._42,m._44) );
1166 
1167  det -= m._14 * determinant(
1168  float3x3( m._21,m._22,m._23,
1169  m._31,m._32,m._33,
1170  m._41,m._42,m._43) );
1171 
1172  return det;
1173 }
1174 
1175 inline float4x4 inverseMatrix(const float4x4& m)
1176 {
1177  float4x4 inv;
1178 
1179  // row 1
1180  inv._11 = determinant(
1181  float3x3( m._22, m._23, m._24,
1182  m._32, m._33, m._34,
1183  m._42, m._43, m._44 ) );
1184 
1185  inv._12 = -determinant(
1186  float3x3( m._21, m._23, m._24,
1187  m._31, m._33, m._34,
1188  m._41, m._43, m._44) );
1189 
1190  inv._13 = determinant(
1191  float3x3 ( m._21, m._22, m._24,
1192  m._31, m._32, m._34,
1193  m._41, m._42, m._44) );
1194 
1195  inv._14 = -determinant(
1196  float3x3 ( m._21, m._22, m._23,
1197  m._31, m._32, m._33,
1198  m._41, m._42, m._43) );
1199 
1200 
1201  // row 2
1202  inv._21 = -determinant(
1203  float3x3( m._12, m._13, m._14,
1204  m._32, m._33, m._34,
1205  m._42, m._43, m._44) );
1206 
1207  inv._22 = determinant(
1208  float3x3( m._11, m._13, m._14,
1209  m._31, m._33, m._34,
1210  m._41, m._43, m._44) );
1211 
1212  inv._23 = -determinant(
1213  float3x3( m._11, m._12, m._14,
1214  m._31, m._32, m._34,
1215  m._41, m._42, m._44) );
1216 
1217  inv._24 = determinant(
1218  float3x3( m._11, m._12, m._13,
1219  m._31, m._32, m._33,
1220  m._41, m._42, m._43) );
1221 
1222 
1223  // row 3
1224  inv._31 = determinant(
1225  float3x3( m._12,m._13,m._14,
1226  m._22,m._23,m._24,
1227  m._42,m._43,m._44) );
1228 
1229  inv._32 = -determinant(
1230  float3x3( m._11,m._13,m._14,
1231  m._21,m._23,m._24,
1232  m._41,m._43,m._44) );
1233 
1234  inv._33 = determinant(
1235  float3x3( m._11,m._12,m._14,
1236  m._21,m._22,m._24,
1237  m._41,m._42,m._44) );
1238 
1239  inv._34 = -determinant(
1240  float3x3( m._11,m._12,m._13,
1241  m._21,m._22,m._23,
1242  m._41,m._42,m._43) );
1243 
1244  // row 4
1245  inv._41 = -determinant(
1246  float3x3( m._12, m._13, m._14,
1247  m._22, m._23, m._24,
1248  m._32, m._33, m._34) );
1249 
1250  inv._42 = determinant(
1251  float3x3( m._11, m._13, m._14,
1252  m._21, m._23, m._24,
1253  m._31, m._33, m._34) );
1254 
1255  inv._43 = -determinant(
1256  float3x3( m._11, m._12, m._14,
1257  m._21, m._22, m._24,
1258  m._31, m._32, m._34) );
1259 
1260  inv._44 = determinant(
1261  float3x3( m._11, m._12, m._13,
1262  m._21, m._22, m._23,
1263  m._31, m._32, m._33) );
1264 
1265  auto det = m._11 * inv._11 + m._12 * inv._12 + m._13 * inv._13 + m._14 * inv._14;
1266  inv = transposeMatrix(inv);
1267  inv *= 1.0f/det;
1268 
1269  return inv;
1270 }
1271 
1272 namespace std
1273 {
1274  template<typename T>
1275  Vector2<T> max( const Vector2<T> &Left, const Vector2<T> &Right )
1276  {
1277  return Vector2<T>(
1278  std::max( Left.x, Right.x ),
1279  std::max( Left.y, Right.y )
1280  );
1281  }
1282 
1283  template<typename T>
1284  Vector3<T> max( const Vector3<T> &Left, const Vector3<T> &Right )
1285  {
1286  return Vector3<T>(
1287  std::max( Left.x, Right.x ),
1288  std::max( Left.y, Right.y ),
1289  std::max( Left.z, Right.z )
1290  );
1291  }
1292 
1293  template<typename T>
1294  Vector4<T> max( const Vector4<T> &Left, const Vector4<T> &Right )
1295  {
1296  return Vector4<T>(
1297  std::max( Left.x, Right.x ),
1298  std::max( Left.y, Right.y ),
1299  std::max( Left.z, Right.z ),
1300  std::max( Left.w, Right.w )
1301  );
1302  }
1303 
1304 
1305  template<typename T>
1306  Vector2<T> min( const Vector2<T> &Left, const Vector2<T> &Right )
1307  {
1308  return Vector2<T>(
1309  std::min( Left.x, Right.x ),
1310  std::min( Left.y, Right.y )
1311  );
1312  }
1313 
1314  template<typename T>
1315  Vector3<T> min( const Vector3<T> &Left, const Vector3<T> &Right )
1316  {
1317  return Vector3<T>(
1318  std::min( Left.x, Right.x ),
1319  std::min( Left.y, Right.y ),
1320  std::min( Left.z, Right.z )
1321  );
1322  }
1323 
1324  template<typename T>
1325  Vector4<T> min( const Vector4<T> &Left, const Vector4<T> &Right )
1326  {
1327  return Vector4<T>(
1328  std::min( Left.x, Right.x ),
1329  std::min( Left.y, Right.y ),
1330  std::min( Left.z, Right.z ),
1331  std::min( Left.w, Right.w )
1332  );
1333  }
1334 
1335 
1336  template<typename T>
1337  struct hash<Vector2<T>>
1338  {
1339  size_t operator()( const Vector2<T> &v2 ) const
1340  {
1341  return Diligent::ComputeHash(v2.x, v2.y);
1342  }
1343  };
1344 
1345  template<typename T>
1346  struct hash<Vector3<T>>
1347  {
1348  size_t operator()( const Vector3<T> &v3 ) const
1349  {
1350  return Diligent::ComputeHash(v3.x, v3.y, v3.z);
1351  }
1352  };
1353 
1354  template<typename T>
1355  struct hash<Vector4<T>>
1356  {
1357  size_t operator()( const Vector4<T> &v4 ) const
1358  {
1359  return Diligent::ComputeHash(v4.x, v4.y, v4.z, v4.w);
1360  }
1361  };
1362 
1363  template<typename T>
1364  struct hash<Matrix3x3<T>>
1365  {
1366  size_t operator()( const Matrix3x3<T> &m ) const
1367  {
1368  return Diligent::ComputeHash(
1369  m._m00, m._m01, m._m02,
1370  m._m10, m._m11, m._m12,
1371  m._m20, m._m21, m._m22
1372  );
1373  }
1374  };
1375 
1376  template<typename T>
1377  struct hash<Matrix4x4<T>>
1378  {
1379  size_t operator()( const Matrix4x4<T> &m ) const
1380  {
1381  return Diligent::ComputeHash(
1382  m._m00, m._m01, m._m02, m._m03,
1383  m._m10, m._m11, m._m12, m._m13,
1384  m._m20, m._m21, m._m22, m._m23,
1385  m._m30, m._m31, m._m32, m._m33
1386  );
1387  }
1388  };
1389 }
Definition: AdvancedMath.h:316