/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* E.P. Scene Graph
* Developed by:
*       - Eduardo Ribeiro (eribeiro @ tecgraf . puc-rio . br)
*       - Peter Dam (peter @ tecgraf . puc-rio . br)
* File: Vec3.h
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef _EPSG_VEC3_
#define _EPSG_VEC3_

#include <math.h>

namespace EPSG
{
	template <typename T>
	class Vec3
	{
	public:
		/* [CONSTRUCTOR] */	Vec3();
		/* [CONSTRUCTOR] */	Vec3( T x, T y, T z );

		EPSG::Vec3<T>&		operator+=( const Vec3& rhs );
		EPSG::Vec3<T>&		operator-=( const Vec3& rhs );
		void				operator=( const Vec3& rhs );
		T&					operator[]( int index );

		void				setValues( T x, T y, T z );
		EPSG::Vec3<T>		cross( const Vec3& a, const Vec3& b );
		float				normalize();
		float				length();
		
		T					x;
		T					y;
		T					z;

	private:
		T					invalid;
	};


}

/* TEMPLATE METHODS */
template <typename T>
EPSG::Vec3<T>::Vec3()
{
	x = y = z = 0;
}

template <typename T>
EPSG::Vec3<T>::Vec3( T x, T y, T z )
{
	this->x = x;
	this->y = y;
	this->z = z;
}

/* OPERATORS */
template <typename T>
EPSG::Vec3<T>& EPSG::Vec3<T>::operator+=( const Vec3& rhs )
{
	x += rhs.x;
	y += rhs.y;
	z += rhs.z;

	return *this;
}

template <typename T>
EPSG::Vec3<T>& EPSG::Vec3<T>::operator-=( const Vec3& rhs )
{
	x -= rhs.x;
	y -= rhs.y;
	z -= rhs.z;

	return *this;
}

template <typename T>
void EPSG::Vec3<T>::operator=( const Vec3& rhs )
{
	x = rhs.x;
	y = rhs.y;
	z = rhs.z;

}

template <typename T>
T& EPSG::Vec3<T>::operator[]( int index )
{
	switch( index )
	{
	case 0:
		return x;
	case 1:
		return y;
	case 2:
		return z;
	default:
		return invalid;
	}
}

template <typename T>
void EPSG::Vec3<T>::setValues( T x, T y, T z )
{
	this->x = x;
	this->y = y;
	this->z = z;
}

template <typename T>
EPSG::Vec3<T> EPSG::Vec3<T>::cross( const Vec3& a, const Vec3& b )
{
	return EPSG::Vec3<float>( a.y * b.z - b.y * a.z, b.x * a.z - a.x * b.z, a.x * b.y - b.x * a.y )
}

template <typename T>
float EPSG::Vec3<T>::length()
{
    return (float)sqrt( x*x + y*y + z*z );
}

template <typename T>
float EPSG::Vec3<T>::normalize()
{
	float l = length();
	if( l != 0.0 )
	{
		float d = 1.0 / l;
		x *= d; y *= d; z *= d;
	}
	return l;
}

#endif //_EPSG_VEC3_