#ifndef GFXVEC3_INCLUDED // -*- C++ -*- #define GFXVEC3_INCLUDED #if !defined(__GNUC__) # pragma once #endif /************************************************************************ 3D Vector class $Id: vec3.h 427 2004-09-27 04:45:31Z garland $ ************************************************************************/ #include "vec2.h" namespace gfx { template class TVec3 { private: T elt[3]; public: // Standard constructors // TVec3(T s=0) { *this = s; } TVec3(T x, T y, T z) { elt[0]=x; elt[1]=y; elt[2]=z; } // Copy constructors & assignment operators template TVec3(const TVec3& v) { *this = v; } #ifndef STDMIX_INCLUDED // This is now a standard constructor, except when compiling legacy MixKit // code. template TVec3(const U v[3]) { elt[0]=v[0]; elt[1]=v[1]; elt[2]=v[2]; } #else // For MixKit code, we need these constructors instead. // They SHOULD NOT be used in new code. TVec3(const float *v) { elt[0]=v[0]; elt[1]=v[1]; elt[2]=v[2]; } TVec3(const double *v) { elt[0]=v[0]; elt[1]=v[1]; elt[2]=v[2]; } #endif template TVec3& operator=(const TVec3& v) { elt[0]=v[0]; elt[1]=v[1]; elt[2]=v[2]; return *this; } TVec3& operator=(T s) { elt[0]=elt[1]=elt[2]=s; return *this; } // Descriptive interface // typedef T value_type; static int dim() { return 3; } // Access methods // operator T*() { return elt; } operator const T*() const { return elt; } #ifndef HAVE_CASTING_LIMITS T& operator[](int i) { return elt[i]; } T operator[](int i) const { return elt[i]; } operator const T*() { return elt; } #endif // Assignment and in-place arithmetic methods // inline TVec3& operator+=(const TVec3& v); inline TVec3& operator-=(const TVec3& v); inline TVec3& operator*=(T s); inline TVec3& operator/=(T s); }; //////////////////////////////////////////////////////////////////////// // // Method definitions // template inline TVec3& TVec3::operator+=(const TVec3& v) { elt[0] += v[0]; elt[1] += v[1]; elt[2] += v[2]; return *this; } template inline TVec3& TVec3::operator-=(const TVec3& v) { elt[0] -= v[0]; elt[1] -= v[1]; elt[2] -= v[2]; return *this; } template inline TVec3& TVec3::operator*=(T s) { elt[0] *= s; elt[1] *= s; elt[2] *= s; return *this; } template inline TVec3& TVec3::operator/=(T s) { elt[0] /= s; elt[1] /= s; elt[2] /= s; return *this; } //////////////////////////////////////////////////////////////////////// // // Operator definitions // template inline TVec3 operator+(const TVec3 &u, const TVec3& v) { return TVec3(u[0]+v[0], u[1]+v[1], u[2]+v[2]); } template inline TVec3 operator-(const TVec3 &u, const TVec3& v) { return TVec3(u[0]-v[0], u[1]-v[1], u[2]-v[2]); } template inline TVec3 operator-(const TVec3 &v) { return TVec3(-v[0], -v[1], -v[2]); } #if _MSC_VER>=1200 // Normally, we use the construct below to allow the scalar // argument to be different than the template type. This, for example, allows // the user to write things like v/2. Unfortunately, Microsoft VC6.0 (aka // v1200) gets confused by this. We used to include explicit versions for the // case of int's, but this was causing silent (and incorrect) coercion of // floats to ints. // template inline TVec3 operator*(T s, const TVec3 &v) { return TVec3(v[0]*s, v[1]*s, v[2]*s); } template inline TVec3 operator*(const TVec3 &v, T s) { return s*v; } template inline TVec3 operator/(const TVec3 &v, T s) { return TVec3(v[0]/s, v[1]/s, v[2]/s); } #else template inline TVec3 operator*(N s, const TVec3 &v) { return TVec3(v[0]*s, v[1]*s, v[2]*s); } template inline TVec3 operator*(const TVec3 &v, N s) { return s*v; } template inline TVec3 operator/(const TVec3 &v, N s) { return TVec3(v[0]/s, v[1]/s, v[2]/s); } #endif template inline T operator*(const TVec3 &u, const TVec3& v) { return u[0]*v[0] + u[1]*v[1] + u[2]*v[2]; } template inline TVec3 cross(const TVec3& u, const TVec3& v) { return TVec3( u[1]*v[2] - v[1]*u[2], -u[0]*v[2] + v[0]*u[2], u[0]*v[1] - v[0]*u[1] ); } template inline TVec3 operator^(const TVec3& u, const TVec3& v) { return cross(u, v); } template inline std::ostream &operator<<(std::ostream &out, const TVec3& v) { return out << v[0] << " " << v[1] << " " << v[2]; } template inline std::istream &operator>>(std::istream &in, TVec3& v) { return in >> v[0] >> v[1] >> v[2]; } //////////////////////////////////////////////////////////////////////// // // Misc. function definitions // template inline T norm2(const TVec3& v) { return v*v; } template inline T norm(const TVec3& v) { return sqrt(norm2(v)); } template inline void unitize(TVec3& v) { T l = norm2(v); if( l!=1.0 && l!=0.0 ) v /= sqrt(l); } template inline TVec2 proj(const TVec3& v) { TVec2 u(v[0], v[1]); if( v[2]!=1.0 && v[2]!=0.0 ) u /= v[2]; return u; } typedef TVec3 Vec3; typedef TVec3 Vec3f; } // namespace gfx // GFXVEC3_INCLUDED #endif