#ifndef __M_VECTOR3_H
#define __M_VECTOR3_H

#include "maths_defs.h"
#include <iostream>

//class ostream;

struct Vector3
{
  real x, y, z;

  //
	Vector3() {};

	Vector3(const Vector3& _vect)
	 : x(_vect.x), y(_vect.y), z(_vect.z)
	{}

	Vector3(const real& _x, const real& _y, const real& _z)
	 : x(_x), y(_y), z(_z)
	{}

	Vector3& operator=(const Vector3& _vect)
	{
	  x = _vect.x;
	  y = _vect.y;
	  z = _vect.z;
	  return *this;
	}
	
	inline real    operator[](const unsigned& i) const {return *((&x)+i*sizeof(real));}
	inline real    operator[](const unsigned& i)       {return *((&x)+i*sizeof(real));}
  inline Vector3 operator- () const {return Vector3(-x, -y, -z);}


	// produit vectoriel
	inline friend Vector3 operator^(const Vector3& _v1, const Vector3 _v2)
	{
         return Vector3 ( _v1.y*_v2.z-_v1.z*_v2.y,
                          _v1.z*_v2.x-_v1.x*_v2.z,
                          _v1.x*_v2.y-_v1.y*_v2.x);
	}
	// produit scalaire
	inline friend real operator*(const Vector3& _v1, const Vector3& _v2)
	{
	  return static_cast<real>(_v1.x*_v2.x + _v1.y*_v2.y + _v1.z*_v2.z);
	}
  // produit scalaire * vecteur
  inline friend Vector3 operator*(const real& _f, const Vector3& _v)
  {
    return Vector3(_f*_v.x,_f*_v.y,_f*_v.z);
  }
  // produit vecteur * scalaire
  inline friend Vector3 operator*(const Vector3& _v, const real& _f)
  {
    return Vector3(_f*_v.x,_f*_v.y,_f*_v.z);
  }
  // addition et soustraction de scalaires
  inline friend Vector3 operator+(const Vector3& _v1, const Vector3& _v2)
  {
    return Vector3(_v1.x+_v2.x , _v1.y+_v2.y , _v1.z+_v2.z);
  }
  inline friend Vector3 operator-(const Vector3& _v1, const Vector3& _v2)
  {
    return Vector3(_v1.x-_v2.x , _v1.y-_v2.y , _v1.z-_v2.z);
  }

  inline real Norm() const
  {
    return static_cast<real>(Sqrt(x*x + y*y + z*z));
  }
  
  inline real sqrNorm() const
  {
    return static_cast<real>(x*x + y*y + z*z);
  }

  void Normalize();

  void operator += (Vector3& _v) { x += _v.x ; y += _v.y ; z += _v.z;  }
	void operator += (Vector3* _v) { x += _v->x; y += _v->y; z += _v->z; }
	void operator -= (Vector3& _v) { x -= _v.x ; y -= _v.y ; z -= _v.z;  }
	void operator -= (Vector3* _v) { x -= _v->x; y -= _v->y; z -= _v->z; }
	void operator *= (real _f)     { x *= _f   ; y *= _f   ; z *= _f;    }
	void operator *= (Vector3& _v) { x *= _v.x ; y *= _v.y ; z *= _v.z;  }
	void operator *= (Vector3* _v) { x *= _v->x; y *= _v->y; z *= _v->z; }

};

 #endif

