Figure 2: The GLvector3 template class

//********************************************************
// OpenGL reusable template classes GLpoint4 and GLvector3  
// By G.Bavestrelli,    Copyright Techint S.p.A. 1998-1999
// Any feedback is welcome:
// You can contact me at  : giovanni.bavestrelli@pomini.it
//********************************************************

// Class GLvector3: A vector in 3D space
template <class Numeric>
class GLvector3
{

public:

   Numeric x;
   Numeric y;
   Numeric z;

   GLvector3()
      :x(0),y(0),z(0)
      {}
      
   GLvector3(Numeric x, Numeric y, Numeric z)
      :x(x),y(y),z(z)
      {}

   GLvector3(const Numeric * v)
      :x(v[0]),y(v[1]),z(v[2])
      {}

   operator const Numeric * () const
   { 
      // If this line does not compile,
      // it's because the Numeric members x and y
      // are not aligned like C arrays
      STATIC_ASSERT(offsetof(GLvector3<Numeric>,y)
                   -offsetof(GLvector3<Numeric>,x)
                   ==sizeof(Numeric));
      return &x; 
   }

   GLvector3 & operator =(const Numeric * v)
   {
       x=v[0]; y=v[1]; z=v[2]; 
       return *this; 
   }

   GLvector3 operator - ()
   {
       return GLvector3<Numeric>(-x,-y,-z); 
   }

   double GetLength() const 
   { 
       return sqrt(static_cast<double>(x*x+y*y+z*z)); 
   }

   BOOL Normalize() 
   {
      Numeric Length=GetLength();
      if (Length==0.0) 
         return false;
      x/=Length; y/=Length; z/=Length; 
      return true;
   }

   GLvector3 GetNormal() const 
   {
      Numeric Length=GetLength();
      if (Length==0.0) 
         return GLvector3();
      else 
         return GLvector3(x/Length,y/Length,z/Length);
   }

};

template <class Numeric>
BOOL operator == (const GLvector3<Numeric> & V1, 
                  const GLvector3<Numeric> & V2)
{
   return V1.x==V2.x && V1.y==V2.y && V1.z==V2.z;
}

template <class Numeric>
BOOL operator != (const GLvector3<Numeric> & V1, 
                  const GLvector3<Numeric> & V2)
{
   return !(V1==V2);
}