#pragma once

#include "GL/gl.h"

///////////////////////////////////////////////////////////////////////////////


/**
 * \ingroup Ecstasy/Utils
 *
 * \brief Implementation of a 4-vector
 *
 * \version 1.0
 * first version
 *
 * \date 08-09-2002
 *
 * \author SiW
 *

 * \todo 
 *
 * \bug 
 *
 */
class CEVector4
{
public:
	GLfloat x;
	GLfloat y;
	GLfloat z;
	GLfloat w;

public:
	// constructors
	CEVector4();
	CEVector4(const CEVector4& val);
	CEVector4(GLfloat valX, GLfloat valY, GLfloat valZ, GLfloat valW);
	CEVector4(GLfloat *val);
	
	~CEVector4(void);

	void Set(GLfloat valX, GLfloat valY, GLfloat valZ, GLfloat valW);
	void Set(GLfloat *val);

	// operators
	CEVector4& operator= (const CEVector4& val);
	CEVector4 operator- (const CEVector4& val) const;
	CEVector4 operator+ (const CEVector4& val) const;
	CEVector4 operator* (const GLfloat scalar) const;
	CEVector4 operator/ (const GLfloat scalar) const;
	CEVector4& operator*= (const GLfloat scalar);
	CEVector4& operator/= (const GLfloat scalar);
	CEVector4& operator-= (const GLfloat val);
	CEVector4& operator+= (const GLfloat val);
	
	// equality operators
	bool operator== (const CEVector4& val) const;
	bool operator!= (const CEVector4& val) const;
	bool operator>= (const CEVector4& val) const;
	bool operator<= (const CEVector4& val) const;
	bool operator> (const CEVector4& val) const;
	bool operator< (const CEVector4& val) const;

	// pseudo-operators
	void Scale(GLfloat val);
	

	// casting operators
	GLfloat& operator[] (int i) const;
    operator GLfloat* ();

	// operations
	GLfloat Length() const;
	GLfloat Dot(const CEVector4& val);
	CEVector4 Cross(const CEVector4& val);
	void Normalize();
	CEVector4 GetNormalized();

};

///////////////////////////////////////////////////////////////////////////////

/**
 * \ingroup Ecstasy/Utils
 *
 * \brief Implementation of a 3-vector
 *
 * \version 1.0
 * first version
 *
 * \date 08-09-2002
 *
 * \author SiW
 *

 * \todo 
 *
 * \bug 
 *
 */
class CEVector3
{
public:
	GLfloat x;
	GLfloat y;
	GLfloat z;

public:
	// constructors
	CEVector3();
	CEVector3(const CEVector3& val);
	CEVector3(GLfloat valX, GLfloat valY, GLfloat valZ);
	CEVector3(GLfloat *val);
	
	~CEVector3(void);

	void Set(GLfloat valX, GLfloat valY, GLfloat valZ);
	void Set(GLfloat *val);

	// operators
	CEVector3& operator= (const CEVector3& val);
	CEVector3 operator- (const CEVector3& val) const;
	CEVector3 operator+ (const CEVector3& val) const;
	CEVector3 operator+ (const GLfloat val) const;
	CEVector3 operator* (const GLfloat scalar) const;
	CEVector3 operator/ (const GLfloat scalar) const;
	CEVector3& operator*= (const GLfloat scalar);
	CEVector3& operator/= (const GLfloat scalar);
	CEVector3& operator-= (const GLfloat val);
	CEVector3& operator+= (const GLfloat val);
	
	// equality operators
	bool operator== (const CEVector3& val) const;
	bool operator!= (const CEVector3& val) const;
	bool operator>= (const CEVector3& val) const;
	bool operator<= (const CEVector3& val) const;
	bool operator> (const CEVector3& val) const;
	bool operator< (const CEVector3& val) const;

	// pseudo-operators
	void Scale(GLfloat val);
	void RotateAboutPoint(const float angle, CEVector3 axis, const CEVector3& pt); 
	

	// casting operators
	GLfloat& operator[] (int i) const;
    operator GLfloat* ();

	// operations
	GLfloat Length() const;
	GLfloat Dot(const CEVector3& val);
	CEVector3 Cross(const CEVector3& val);
	void Normalize();
	CEVector3 GetNormalized();
};

///////////////////////////////////////////////////////////////////////////////

/**
 * \ingroup Ecstasy/Utils
 *
 * \brief Implementation of a 2-vector
 *
 * \version 1.0
 * first version
 *
 * \date 08-09-2002
 *
 * \author SiW
 *

 * \todo 
 *
 * \bug 
 *
 */
class CEVector2
{
public:
	GLfloat x;
	GLfloat y;

public:
	// constructors
	CEVector2();
	CEVector2(const CEVector2& val);
	CEVector2(GLfloat valX, GLfloat valY);
	CEVector2(GLfloat *val);
	
	~CEVector2(void);

	void Set(GLfloat valX, GLfloat valY);
	void Set(GLfloat *val);

	// operators
	CEVector2& operator= (const CEVector2& val);
	CEVector2 operator- (const CEVector2& val) const;
	CEVector2 operator+ (const CEVector2& val) const;
	CEVector2 operator* (const GLfloat scalar) const;
	CEVector2 operator/ (const GLfloat scalar) const;
	CEVector2& operator*= (const GLfloat scalar);
	CEVector2& operator/= (const GLfloat scalar);
	CEVector2& operator-= (const GLfloat val);
	CEVector2& operator+= (const GLfloat val);
	
	// equality operators
	bool operator== (const CEVector2& val) const;
	bool operator!= (const CEVector2& val) const;
	bool operator>= (const CEVector2& val) const;
	bool operator<= (const CEVector2& val) const;
	bool operator> (const CEVector2& val) const;
	bool operator< (const CEVector2& val) const;

	// pseudo-operators
	void Scale(GLfloat val);
	

	// casting operators
	GLfloat& operator[] (int i) const;
    operator GLfloat* ();

	// operations
	GLfloat Length() const;
	void Normalize();
	CEVector2 GetNormalized();

};

///////////////////////////////////////////////////////////////////////////////

class CERay3
{
public:
	CEVector3 m_Origin;
	CEVector3 m_Direction;
};

class CERay2
{
public:
	CEVector2 m_Origin;
	CEVector2 m_Direction;
};


