
#pragma once
#include <math.h>
#define PI				3.14159265358979323846f
#define DEG2RAD(X)		(PI*(X)/180.0f)
typedef unsigned int   uint;

struct vector
{
	vector() {v[0] = v[1] = v[2] = 0;}
	vector(float px, float py, float pz) {v[0] = px; v[1] = py; v[2] = pz;}
	vector(const vector &pVec) {v[0] = pVec.v[0]; v[1] = pVec.v[1]; v[2] = pVec.v[2];}
	vector(const float *pVec)  {v[0] = pVec[0]; v[1] = pVec[1]; v[2] = pVec[2];}

	vector operator=(const vector &pVec)
		{return vector(v[0] = pVec.v[0], v[1] = pVec.v[1], v[2] = pVec.v[2]);}
	vector operator=(const float *ptr)
		{return vector(v[0] = ptr[0], v[1] = ptr[1], v[2] = ptr[2]);}
	bool operator==(const vector &pVec) const
		{return (v[0] == pVec.v[0] && v[1] == pVec.v[1] && v[2] == pVec.v[2]);}
	bool operator==(const float *pVec) const
		{return (v[0] == pVec[0] && v[1] == pVec[1] && v[2] == pVec[2]);}
	inline bool operator!=(const vector &pVec) const
		{return !((*this) == pVec);}
	inline bool operator!=(const float *pVec)
		{return !(pVec == (*this));}
	bool operator<(const vector vec) const
		{return ((v[0] < vec[0]) && (v[1] < vec[1]) && (v[2] < vec[2]));}
	bool operator<=(const vector vec) const
		{return ((v[0] <= vec[0]) && (v[1] <= vec[1]) && (v[2] <= vec[2]));}
	bool operator>(const vector vec) const
		{return ((v[0] > vec[0]) && (v[1] > vec[1]) && (v[2] > vec[2]));}
	bool operator>=(const vector vec) const
		{return ((v[0] >= vec[0]) && (v[1] >= vec[1]) && (v[2] >= vec[2]));}

	const float &operator[](int ndx) const {return v[ndx];}
	float &operator[](int ndx)             {return v[ndx];}
	operator float*(void)                  {return v;}

	vector &operator+=(const vector &pVec) {*this = *this + pVec; return *this;}
	vector &operator-=(const vector &pVec) {*this = *this - pVec; return *this;}
	vector &operator*=(const vector &pVec) {*this = *this * pVec; return *this;}
	vector &operator*=(float val)          {*this = *this * val; return *this;}
	vector &operator/=(const vector &pVec) {*this = *this / pVec; return *this;}
	vector &operator/=(float val)          {*this = *this / val; return *this;}

	vector operator+(const vector &pVec) const
		{return vector(v[0] + pVec.v[0], v[1] + pVec.v[1], v[2] + pVec.v[2]);}
	vector operator-(const vector &pVec) const
		{return vector(v[0] - pVec.v[0], v[1] - pVec.v[1], v[2] - pVec.v[2]);}
	vector operator*(const vector &pVec) const
		{return vector(v[0] * pVec.v[0], v[1] * pVec.v[1], v[2] * pVec.v[2]);}
	vector operator*(float val) const
		{return vector(v[0] * val, v[1] * val, v[2] * val);}
	friend vector operator*(float val, const vector &v)
		{return vector(v[0] * val, v[1] * val, v[2] * val);}
	vector operator/(const vector &pVec) const
		{return vector(v[0] / pVec.v[0], v[1] / pVec.v[1], v[2] / pVec.v[2]);}
	vector operator/(float val) const
		{return vector(v[0] / val, v[1] / val, v[2] / val);}
	vector operator-(void) const {return vector(-v[0], -v[1], -v[2]);} 

	vector operator^ ( const vector& vect ) const
	{
		vector res;
		res.v[0] = (vect.v[1] * v[2]) - (vect.v[2] * v[1]);
		res.v[1] = (vect.v[2] * v[0]) - (vect.v[0] * v[2]);
		res.v[2] = (vect.v[0] * v[1]) - (vect.v[1] * v[0]);

		return res;
	}

	float operator | ( const vector &vect ) const
	{ return v[0] * vect.v[0] + v[1] * vect.v[1] + v[2] * vect.v[2]; }

