Fix issue in Rocket.lua script.
[Cafu-Engine.git] / Libs / Math3D / Vector3.hpp
blobed6ea1729c5df4981835d8e897fba0f071d38b5b
1 /*
2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
5 */
7 #ifndef CAFU_MATH_VECTOR3_HPP_INCLUDED
8 #define CAFU_MATH_VECTOR3_HPP_INCLUDED
10 #include "Errors.hpp"
12 #include <cassert>
13 #include <cmath>
14 #include <iomanip>
15 #include <limits>
16 #include <sstream>
19 /// This class represents a polymorphic 3-dimensional vector.
20 ///
21 /// In order to clearly distinguish between methods that modify their "this" Vector3T<T> and those that don't,
22 /// the general idea is that all const, non-modifying methods start with "Get", e.g. GetLength().
23 /// However the dot() and cross() methods are exceptions for increased readability of user code.
24 /// Semantically and intuitively, we prefer to treat them as special binary infix operators as we do in
25 /// hand-written math -- its just the C++ language that doesn't provide us with appropriate symbols.
26 ///
27 /// For operators, it is intuitively clear whether they modify the this object or not.
28 /// E.g. the += operator modifies the this object, the + operator does not.
29 /// Note that there is no need to define "constructive", binary infix operators (like the + operator)
30 /// outside (that is, not as members) of this class, because promotion of the left-hand argument as described
31 /// in the C++ FAQs does not occur in and thus is not relevant for this class (we have no constructor to
32 /// promote a built-in type to a Vector3T<T>).
33 /// See http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.9 items 5 to 7 (especially 7)
34 /// and http://www.parashift.com/c++-faq-lite/friends.html#faq-14.5 for details about this.
35 template<class T>
36 class Vector3T
38 public:
40 T x; ///< The x-component of this vector.
41 T y; ///< The y-component of this vector.
42 T z; ///< The z-component of this vector.
46 /// The default constructor. It initializes all components to zero.
47 Vector3T() : x(0), y(0), z(0) { }
49 /// This constructor initializes the components from x_, y_ and z_ respectively.
50 Vector3T(T x_, T y_, T z_) : x(x_), y(y_), z(z_) { }
52 /// This constructor initializes the components from an array of (at least) three Ts.
53 template<class C> explicit Vector3T(const C Values[]) : x(T(Values[0])), y(T(Values[1])), z(T(Values[2])) { }
57 /// Returns true if the vector is valid, that is, all components are non-NANs.
58 bool IsValid() const
60 return true;
63 /// Component access by index number (0 to 2) rather than by name.
64 /// @param Index Index of the component to access. Can only be 0, 1 or 2 (for x, y, z).
65 /// @throws InvalidOperationE if Index is not 0, 1 or 2.
66 T& operator [] (unsigned int Index)
68 switch (Index)
70 case 0: return x;
71 case 1: return y;
72 case 2: return z;
73 default: throw InvalidOperationE();
77 /// Component access by index number (0 to 2) rather than by name.
78 /// @param Index Index of the component to access. Can only be 0, 1 or 2 (for x, y, z).
79 /// @throws InvalidOperationE if Index is not 0, 1 or 2.
80 const T& operator [] (unsigned int Index) const
82 switch (Index)
84 case 0: return x;
85 case 1: return y;
86 case 2: return z;
87 default: throw InvalidOperationE();
93 /// Gets this Vector3T<T> as a Vector3T<float>, so that the cast is explicitly visible in user code.
94 Vector3T<float> AsVectorOfFloat() const
96 #ifdef _WIN32
97 assert(typeid(T)!=typeid(float));
98 #endif
100 return Vector3T<float>(float(x), float(y), float(z));
103 /// Gets this Vector3T<T> as a Vector3T<double>, so that the cast is explicitly visible in user code.
104 Vector3T<double> AsVectorOfDouble() const
106 #ifdef _WIN32
107 assert(typeid(T)!=typeid(double));
108 #endif
110 return Vector3T<double>(double(x), double(y), double(z));
113 /// Gets this Vector3T<T> as a Vector3T<int>, so that the cast is explicitly visible in user code.
114 Vector3T<int> AsVectorOfInt() const
116 return Vector3T<int>(int(x), int(y), int(z));
121 /// @name Group of const inspector methods. They are all const and thus do not modify this object.
122 //@{
124 // I've commented out this method because class methods of a template cannot be indivially specialized.
125 // That it, the GetLength() method cannot be individually be specialized for floats.
126 // Use the global length() function (defined below) instead!
127 // /// Returns the length of this vector.
128 // T GetLength() const { return sqrt(GetLengthSqr()); }
130 /// Returns the square of the length of this vector.
131 T GetLengthSqr() const { return x*x + y*y + z*z; }
133 /// Returns whether this vector is equal to B within tolerance Epsilon, that is, whether it is geometrically closer to B than Epsilon.
134 /// @param B Vector to compare to.
135 /// @param Epsilon Tolerance value.
136 /// @see operator ==
137 bool IsEqual(const Vector3T<T>& B, const T Epsilon) const
139 return (*this-B).GetLengthSqr() <= Epsilon*Epsilon;
142 /// Returns a copy of this vector scaled by s, that is, the scalar product (Skalarmultiplikation) of this vector and s.
143 /// @param s Scale factor to scale this vector by.
144 /// @see Also see the operator *, which does exactly the same.
145 Vector3T<T> GetScaled(const T s) const
147 return Vector3T<T>(x*s, y*s, z*s);
150 /// Returns a copy of this vector non-uniformely scaled by S.
151 Vector3T<T> GetScaled(const Vector3T<T>& S) const
153 return Vector3T<T>(x*S.x, y*S.y, z*S.z);
156 /// Returns a copy of this vector rotated around the x-axis by Angle degrees.
157 Vector3T<T> GetRotX(const T Angle) const
159 const T RadAngle=Angle*T(3.14159265358979323846/180.0);
160 const T SinAngle=sin(RadAngle);
161 const T CosAngle=cos(RadAngle);
163 return Vector3T<T>(x,
164 CosAngle*y-SinAngle*z,
165 SinAngle*y+CosAngle*z);
168 /// Returns a copy of this vector rotated around the y-axis by Angle degrees.
169 Vector3T<T> GetRotY(const T Angle) const
171 const T RadAngle=Angle*T(3.14159265358979323846/180.0);
172 const T SinAngle=sin(RadAngle);
173 const T CosAngle=cos(RadAngle);
175 return Vector3T<T>(CosAngle*x+SinAngle*z,
177 -SinAngle*x+CosAngle*z);
180 /// Returns a copy of this vector rotated around the z-axis by Angle degrees.
181 Vector3T<T> GetRotZ(const T Angle) const
183 const T RadAngle=Angle*T(3.14159265358979323846/180.0);
184 const T SinAngle=sin(RadAngle);
185 const T CosAngle=cos(RadAngle);
187 return Vector3T<T>(CosAngle*x-SinAngle*y,
188 SinAngle*x+CosAngle*y,
192 /// Returns two vectors that are orthogonal to this vector and to each other.
193 void CreateOrthoVectors(Vector3T<T>& Left, Vector3T<T>& Down) const
195 const T DistSqr=x*x+y*y;
197 if (DistSqr==0)
199 Left.x=1;
200 Left.y=0;
201 Left.z=0;
203 else
205 const T Dist=sqrt(DistSqr);
207 Left.x=-y/Dist;
208 Left.y=x/Dist;
209 Left.z=0;
212 Down=Left.cross(*this);
215 //@}
219 /// @name Group of (constructive) binary operators that do not modify their operands.
220 //@{
222 /// Returns whether this vector and B are truly (bit-wise) identical.
223 /// Use this operator with care, as it comes *without* any epsilon threshold for taking rounding errors into account.
224 /// @param B Vector to compare to.
225 /// @see IsEqual()
226 bool operator == (const Vector3T<T>& B) const
228 return x==B.x &&
229 y==B.y &&
230 z==B.z;
233 /// Returns whether this vector and B are not equal (bit-wise).
234 /// Use this operator with care, as it comes *without* any epsilon threshold for taking rounding errors into account.
235 /// @param B Vector to compare to.
236 /// @see IsEqual()
237 bool operator != (const Vector3T<T>& B) const
239 return x!=B.x ||
240 y!=B.y ||
241 z!=B.z;
244 /// Returns the sum of this Vector3T<T> and B.
245 Vector3T<T> operator + (const Vector3T<T>& B) const
247 return Vector3T<T>(x+B.x, y+B.y, z+B.z);
250 /// Returns the difference between this Vector3T<T> and B.
251 Vector3T<T> operator - (const Vector3T<T>& B) const
253 return Vector3T<T>(x-B.x, y-B.y, z-B.z);
256 /// The unary minus operator. B=-A is quasi identical with B=A.GetScaled(-1).
257 Vector3T<T> operator - () const
259 return Vector3T<T>(-x, -y, -z);
262 /// Returns a copy of this vector scaled by s, that is, the scalar product (Skalarmultiplikation) of this vector and s.
263 /// @param s Factor to multiply this vector with.
264 /// @see GetScaled(), which does exactly the same.
265 Vector3T<T> operator * (const T s) const
267 return GetScaled(s);
270 /// Returns a copy of this vector divided by s, that is, the scalar product (Skalarmultiplikation) of this vector and 1/s.
271 Vector3T<T> operator / (const T s) const
273 // Cannot multiply by the reciprocal, because that won't work with integers.
274 return Vector3T<T>(x/s, y/s, z/s);
277 /// Returns the dot product (Skalarprodukt) of this vector and B.
278 T dot(const Vector3T<T>& B) const
280 return x*B.x + y*B.y + z*B.z;
283 /// Returns the cross product (Vektorprodukt) of this vector and B.
284 Vector3T<T> cross(const Vector3T<T>& B) const
286 return Vector3T<T>(y*B.z - z*B.y,
287 z*B.x - x*B.z,
288 x*B.y - y*B.x);
291 //@}
295 /// @name Group of operators that modify this vector.
296 //@{
298 /// Adds B to this vector.
299 Vector3T<T>& operator += (const Vector3T<T>& B)
301 x+=B.x;
302 y+=B.y;
303 z+=B.z;
305 return *this;
308 /// Subtracts B from this vector.
309 Vector3T<T>& operator -= (const Vector3T<T>& B)
311 x-=B.x;
312 y-=B.y;
313 z-=B.z;
315 return *this;
318 /// Scales this vector by s.
319 Vector3T<T>& operator *= (const T s)
321 x*=s;
322 y*=s;
323 z*=s;
325 return *this;
328 /// Divides this vector by s. Assumes that s is not 0.
329 Vector3T<T>& operator /= (const T s)
331 // Cannot multiply by the reciprocal, because that won't work with integers.
332 x/=s;
333 y/=s;
334 z/=s;
336 return *this;
339 //@}
343 /// Returns A scaled by r, that is, the scalar product (Skalarmultiplikation) of A and r.
344 template<class T> inline Vector3T<T> scale(const Vector3T<T>& A, const T r)
346 return Vector3T<T>(A.x*r, A.y*r, A.z*r);
349 /// Returns A, non-uniformely scaled by R.
350 template<class T> inline Vector3T<T> scale(const Vector3T<T>& A, const Vector3T<T>& R)
352 return Vector3T<T>(A.x*R.x, A.y*R.y, A.z*R.z);
355 /// Returns the dot product (Skalarprodukt) of A and B.
356 template<class T> inline T dot(const Vector3T<T>& A, const Vector3T<T>& B)
358 return A.x*B.x + A.y*B.y + A.z*B.z;
361 /// Returns the cross product (Vektorprodukt) of A and B.
362 template<class T> inline Vector3T<T> cross(const Vector3T<T>& A, const Vector3T<T>& B)
364 return Vector3T<T>(A.y*B.z-A.z*B.y,
365 A.z*B.x-A.x*B.z,
366 A.x*B.y-A.y*B.x);
369 /// Returns the length of A.
370 template<class T> inline T length(const Vector3T<T>& A)
372 return sqrt(dot(A, A));
375 /// Returns the length of A. This is a specialized version of the generic length<T> function for floats.
376 template<> inline float length(const Vector3T<float>& A)
378 return sqrtf(dot(A, A));
381 /// Returns the normalized (unit length) version of A.
382 /// @throws DivisionByZeroE if length(A)<=Epsilon.
383 template<class T> inline Vector3T<T> normalize(const Vector3T<T>& A, const T Epsilon)
385 const T Length=length(A);
387 // I'm using <= here rather than only <, so that Epsilon==0 yields a meaningful test (e.g. if T==int).
388 if (Length<=Epsilon) throw DivisionByZeroE();
390 return A/Length;
393 /// Returns the normalized (unit length) version of A if length(A)>Epsilon, or the (0, 0, 0) vector otherwise.
394 template<class T> inline Vector3T<T> normalizeOr0(const Vector3T<T>& A, const T Epsilon=0)
396 const T Length=length(A);
398 return (Length>Epsilon) ? scale(A, T(1.0)/Length) : Vector3T<T>(0, 0, 0);
401 template<class T> inline std::string convertToString(const Vector3T<T>& A)
403 // From MSDN documentation: "digits10 returns the number of decimal digits that the type can represent without loss of precision."
404 // For floats, that's usually 6, for doubles, that's usually 15. However, we want to use the number of *significant* decimal digits here,
405 // see http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2006/n2005.pdf for details.
406 const int sigdigits=std::numeric_limits<T>::digits10 + 3;
408 std::ostringstream out;
410 out << std::setprecision(sigdigits) << "(" << A.x << ", " << A.y << ", " << A.z << ")";
412 return out.str();
416 template<class T> inline std::ostream& operator << (std::ostream& os, const Vector3T<T>& A)
418 return os << "(" << A.x << ", " << A.y << ", " << A.z << ")";
422 /// Typedef for a Vector3T of floats.
423 typedef Vector3T<float> Vector3fT;
425 /// Typedef for a Vector3T of doubles.
426 typedef Vector3T<double> Vector3dT;
427 typedef Vector3T<double> VectorT; // For compatibility with the old VectorT class.
429 /// Typedef for a Vector3T of ints.
430 typedef Vector3T<int> Vector3iT;
432 #endif