#ifndef __GenVector #define __GenVector #include <stdio.h> #include <stdlib.h> #include <math.h> //enable the padding conversion function - slow //#define VECTOR_PADDING_CONVERSION //control if all components are set to zero on construction #define VECTOR_INITIALIZE_TO_ZERO //default vector #define v3float float //error checking for divide by 0 and other degenerate cases //#define VECTOR_ERROR_CHECKING // set an epsilon if not set #ifndef EPSILON #define EPSILON 0.000000001f #endif template <int dimension, class T = v3float, int padding = 0> class GenVector { public: static const int dim = dimension; T c[dimension+padding]; //typically 3 dim of x, y, z // GenVector creation GenVector() { #ifdef VECTOR_INITIALIZE_TO_ZERO for(int i=0; i<dimension; i++) c[i] = 0; #endif } GenVector(const GenVector &source) { for(int i=0; i<dimension; i++) c[i] = source.c[i]; } GenVector(const T *source) { for(int i=0; i<dimension; i++) c[i] = source[i]; } GenVector(const T f) { for(int i=0; i<dimension; i++) c[i] = f; } GenVector(const T x, const T y) { c[0] = x; c[1] = y; } GenVector(const T x, const T y, const T z) { c[0] = x; c[1] = y; c[2] = z; } GenVector(const T x, const T y, const T z, const T w) { c[0] = x; c[1] = y; c[2] = z; c[3] = w; } GenVector(const GenVector &to, const GenVector &from) { for(int i=0; i<dimension; i++) c[i] = to.c[i] - from.c[i]; } #ifdef VECTOR_PADDING_CONVERSION template <int paddingIn> operator GenVector<dimension, T, paddingIn>() const { GenVector<dimension, T, paddingIn> out; for(int i=0; i<dimension; i++) out.c[i] = this->c[i]; return out; } #endif // operator overload GenVector operator+(const GenVector &v1) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] + v1.c[i]; return t; } GenVector operator-(const GenVector &v1) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] - v1.c[i]; return t; } GenVector operator*(const GenVector &v1) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] * v1.c[i]; return t; } GenVector operator/(const GenVector &v1) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] / v1.c[i]; return t; } GenVector operator+(const T f) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] + f; return t; } GenVector operator-(const T f) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] - f; return t; } GenVector operator*(const T f) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] * f; return t; } GenVector operator/(const T f) const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = c[i] / f; return t; } GenVector& operator+=(const GenVector &v1) { for(int i=0; i<dimension; i++) c[i] += v1.c[i]; return *this; } GenVector& operator-=(const GenVector &v1) { for(int i=0; i<dimension; i++) c[i] -= v1.c[i]; return *this; } GenVector& operator*=(const GenVector &v1) { for(int i=0; i<dimension; i++) c[i] *= v1.c[i]; return *this; } GenVector& operator/=(const GenVector &v1) { for(int i=0; i<dimension; i++) c[i] /= v1.c[i]; return *this; } GenVector& operator+=(const T f) { for(int i=0; i<dimension; i++) c[i] += f; return *this; } GenVector& operator-=(const T f) { for(int i=0; i<dimension; i++) c[i] -= f; return *this; } GenVector& operator*=(const T f) { for(int i=0; i<dimension; i++) c[i] *= f; return *this; } GenVector& operator/=(const T f) { for(int i=0; i<dimension; i++) c[i] /= f; return *this; } GenVector& operator=(const GenVector &v1) { for(int i=0; i<dimension; i++) c[i] = v1.c[i]; return *this; } template<int otherDim> GenVector& operator=(const GenVector<otherDim> &v1) { #ifdef VECTOR_ERROR_CHECKING if(otherDim < dimension) { throw(1); } #endif //truncate extra dimension in input vector for(int i=0; i<dimension; i++) c[i] = v1.c[i]; return *this; } GenVector& operator=(const T f) { for(int i=0; i<dimension; i++) c[i] = f; return *this; } bool operator==(const GenVector &v1) const { bool equal = true; for(int i=0; i<dimension; i++) equal = equal && c[i] == v1.c[i]; return equal; } bool operator!=(const GenVector &v1) const { return !(v1 == *this); } GenVector operator-() const { GenVector t; for(int i=0; i<dimension; i++) t.c[i] = -c[i]; return t; } T operator[](const int i) const { return c[i]; } T& operator[](const int i) { return c[i]; } T operator()(const int i) const { return c[i]; } T& operator()(const int i) { return c[i]; } // arithmetic operations T dot(const GenVector &a) const { T f = 0; for(int i=0; i<dimension; i++) f += c[i]*a(i); return f; //return a.c[0]*c[0] + a.c[1]*c[1] + a.c[2]*c[2]; } GenVector cross(const GenVector &a) const { #ifdef VECTOR_ERROR_CHECKING if(dimension!=3) { //throw exception? explode? return (*this); } #endif GenVector dest; dest.c[0] = c[1]*a.c[2] - c[2]*a.c[1]; dest.c[1] = c[2]*a.c[0] - c[0]*a.c[2]; dest.c[2] = c[0]*a.c[1] - c[1]*a.c[0]; return dest; } // GenVector unit operations T squaredLength() const { T sqrdLength = 0.0f; for(int i=0; i<dimension; i++) sqrdLength += c[i] * c[i]; return sqrdLength; } T length() const { return sqrt(this->squaredLength()); } GenVector& normalize() { T normalizeLength; normalizeLength = this->length(); #ifdef VECTOR_ERROR_CHECKING if(normalizeLength <= EPSILON) { throw(1); return *this; } #endif *this /= normalizeLength; return *this; } // GenVector combination operations T distanceSquared(const GenVector &a) { T d = 0.0; for(int i=0; i<dimension; i++) d += pow(a.c[i] - c[i], 2); return d; } T distance(const GenVector& a) { T disSquared = this->distanceSquared(a); return sqrt( disSquared ); } T angleBetweem(const GenVector &a) { return acos(this->dot(a) / this->length() / a.length()); } GenVector reflect(const GenVector &normal) { T dp; GenVector dest; dp = 2*this->dot(normal); dest = *this - (normal*dp); return dest; } void projectToPlane(const GenVector &normal) { float scale = this->dot(normal); *this = *this - (normal * scale); } int maxComponent() { int largest = 0; for(int i=1; i<dimension; i++) if(c[i] > c[i-1]) largest = i; return largest; } int maxMagnitudeComponent() { int largest = 0; for(int i=1; i<dimension; i++) if(fabs(c[i]) > fabs(c[i-1])) largest = i; return largest; } }; template <int dimension, class T, int padding> static GenVector<dimension, T, padding> operator*(const T f, const GenVector<dimension, T, padding> &v1) { return v1*f; } template <int dimension, class T, int padding> static GenVector<dimension, T, padding> operator-(const T f, const GenVector<dimension, T, padding> &v1) { GenVector<dimension, T, padding> t; for(int i=0; i<v1.dim; i++) t[i] = f - v1[i]; return t; } template <int dimension, class T, int padding> static GenVector<dimension, T, padding> operator/(const T f, const GenVector<dimension, T, padding> &v1) { GenVector<dimension, T, padding> t; for(int i=0; i<v1.dim; i++) t[i] = f / v1[i]; return t; } typedef GenVector<2> Vector2; typedef GenVector<3> Vector3; typedef GenVector<4> Vector4; typedef GenVector<3, unsigned char> Color; #endif