   void Clear(void)                    {v[0] = v[1] = v[2] = 0;}
   void Set(float x, float y, float z) {v[0] = x; v[1] = y; v[2] = z;}
   void Set(const vector &p)           {v[0] = p[0]; v[1] = p[1]; v[2] = p[2];}
   void Add(const vector &a, const vector &b)
    {v[0] = a.v[0] + b.v[0]; v[1] = a.v[1] + b.v[1]; v[2] = a.v[2] + b.v[2];}
   void Add(const vector &a)
    {v[0] += a.v[0]; v[1] += a.v[1]; v[2] += a.v[2];}
   void Subtract(const vector &a, const vector &b)
    {v[0] = a.v[0] - b.v[0]; v[1] = a.v[1] - b.v[1]; v[2] = a.v[2] - b.v[2];}
   void Subtract(const vector &a)
    {v[0] -= a.v[0]; v[1] -= a.v[1]; v[2] -= a.v[2];}
   void Multiply(const vector &a, const vector &b)
    {v[0] = a.v[0] * b.v[0]; v[1] = a.v[1] * b.v[1]; v[2] = a.v[2] * b.v[2];}
   void Multiply(const vector &a)
    {v[0] *= a.v[0]; v[1] *= a.v[1]; v[2] *= a.v[2];}
   void Divide(const vector &a, const vector &b)
    {v[0] = a.v[0] / b.v[0]; v[1] = a.v[1] / b.v[1]; v[2] = a.v[2] / b.v[2];}
   void Divide(const vector &a)
    {v[0] /= a.v[0]; v[1] /= a.v[1]; v[2] /= a.v[2];}
   void Scale(float val)
    {v[0] *= val; v[1] *= val; v[2] *= val;}
   void Fabs(const vector &src) {v[0] = (float) fabs(src.v[0]);
    v[1] = (float) fabs(src.v[1]); v[2] = (float) fabs(src.v[2]);}
   void Fabs(void) {v[0] = (float) fabs(v[0]); v[1] = (float) fabs(v[1]);
    v[2] = (float) fabs(v[2]);}

	void Normalize(void);
   float Length(void);
   float Dot(const vector &pVec)
    {return v[0] * pVec.v[0] + v[1] * pVec.v[1] + v[2] * pVec.v[2];}
   void Cross(const vector &p, const vector &q);
   float GetDistance(const vector &dest);
	 void Set ( float val )
	 { v[0] = val; v[1] = val; v[2] = val; }

	void FindDirection ( vector &src, vector &dest )
	{
		v[0] = dest.v[0] - src.v[0];
		v[1] = dest.v[1] - src.v[1];
		v[2] = dest.v[2] - src.v[2];
		Normalize();
	}

	void RotateX ( float angle );
	void RotateZ ( float angle );
	void RotateY ( float angle );

public:
   float v[3];
};


inline void vector::Normalize(void) 
{
	float length, len = 0;

	length = Length();

	if (length == 0)
		return;

	len = 1.0f / length;

	v[0] *= len;
	v[1] *= len;
	v[2] *= len;
}

inline float vector::Length(void) 
{
   double length = (v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]);
	
	return (float) sqrt(length);
}

inline void vector::Cross(const vector &p, const vector &q)
{
	v[0] = (p.v[1] * q.v[2]) - (p.v[2] * q.v[1]);
	v[1] = (p.v[2] * q.v[0]) - (p.v[0] * q.v[2]);
	v[2] = (p.v[0] * q.v[1]) - (p.v[1] * q.v[0]);
}

inline float vector::GetDistance(const vector &dest)
{
	float d1 = dest[0] - v[0];
	float d2 = dest[1] - v[1];
	float d3 = dest[2] - v[2];

	return sqrtf((d1 * d1) + (d2 * d2) + (d3 * d3));
}


struct vector4
{
   vector4() {v[0] = v[1] = v[2] = 0;}
   vector4(float px, float py, float pz) {v[0] = px; v[1] = py; v[2] = pz;}
   vector4(const vector4 &pVec)
    {v[0] = pVec.v[0]; v[1] = pVec.v[1]; v[2] = pVec.v[2];}
   vector4(const float *pVec) {v[0] = pVec[0]; v[1] = pVec[1]; v[2] = pVec[2];}

