// Forward declarations
template <class scalarT> class Vector2D;
template <class scalarT> class Vector3D;
template <class scalarT> class Vector4D;

// Variations of Vector2D
typedef Vector2D<int>    iVector2D;
typedef Vector2D<float>  fVector2D;
typedef Vector2D<double> dVector2D;
typedef Vector2D<unsigned char> bVector2D;

// Variations of Vector3D
typedef Vector3D<int>    iVector3D;
typedef Vector3D<float>  fVector3D;
typedef Vector3D<double> dVector3D;
typedef Vector3D<unsigned char> bVector3D;

// Variations of Vector4D
typedef Vector4D<int>    iVector4D;
typedef Vector4D<float>  fVector4D;
typedef Vector4D<double> dVector4D;
typedef Vector4D<unsigned char> bVector4D;

////////////////////////
// Predefined Points
////////////////////////
extern opengl_const fVector2D fzero2D, ul,ur,ll,lr, ml,mr,um,lm,mm;

////////////////////////
// Predefined 3-vectors
////////////////////////
extern opengl_const fVector3D fzero3D, faxisX, faxisY, faxisZ;

///////////////////////////////////////////////////////////////////////////////
// Vector2D
// - Two dimensional vector
// - scalarT is the scalar type for color components (double, float, byte...)
///////////////////////////////////////////////////////////////////////////////
template <class scalarT>
class Vector2D
{
private:
   typedef Vector2D<scalarT> self;              // Shortcut type to simplify declarations
public:
   scalarT x,y;                                 // x and y axis values

   // Constructors
   inline Vector2D() ; // Notice there is no "default" value of zero
   inline Vector2D(scalarT _x, scalarT _y)            
   inline Vector2D(const self &v)                     
   // This is a shortcut for assignment that "looks" like a constructor
   inline void operator ()(scalarT _x, scalarT _y)    

   // Operator for converting to openGL an array of scalarT values (scalarT[])
   inline operator const scalarT *() const  
   inline operator scalarT *()              

   // Simple way to get a 3D vector from the 2D vector
   inline Vector3D<scalarT> get3D(scalarT z=0);

   // Vector math functions
   // Manhattan length
   inline scalarT      manLength()  const 
   // Proper length
   inline scalarT      length()     const 
   // Normalize this vector, return it
   inline self &       normalize()
   
   // Return the dot product of two vectors
   inline scalarT      dot(const self &rhs) const 

   // Mathematical operators
   inline self operator +(const self &rhs) const    
   inline self operator -(const self &rhs) const    
   inline self operator /(scalarT scale) const      
   inline self operator *(scalarT scale) const      

   inline bool operator ==(const self &rhs) const   
   inline bool operator !=(const self &rhs) const   

   inline self operator -=(const self &rhs)   
   inline self operator +=(const self &rhs)   
   inline self operator /=(scalarT scale)     
   inline self operator *=(scalarT scale)     

   // Negation
   inline self operator -() 
};

///////////////////////////////////////////////////////////////////////////////
// Vector3D
// - Three dimensional vector
// - scalarT is the scalar type for color components (double, float, byte...)
///////////////////////////////////////////////////////////////////////////////
template <class scalarT>
class Vector3D
{
public:
   scalarT x,y,z;                               // x, y, z axis values
private:
   scalarT w;                                   // Padding in case a 4th value is accessed

   typedef Vector3D<scalarT> self;              // Shortcut type to simplify declarations

public:
   // Constructors
   inline Vector3D() ; // Notice there is no "default" value of zero
   inline Vector3D(scalarT _x, scalarT _y, scalarT _z)            
   inline Vector3D(const self &v)                                 
   inline Vector3D(const Vector2D<scalarT> &v, scalarT _z=0)

   // This is a shortcut for assignment that "looks" like a constructor
   inline void operator ()(scalarT _x, scalarT _y, scalarT _z)    

   // Operator for converting to openGL an array of scalarT values (scalarT[])
   inline operator const scalarT *() const  
   inline operator scalarT *()              

   // Simple way to get a 4D vector from the 3D vector
   inline Vector4D<scalarT> get4D(scalarT w=0);

   // Vector math functions
   // Manhattan length
   inline scalarT    manLength()  const 
   // Proper length
   inline scalarT    length()     const 
   // Normalize this vector, return it
   inline self &     normalize()
   

   // Return the cross product of two vectors
   inline self       cross(const self &rhs) const       
      
   // Return the dot product of two vectors
   inline scalarT    dot  (const self &rhs) const
      

   // Mathematical operators
   inline self      operator +(const self &rhs) const  
   inline self      operator -(const self &rhs) const  
   inline self      operator /(scalarT scale) const    
   inline self      operator *(scalarT scale) const    

   inline bool      operator ==(const self &rhs) const 
   inline bool      operator !=(const self &rhs) const 

   inline self      operator -=(const self &rhs)   
   inline self      operator +=(const self &rhs)   
   inline self      operator /=(scalarT scale)     
   inline self      operator *=(scalarT scale)     

   // Negation
   inline self      operator -() 
};

///////////////////////////////////////////////////////////////////////////////
// Vector4D
// - Four dimensional vector (Quaternion)
// - scalarT is the scalar type for color components (double, float, byte...)
///////////////////////////////////////////////////////////////////////////////
template <class scalarT>
class Vector4D
{
private:
   typedef Vector4D<scalarT> self;              // Shortcut type to simplify declarations
public:
   scalarT x,y,z,w;                             // x, y, z axis values

   // Constructors
   inline Vector4D() ; // Notice there is no "default" value of zero
   inline Vector4D(scalarT _x,scalarT _y,scalarT _z,scalarT _w)          
   inline Vector4D(const self &v)                                        
   inline Vector4D(const Vector3D<scalarT> &v, scalarT _w=0)
   // This is a shortcut for assignment that "looks" like a constructor
   inline void operator ()(scalarT _x,scalarT _y,scalarT _z,scalarT _w)  

   // Create quaternions from Euler rotations around a singe axis
   // Degrees
   inline static self fromEulerXdeg(scalarT degrees) 
   inline static self fromEulerYdeg(scalarT degrees) 
   inline static self fromEulerZdeg(scalarT degrees) 
          static self fromEulerDeg(const Vector3D<scalarT> &degrees);
   // Radians
   inline static self fromEulerXrad(scalarT rads)    
   inline static self fromEulerYrad(scalarT rads)    
   inline static self fromEulerZrad(scalarT rads)    
          static self fromEulerRad(const Vector3D<scalarT> &radians);

   // Operator for converting to openGL an array of scalarT values (scalarT[])
   inline operator const scalarT *() const 
   inline operator scalarT *()             

   // Vector math functions
   // Manhattan length
   inline scalarT      manLength()  const 
   // Proper length
   inline scalarT      length()     const 
   // Normalize this vector, return it
   inline self &       normalize()
   

   // Mathematical operators
   inline self operator +(const self &rhs) const   
   inline self operator -(const self &rhs) const   
   inline self operator /(scalarT scale) const     
   inline self operator *(scalarT scale) const     

   inline bool operator ==(const self &rhs) const  
   inline bool operator !=(const self &rhs) const  

   inline self operator -=(const self &rhs)  
   inline self operator +=(const self &rhs)  
   inline self operator /=(scalarT scale)    
   inline self operator *=(scalarT scale)    

   // Multiply two quaternions - this can be used to combine rotations
   self operator *(const self &rhs) const 

   // Negation
   inline self operator -() 
};