#ifndef _VECTOR_H_
#define _VECTOR_H_
#include <vDEC/include/vdec_types.h>
#include <cstdlib>
#include <cmath>
struct Vec2{ real x, y; inline static const Vec2 Zero(); inline static const Vec2 Basis(unsigned int which); inline Vec2();
inline Vec2(const Vec2 &V);
inline Vec2(const real &_x, const real &_y);
inline Vec2& operator=(const Vec2 &V); inline static Vec2 RandomNormal();
inline Vec2& operator *= (const real &C);
inline Vec2& operator /= (const real &C);
inline Vec2& operator += (const Vec2 &Right);
inline Vec2& operator -= (const Vec2 &Right); inline real& operator [] (unsigned int axis); inline real operator [] (unsigned int axis) const; inline void Normalize(); inline real Length() const; inline real LengthSq() const; inline static real Dot(const Vec2 &Left, const Vec2 &Right); inline static real Cross(const Vec2 &Left, const Vec2 &Right);
};inline Vec2 operator * (const Vec2 &Left, real Right);
inline Vec2 operator * (real Left, const Vec2 &Right);
inline Vec2 operator / (const Vec2 &Left, real Right);
inline Vec2 operator + (const Vec2 &Left, const Vec2 &Right);
inline Vec2 operator - (const Vec2 &Left, const Vec2 &Right);
inline Vec2 operator - (const Vec2 &V);
struct Vec3 { real x, y, z; inline static const Vec3 Zero(); inline static const Vec3 Basis(unsigned int which); inline Vec3();
inline Vec3(const Vec3 &V);
inline Vec3(const real &_x, const real &_y, const real &_z);
inline Vec3& operator=(const Vec3 &V); inline static Vec3 RandomNormal();
inline Vec3& operator *= (const real &C);
inline Vec3& operator /= (const real &C);
inline Vec3& operator += (const Vec3 &Right);
inline Vec3& operator -= (const Vec3 &Right); inline real& operator [] (unsigned int axis); inline real operator [] (unsigned int axis) const; inline void Normalize(); inline real Length() const; inline real LengthSq() const; inline static Vec3 Cross(const Vec3 &Left, const Vec3 &Right); inline static real Dot(const Vec3 &Left, const Vec3 &Right); inline static real AngleBetween(const Vec3 &Left, const Vec3 &Right); inline static void MakeBasis(const Vec3 &v0, Vec3 &v1, Vec3 &v2);
};inline Vec3 operator * (const Vec3 &Left, real Right);
inline Vec3 operator * (real Left, const Vec3 &Right);
inline Vec3 operator / (const Vec3 &Left, real Right);
inline Vec3 operator + (const Vec3 &Left, const Vec3 &Right);
inline Vec3 operator - (const Vec3 &Left, const Vec3 &Right);
inline Vec3 operator - (const Vec3 &V);
struct Vec4 { real x, y, z, w; inline Vec4();
inline Vec4(const Vec4 &V);
inline Vec4(const real &_x, const real &_y, const real &_z, const real &_w);
inline Vec4& operator = (const Vec4 &V);
inline Vec4& operator *= (const real &C);
inline Vec4& operator /= (const real &C);
inline Vec4& operator += (const Vec4 &Right);
inline Vec4& operator -= (const Vec4 &Right); inline real& operator [] (unsigned int axis); inline real operator [] (unsigned int axis) const; inline void Normalize(); inline real Length() const; inline real LengthSq() const; inline static real Dot(const Vec4 &Left, const Vec4 &Right);
};inline Vec4 operator * (const Vec4 &Left, real Right);
inline Vec4 operator * (real Left, const Vec4 &Right);
inline Vec4 operator / (const Vec4 &Left, real Right);
inline Vec4 operator + (const Vec4 &Left, const Vec4 &Right);
inline Vec4 operator - (const Vec4 &Left, const Vec4 &Right);
inline Vec4 operator - (const Vec4 &V);template <unsigned int N>
struct Vec{
real e[N];
Vec<N>& operator = (const Vec<N> &V){ for(unsigned int i = 0; i < N; ++i){ e[i] = V.e[i]; } return *this; }
Vec<N>& operator *= (const real &C){ for(unsigned int i = 0; i < N; ++i){ e[i] *= C; } return *this; }
Vec<N>& operator /= (const real &C){ real f = (real)1.0/C; for(unsigned int i = 0; i < N; ++i){ e[i] *= f; } return *this; }
Vec<N>& operator += (const Vec<N> &Right){ for(unsigned int i = 0; i < N; ++i){ e[i] += Right.e[i]; } return *this; }
Vec<N>& operator -= (const Vec<N> &Right){ for(unsigned int i = 0; i < N; ++i){ e[i] -= Right.e[i]; } return *this; } real& operator [] (unsigned int axis){ return e[axis]; } real operator [] (unsigned int axis) const{ return e[axis]; } void Normalize(){ real l = Length(); for(unsigned int i = 0; i < N; ++i){ e[i] /= l; } } real Length() const{ return (real)VDEC_SQRT(LengthSq()); } real LengthSq() const{ real s = 0; for(unsigned int i = 0; i < N; ++i){ s += e[i]*e[i]; } return s; } static real Dot(const Vec<N> &Left, const Vec<N> &Right){
real s = 0;
for(unsigned int i = 0; i < N; ++i){ s += Left.e[i] * Right.e[i]; }
return s;
}
};
template <unsigned int N>
Vec<N> operator * (const Vec<N> &V, const real &C){
Vec<N> Result(V);
return (Result *= C);
}
template <unsigned int N>
Vec<N> operator * (const real &C, const Vec<N> &V){
Vec<N> Result(V);
return (Result *= C);
}
template <unsigned int N>
Vec<N> operator / (const Vec<N> &V, const real &C){
Vec<N> Result(V);
return (Result /= C);
}
template <unsigned int N>
Vec<N> operator + (const Vec<N> &Left, const Vec<N> &Right){
Vec<N> Result(Left);
return (Result += Right);
}
template <unsigned int N>
Vec<N> operator - (const Vec<N> &Left, const Vec<N> &Right){
Vec<N> Result(Left);
return (Result -= Right);
}
template <unsigned int N>
Vec<N> operator - (const Vec<N> &V){
Vec<N> Result(V);
return (Result *= -1);
}inline real operator^(const Vec<2> &Left, const Vec<2> &Right);inline Vec<3> operator^(const Vec<3> &Left, const Vec<3> &Right);
const Vec2 Vec2::Zero(){
static const Vec2 z(0,0);
return z;
}
const Vec2 Vec2::Basis(unsigned int which){
static const Vec2 bases[2] = {Vec2(1,0), Vec2(0,1)};
return bases[which];
}
Vec2::Vec2():x(0),y(0){}
Vec2::Vec2(const Vec2 &V):x(V.x),y(V.y){}
Vec2::Vec2(const real &_x, const real &_y):x(_x),y(_y){}
Vec2& Vec2::operator=(const Vec2 &V){
x = V.x;
y = V.y;
return *this;
}
Vec2 Vec2::RandomNormal(){
real theta = (real)(real(rand()) * 2.0 * M_PI / (real)RAND_MAX);
return Vec2(VDEC_COS(theta), VDEC_SIN(theta));
}
Vec2& Vec2::operator *= (const real &C){ x *= C; y *= C; return *this; }
Vec2& Vec2::operator /= (const real &C){ x /= C; y /= C; return *this; }
Vec2& Vec2::operator += (const Vec2 &Right){ x += Right.x; y += Right.y; return *this; }
Vec2& Vec2::operator -= (const Vec2 &Right){ x -= Right.x; y -= Right.y; return *this; }
real& Vec2::operator [] (unsigned int axis) { return ((real*)this)[axis]; }
real Vec2::operator [] (unsigned int axis) const{ return ((real*)this)[axis]; }
void Vec2::Normalize(){
real s = (real)1.0/Length();
x *= s; y *= s;
}
real Vec2::Length() const{ return (real)VDEC_SQRT(x*x+y*y); }
real Vec2::LengthSq() const{ return (real)(x*x+y*y); }
real Vec2::Dot(const Vec2 &Left, const Vec2 &Right){ return (Left.x * Right.x + Left.y * Right.y); }
real Vec2::Cross(const Vec2 &Left, const Vec2 &Right){ return Left.x * Right.y - Left.y * Right.x; }
Vec2 operator * (const Vec2 &Left, real Right){
Vec2 Return;
Return.x = Left.x * Right;
Return.y = Left.y * Right;
return Return;
}
Vec2 operator * (real Right, const Vec2 &Left){
Vec2 Return;
Return.x = Left.x * Right;
Return.y = Left.y * Right;
return Return;
}
Vec2 operator / (const Vec2 &Left, real Right){
Vec2 Return;
Return.x = Left.x / Right;
Return.y = Left.y / Right;
return Return;
}
Vec2 operator + (const Vec2 &Left, const Vec2 &Right){
Vec2 Return;
Return.x = Left.x + Right.x;
Return.y = Left.y + Right.y;
return Return;
}
Vec2 operator - (const Vec2 &Left, const Vec2 &Right){
Vec2 Return;
Return.x = Left.x - Right.x;
Return.y = Left.y - Right.y;
return Return;
}
Vec2 operator - (const Vec2 &V){
Vec2 Result;
Result.x = -V.x;
Result.y = -V.y;
return Result;
}
const Vec3 Vec3::Zero(){
static const Vec3 z(0,0,0);
return z;
}
const Vec3 Vec3::Basis(unsigned int which){
static const Vec3 bases[3] = {Vec3(1,0,0), Vec3(0,1,0), Vec3(0,0,1)};
return bases[which];
}
Vec3::Vec3():x(0),y(0),z(0){}
Vec3::Vec3(const Vec3 &V):x(V.x),y(V.y),z(V.z){}
Vec3::Vec3(const real &_x, const real &_y, const real &_z):x(_x),y(_y),z(_z){}
Vec3& Vec3::operator=(const Vec3 &V){
x = V.x;
y = V.y;
z = V.z;
return *this;
}
Vec3 Vec3::RandomNormal(){
Vec3 ret(0,0, real(rand()) / RAND_MAX);
real theta = (real)(real(rand()) * 2.0 * M_PI / (real)RAND_MAX);
ret.x = VDEC_SQRT(1-ret.z*ret.z);
ret.y = ret.x * VDEC_SIN(theta);
ret.x *= VDEC_COS(theta);
return ret;
}Vec3& Vec3::operator *= (const real &C){ x *= C; y *= C; z *= C; return *this; }
Vec3& Vec3::operator /= (const real &C){ x /= C; y /= C; z /= C; return *this; }
Vec3& Vec3::operator += (const Vec3 &Right){ x += Right.x; y += Right.y; z += Right.z; return *this; }
Vec3& Vec3::operator -= (const Vec3 &Right){ x -= Right.x; y -= Right.y; z -= Right.z; return *this; }
real& Vec3::operator [] (unsigned int axis){ return ((real*)this)[axis]; }
real Vec3::operator [] (unsigned int axis) const{ return ((real*)this)[axis]; }
void Vec3::Normalize(){
real s = (real)1.0/Length();
x *= s;
y *= s;
z *= s;
}
real Vec3::Length() const{ return (real)VDEC_SQRT(x*x+y*y+z*z); }
real Vec3::LengthSq() const{ return (real)(x*x+y*y+z*z); }
Vec3 Vec3::Cross(const Vec3 &Left, const Vec3 &Right){
return Vec3(
Left.y * Right.z - Left.z * Right.y,
Left.z * Right.x - Left.x * Right.z,
Left.x * Right.y - Left.y * Right.x);
}
real Vec3::Dot(const Vec3 &Left, const Vec3 &Right){ return (Left.x * Right.x + Left.y * Right.y + Left.z * Right.z); }
real Vec3::AngleBetween(const Vec3 &Left, const Vec3 &Right){
Vec3 V1(Left), V2(Right);
V1.Normalize();
V2.Normalize();
real Dot = Vec3::Dot(V1, V2);
if(VDEC_FABS(Dot) >= 1.0f){ Dot = 1; }
return (real)VDEC_ACOS(Dot);
}
void Vec3::MakeBasis(const Vec3 &v0, Vec3 &v1, Vec3 &v2){
Vec3 Given = v0;
Given.Normalize();
if(VDEC_FABS(Given.x) > VDEC_FABS(Given.y)){
real invLen = 1 / VDEC_SQRT(Given.x*Given.x + Given.z*Given.z);
v1.x = -Given.z * invLen;
v1.y = 0;
v1.z = Given.x * invLen;
}else{
real invLen = 1 / VDEC_SQRT(Given.y*Given.y + Given.z*Given.z);
v1.x = 0;
v1.y = Given.z * invLen;
v1.z = -Given.y * invLen;
}
v2 = Vec3::Cross(Given, v1);
}
Vec3 operator * (const Vec3 &Left, real Right){
Vec3 Return;
Return.x = Left.x * Right;
Return.y = Left.y * Right;
Return.z = Left.z * Right;
return Return;
}
Vec3 operator * (real Right, const Vec3 &Left){
Vec3 Return;
Return.x = Left.x * Right;
Return.y = Left.y * Right;
Return.z = Left.z * Right;
return Return;
}
Vec3 operator / (const Vec3 &Left, real Right){
Vec3 Return;
Return.x = Left.x / Right;
Return.y = Left.y / Right;
Return.z = Left.z / Right;
return Return;
}
Vec3 operator + (const Vec3 &Left, const Vec3 &Right){
Vec3 Return;
Return.x = Left.x + Right.x;
Return.y = Left.y + Right.y;
Return.z = Left.z + Right.z;
return Return;
}
Vec3 operator - (const Vec3 &Left, const Vec3 &Right){
Vec3 Return;
Return.x = Left.x - Right.x;
Return.y = Left.y - Right.y;
Return.z = Left.z - Right.z;
return Return;
}
Vec3 operator - (const Vec3 &V){
Vec3 Result;
Result.x = -V.x;
Result.y = -V.y;
Result.z = -V.z;
return Result;
}
Vec4::Vec4():x(0),y(0),z(0),w(0){}
Vec4::Vec4(const Vec4 &V):x(V.x),y(V.y),z(V.z),w(V.w){}
Vec4::Vec4(const real &_x, const real &_y, const real &_z, const real &_w):x(_x),y(_y),z(_z),w(_w){}
Vec4& Vec4::operator = (const Vec4 &V){ x = V.x; y = V.y; z = V.z; w = V.w; return *this; }
Vec4& Vec4::operator *= (const real &C){ x *= C; y *= C; z *= C; w *= C; return *this; }
Vec4& Vec4::operator /= (const real &C){ x /= C; y /= C; z /= C; w /= C; return *this; }
Vec4& Vec4::operator += (const Vec4 &Right){ x += Right.x; y += Right.y; z += Right.z; w += Right.w; return *this; }
Vec4& Vec4::operator -= (const Vec4 &Right){ x -= Right.x; y -= Right.y; z -= Right.z; w -= Right.w; return *this; }
real& Vec4::operator [] (unsigned int axis){ return ((real*)this)[axis]; }
real Vec4::operator [] (unsigned int axis) const{ return ((real*)this)[axis]; }
void Vec4::Normalize(){ real s = (real)1.0/Length(); x *= s; y *= s; z *= s; w *= s; }
real Vec4::Length() const{ return (real)VDEC_SQRT(x*x+y*y+z*z+w*w); }
real Vec4::LengthSq() const{ return (real)(x*x+y*y+z*z+w*w); }
real Vec4::Dot(const Vec4 &Left, const Vec4 &Right){ return (Left.x * Right.x + Left.y * Right.y + Left.z * Right.z + Left.w * Right.w); }
Vec4 operator * (const Vec4 &Left, real Right){
Vec4 Return;
Return.x = Left.x * Right;
Return.y = Left.y * Right;
Return.z = Left.z * Right;
Return.w = Left.w * Right;
return Return;
}
Vec4 operator * (real Right, const Vec4 &Left){
Vec4 Return;
Return.x = Left.x * Right;
Return.y = Left.y * Right;
Return.z = Left.z * Right;
Return.w = Left.w * Right;
return Return;
}
Vec4 operator / (const Vec4 &Left, real Right){
Vec4 Return;
Return.x = Left.x / Right;
Return.y = Left.y / Right;
Return.z = Left.z / Right;
Return.w = Left.w / Right;
return Return;
}
Vec4 operator + (const Vec4 &Left, const Vec4 &Right){
Vec4 Return;
Return.x = Left.x + Right.x;
Return.y = Left.y + Right.y;
Return.z = Left.z + Right.z;
Return.w = Left.w + Right.w;
return Return;
}
Vec4 operator - (const Vec4 &Left, const Vec4 &Right){
Vec4 Return;
Return.x = Left.x - Right.x;
Return.y = Left.y - Right.y;
Return.z = Left.z - Right.z;
Return.w = Left.w - Right.w;
return Return;
}
Vec4 operator - (const Vec4 &V){
Vec4 Result;
Result.x = -V.x;
Result.y = -V.y;
Result.z = -V.z;
Result.w = -V.w;
return Result;
}
real operator^(const Vec<2> &Left, const Vec<2> &Right){
return (Left[0] * Right[1] - Left[1] * Right[0]);
}
Vec<3> operator^(const Vec<3> &Left, const Vec<3> &Right){
Vec<3> ret;
ret[0] = Left[1] * Right[2] - Left[2] * Right[1];
ret[1] = Left[2] * Right[0] - Left[0] * Right[2];
ret[2] = Left[0] * Right[1] - Left[1] * Right[0];
return ret;
}
#endif