   vector4 operator=(const vector4 &pVec)
    {return vector4(v[0] = pVec.v[0], v[1] = pVec.v[1], v[2] = pVec.v[2]);}
   vector4 operator=(const float *ptr)
    {return vector4(v[0] = ptr[0], v[1] = ptr[1], v[2] = ptr[2]);}
   bool operator==(const vector4 &pVec) const
    {return (v[0] == pVec.v[0] && v[1] == pVec.v[1] && v[2] == pVec.v[2]);}
   bool operator==(const float *pVec) const
    {return (v[0] == pVec[0] && v[1] == pVec[1] && v[2] == pVec[2]);}
   inline bool operator!=(const vector4 &pVec) const
    {return !((*this) == pVec);}
   inline bool operator!=(const float *pVec)
    {return !(pVec == (*this));}
   bool operator<(const vector4 vec) const
    {return ((v[0] < vec[0]) && (v[1] < vec[1]) && (v[2] < vec[2]));}
   bool operator<=(const vector4 vec) const
    {return ((v[0] <= vec[0]) && (v[1] <= vec[1]) && (v[2] <= vec[2]));}
   bool operator>(const vector4 vec) const
    {return ((v[0] > vec[0]) && (v[1] > vec[1]) && (v[2] > vec[2]));}
   bool operator>=(const vector4 vec) const
    {return ((v[0] >= vec[0]) && (v[1] >= vec[1]) && (v[2] >= vec[2]));}

   const float &operator[](int ndx) const {return v[ndx];}
   float &operator[](int ndx)             {return v[ndx];}
   operator float*(void)                  {return v;}

   vector4 &operator+=(const vector4 &pVec) {*this = *this + pVec; return *this;}
   vector4 &operator-=(const vector4 &pVec) {*this = *this - pVec; return *this;}
   vector4 &operator*=(const vector4 &pVec) {*this = *this * pVec; return *this;}
   vector4 &operator*=(float val)          {*this = *this * val; return *this;}
   vector4 &operator/=(const vector4 &pVec) {*this = *this / pVec; return *this;}
   vector4 &operator/=(float val)          {*this = *this / val; return *this;}

   vector4 operator+(const vector4 &pVec) const
    {return vector4(v[0] + pVec.v[0], v[1] + pVec.v[1], v[2] + pVec.v[2]);}
   vector4 operator-(const vector4 &pVec) const
    {return vector4(v[0] - pVec.v[0], v[1] - pVec.v[1], v[2] - pVec.v[2]);}
   vector4 operator*(const vector4 &pVec) const
    {return vector4(v[0] * pVec.v[0], v[1] * pVec.v[1], v[2] * pVec.v[2]);}
   vector4 operator*(float val) const
    {return vector4(v[0] * val, v[1] * val, v[2] * val);}
   friend vector4 operator*(float val, const vector4 &v)
    {return vector4(v[0] * val, v[1] * val, v[2] * val);}
   vector4 operator/(const vector4 &pVec) const
    {return vector4(v[0] / pVec.v[0], v[1] / pVec.v[1], v[2] / pVec.v[2]);}
   vector4 operator/(float val) const
    {return vector4(v[0] / val, v[1] / val, v[2] / val);}
   vector4 operator-(void) const {return vector4(-v[0], -v[1], -v[2]);} 
   
	 vector4 operator^ ( const vector4& vect ) const
  	{
			vector4 res;
				res.v[0] = (vect.v[1] * v[2]) - (vect.v[2] * v[1]);
				res.v[1] = (vect.v[2] * v[0]) - (vect.v[0] * v[2]);
				res.v[2] = (vect.v[0] * v[1]) - (vect.v[1] * v[0]);
			return res;
	 }
   float operator | ( const vector4 &vect ) const
   { return v[0] * vect.v[0] + v[1] * vect.v[1] + v[2] * vect.v[2]; }

   void Clear(void)                    {v[0] = v[1] = v[2] = 0;}
   void Set(float x, float y, float z, float a) {v[0] = x; v[1] = y; v[2] = z; v[3] = a;}
   void Set(const vector4 &p)           {v[0] = p[0]; v[1] = p[1]; v[2] = p[2];}
   void Add(const vector4 &a, const vector4 &b)
    {v[0] = a.v[0] + b.v[0]; v[1] = a.v[1] + b.v[1]; v[2] = a.v[2] + b.v[2];}
   void Add(const vector4 &a)
    {v[0] += a.v[0]; v[1] += a.v[1]; v[2] += a.v[2];}
   void Subtract(const vector4 &a, const vector4 &b)
    {v[0] = a.v[0] - b.v[0]; v[1] = a.v[1] - b.v[1]; v[2] = a.v[2] - b.v[2];}
   void Subtract(const vector4 &a)
    {v[0] -= a.v[0]; v[1] -= a.v[1]; v[2] -= a.v[2];}
   void Multiply(const vector4 &a, const vector4 &b)
    {v[0] = a.v[0] * b.v[0]; v[1] = a.v[1] * b.v[1]; v[2] = a.v[2] * b.v[2];}
   void Multiply(const vector4 &a)
    {v[0] *= a.v[0]; v[1] *= a.v[1]; v[2] *= a.v[2];}
   void Divide(const vector4 &a, const vector4 &b)
    {v[0] = a.v[0] / b.v[0]; v[1] = a.v[1] / b.v[1]; v[2] = a.v[2] / b.v[2];}
   void Divide(const vector4 &a)
    {v[0] /= a.v[0]; v[1] /= a.v[1]; v[2] /= a.v[2];}
   void Scale(float val)
    {v[0] *= val; v[1] *= val; v[2] *= val;}
   void Fabs(const vector4 &src) {v[0] = (float) fabs(src.v[0]);
    v[1] = (float) fabs(src.v[1]); v[2] = (float) fabs(src.v[2]);}
   void Fabs(void) {v[0] = (float) fabs(v[0]); v[1] = (float) fabs(v[1]);
    v[2] = (float) fabs(v[2]);}

