#pragma once
//namespace BS3
//{

struct Vector4
{

	// members
	float	x;
	float	y;
	float	z;
	float	w;
		
	// constructors
	inline	Vector4() {}
	inline	Vector4(float x, float y, float z, float w);
	inline	Vector4(const float v[]);
	inline	Vector4(const Vector4& v);

	// operators
	inline	Vector4		operator +  () const;
	inline	Vector4		operator -  () const;
	inline	Vector4		operator +  (const Vector4& v) const;
	inline	Vector4		operator -  (const Vector4& v) const;
	inline	Vector4		operator *  (const Vector4& v) const;
	inline	Vector4		operator *  (const float& s) const;
	inline	Vector4		operator /  (const float& s) const;
	inline	Vector4&		operator += (const Vector4& v);
	inline	Vector4&		operator -= (const Vector4& v);
	inline	Vector4&		operator *= (const Vector4& v);
	inline	Vector4&		operator *= (const float& s);
	inline	Vector4&		operator /= (const float& s);
	inline	void			operator  = (const Vector4& v);
	inline	void			operator  = (const Vector3& v);
	inline	bool			operator == (const Vector4& v) const;
	inline	bool			operator != (const Vector4& v) const;
	inline	const float&	operator [] (int index) const;
	inline	float&			operator [] (int index);
	inline					operator const float* () const;
	inline					operator float* ();

#define _bound(min,x,max) ((x)<(min)?(min):(x)>(max)?(max):(x))
	DWORD GetColor()
	{		
		return (int(_bound(0,x,1)*255)<<0)|(int(_bound(0,y,1)*255)<<8)|(int(_bound(0,z,1)*255)<<16)|(int(_bound(0,w,1)*255)<<24);
	}
#undef _bound
};

inline	Vector3	Normalize(const Vector3& v);
inline	float		DotProduct(const Vector4& a, const Vector4& b);
inline	Vector4	Lerp(const Vector4& a, const Vector4& b, float t);
inline	Vector4	operator * (float s, const Vector4& v);


inline Vector4 Normalize(const Vector4& v)
{
	float s=(float)sqrtf(v.x*v.x+v.y*v.y+v.z*v.z);
	if(s) s=1/s;
	return Vector4(v.x*s,v.y*s,v.z*s,1);
}

inline Vector4::Vector4(float vx, float vy, float vz, float vw) : x(vx), y(vy), z(vz), w(vw)
{
}

inline Vector4::Vector4(const float v[]) : x(v[0]), y(v[1]), z(v[2]), w(v[3])
{
}

inline Vector4::Vector4(const Vector4& v) : x(v.x), y(v.y), z(v.z), w(v.w)
{
}

inline Vector4 Vector4::operator + () const
{
	return *this;
}

inline Vector4 Vector4::operator - () const
{
	return Vector4(-x,-y,-z,-w);
}

inline Vector4 Vector4::operator + (const Vector4& v) const
{
	return Vector4(x+v.x,y+v.y,z+v.z,w+v.w);
}

inline Vector4 Vector4::operator - (const Vector4& v) const
{
	return Vector4(x-v.x,y-v.y,z-v.z,w-v.w);
}

inline Vector4 Vector4::operator * (const Vector4& v) const
{
	return Vector4(x*v.x,y*v.y,z*v.z,w*v.w);
}

inline Vector4 Vector4::operator * (const float& s) const
{
	return Vector4(x*s,y*s,z*s,w*s);
}

inline Vector4 Vector4::operator / (const float& s) const
{
	float is=1/s;
	return Vector4(x*is,y*is,z*is,w*is);
}

inline Vector4& Vector4::operator += (const Vector4& v)
{
	x+=v.x;
	y+=v.y;
	z+=v.z;
	w+=v.w;
	return *this;
}

inline Vector4& Vector4::operator -= (const Vector4& v)
{
	x-=v.x;
	y-=v.y;
	z-=v.z;
	w-=v.w;
	return *this;
}

inline Vector4& Vector4::operator *= (const Vector4& v)
{
	x*=v.x;
	y*=v.y;
	z*=v.z;
	w*=v.w;
	return *this;
}

inline Vector4& Vector4::operator *= (const float& s)
{
	x*=s;
	y*=s;
	z*=s;
	w*=s;
	return *this;
}

inline Vector4& Vector4::operator /= (const float& s)
{
	float is=1/s;
	x*=is;
	y*=is;
	z*=is;
	w*=is;
	return *this;
}

inline void Vector4::operator = (const Vector4& v)
{
	x=v.x;
	y=v.y;
	z=v.z;
	w=v.w;
}

inline void Vector4::operator = (const Vector3& v)
{
	x=v.x;
	y=v.y;
	z=v.z;
}

inline bool Vector4::operator == (const Vector4& v) const
{
	return x==v.x && y==v.y && z==v.z && w==v.w;
}

inline bool Vector4::operator != (const Vector4& v) const
{
	return x!=v.x || y!=v.y || z!=v.z || w!=v.w;
}

inline const float& Vector4::operator [] (int index) const
{
	return reinterpret_cast<const float*>(this)[index];
}

inline float& Vector4::operator [] (int index)
{
	return reinterpret_cast<float*>(this)[index];
}

inline Vector4::operator const float* () const
{
	return reinterpret_cast<const float*>(this);
}

inline Vector4::operator float* ()
{
	return reinterpret_cast<float*>(this);
}

inline float DotProduct(const Vector4& a, const Vector4& b)
{
	return a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w;
}

inline Vector4 Lerp(const Vector4& a, const Vector4& b, float t)
{
	return Vector4(a.x+(b.x - a.x)*t,a.y+(b.y-a.y)*t,a.z+(b.z-a.z)*t,a.w+(b.w-a.w)*t);
}

inline Vector4 operator * (float s, const Vector4& v)
{
	return Vector4(v.x*s,v.y*s,v.z*s,v.w*s);
}

//};

