TurtleBrains  0.3.5
High quality, portable, C++ framework for rapid 2D game development.
tb_vector.hpp
1 
9 #ifndef TurtleBrains_Vector_hpp
10 #define TurtleBrains_Vector_hpp
11 
12 #include <turtle_brains/core/tb_configuration.hpp>
13 #include <turtle_brains/core/tb_error.hpp>
14 #include <turtle_brains/core/tb_defines.hpp>
15 #include <turtle_brains/math/tb_math.hpp>
16 #include <turtle_brains/math/tb_angle.hpp>
17 #include <turtle_brains/core/tb_string.hpp>
18 
19 #include <iostream>
20 
21 // 2024-10-30: In July 2022 CyanPhoton exploded my mind with the following visualization technique of cross products. They
22 // can be visualized by taking the left-side parameter and drawing an arc to the right-side parameter using the
23 // smallest angle between. So axis, X and Y and getting cross(X, Y) would draw the arc in the 90 degree region rather
24 // than 270 degrees. This would cause (assuming X is right, and Y is up) a counter-clockwise arc from X to Y. Imagine
25 // a (REGULAR/CW TIGHTENING) screw and twist in the direction of the arc, in this case it would loosen and pull out of
26 // the plane. This is the direction the cross product will point, and give us the Z axis in a Right-Handed System.
27 //
28 // Note: For a left handed system you turn the imaginary screw the other direction so Z would go into the plane).
29 
30 namespace TurtleBrains
31 {
32  namespace Math
33  {
34  // 2024-12-05: TODO: TurtleBrains: Math: API-BREAK: We need to support tbMath::Vector3 and ice::Vector3 being
35  // different even if iceScalar became float in the future. We also need the Vector3 operator that casts from
36  // Scalar<float> to Scalar<double> etc to be EXPLICIT. I can see we made it implicit because of the amount of
37  // conversions, but I've found physics code that dropped precision because of this implicit behavior. Must avoid.
38  //
39  // While digging through this non-sense we should also add a typedef float Scalar; for TurtleBrains which of
40  // course breaks projects that use "Scalar" specifically for iceScalar... ugh. Past Tim didn't feel TurtleBrains
41  // needed a Scalar since it would ALWAYS be float (for graphics), unlike physics which might change float/double
42  // etc... Current Tim thinks it is odd that ONLY Scalar is different between the two. Renaming the Type in all
43  // the math TypedThing<Type> to ScalarType would be a great idea as well since it specifies what it is.
44  //
45  // ikiwixz suggests making the Scalar<typename Tag> for the strong typed, which would mean tbScalar and iceScalar
46  // would be different even when both are floats, desired! That would also mean TypedVector3<tbScalar> would
47  // automatically be different from TypedVector3<iceScalar> ... this would require coming up with a TypedScalar<>
48 
49  //Forward Declarations used in Vector classes.
50  //template<typename ScalarType> class TypedVector2;
51  //template<typename ScalarType> class TypedVector3;
52  //template<typename ScalarType> class TypedVector4;
53 
54  template<typename Type> class TypedVector2;
55  template<typename Type> class TypedVector3;
56  template<typename Type> class TypedVector4;
57 
58  template<typename Type> Type Vector2DotProduct(const TypedVector2<Type>* leftSide, const TypedVector2<Type>* rightSide);
59  template<typename Type> Type Vector3DotProduct(const TypedVector3<Type>* leftSide, const TypedVector3<Type>* rightSide);
60  template<typename Type> Type Vector4DotProduct(const TypedVector4<Type>* leftSide, const TypedVector4<Type>* rightSide);
61  template<typename Type> TypedVector3<Type>* Vector3CrossProduct(TypedVector3<Type>* result, const TypedVector3<Type>* leftSide,
62  const TypedVector3<Type>* rightSide);
63 
64  template<typename Type> TypedVector2<Type>* Vector2Normalize(TypedVector2<Type>* result, const TypedVector2<Type>* value);
65  template<typename Type> TypedVector3<Type>* Vector3Normalize(TypedVector3<Type>* result, const TypedVector3<Type>* value);
66  template<typename Type> TypedVector4<Type>* Vector4Normalize(TypedVector4<Type>* result, const TypedVector4<Type>* value);
67 
68  template<typename Type> TypedVector2<Type>* Vector2NormalizeMagnitude(TypedVector2<Type>* result, const TypedVector2<Type>* value, Type& magnitude);
69  template<typename Type> TypedVector3<Type>* Vector3NormalizeMagnitude(TypedVector3<Type>* result, const TypedVector3<Type>* value, Type& magnitude);
70  template<typename Type> TypedVector4<Type>* Vector4NormalizeMagnitude(TypedVector4<Type>* result, const TypedVector4<Type>* value, Type& magnitude);
71 
80  enum SkipInitialization { kSkipInitialization = 0, };
81 
87  {
92  };
93 
98  template<typename Type> class TypedVector2
99  {
100  public:
104  static TypedVector2 Zero(void) { return TypedVector2(Type(0), Type(0)); }
105 
109  static TypedVector2 One(void) { return TypedVector2(Type(1), Type(1)); }
110 
111  static TypedVector2 Right(void) { return TypedVector2(Type(1), Type(0)); }
112  static TypedVector2 Left(void) { return -Right(); }
113  static TypedVector2 Up(void) { return TypedVector2(Type(0), Type(1)); }
114  static TypedVector2 Down(void) { return -Up(); }
115 
116  union
117  {
118  Type mComponents[2];
119 
120 #if defined(tb_visual_cpp)
121 #pragma warning(push)
122 #pragma warning(disable: 4201)
123  struct { Type x, y; };
124 #pragma warning(pop)
125 #else
126  struct { Type x, y; };
127 #endif
128  };
129 
136  inline explicit TypedVector2(const SkipInitialization& fastAndStupid)
137  {
138  tb_unused(fastAndStupid);
139  }
140 
144  inline TypedVector2(void) :
145  x(Type(0)),
146  y(Type(0))
147  {
148  }
149 
156  inline TypedVector2(const Type valueX, const Type valueY) :
157  x(valueX),
158  y(valueY)
159  {
160  }
161 
167  inline explicit TypedVector2(const Type* componentArray) :
168  x(componentArray[0]),
169  y(componentArray[1])
170  {
171  }
172 
179  inline TypedVector2(const TypedVector2& other) :
180  x(other.x),
181  y(other.y)
182  {
183  }
184 
185 
186  template<typename FromType> explicit TypedVector2(const TypedVector2<FromType>& other) :
187  x(static_cast<Type>(other.x)),
188  y(static_cast<Type>(other.y))
189  {
190  }
191 
192 
196  inline ~TypedVector2(void)
197  {
198  }
199 
205  inline TypedVector2& operator=(const TypedVector2& other)
206  {
207  x = other.x;
208  y = other.y;
209  return *this;
210  }
211 
221  inline bool operator==(const TypedVector2& other) const
222  {
223  return (true == IsEqual(x, other.x) && true == IsEqual(y, other.y)) ? true : false;
224  }
225 
230  inline bool operator!=(const TypedVector2& other) const
231  {
232  return (true == operator==(other)) ? false : true;
233  }
234 
238  inline explicit operator const Type* (void) const { return mComponents; }
239 
244  inline explicit operator Type* (void) { return mComponents; }
245 
249  template<typename ToType> explicit operator TypedVector2<ToType>(void) const
250  {
251  return TypedVector2<ToType>(static_cast<ToType>(x), static_cast<ToType>(y));
252  }
253 
257  inline const Type& operator[](const int index) const { return mComponents[index]; }
258  inline const Type& operator[](const std::size_t& index) const { return mComponents[index]; }
259 
264  inline Type& operator[](const int index) { return mComponents[index]; }
265  inline Type& operator[](const std::size_t& index) { return mComponents[index]; }
266 
270  static inline Type Dot(const TypedVector2<Type>& leftSide, const TypedVector2<Type>& rightSide)
271  {
272  return Vector2DotProduct(&leftSide, &rightSide);
273  }
274 
278  static inline TypedVector2 Normalize(const TypedVector2<Type>& value)
279  {
280  TypedVector2<Type> result(kSkipInitialization);
281  Vector2Normalize(&result, &value);
282  return result;
283  }
284 
289  static inline TypedVector2 Normalize(const TypedVector2<Type>& value, Type& magnitude)
290  {
291  TypedVector2<Type> result(kSkipInitialization);
292  Vector2NormalizeMagnitude(&result, &value, magnitude);
293  return result;
294  }
295 
296 #if defined(tb_with_math_operators)
300  inline TypedVector2 operator+(const TypedVector2& rightSide) const { return TypedVector2(x + rightSide.x, y + rightSide.y); }
301 
306  inline TypedVector2& operator+=(const TypedVector2& rightSide) { x += rightSide.x; y += rightSide.y; return *this; }
307 
311  inline TypedVector2 operator-(const TypedVector2& rightSide) const { return TypedVector2(x - rightSide.x, y - rightSide.y); }
312 
316  inline TypedVector2& operator-=(const TypedVector2& rightSide) { x -= rightSide.x; y -= rightSide.y; return *this; }
317 
321  inline TypedVector2 operator*(Type scalar) const { return TypedVector2(x * scalar, y * scalar); }
322 
327  friend TypedVector2 operator*(Type scalar, const TypedVector2& rightSide) { return TypedVector2(scalar * rightSide.x, scalar * rightSide.y); }
328 
333  inline TypedVector2& operator*=(Type scalar) { x *= scalar; y *= scalar; return *this; }
334 
338  inline TypedVector2 operator/(Type scalar) const { return TypedVector2(x / scalar, y / scalar); }
339 
344  inline TypedVector2& operator/=(Type scalar) { x /= scalar; y /= scalar; return *this; }
345 
349  friend TypedVector2 operator/(Type scalar, const TypedVector2& rightSide) { return TypedVector2(scalar / rightSide.x, scalar / rightSide.y); }
350 
354  inline TypedVector2 operator-(void) const { return TypedVector2(-x, -y); }
355 
359  inline Type operator*(const TypedVector2& rhs) const { return (x * rhs.x) + (y * rhs.y); }
360 
365  inline Type Magnitude(void) const { return sqrt((x * x) + (y * y)); }
366 
371  inline Type MagnitudeSquared(void) const { return (x * x) + (y * y); }
372 
377  inline TypedVector2 GetNormalized(void) const
378  {
379  const Type magnitude(Magnitude());
380  if (true == IsZero(magnitude)) { return Zero(); }
381  return TypedVector2(x / magnitude, y / magnitude);
382  }
383 
389  inline Type Normalize(void)
390  {
391  const Type magnitude(Magnitude());
392  if (false == IsZero(magnitude))
393  {
394  x /= magnitude;
395  y /= magnitude;
396  }
397  return magnitude;
398  }
399 
403  inline void Scale(Type scalar) { *this *= scalar; }
404 
412  inline void SetLength(Type length) { Normalize(); *this *= length; }
413 
419  inline TypedAngle<Type> AngleTo(const TypedVector2& other) const
420  {
421  const Type productOfMagnitudes(Magnitude() * other.Magnitude());
422  if (true == IsZero(productOfMagnitudes)) { return TypedAngle<Type>::Radians(Type(0.0)); }
423  const Type value(Dot(*this, other) / productOfMagnitudes);
424  const Type clampedValue((value < Type(-1.0)) ? Type(-1.0) : (value > Type(1.0)) ? Type(1.0) : value); //Clamp: -1.0f <= value <= 1.0f
425  return TypedAngle<Type>::Radians(acos(clampedValue));
426  }
427 
433  inline TypedVector2<Type> DirectionTo(const TypedVector2& other) const
434  {
435  return (other - *this).GetNormalized();
436  }
437 
443  inline Type DistanceTo(const TypedVector2& other) const
444  {
445  return (other - *this).Magnitude();
446  }
447 
454  inline Type SquaredDistanceTo(const TypedVector2& other) const
455  {
456  return (other - *this).MagnitudeSquared();
457  }
458 
459 
460 #endif /* tb_with_math_operators */
461  };
462 
463 //--------------------------------------------------------------------------------------------------------------------//
464 //--------------------------------------------------------------------------------------------------------------------//
465 //--------------------------------------------------------------------------------------------------------------------//
466 
471  template<typename Type> class TypedVector3
472  {
473  public:
477  static TypedVector3 Zero(void) { return TypedVector3(Type(0), Type(0), Type(0)); }
478 
482  static TypedVector3 One(void) { return TypedVector3(Type(1), Type(1), Type(1)); }
483 
484  static TypedVector3 Right(void) { return TypedVector3(Type(1), Type(0), Type(0)); }
485  static TypedVector3 Left(void) { return -Right(); }
486  static TypedVector3 Up(void) { return TypedVector3(Type(0), Type(1), Type(0)); }
487  static TypedVector3 Down(void) { return -Up(); }
488 #if defined(tb_righthanded_math)
489  static TypedVector3 Forward(void) { return TypedVector3(Type(0), Type(0), Type(-1)); }
490 #else
491  static TypedVector3 Forward(void) { return TypedVector3(Type(0), Type(0), Type(1)); }
492 #endif
493  static TypedVector3 Backward(void) { return -Forward(); }
494 
495  union
496  {
497  Type mComponents[3];
498 
499 #if defined(tb_visual_cpp)
500 #pragma warning(push)
501 #pragma warning(disable: 4201)
502  struct { Type x, y, z; };
503 #pragma warning(pop)
504 #else
505  struct { Type x, y, z; };
506 #endif
507  };
508 
515  inline explicit TypedVector3(const SkipInitialization& fastAndStupid)
516  {
517  tb_unused(fastAndStupid);
518  }
519 
523  inline TypedVector3(void) :
524  x(Type(0)),
525  y(Type(0)),
526  z(Type(0))
527  {
528  }
529 
537  inline TypedVector3(const Type valueX, const Type valueY, const Type valueZ) :
538  x(valueX),
539  y(valueY),
540  z(valueZ)
541  {
542  }
543 
550  inline explicit TypedVector3(const TypedVector2<Type>& other, const Type valueZ) :
551  x(other.x),
552  y(other.y),
553  z(valueZ)
554  {
555  }
556 
562  inline explicit TypedVector3(const Type* componentArray) :
563  x(componentArray[0]),
564  y(componentArray[1]),
565  z(componentArray[2])
566  {
567  }
568 
576  x(other.x),
577  y(other.y),
578  z(other.z)
579  {
580  }
581 
582  template<typename FromType> explicit TypedVector3(const TypedVector3<FromType>& other) :
583  x(static_cast<Type>(other.x)),
584  y(static_cast<Type>(other.y)),
585  z(static_cast<Type>(other.z))
586  {
587  }
588 
593  {
594  }
595 
601  inline TypedVector3& operator=(const TypedVector3& other)
602  {
603  x = other.x;
604  y = other.y;
605  z = other.z;
606  return *this;
607  }
608 
609  //
610  // TODO: TIM: Planning: Would this be useful to have, or just dangerous?
611  //
612  //inline TypedVector3& operator=(const TypedVector2 &v)
613  //{
614  // x = v.x; y = v.y; /* z = z; */
615  // return (*this);
616  //}
617 
627  inline bool operator==(const TypedVector3& other) const
628  {
629  return (true == tbMath::IsEqual(x, other.x) && true == tbMath::IsEqual(y, other.y) && true == tbMath::IsEqual(z, other.z)) ? true : false;
630  }
631 
636  inline bool operator!=(const TypedVector3& other) const
637  {
638  return (true == operator==(other)) ? false : true;
639  }
640 
644  inline explicit operator const Type* (void) const { return mComponents; }
645 
650  inline explicit operator Type* (void) { return mComponents; }
651 
655  template<typename ToType> operator TypedVector3<ToType>(void) const
656  {
657  return TypedVector3<ToType>(static_cast<ToType>(x), static_cast<ToType>(y), static_cast<ToType>(z));
658  }
659 
663  inline const Type& operator[](const int index) const { return mComponents[index]; }
664  inline const Type& operator[](const std::size_t& index) const { return mComponents[index]; }
665 
670  inline Type& operator[](const int index) { return mComponents[index]; }
671  inline Type& operator[](const std::size_t& index) { return mComponents[index]; }
672 
676  static inline Type Dot(const TypedVector3<Type>& leftSide, const TypedVector3<Type>& rightSide)
677  {
678  return Vector3DotProduct(&leftSide, &rightSide);
679  }
680 
685  static inline TypedVector3 Cross(const TypedVector3<Type>& leftSide, const TypedVector3<Type>& rightSide)
686  {
687  TypedVector3<Type> result(kSkipInitialization);
688  Vector3CrossProduct(&result, &leftSide, &rightSide);
689  return result;
690  }
691 
695  static inline TypedVector3 Normalize(const TypedVector3<Type>& value)
696  {
697  TypedVector3<Type> result(kSkipInitialization);
698  Vector3Normalize(&result, &value);
699  return result;
700  }
701 
706  static inline TypedVector3 Normalize(const TypedVector3<Type>& value, Type& magnitude)
707  {
708  TypedVector3<Type> result(kSkipInitialization);
709  Vector3NormalizeMagnitude(&result, &value, magnitude);
710  return result;
711  }
712 
713 #if defined(tb_with_math_operators)
717  inline TypedVector3<Type> operator+(const TypedVector3<Type>& rightSide) const
718  {
719  return TypedVector3<Type>(x + rightSide.x, y + rightSide.y, z + rightSide.z);
720  }
721 
726  inline TypedVector3& operator+=(const TypedVector3& rightSide) { x += rightSide.x; y += rightSide.y; z += rightSide.z; return *this; }
727 
731  inline TypedVector3 operator-(const TypedVector3& rightSide) const { return TypedVector3(x - rightSide.x, y - rightSide.y, z - rightSide.z); }
732 
736  inline TypedVector3& operator-=(const TypedVector3& rightSide) { x -= rightSide.x; y -= rightSide.y; z -= rightSide.z; return *this; }
737 
738 
742  inline TypedVector3 operator*(Type scalar) const { return TypedVector3(x * scalar, y * scalar, z * scalar); }
743 
748  friend TypedVector3 operator*(Type scalar, const TypedVector3& rightSide) { return TypedVector3(scalar * rightSide.x, scalar * rightSide.y, scalar * rightSide.z); }
749 
754  inline TypedVector3& operator*=(Type scalar) { x *= scalar; y *= scalar; z *= scalar; return *this; }
755 
759  inline TypedVector3 operator/(Type scalar) const { return TypedVector3(x / scalar, y / scalar, z / scalar); }
760 
765  inline TypedVector3& operator/=(Type scalar) { x /= scalar; y /= scalar; z /= scalar; return *this; }
766 
770  friend TypedVector3 operator/(Type scalar, const TypedVector3& rightSide) { return TypedVector3(scalar / rightSide.x, scalar / rightSide.y, scalar / rightSide.z); }
771 
775  inline TypedVector3 operator-(void) const { return TypedVector3(-x, -y, -z); }
776 
784  inline Type operator*(const TypedVector3& rhs) const { return (x * rhs.x) + (y * rhs.y) + (z * rhs.z); }
785 
794  inline TypedVector3 operator^(const TypedVector3& rightSide) const
795  {
796  return TypedVector3((y * rightSide.z) - (rightSide.y * z), -((x * rightSide.z) - (rightSide.x * z)), (x * rightSide.y) - (rightSide.x * y));
797  }
798 
799 
804  inline Type Magnitude(void) const { return sqrt((x * x) + (y * y) + (z * z)); }
805 
810  inline Type MagnitudeSquared(void) const { return (x * x) + (y * y) + (z * z); }
811 
818  inline TypedVector3 GetNormalized(void) const
819  {
820  const Type magnitude(Magnitude());
821  if (true == tbMath::IsZero(magnitude)) { return Zero(); }
822  return TypedVector3(x / magnitude, y / magnitude, z / magnitude);
823  }
824 
828  inline TypedVector3 GetNormalized(Type& magnitude) const
829  {
830  magnitude = (Magnitude());
831  if (true == tbMath::IsZero(magnitude)) { return Zero(); }
832  return TypedVector3(x / magnitude, y / magnitude, z / magnitude);
833  }
834 
840  inline Type Normalize(void)
841  {
842  const Type magnitude(Magnitude());
843  if (false == tbMath::IsZero(magnitude))
844  {
845  x /= magnitude;
846  y /= magnitude;
847  z /= magnitude;
848  }
849  return magnitude;
850  }
851 
855  inline void Scale(Type scalar) { *this *= scalar; }
856 
864  inline void SetLength(const Type length) { Normalize(); *this *= length; }
865 
871  inline TypedAngle<Type> AngleTo(const TypedVector3& other) const
872  {
873  const Type productOfMagnitudes(Magnitude() * other.Magnitude());
874  if (true == IsZero(productOfMagnitudes)) { return TypedAngle<Type>::Radians(Type(0.0)); }
875  const Type value(Dot(*this, other) / productOfMagnitudes);
876  const Type clampedValue((value < Type(-1.0)) ? Type(-1.0) : (value > Type(1.0)) ? Type(1.0) : value); //Clamp: -1.0f <= value <= 1.0f
877  return TypedAngle<Type>::Radians(acos(clampedValue));
878 
879  // 2024-03-22: Godot 4.2.1 implementation of Vector3::angle_to, differed a bit, tested to see if the
880  // SnailedIt! snail could roll on walls. It currently detects walls good for crawling, just not rolling.
881  //return TypedAngle<Type>::Radians(std::atan2(Cross(*this, other).Magnitude(), Dot(*this, other)));
882  }
883 
889  inline TypedVector3<Type> DirectionTo(const TypedVector3& other) const
890  {
891  return (other - *this).GetNormalized();
892  }
893 
899  inline Type DistanceTo(const TypedVector3& other) const
900  {
901  return (other - *this).Magnitude();
902  }
903 
910  inline Type SquaredDistanceTo(const TypedVector3& other) const
911  {
912  return (other - *this).MagnitudeSquared();
913  }
914 
915 #endif /* tb_with_math_operators */
916  };
917 
918 //--------------------------------------------------------------------------------------------------------------------//
919 //--------------------------------------------------------------------------------------------------------------------//
920 //--------------------------------------------------------------------------------------------------------------------//
921 
926  template<typename Type> class TypedVector4
927  {
928  public:
932  static TypedVector4 Zero(void) { return TypedVector4(Type(0), Type(0), Type(0), Type(0)); }
933 
937  static TypedVector4 One(void) { return TypedVector4(Type(1), Type(1), Type(1), Type(1)); }
938 
939  union
940  {
941  Type mComponents[4];
942 
943 #if defined(tb_visual_cpp)
944 #pragma warning(push)
945 #pragma warning(disable: 4201)
946  struct { Type x, y, z, w; };
947 #pragma warning(pop)
948 #else
949  struct { Type x, y, z, w; };
950 #endif
951  };
952 
959  inline explicit TypedVector4(const SkipInitialization& fastAndStupid)
960  {
961  tb_unused(fastAndStupid);
962  }
963 
967  inline TypedVector4(void) :
968  x(Type(0)),
969  y(Type(0)),
970  z(Type(0)),
971  w(Type(0))
972  {
973  }
974 
983  inline TypedVector4(const Type valueX, const Type valueY, const Type valueZ, const Type valueW) :
984  x(valueX),
985  y(valueY),
986  z(valueZ),
987  w(valueW)
988  {
989  }
990 
998  inline explicit TypedVector4(const TypedVector2<Type>& other, const Type valueZ, const Type valueW) :
999  x(other.x),
1000  y(other.y),
1001  z(valueZ),
1002  w(valueW)
1003  {
1004  }
1005 
1012  inline explicit TypedVector4(const TypedVector3<Type>& other, const Type valueW) :
1013  x(other.x),
1014  y(other.y),
1015  z(other.z),
1016  w(valueW)
1017  {
1018  }
1019 
1025  inline explicit TypedVector4(const Type* componentArray) :
1026  x(componentArray[0]),
1027  y(componentArray[1]),
1028  z(componentArray[2]),
1029  w(componentArray[3])
1030  {
1031  }
1032 
1039  inline TypedVector4(const TypedVector4& other) :
1040  x(other.x),
1041  y(other.y),
1042  z(other.z),
1043  w(other.w)
1044  {
1045  }
1046 
1047  template<typename FromType> explicit TypedVector4(const TypedVector4<FromType>& other) :
1048  x(static_cast<Type>(other.x)),
1049  y(static_cast<Type>(other.y)),
1050  z(static_cast<Type>(other.z)),
1051  w(static_cast<Type>(other.w))
1052  {
1053  }
1054 
1059  {
1060  }
1061 
1067  inline TypedVector4& operator=(const TypedVector4& other)
1068  {
1069  x = other.x;
1070  y = other.y;
1071  z = other.z;
1072  w = other.w;
1073  return *this;
1074  }
1075 
1085  inline bool operator==(const TypedVector4& other) const
1086  {
1087  return (true == IsEqual(x, other.x) && true == IsEqual(y, other.y) &&
1088  true == IsEqual(z, other.z) && true == IsEqual(w, other.w)) ? true : false;
1089  }
1090 
1095  inline bool operator!=(const TypedVector4& other) const
1096  {
1097  return (true == operator==(other)) ? false : true;
1098  }
1099 
1103  inline explicit operator const Type* (void) const { return mComponents; }
1104 
1109  inline explicit operator Type* (void) { return mComponents; }
1110 
1114  template<typename ToType> explicit operator TypedVector4<ToType>(void) const
1115  {
1116  return TypedVector4<ToType>(static_cast<ToType>(x), static_cast<ToType>(y), static_cast<ToType>(z), static_cast<ToType>(w));
1117  }
1118 
1122  inline const Type& operator[](const int index) const { return mComponents[index]; }
1123  inline const Type& operator[](const std::size_t& index) const { return mComponents[index]; }
1124 
1129  inline Type& operator[](const int index) { return mComponents[index]; }
1130  inline Type& operator[](const std::size_t& index) { return mComponents[index]; }
1131 
1135  static inline Type Dot(const TypedVector4<Type>& leftSide, const TypedVector4<Type>& rightSide)
1136  {
1137  return Vector4DotProduct(&leftSide, &rightSide);
1138  }
1139 
1144  static inline TypedVector4 Cross(const TypedVector4<Type>& leftSide, const TypedVector4<Type>& rightSide)
1145  {
1146  TypedVector4<Type> result(kSkipInitialization);
1147  Vector4CrossProduct(&result, &leftSide, &rightSide);
1148  return result;
1149  }
1150 
1154  static inline TypedVector4 Normalize(const TypedVector4<Type>& value)
1155  {
1156  TypedVector4<Type> result(kSkipInitialization);
1157  Vector4Normalize(&result, &value);
1158  return result;
1159  }
1160 
1165  static inline TypedVector4 Normalize(const TypedVector4<Type>& value, Type& magnitude)
1166  {
1167  TypedVector4<Type> result(kSkipInitialization);
1168  Vector4NormalizeMagnitude(&result, &value, magnitude);
1169  return result;
1170  }
1171 
1172 
1173 #if defined(tb_with_math_operators)
1177  inline TypedVector4 operator+(const TypedVector4& rightSide) const { return TypedVector4(x + rightSide.x, y + rightSide.y, z + rightSide.z, w + rightSide.w); }
1178 
1183  inline TypedVector4& operator+=(const TypedVector4& rightSide) { x += rightSide.x; y += rightSide.y; z += rightSide.z; w += rightSide.w; return *this; }
1184 
1188  inline TypedVector4 operator-(const TypedVector4& rightSide) const { return TypedVector4(x - rightSide.x, y - rightSide.y, z - rightSide.z, w - rightSide.w); }
1189 
1193  inline TypedVector4& operator-=(const TypedVector4& rightSide) { x -= rightSide.x; y -= rightSide.y; z -= rightSide.z; w -= rightSide.w; return *this; }
1194 
1195 
1199  inline TypedVector4 operator*(Type scalar) const { return TypedVector4(x * scalar, y * scalar, z * scalar, w * scalar); }
1200 
1205  friend TypedVector4 operator*(Type scalar, const TypedVector4& rightSide) { return TypedVector4(scalar * rightSide.x, scalar * rightSide.y, scalar * rightSide.z, scalar * rightSide.w); }
1206 
1211  inline TypedVector4& operator*=(Type scalar) { x *= scalar; y *= scalar; z *= scalar; w *= scalar; return *this; }
1212 
1216  inline TypedVector4 operator/(Type scalar) const { return TypedVector4(x / scalar, y / scalar, z / scalar, w / scalar); }
1217 
1222  inline TypedVector4& operator/=(Type scalar) { x /= scalar; y /= scalar; z /= scalar; w /= scalar; return *this; }
1223 
1227  friend TypedVector4 operator/(Type scalar, const TypedVector4& rightSide) { return TypedVector4(scalar / rightSide.x, scalar / rightSide.y, scalar / rightSide.z, scalar / rightSide.w); }
1228 
1232  inline TypedVector4 operator-(void) const { return TypedVector4(-x, -y, -z, -w); }
1233 
1237  inline Type operator*(const TypedVector4& rightSide) const { return (x * rightSide.x) + (y * rightSide.y) + (z * rightSide.z) + (w * rightSide.w); }
1238 
1239  //TODO: TIM: Reconsider: Does this work, and if it does, how do we want to support it? Document if needed.
1240  //inline TypedVector4 operator^(const TypedVector4 &rhs) const { return TypedVector4((y * rhs.z) - (rhs.y * z), -((x * rhs.z) - (rhs.x * z)), (x * rhs.y) - (rhs.x * y)); }
1241 
1246  inline Type Magnitude(void) const { return sqrt((x * x) + (y * y) + (z * z) + (w * w)); }
1247 
1252  inline Type MagnitudeSquared(void) const { return (x * x) + (y * y) + (z * z) + (w * w); }
1253 
1258  inline TypedVector4 GetNormalized(void) const
1259  {
1260  const Type magnitude(Magnitude());
1261  if (true == IsZero(magnitude)) { return Zero(); }
1262  return TypedVector4(x / magnitude, y / magnitude, z / magnitude, w / magnitude);
1263  }
1264 
1270  inline Type Normalize(void)
1271  {
1272  const Type magnitude(Magnitude());
1273  if (false == IsZero(magnitude))
1274  {
1275  x /= magnitude;
1276  y /= magnitude;
1277  z /= magnitude;
1278  w /= magnitude;
1279  }
1280  return magnitude;
1281  }
1282 
1286  inline void Scale(Type scalar) { *this *= scalar; }
1287 
1295  inline void SetLength(Type length) { Normalize(); *this *= length; }
1296 
1304  inline TypedAngle<Type> AngleTo(const TypedVector4& other) const
1305  {
1306  const Type productOfMagnitudes(Magnitude() * other.Magnitude());
1307  if (true == IsZero(productOfMagnitudes)) { return TypedAngle<Type>::Radians(Type(0.0)); }
1308  const Type value(Dot(*this, other) / productOfMagnitudes);
1309  const Type clampedValue((value < Type(-1.0)) ? Type(-1.0) : (value > Type(1.0)) ? Type(1.0) : value); //Clamp: -1.0f <= value <= 1.0f
1310  return TypedAngle<Type>::Radians(acos(clampedValue));
1311  }
1312 
1318  inline TypedVector4<Type> DirectionTo(const TypedVector4& other) const
1319  {
1320  return (other - *this).GetNormalized();
1321  }
1322 
1328  inline Type DistanceTo(const TypedVector4& other) const
1329  {
1330  return (other - *this).Magnitude();
1331  }
1332 
1339  inline Type SquaredDistanceTo(const TypedVector4& other) const
1340  {
1341  return (other - *this).MagnitudeSquared();
1342  }
1343 #endif /* tb_with_math_operators */
1344  };
1345 
1346  typedef TypedVector2<float> Vector2;
1347  typedef TypedVector3<float> Vector3;
1348  typedef TypedVector4<float> Vector4;
1349 
1350 //--------------------------------------------------------------------------------------------------------------------//
1351 //--------------------------------------------------------------------------------------------------------------------//
1352 //--------------------------------------------------------------------------------------------------------------------//
1353 
1364  inline Vector2* Vector2Add(Vector2* result, const Vector2* leftSide, const Vector2* rightSide)
1365  {
1366  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1367  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1368  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1369 
1370  result->x = leftSide->x + rightSide->x;
1371  result->y = leftSide->y + rightSide->y;
1372  return result;
1373  }
1374 
1378  inline Vector3* Vector3Add(Vector3* result, const Vector3* leftSide, const Vector3* rightSide)
1379  {
1380  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1381  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1382  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1383 
1384  result->x = leftSide->x + rightSide->x;
1385  result->y = leftSide->y + rightSide->y;
1386  result->z = leftSide->z + rightSide->z;
1387  return result;
1388  }
1389 
1393  inline Vector4* Vector4Add(Vector4* result, const Vector4* leftSide, const Vector4* rightSide)
1394  {
1395  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1396  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1397  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1398 
1399  result->x = leftSide->x + rightSide->x;
1400  result->y = leftSide->y + rightSide->y;
1401  result->z = leftSide->z + rightSide->z;
1402  result->w = leftSide->w + rightSide->w;
1403  return result;
1404  }
1405 
1416  inline Vector2* Vector2Subtract(Vector2* result, const Vector2* leftSide, const Vector2* rightSide)
1417  {
1418  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1419  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1420  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1421 
1422  result->x = leftSide->x - rightSide->x;
1423  result->y = leftSide->y - rightSide->y;
1424  return result;
1425  }
1426 
1430  inline Vector3* Vector3Subtract(Vector3* result, const Vector3* leftSide, const Vector3* rightSide)
1431  {
1432  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1433  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1434  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1435 
1436  result->x = leftSide->x - rightSide->x;
1437  result->y = leftSide->y - rightSide->y;
1438  result->z = leftSide->z - rightSide->z;
1439  return result;
1440  }
1441 
1445  inline Vector4* Vector4Subtract(Vector4* result, const Vector4* leftSide, const Vector4* rightSide)
1446  {
1447  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1448  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1449  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1450 
1451  result->x = leftSide->x - rightSide->x;
1452  result->y = leftSide->y - rightSide->y;
1453  result->z = leftSide->z - rightSide->z;
1454  result->w = leftSide->w - rightSide->w;
1455  return result;
1456  }
1457 
1467  inline Vector2* Vector2Scale(Vector2* result, const Vector2* input, const float scalar)
1468  {
1469  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1470  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1471 
1472  result->x = input->x * scalar;
1473  result->y = input->y * scalar;
1474  return result;
1475  }
1476 
1480  inline Vector3* Vector3Scale(Vector3* result, const Vector3* input, const float scalar)
1481  {
1482  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1483  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1484 
1485  result->x = input->x * scalar;
1486  result->y = input->y * scalar;
1487  result->z = input->z * scalar;
1488  return result;
1489  }
1490 
1494  inline Vector4* Vector4Scale(Vector4* result, const Vector4* input, const float scalar)
1495  {
1496  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1497  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1498 
1499  result->x = input->x * scalar;
1500  result->y = input->y * scalar;
1501  result->z = input->z * scalar;
1502  result->w = input->w * scalar;
1503  return result;
1504  }
1505 
1515  inline Vector2* Vector2ScaleDivide(Vector2* result, const Vector2* input, const float scalar)
1516  {
1517  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1518  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1519 
1520  result->x = input->x / scalar;
1521  result->y = input->y / scalar;
1522  return result;
1523  }
1524 
1528  inline Vector3* Vector3ScaleDivide(Vector3* result, const Vector3* input, const float scalar)
1529  {
1530  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1531  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1532 
1533  result->x = input->x / scalar;
1534  result->y = input->y / scalar;
1535  result->z = input->z / scalar;
1536  return result;
1537  }
1538 
1542  inline Vector4* Vector4ScaleDivide(Vector4* result, const Vector4* input, const float scalar)
1543  {
1544  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1545  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1546 
1547  result->x = input->x / scalar;
1548  result->y = input->y / scalar;
1549  result->z = input->z / scalar;
1550  result->w = input->w / scalar;
1551  return result;
1552  }
1553 
1562  inline Vector2* Vector2Negate(Vector2* result, const Vector2* input)
1563  {
1564  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1565  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1566 
1567  result->x = -input->x;
1568  result->y = -input->y;
1569  return result;
1570  }
1571 
1575  inline Vector3* Vector3Negate(Vector3* result, const Vector3* input)
1576  {
1577  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1578  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1579 
1580  result->x = -input->x;
1581  result->y = -input->y;
1582  result->z = -input->z;
1583  return result;
1584  }
1585 
1589  inline Vector4* Vector4Negate(Vector4* result, const Vector4* input)
1590  {
1591  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1592  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1593 
1594  result->x = -input->x;
1595  result->y = -input->y;
1596  result->z = -input->z;
1597  result->w = -input->w;
1598  return result;
1599  }
1600 
1608  template<typename Type> Type Vector2DotProduct(const TypedVector2<Type>* leftSide, const TypedVector2<Type>* rightSide)
1609  {
1610  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1611  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1612  return (leftSide->x * rightSide->x) + (leftSide->y * rightSide->y);
1613  }
1614 
1618  template<typename Type> Type Vector3DotProduct(const TypedVector3<Type>* leftSide, const TypedVector3<Type>* rightSide)
1619  {
1620  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1621  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1622  return (leftSide->x * rightSide->x) + (leftSide->y * rightSide->y) + (leftSide->z * rightSide->z);
1623  }
1624 
1628  template<typename Type> Type Vector4DotProduct(const TypedVector4<Type>* leftSide, const TypedVector4<Type>* rightSide)
1629  {
1630  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1631  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1632  return (leftSide->x * rightSide->x) + (leftSide->y * rightSide->y) + (leftSide->z * rightSide->z) + (leftSide->w * rightSide->w);
1633  }
1634 
1649  const TypedVector3<Type>* leftSide, const TypedVector3<Type>* rightSide)
1650  {
1651  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1652  tb_error_if(nullptr == leftSide, "tbExternalError: Invalid parameter for leftSide, expected valid pointer.");
1653  tb_error_if(nullptr == rightSide, "tbExternalError: Invalid parameter for rightSide, expected valid pointer.");
1654  tb_error_if(leftSide == rightSide, "tbExternalError: Invalid parameter; expected leftSide to be different from rightSide.");
1655  tb_error_if(result == leftSide || result == rightSide, "Invalid parameter; expected result to be different than leftSide and rightSide");
1656 
1657  result->x = ((leftSide->y * rightSide->z) - (rightSide->y * leftSide->z));
1658  result->y = -(((leftSide->x * rightSide->z) - (rightSide->x * leftSide->z)));
1659  result->z = ((leftSide->x * rightSide->y) - (rightSide->x * leftSide->y));
1660  return result;
1661  }
1662 
1663  //Possible future API stuff, for easier usage?
1664  //inline Vector3 Vector3CrossProduct(const Vector3& leftSide, const Vector3& rightSide)
1665  //{
1666  // Vector3 result(kSkipInitialization);
1667  // Vector3CrossProduct(&result, &leftSide, &rightSide);
1668  // return result;
1669  //}
1670 
1678  template<typename Type> Type Vector2Magnitude(const TypedVector2<Type>* input)
1679  {
1680  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1681  return sqrt((input->x * input->x) + (input->y * input->y));
1682  }
1683 
1687  template<typename Type> Type Vector3Magnitude(const TypedVector3<Type>* input)
1688  {
1689  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1690  return std::sqrt((input->x * input->x) + (input->y * input->y) + (input->z * input->z));
1691  }
1692 
1696  template<typename Type> Type Vector4Magnitude(const TypedVector4<Type>* input)
1697  {
1698  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1699  return sqrt((input->x * input->x) + (input->y * input->y) + (input->z * input->z) + (input->w * input->w));
1700  }
1701 
1710  template<typename Type> Type Vector2MagnitudeSquared(const TypedVector2<Type>* input)
1711  {
1712  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1713  return (input->x * input->x) + (input->y * input->y);
1714  }
1715 
1719  template<typename Type> Type Vector3MagnitudeSquared(const TypedVector3<Type>* input)
1720  {
1721  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1722  return (input->x * input->x) + (input->y * input->y) + (input->z * input->z);
1723  }
1724 
1728  template<typename Type> Type Vector4MagnitudeSquared(const TypedVector4<Type>* input)
1729  {
1730  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1731  return (input->x * input->x) + (input->y * input->y) + (input->z * input->z) + (input->w * input->w);
1732  }
1733 
1742  template<typename Type> TypedVector2<Type>* Vector2Normalize(TypedVector2<Type>* result, const TypedVector2<Type>* input)
1743  {
1744  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1745  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1746 
1747  const Type magnitude = Vector2Magnitude(input);
1748  if (true == IsZero(magnitude))
1749  {
1750  result->x = Type(0);
1751  result->y = Type(0);
1752  }
1753  else
1754  {
1755  result->x = input->x / magnitude;
1756  result->y = input->y / magnitude;
1757  }
1758  return result;
1759  }
1760 
1764  template<typename Type> TypedVector3<Type>* Vector3Normalize(TypedVector3<Type>* result, const TypedVector3<Type>* input)
1765  {
1766  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1767  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1768 
1769  const Type magnitude = Vector3Magnitude(input);
1770  if (true == IsZero(magnitude))
1771  {
1772  result->x = Type(0);
1773  result->y = Type(0);
1774  result->z = Type(0);
1775  }
1776  else
1777  {
1778  result->x = input->x / magnitude;
1779  result->y = input->y / magnitude;
1780  result->z = input->z / magnitude;
1781  }
1782  return result;
1783  }
1784 
1788  template<typename Type> TypedVector4<Type>* Vector4Normalize(TypedVector4<Type>* result, const TypedVector4<Type>* input)
1789  {
1790  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1791  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1792 
1793  const Type magnitude = Vector4Magnitude(input);
1794  if (true == IsZero(magnitude))
1795  {
1796  result->x = Type(0);
1797  result->y = Type(0);
1798  result->z = Type(0);
1799  result->w = Type(0);
1800  }
1801  else
1802  {
1803  result->x = input->x / magnitude;
1804  result->y = input->y / magnitude;
1805  result->z = input->z / magnitude;
1806  result->w = input->w / magnitude;
1807  }
1808  return result;
1809  }
1810 
1822  const TypedVector2<Type>* input, Type& magnitude)
1823  {
1824  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1825  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1826 
1827  magnitude = Vector2Magnitude(input);
1828  if (true == IsZero(magnitude))
1829  {
1830  result->x = Type(0);
1831  result->y = Type(0);
1832  }
1833  else
1834  {
1835  result->x = input->x / magnitude;
1836  result->y = input->y / magnitude;
1837  }
1838  return result;
1839  }
1840 
1845  const TypedVector3<Type>* input, Type &magnitude)
1846  {
1847  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1848  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1849 
1850  magnitude = Vector3Magnitude(input);
1851  if (true == IsZero(magnitude))
1852  {
1853  result->x = Type(0);
1854  result->y = Type(0);
1855  result->z = Type(0);
1856  }
1857  else
1858  {
1859  result->x = input->x / magnitude;
1860  result->y = input->y / magnitude;
1861  result->z = input->z / magnitude;
1862  }
1863  return result;
1864  }
1865 
1870  const TypedVector4<Type>* input, Type &magnitude)
1871  {
1872  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter for result, expected valid pointer.");
1873  tb_error_if(nullptr == input, "tbExternalError: Invalid parameter for input, expected valid pointer.");
1874 
1875  magnitude = Vector4Magnitude(input);
1876  if (true == IsZero(magnitude))
1877  {
1878  result->x = Type(0);
1879  result->y = Type(0);
1880  result->z = Type(0);
1881  result->w = Type(0);
1882  }
1883  else
1884  {
1885  result->x = input->x / magnitude;
1886  result->y = input->y / magnitude;
1887  result->z = input->z / magnitude;
1888  result->w = input->w / magnitude;
1889  }
1890  return result;
1891  }
1892 
1897  template<typename Type> TypedAngle<Type> Vector3AngleBetween(const TypedVector3<Type>* left, const TypedVector3<Type>* right)
1898  {
1899  const Type productOfMagnitudes(Vector3Magnitude(left) * Vector3Magnitude(right));
1900  if (true == IsZero(productOfMagnitudes)) { return TypedAngle<Type>::Radians(Type(0)); }
1901  const Type value(Vector3DotProduct(left, right) / productOfMagnitudes);
1902  const Type clampedValue((value < Type(-1)) ? Type(-1) : (value > Type(1)) ? Type(1) : value); //Clamp: -1.0f <= value <= 1.0f
1903  return TypedAngle<Type>::Radians(acos(clampedValue));
1904  }
1905 
1910  static inline Vector3& RotationXZToForwardVector3(Vector3& result, const Angle& orientation)
1911  {
1912  result.x = sin(orientation.AsRadians());
1913  result.y = 0.0f;
1914  result.z = -cos(orientation.AsRadians());
1915  return result;
1916  }
1917 
1922  static inline Vector2& RotationToForwardVector2(Vector2& result, const Angle& orientation)
1923  {
1924  result.x = sin(orientation.AsRadians());
1925  result.y = -cos(orientation.AsRadians());
1926  return result;
1927  }
1928 
1936  static inline Angle ForwardVector3ToRotationXZ(const Vector3& forward)
1937  {
1938  Vector3 vZAxis(0.0f, 0.0f, -1.0f);
1939  float orientation = acos((vZAxis.x * forward.x) + (vZAxis.y * forward.y) + (vZAxis.z * forward.z));
1940  if (forward.x < 0.0f)
1941  {
1942  orientation = fabs(orientation - kTwoPi);
1943  }
1944  return Angle::Radians(orientation);
1945  }
1946 
1954  static inline Angle ForwardVector2ToRotation(const Vector2& forward)
1955  {
1956  Vector2 yAxis(0.0f, -1.0f);
1957  float orientation = acos((yAxis.x * forward.x) + (yAxis.y * forward.y));
1958  if (forward.x < 0.0f)
1959  {
1960  orientation = fabs(orientation - kTwoPi);
1961  }
1962  return Angle::Radians(orientation);
1963  }
1964 
1965 
1969  template<typename Type> std::ostream& operator<<(std::ostream& output, const tbMath::TypedVector2<Type>& data)
1970  {
1971  output << "{ " << data.x << ", " << data.y << " }";
1972  return output;
1973  }
1974 
1975  template<typename Type> std::istream& operator>>(std::istream& input, const tbMath::TypedVector2<Type>& data)
1976  {
1977  String token;
1978  input >> token; // {
1979  input >> token; data.x = tbCore::FromString<Type>(token);
1980  input >> token; data.y = tbCore::FromString<Type>(token);
1981  input >> token; // }
1982  return input;
1983  }
1984 
1985  template<typename Type> std::ostream& operator<<(std::ostream& output, const tbMath::TypedVector3<Type>& data)
1986  {
1987  output << "{ " << data.x << ", " << data.y << ", " << data.z << " }";
1988  return output;
1989  }
1990 
1991  template<typename Type> std::istream& operator>>(std::istream& input, const tbMath::TypedVector3<Type>& data)
1992  {
1993  String token;
1994  input >> token; // {
1995  input >> token; data.x = tbCore::FromString<Type>(token);
1996  input >> token; data.y = tbCore::FromString<Type>(token);
1997  input >> token; data.z = tbCore::FromString<Type>(token);
1998  input >> token; // }
1999  return input;
2000  }
2001 
2002  template<typename Type> std::ostream& operator<<(std::ostream& output, const tbMath::TypedVector4<Type>& data)
2003  {
2004  output << "{ " << data.x << ", " << data.y << ", " << data.z << ", " << data.w << " }";
2005  return output;
2006  }
2007 
2008  template<typename Type> std::istream& operator>>(std::istream& input, const tbMath::TypedVector4<Type>& data)
2009  {
2010  String token;
2011  input >> token; // {
2012  input >> token; data.x = tbCore::FromString<Type>(token);
2013  input >> token; data.y = tbCore::FromString<Type>(token);
2014  input >> token; data.z = tbCore::FromString<Type>(token);
2015  input >> token; data.w = tbCore::FromString<Type>(token);
2016  input >> token; // }
2017  return input;
2018  }
2019 
2020 
2021  //typedef TypedVector2<float> Vector2;
2022  //typedef TypedVector3<float> Vector3;
2023  //typedef TypedVector4<float> Vector4;
2024 
2025  }; /* namespace Math */
2026 }; /* namespace TurtleBrains */
2027 
2028 namespace tbMath = TurtleBrains::Math;
2029 
2030 namespace TurtleBrains
2031 {
2032  using Vector2 = TurtleBrains::Math::Vector2;
2033  using Vector3 = TurtleBrains::Math::Vector3;
2034  using Vector4 = TurtleBrains::Math::Vector4;
2035 };
2036 
2037 #endif /* TurtleBrains_Vector_hpp */
Definition: tb_angle.hpp:38
static TypedAngle Radians(const Type angleInRadians)
Definition: tb_angle.hpp:51
Type AsRadians(void) const
Definition: tb_angle.hpp:87
Definition: tb_vector.hpp:99
~TypedVector2(void)
Definition: tb_vector.hpp:196
TypedVector2(const SkipInitialization &fastAndStupid)
Definition: tb_vector.hpp:136
TypedVector2(const Type valueX, const Type valueY)
Definition: tb_vector.hpp:156
TypedVector2 & operator=(const TypedVector2 &other)
Definition: tb_vector.hpp:205
static TypedVector2 Normalize(const TypedVector2< Type > &value, Type &magnitude)
Definition: tb_vector.hpp:289
static Type Dot(const TypedVector2< Type > &leftSide, const TypedVector2< Type > &rightSide)
Definition: tb_vector.hpp:270
const Type & operator[](const int index) const
Definition: tb_vector.hpp:257
bool operator==(const TypedVector2 &other) const
Definition: tb_vector.hpp:221
TypedVector2(void)
Definition: tb_vector.hpp:144
TypedVector2(const TypedVector2 &other)
Definition: tb_vector.hpp:179
bool operator!=(const TypedVector2 &other) const
Definition: tb_vector.hpp:230
static TypedVector2 Normalize(const TypedVector2< Type > &value)
Definition: tb_vector.hpp:278
static TypedVector2 One(void)
Definition: tb_vector.hpp:109
Type & operator[](const int index)
Definition: tb_vector.hpp:264
static TypedVector2 Zero(void)
Definition: tb_vector.hpp:104
TypedVector2(const Type *componentArray)
Definition: tb_vector.hpp:167
Definition: tb_vector.hpp:472
bool operator!=(const TypedVector3 &other) const
Definition: tb_vector.hpp:636
static TypedVector3 One(void)
Definition: tb_vector.hpp:482
Type & operator[](const int index)
Definition: tb_vector.hpp:670
TypedVector3(const TypedVector3< Type > &other)
Definition: tb_vector.hpp:575
static TypedVector3 Cross(const TypedVector3< Type > &leftSide, const TypedVector3< Type > &rightSide)
Definition: tb_vector.hpp:685
bool operator==(const TypedVector3 &other) const
Definition: tb_vector.hpp:627
const Type & operator[](const int index) const
Definition: tb_vector.hpp:663
TypedVector3(void)
Definition: tb_vector.hpp:523
static Type Dot(const TypedVector3< Type > &leftSide, const TypedVector3< Type > &rightSide)
Definition: tb_vector.hpp:676
TypedVector3(const SkipInitialization &fastAndStupid)
Definition: tb_vector.hpp:515
static TypedVector3 Normalize(const TypedVector3< Type > &value)
Definition: tb_vector.hpp:695
~TypedVector3(void)
Definition: tb_vector.hpp:592
static TypedVector3 Normalize(const TypedVector3< Type > &value, Type &magnitude)
Definition: tb_vector.hpp:706
TypedVector3(const Type *componentArray)
Definition: tb_vector.hpp:562
static TypedVector3 Zero(void)
Definition: tb_vector.hpp:477
TypedVector3(const Type valueX, const Type valueY, const Type valueZ)
Definition: tb_vector.hpp:537
TypedVector3 & operator=(const TypedVector3 &other)
Definition: tb_vector.hpp:601
TypedVector3(const TypedVector2< Type > &other, const Type valueZ)
Definition: tb_vector.hpp:550
Definition: tb_vector.hpp:927
bool operator!=(const TypedVector4 &other) const
Definition: tb_vector.hpp:1095
static TypedVector4 One(void)
Definition: tb_vector.hpp:937
~TypedVector4(void)
Definition: tb_vector.hpp:1058
TypedVector4(const TypedVector4 &other)
Definition: tb_vector.hpp:1039
static TypedVector4 Normalize(const TypedVector4< Type > &value)
Definition: tb_vector.hpp:1154
TypedVector4(const TypedVector3< Type > &other, const Type valueW)
Definition: tb_vector.hpp:1012
Type & operator[](const int index)
Definition: tb_vector.hpp:1129
const Type & operator[](const int index) const
Definition: tb_vector.hpp:1122
TypedVector4(const SkipInitialization &fastAndStupid)
Definition: tb_vector.hpp:959
TypedVector4(const Type valueX, const Type valueY, const Type valueZ, const Type valueW)
Definition: tb_vector.hpp:983
TypedVector4(const TypedVector2< Type > &other, const Type valueZ, const Type valueW)
Definition: tb_vector.hpp:998
static TypedVector4 Normalize(const TypedVector4< Type > &value, Type &magnitude)
Definition: tb_vector.hpp:1165
TypedVector4 & operator=(const TypedVector4 &other)
Definition: tb_vector.hpp:1067
TypedVector4(const Type *componentArray)
Definition: tb_vector.hpp:1025
static TypedVector4 Cross(const TypedVector4< Type > &leftSide, const TypedVector4< Type > &rightSide)
Definition: tb_vector.hpp:1144
bool operator==(const TypedVector4 &other) const
Definition: tb_vector.hpp:1085
static TypedVector4 Zero(void)
Definition: tb_vector.hpp:932
static Type Dot(const TypedVector4< Type > &leftSide, const TypedVector4< Type > &rightSide)
Definition: tb_vector.hpp:1135
TypedVector4(void)
Definition: tb_vector.hpp:967
#define tb_unused(parameter)
Definition: tb_defines.hpp:25
#define tb_error_if(errorTest, message,...)
Definition: tb_error.hpp:42
std::string String
Definition: tb_string.hpp:302
Contains objects and functions for dealing with Vector and Matrix math.
Type Vector3DotProduct(const TypedVector3< Type > *leftSide, const TypedVector3< Type > *rightSide)
Definition: tb_vector.hpp:1618
VectorComponent
Definition: tb_vector.hpp:87
@ kComponentY
Definition: tb_vector.hpp:89
@ kComponentZ
Definition: tb_vector.hpp:90
@ kComponentW
Definition: tb_vector.hpp:91
@ kComponentX
Definition: tb_vector.hpp:88
Type Vector3MagnitudeSquared(const TypedVector3< Type > *input)
Definition: tb_vector.hpp:1719
Vector4 * Vector4Add(Vector4 *result, const Vector4 *leftSide, const Vector4 *rightSide)
Definition: tb_vector.hpp:1393
TypedVector4< Type > * Vector4NormalizeMagnitude(TypedVector4< Type > *result, const TypedVector4< Type > *value, Type &magnitude)
Definition: tb_vector.hpp:1869
TypedVector4< Type > * Vector4Normalize(TypedVector4< Type > *result, const TypedVector4< Type > *value)
Definition: tb_vector.hpp:1788
Vector3 * Vector3Negate(Vector3 *result, const Vector3 *input)
Definition: tb_vector.hpp:1575
Type Vector4DotProduct(const TypedVector4< Type > *leftSide, const TypedVector4< Type > *rightSide)
Definition: tb_vector.hpp:1628
Type Vector2MagnitudeSquared(const TypedVector2< Type > *input)
Definition: tb_vector.hpp:1710
static const float kTwoPi
A constant for Pi * 2 stored in a float.
Definition: tb_constants.hpp:20
std::ostream & operator<<(std::ostream &output, const tbMath::TypedAngle< Type > &angle)
Definition: tb_angle.hpp:203
bool IsZero(const Type &value, const Type tolerance=tbMath::kTolerance)
Definition: tb_math.hpp:74
static Angle ForwardVector2ToRotation(const Vector2 &forward)
Definition: tb_vector.hpp:1954
bool IsEqual(const Type &leftValue, const Type &rightValue, const Type tolerance=tbMath::kTolerance)
Definition: tb_math.hpp:56
Vector4 * Vector4Scale(Vector4 *result, const Vector4 *input, const float scalar)
Definition: tb_vector.hpp:1494
Vector4 * Vector4Subtract(Vector4 *result, const Vector4 *leftSide, const Vector4 *rightSide)
Definition: tb_vector.hpp:1445
Vector2 * Vector2ScaleDivide(Vector2 *result, const Vector2 *input, const float scalar)
Definition: tb_vector.hpp:1515
Type Vector3Magnitude(const TypedVector3< Type > *input)
Definition: tb_vector.hpp:1687
Vector3 * Vector3ScaleDivide(Vector3 *result, const Vector3 *input, const float scalar)
Definition: tb_vector.hpp:1528
Vector2 * Vector2Subtract(Vector2 *result, const Vector2 *leftSide, const Vector2 *rightSide)
Definition: tb_vector.hpp:1416
Type Vector4Magnitude(const TypedVector4< Type > *input)
Definition: tb_vector.hpp:1696
TypedVector2< Type > * Vector2NormalizeMagnitude(TypedVector2< Type > *result, const TypedVector2< Type > *value, Type &magnitude)
Definition: tb_vector.hpp:1821
TypedAngle< Type > Vector3AngleBetween(const TypedVector3< Type > *left, const TypedVector3< Type > *right)
Definition: tb_vector.hpp:1897
Type Vector4MagnitudeSquared(const TypedVector4< Type > *input)
Definition: tb_vector.hpp:1728
Vector2 * Vector2Scale(Vector2 *result, const Vector2 *input, const float scalar)
Definition: tb_vector.hpp:1467
Vector3 * Vector3Scale(Vector3 *result, const Vector3 *input, const float scalar)
Definition: tb_vector.hpp:1480
TypedVector2< Type > * Vector2Normalize(TypedVector2< Type > *result, const TypedVector2< Type > *value)
Definition: tb_vector.hpp:1742
Type Vector2Magnitude(const TypedVector2< Type > *input)
Definition: tb_vector.hpp:1678
Vector3 * Vector3Add(Vector3 *result, const Vector3 *leftSide, const Vector3 *rightSide)
Definition: tb_vector.hpp:1378
static Vector3 & RotationXZToForwardVector3(Vector3 &result, const Angle &orientation)
Definition: tb_vector.hpp:1910
SkipInitialization
Definition: tb_vector.hpp:80
Vector4 * Vector4ScaleDivide(Vector4 *result, const Vector4 *input, const float scalar)
Definition: tb_vector.hpp:1542
Vector4 * Vector4Negate(Vector4 *result, const Vector4 *input)
Definition: tb_vector.hpp:1589
Vector2 * Vector2Negate(Vector2 *result, const Vector2 *input)
Definition: tb_vector.hpp:1562
Vector3 * Vector3Subtract(Vector3 *result, const Vector3 *leftSide, const Vector3 *rightSide)
Definition: tb_vector.hpp:1430
Vector2 * Vector2Add(Vector2 *result, const Vector2 *leftSide, const Vector2 *rightSide)
Definition: tb_vector.hpp:1364
static Vector2 & RotationToForwardVector2(Vector2 &result, const Angle &orientation)
Definition: tb_vector.hpp:1922
TypedVector3< Type > * Vector3NormalizeMagnitude(TypedVector3< Type > *result, const TypedVector3< Type > *value, Type &magnitude)
Definition: tb_vector.hpp:1844
TypedVector3< Type > * Vector3CrossProduct(TypedVector3< Type > *result, const TypedVector3< Type > *leftSide, const TypedVector3< Type > *rightSide)
Definition: tb_vector.hpp:1648
Type Vector2DotProduct(const TypedVector2< Type > *leftSide, const TypedVector2< Type > *rightSide)
Definition: tb_vector.hpp:1608
static Angle ForwardVector3ToRotationXZ(const Vector3 &forward)
Definition: tb_vector.hpp:1936
TypedVector3< Type > * Vector3Normalize(TypedVector3< Type > *result, const TypedVector3< Type > *value)
Definition: tb_vector.hpp:1764
Here is some information about the primary namespace.
Definition: tb_application_dialog.hpp:22