   void Normalize(void);
   float Length(void) const;
   float Dot(const vector4 &pVec) const
    {return v[0] * pVec.v[0] + v[1] * pVec.v[1] + v[2] * pVec.v[2];}
   void Cross(const vector4 &p, const vector4 &q);
   float GetDistance(const vector4 &dest) const;
	 void Set ( float val )
	 { v[0] = val; v[1] = val; v[2] = val; v[3] = val;}

	inline void RotateX ( float angle )
	{
		float oy = v[1], oz = v[2];
		angle = DEG2RAD ( angle );
		v[1] = (float)((oy * cos(angle) )+(oz * (-sin(angle) ) ));
		v[2] = (float)((oy * sin(angle) )+(oz * ( cos(angle) ) ));
	}

	inline void RotateZ ( float angle )
	{
		float ox = v[0], oz = v[2];
		angle = DEG2RAD ( angle );
		v[0] = (float)((ox * cos(angle) )+(oz * (-sin(angle) ) ));
		v[2] = (float)((ox * sin(angle) )+(oz * ( cos(angle) ) ));
	}

	inline void RotateY ( float angle )
	{
		float ox = v[1], oy = v[1];
		angle = DEG2RAD ( angle );
		v[0] = (float)((ox * cos(angle) )+(oy * (-sin(angle) ) ));
		v[1] = (float)((ox * sin(angle) )+(oy * ( cos(angle) ) ));
	}

public:
   float v[4];
};

inline void vector4::Normalize(void) 
{
	float length, len = 0;

	length = Length();

	if (length == 0)
		return;

	len = 1.0f / length;

	v[0] *= len;
	v[1] *= len;
	v[2] *= len;
}

inline float vector4::Length(void) const
{
   double length = (v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]);
	
	return (float) sqrt(length);
}

inline void vector4::Cross(const vector4 &p, const vector4 &q)
{
	v[0] = (p.v[1] * q.v[2]) - (p.v[2] * q.v[1]);
	v[1] = (p.v[2] * q.v[0]) - (p.v[0] * q.v[2]);
	v[2] = (p.v[0] * q.v[1]) - (p.v[1] * q.v[0]);
}


inline float vector4::GetDistance(const vector4 &dest) const
{
   float d1 = dest[0] - v[0];
   float d2 = dest[1] - v[1];
   float d3 = dest[2] - v[2];
   
   return (float) sqrt((d1 * d1) + (d2 * d2) + (d3 * d3));
}



struct vector2
{
   vector2() {v[0] = v[1] = 0;}
   vector2(float px, float py) {v[0] = px; v[1] = py;}
   vector2(const vector2 &pVec)
    {v[0] = pVec.v[0]; v[1] = pVec.v[1];}
   vector2(const float *pVec) {v[0] = pVec[0]; v[1] = pVec[1];}

   vector2 operator=(const vector2 &pVec)
    {return vector2(v[0] = pVec.v[0], v[1] = pVec.v[1]);}
   vector2 operator=(const float *ptr)
    {return vector2(v[0] = ptr[0], v[1] = ptr[1]);}
   bool operator==(const vector2 &pVec) const
    {return (v[0] == pVec.v[0] && v[1] == pVec.v[1]);}
   bool operator==(const float *pVec) const
    {return (v[0] == pVec[0] && v[1] == pVec[1]);}
   inline bool operator!=(const vector2 &pVec) const
    {return !((*this) == pVec);}
   inline bool operator!=(const float *pVec)
    {return !(pVec == (*this));}
   bool operator<(const vector2 vec) const
    {return ((v[0] < vec[0]) && (v[1] < vec[1]));}
   bool operator<=(const vector2 vec) const
    {return ((v[0] <= vec[0]) && (v[1] <= vec[1]));}
   bool operator>(const vector2 vec) const
    {return ((v[0] > vec[0]) && (v[1] > vec[1]));}
   bool operator>=(const vector2 vec) const
    {return ((v[0] >= vec[0]) && (v[1] >= vec[1]));}

