2008-06-24 03:17:31 -07:00
|
|
|
#ifndef _VECTOR3_H
|
|
|
|
#define _VECTOR3_H
|
|
|
|
|
|
|
|
#include <math.h>
|
2010-04-24 12:22:34 -07:00
|
|
|
#include <stdio.h>
|
2011-09-03 16:05:42 -07:00
|
|
|
#include "FloatComparison.h"
|
2008-06-24 03:17:31 -07:00
|
|
|
|
2011-02-08 17:59:36 -08:00
|
|
|
// Need this pragma due to operator[] implementation.
|
|
|
|
#pragma pack(4)
|
|
|
|
|
2011-10-27 20:12:22 -07:00
|
|
|
template <typename T> struct other_floating_type {};
|
|
|
|
template <> struct other_floating_type<float> { typedef double type; };
|
|
|
|
template <> struct other_floating_type<double> { typedef float type; };
|
|
|
|
|
2008-06-24 03:17:31 -07:00
|
|
|
template <typename T>
|
|
|
|
class vector3 {
|
2011-02-08 17:59:36 -08:00
|
|
|
public:
|
2008-06-24 03:17:31 -07:00
|
|
|
T x,y,z;
|
|
|
|
|
2011-02-08 21:01:59 -08:00
|
|
|
// Constructor definitions are outside class declaration to enforce that
|
|
|
|
// only float and double versions are possible.
|
|
|
|
vector3();
|
2011-10-27 20:12:22 -07:00
|
|
|
vector3(const vector3<T> &v);
|
|
|
|
vector3(const T vals[3]);
|
2011-02-08 21:01:59 -08:00
|
|
|
vector3(T val);
|
|
|
|
vector3(T _x, T _y, T _z);
|
2011-10-27 20:12:22 -07:00
|
|
|
|
|
|
|
// disallow implicit conversion between floating point sizes
|
|
|
|
explicit vector3(const vector3<typename other_floating_type<T>::type> &v);
|
|
|
|
explicit vector3(const typename other_floating_type<T>::type vals[3]);
|
2011-02-13 16:40:43 -08:00
|
|
|
|
2011-05-10 17:57:37 -07:00
|
|
|
const T& operator[](const size_t i) const { return (const_cast<const T *>(&x))[i]; }
|
2011-02-13 16:40:43 -08:00
|
|
|
T& operator[](const size_t i) { return (&x)[i]; }
|
|
|
|
|
|
|
|
vector3 operator+(const vector3 &a) const { return vector3 (a.x+x, a.y+y, a.z+z); }
|
|
|
|
vector3 &operator+=(const vector3 &a) { x+=a.x; y+=a.y; z+=a.z; return *this; }
|
|
|
|
vector3 &operator-=(const vector3 &a) { x-=a.x; y-=a.y; z-=a.z; return *this; }
|
|
|
|
vector3 &operator*=(const float a) { x*=a; y*=a; z*=a; return *this; }
|
|
|
|
vector3 &operator*=(const double a) { x*=a; y*=a; z*=a; return *this; }
|
2011-05-10 17:57:37 -07:00
|
|
|
vector3 &operator/=(const float a) { const T inva = T(1.0/a); x*=inva; y*=inva; z*=inva; return *this; }
|
|
|
|
vector3 &operator/=(const double a) { const T inva = T(1.0/a); x*=inva; y*=inva; z*=inva; return *this; }
|
2011-02-13 16:40:43 -08:00
|
|
|
vector3 operator-(const vector3 &a) const { return vector3(x-a.x, y-a.y, z-a.z); }
|
|
|
|
vector3 operator-() const { return vector3(-x, -y, -z); }
|
2011-08-15 23:35:02 -07:00
|
|
|
|
2011-08-18 18:27:30 -07:00
|
|
|
bool ExactlyEqual(const vector3 &a) const {
|
2012-02-18 19:22:01 -08:00
|
|
|
return is_equal_exact(a.x, x) && is_equal_exact(a.y, y) && is_equal_exact(a.z, z);
|
2011-08-18 18:27:30 -07:00
|
|
|
}
|
2011-02-13 16:40:43 -08:00
|
|
|
|
2011-05-10 17:57:37 -07:00
|
|
|
friend vector3 operator*(const vector3 &a, const float scalar) { return vector3(T(a.x*scalar), T(a.y*scalar), T(a.z*scalar)); }
|
|
|
|
friend vector3 operator*(const vector3 &a, const double scalar) { return vector3(T(a.x*scalar), T(a.y*scalar), T(a.z*scalar)); }
|
2011-02-13 16:40:43 -08:00
|
|
|
friend vector3 operator*(const float scalar, const vector3 &a) { return a*scalar; }
|
|
|
|
friend vector3 operator*(const double scalar, const vector3 &a) { return a*scalar; }
|
2011-05-10 17:57:37 -07:00
|
|
|
friend vector3 operator/(const vector3 &a, const float scalar) { const T inv = 1.0/scalar; return vector3(a.x*inv, a.y*inv, a.z*inv); }
|
|
|
|
friend vector3 operator/(const vector3 &a, const double scalar) { const T inv = 1.0/scalar; return vector3(a.x*inv, a.y*inv, a.z*inv); }
|
2008-06-24 03:17:31 -07:00
|
|
|
|
2011-02-13 16:40:43 -08:00
|
|
|
vector3 Cross(const vector3 &b) const { return vector3 (y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x); }
|
|
|
|
T Dot(const vector3 &b) const { return x*b.x + y*b.y + z*b.z; }
|
2011-02-08 21:01:59 -08:00
|
|
|
T Length() const { return sqrt (x*x + y*y + z*z); }
|
2011-02-16 21:41:14 -08:00
|
|
|
T LengthSqr() const { return x*x + y*y + z*z; }
|
2011-02-08 21:01:59 -08:00
|
|
|
vector3 Normalized() const { const T l = 1.0f / sqrt(x*x + y*y + z*z); return vector3(x*l, y*l, z*l); }
|
2011-02-16 21:41:14 -08:00
|
|
|
vector3 NormalizedSafe() const {
|
2011-08-18 18:27:57 -07:00
|
|
|
const T lenSqr = x*x + y*y + z*z;
|
|
|
|
if (lenSqr < 1e-18) // sqrt(lenSqr) < 1e-9
|
|
|
|
return vector3(1,0,0);
|
|
|
|
else {
|
|
|
|
const T l = sqrt(lenSqr);
|
|
|
|
return vector3(x/l, y/l, z/l);
|
|
|
|
}
|
2011-02-16 21:41:14 -08:00
|
|
|
}
|
2008-06-24 03:17:31 -07:00
|
|
|
|
2011-02-08 21:01:59 -08:00
|
|
|
void Print() const { printf("v(%f,%f,%f)\n", x, y, z); }
|
2008-06-24 03:17:31 -07:00
|
|
|
|
|
|
|
/* Rotate this vector about point o, in axis defined by v. */
|
2011-02-08 21:01:59 -08:00
|
|
|
void ArbRotateAroundPoint(const vector3 &o, const vector3 &__v, T ang) {
|
2008-06-24 03:17:31 -07:00
|
|
|
vector3 t;
|
|
|
|
T a = o.x;
|
|
|
|
T b = o.y;
|
|
|
|
T c = o.z;
|
|
|
|
T u = __v.x;
|
|
|
|
T v = __v.y;
|
|
|
|
T w = __v.z;
|
2011-05-10 17:57:37 -07:00
|
|
|
T cos_a = cos (ang);
|
|
|
|
T sin_a = sin (ang);
|
2008-06-24 03:17:31 -07:00
|
|
|
T inv_poo = 1.0f/(u*u+v*v+w*w);
|
|
|
|
t.x = a*(v*v+w*w)+u*(-b*v-c*w+u*x+v*y+w*z)+(-a*(v*v+w*w)+u*(b*v+c*w-v*y-w*z)+(v*v+w*w)*x)*cos_a+
|
|
|
|
sqrtf (u*u+v*v+w*w)*(-c*v+b*w-w*y+v*z)*sin_a;
|
|
|
|
t.x *= inv_poo;
|
|
|
|
t.y = b*(u*u+w*w)+v*(-a*u-c*w+u*x+v*y+w*z)+(-b*(u*u+w*w)+v*(a*u+c*w-u*x-w*z)+(u*u+w*w)*y)*cos_a+
|
|
|
|
sqrtf (u*u+v*v+w*w)*(-c*u-a*w+w*x-u*z)*sin_a;
|
|
|
|
t.y *= inv_poo;
|
|
|
|
t.z = c*(u*u+v*v)+w*(-a*u+b*v+u*x+v*y+w*z)+(-c*(u*u+v*v)+w*(a*u+b*v-u*x-v*y)+(u*u+v*v)*z)*cos_a+
|
|
|
|
sqrtf (u*u+v*v+w*w)*(-b*u+a*v-v*x+u*y)*sin_a;
|
|
|
|
t.z *= inv_poo;
|
|
|
|
*this = t;
|
|
|
|
}
|
2011-02-08 21:01:59 -08:00
|
|
|
|
2008-06-24 03:17:31 -07:00
|
|
|
/* Rotate this vector about origin, in axis defined by v. */
|
2011-02-08 21:01:59 -08:00
|
|
|
void ArbRotate(const vector3 &__v, T ang) {
|
2008-06-24 03:17:31 -07:00
|
|
|
vector3 t;
|
|
|
|
T u = __v.x;
|
|
|
|
T v = __v.y;
|
|
|
|
T w = __v.z;
|
2011-05-10 17:57:37 -07:00
|
|
|
T cos_a = cos(ang);
|
|
|
|
T sin_a = sin(ang);
|
2008-06-24 03:17:31 -07:00
|
|
|
T inv_poo = 1.0f/(u*u+v*v+w*w);
|
|
|
|
t.x = u*(u*x+v*y+w*z)+(u*(-v*y-w*z)+(v*v+w*w)*x)*cos_a+
|
|
|
|
sqrtf (u*u+v*v+w*w)*(-w*y+v*z)*sin_a;
|
|
|
|
t.x *= inv_poo;
|
|
|
|
t.y = v*(u*x+v*y+w*z)+(v*(-u*x-w*z)+(u*u+w*w)*y)*cos_a+
|
|
|
|
sqrtf (u*u+v*v+w*w)*(w*x-u*z)*sin_a;
|
|
|
|
t.y *= inv_poo;
|
|
|
|
t.z = w*(u*x+v*y+w*z)+(w*(-u*x-v*y)+(u*u+v*v)*z)*cos_a+
|
|
|
|
sqrtf (u*u+v*v+w*w)*(-v*x+u*y)*sin_a;
|
|
|
|
t.z *= inv_poo;
|
|
|
|
*this = t;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-02-08 21:01:59 -08:00
|
|
|
// These are here in this manner to enforce that only float and double versions are possible.
|
|
|
|
template<> inline vector3<float >::vector3() {}
|
|
|
|
template<> inline vector3<double>::vector3() {}
|
|
|
|
template<> inline vector3<float >::vector3(const vector3<float > &v): x(v.x), y(v.y), z(v.z) {}
|
2011-05-10 17:57:37 -07:00
|
|
|
template<> inline vector3<float >::vector3(const vector3<double> &v): x(float(v.x)), y(float(v.y)), z(float(v.z)) {}
|
2011-02-08 21:01:59 -08:00
|
|
|
template<> inline vector3<double>::vector3(const vector3<float > &v): x(v.x), y(v.y), z(v.z) {}
|
|
|
|
template<> inline vector3<double>::vector3(const vector3<double> &v): x(v.x), y(v.y), z(v.z) {}
|
|
|
|
template<> inline vector3<float >::vector3(float val): x(val), y(val), z(val) {}
|
|
|
|
template<> inline vector3<double>::vector3(double val): x(val), y(val), z(val) {}
|
|
|
|
template<> inline vector3<float >::vector3(float _x, float _y, float _z): x(_x), y(_y), z(_z) {}
|
|
|
|
template<> inline vector3<double>::vector3(double _x, double _y, double _z): x(_x), y(_y), z(_z) {}
|
|
|
|
template<> inline vector3<float >::vector3(const float vals[3]): x(vals[0]), y(vals[1]), z(vals[2]) {}
|
2011-05-10 17:57:37 -07:00
|
|
|
template<> inline vector3<float >::vector3(const double vals[3]): x(float(vals[0])), y(float(vals[1])), z(float(vals[2])) {}
|
2011-02-13 16:40:43 -08:00
|
|
|
template<> inline vector3<double>::vector3(const float vals[3]): x(vals[0]), y(vals[1]), z(vals[2]) {}
|
2011-02-08 21:01:59 -08:00
|
|
|
template<> inline vector3<double>::vector3(const double vals[3]): x(vals[0]), y(vals[1]), z(vals[2]) {}
|
|
|
|
|
2011-02-08 17:59:36 -08:00
|
|
|
#pragma pack()
|
2009-05-31 13:44:03 -07:00
|
|
|
|
2011-02-08 21:01:59 -08:00
|
|
|
typedef vector3<float > vector3f;
|
2008-06-24 03:17:31 -07:00
|
|
|
typedef vector3<double> vector3d;
|
|
|
|
|
|
|
|
#endif /* _VECTOR3_H */
|