   const float &operator[](int ndx) const {return v[ndx];}
   float &operator[](int ndx)             {return v[ndx];}
   operator float*(void)                  {return v;}

   vector2 &operator+=(const vector2 &pVec) {*this = *this + pVec; return *this;}
   vector2 &operator-=(const vector2 &pVec) {*this = *this - pVec; return *this;}
   vector2 &operator*=(const vector2 &pVec) {*this = *this * pVec; return *this;}
   vector2 &operator*=(float val)          {*this = *this * val; return *this;}
   vector2 &operator/=(const vector2 &pVec) {*this = *this / pVec; return *this;}
   vector2 &operator/=(float val)          {*this = *this / val; return *this;}

   vector2 operator+(const vector2 &pVec) const
    {return vector2(v[0] + pVec.v[0], v[1] + pVec.v[1]);}
   vector2 operator-(const vector2 &pVec) const
    {return vector2(v[0] - pVec.v[0], v[1] - pVec.v[1]);}
   vector2 operator*(const vector2 &pVec) const
    {return vector2(v[0] * pVec.v[0], v[1] * pVec.v[1]);}
   vector2 operator*(float val) const
    {return vector2(v[0] * val, v[1] * val);}
   friend vector2 operator*(float val, const vector2 &v)
    {return vector2(v[0] * val, v[1] * val);}
   vector2 operator/(const vector2 &pVec) const
    {return vector2(v[0] / pVec.v[0], v[1] / pVec.v[1]);}
   vector2 operator/(float val) const
    {return vector2(v[0] / val, v[1] / val);}
   vector2 operator-(void) const {return vector2(-v[0], -v[1]);} 


   void Clear(void)                    {v[0] = v[1] = 0;}
   void Set(float x, float y) {v[0] = x; v[1] = y;}
   void Set(const vector2 &p)           {v[0] = p[0]; v[1] = p[1];}
   void Add(const vector2 &a, const vector2 &b)
    {v[0] = a.v[0] + b.v[0]; v[1] = a.v[1] + b.v[1];}
   void Add(const vector2 &a)
    {v[0] += a.v[0]; v[1] += a.v[1];}
   void Subtract(const vector2 &a, const vector2 &b)
    {v[0] = a.v[0] - b.v[0]; v[1] = a.v[1] - b.v[1];}
   void Subtract(const vector2 &a)
    {v[0] -= a.v[0]; v[1] -= a.v[1];}
   void Multiply(const vector2 &a, const vector2 &b)
    {v[0] = a.v[0] * b.v[0]; v[1] = a.v[1] * b.v[1];}
   void Multiply(const vector2 &a)
    {v[0] *= a.v[0]; v[1] *= a.v[1];}
   void Divide(const vector2 &a, const vector2 &b)
    {v[0] = a.v[0] / b.v[0]; v[1] = a.v[1] / b.v[1];}
   void Divide(const vector2 &a)
    {v[0] /= a.v[0]; v[1] /= a.v[1];}
   void Scale(float val)
    {v[0] *= val; v[1] *= val;}
   void Fabs(const vector2 &src) {v[0] = (float) fabs(src.v[0]);
    v[1] = (float) fabs(src.v[1]);}
   void Fabs(void) {v[0] = (float) fabs(v[0]); v[1] = (float) fabs(v[1]);}

public:
   float v[2];
};


#define VECTOR_SET3(vec,x,y,z)		 vec.v[0]=x;vec.v[1]=y;vec.v[2]=z;
#define VECTOR_SET(vec,vl)				 vec.v[0]=vec.v[1]=vec.v[2]=vl;
#define VECTOR_SUB(dest,v1,v2)		 dest.v[0]=v1.v[0]-v2.v[0];dest.v[1]=v1.v[1]-v2.v[1];dest.v[2]=v1.v[2]-v2.v[2];
#define VECTOR2_SET2(vec,x,y)			 vec.v[0]=x;vec.v[1]=y;
#define VECTOR2_SET(vec,vl)				 vec.v[0]=vec.v[1]=vl;
#define VECTOR4_SET4(vec,x,y,z,a)  vec.v[0]=x;vec.v[1]=y;vec.v[2]=z;vec.v[3]=a;
#define VECTOR4_SET(vec,vl)        vec.v[0]=vec.v[1]=vec.v[2]=vec.v[3]=vl;
