#ifndef __CVEC4T_H__ #define __CVEC4T_H__ #include "cvec2t.h" #include "cvec3t.h" template class CVec4T; // another VC 6.0 problem: would not accept this definition // after the class template istream& operator>>(istream& is, CVec4T& v) { is >> v.x() >> v.y() >> v.z() >> v.w(); return is; } template ostream& operator<<(ostream& os, const CVec4T& v) { return os << v(0) << " " << v(1) << " " << v(2) << " " << v(3); } //: template for vectors of length 4 template class CVec4T { public: enum{ X = 0, Y = 1, Z = 2, W = 3 }; CVec4T(int a = 0) { v[X] = a, v[Y] = a, v[Z] = a, v[W] = a; } CVec4T(const CVec4T& c) { v[X] = c.v[X], v[Y] = c.v[Y], v[Z] = c.v[Z], v[W] = c.v[W]; } CVec4T(const T& a) { v[X] = a, v[Y] = a, v[Z] = a, v[W] = a; } CVec4T(const T& a, const T& b, const T& c, const T& d) { v[X] = a, v[Y] = b, v[Z] = c, v[W] = d; } CVec4T(const T* a) { v[X] = a[X], v[Y] = a[Y], v[Z] = a[Z], v[W] = a[W]; } // from vector of length 2 CVec4T(const CVec2T& c, T z, T w) { v[X] = c.x(), v[Y] = c.y(), v[Z] = z, v[W] = w; } // from vector of length 3 CVec4T(const CVec3T& c, T w) { v[X] = c.x(), v[Y] = c.y(), v[Z] = c.z(), v[W] = w; } // type convertion to array of T operator T*( void ) { return &v[X]; } operator const T*( void ) const { return &v[X]; } operator CVec3T( void ) const { return CVec3T(&v[X]); } CVec4T& operator=( const CVec4T& c ) { v[X] = c.v[X]; v[Y] = c.v[Y]; v[Z] = c.v[Z]; v[W] = c.v[W]; return *this; } CVec4T operator+( const CVec4T& c ) const { return CVec4T( v[X]+c.v[X], v[Y]+c.v[Y], v[Z]+c.v[Z], v[W]+c.v[W] ); } CVec4T operator-( const CVec4T& c ) const { return CVec4T( v[X]-c.v[X], v[Y]-c.v[Y], v[Z]-c.v[Z], v[W]-c.v[W] ); } CVec4T operator*( const T& s ) const { return CVec4T( s * v[X], s * v[Y], s * v[Z], s * v[W] ); } CVec4T operator*( const CVec4T& c ) const { return CVec4T( v[X]*c.v[X], v[Y]*c.v[Y], v[Z]*c.v[Z], v[W]*c.v[W] ); } friend CVec4T operator*( const T& s, const CVec4T& c ) { return CVec4T( s * c.v[X], s * c.v[Y], s * c.v[Z], s * c.v[W] ); } CVec4T operator/( const T& s ) const { return CVec4T( v[X] / s, v[Y] / s , v[Z] / s, v[W] / s ); } CVec4T& operator+=( const CVec4T& c ) { v[X]+=c.v[X], v[Y]+=c.v[Y], v[Z]+=c.v[Z], v[W]+=c.v[W]; return *this; } CVec4T& operator-=( const CVec4T& c ) { v[X]-=c.v[X], v[Y]-=c.v[Y], v[Z]-=c.v[Z], v[W]-=c.v[W]; return *this; } CVec4T& operator*=( const T& s ) { v[X] *= s, v[Y] *= s, v[Z] *= s, v[W] *= s; return *this; } CVec4T& operator/=( const T& s ) { v[X] /= s, v[Y] /= s, v[Z] /= s, v[W] /= s; return *this; } CVec4T operator-( void ) const { return CVec4T( -v[X], -v[Y], -v[Z], -v[W]); } void plus_aX(const T& a, const CVec4T& u) { v[X] += a*u[X]; v[Y] += a*u[X]; v[Z] += a*u[Z]; v[W] += a*u[W]; } T& x( void ) { return v[X]; } const T& x( void ) const { return v[X]; } T& y( void ) { return v[Y]; } const T& y( void ) const { return v[Y]; } T& z( void ) { return v[Z]; } const T& z( void ) const { return v[Z]; } T& w( void ) { return v[W]; } const T& w( void ) const { return v[W]; } T& operator() (const int i) { return v[i]; } const T& operator() (const int i) const { return v[i]; } //: returns v + t(v1 - v), where v is *this CVec4T lerp( const CVec4T& v1, const T& t ) const { return CVec4T( v[X] + t * ( v1.v[X] - v[X] ), v[Y] + t * ( v1.v[Y] - v[Y] ), v[Z] + t * ( v1.v[Z] - v[Z] ), v[W] + t * ( v1.v[W] - v[W] )); } //: returns the componentwise minimum CVec4T min( const CVec4T& o ) const { T a = ::min( v[X], o.v[X] ); T b = ::min( v[Y], o.v[Y] ); T c = ::min( v[Z], o.v[Z] ); T d = ::min( v[W], o.v[W] ); return CVec4T( a, b, c, d ); } //: returns the componentwise maximum CVec4T max( const CVec4T& o ) const { T a = ::max( v[X], o.v[X] ); T b = ::max( v[Y], o.v[Y] ); T c = ::max( v[Z], o.v[Z] ); T d = ::max( v[W], o.v[W] ); return CVec4T( a, b, c, d ); } T dot( const CVec4T& c ) const { return v[X] * c.v[X] + v[Y] * c.v[Y] + v[Z] * c.v[Z] + v[W] * c.v[W]; } T dot( void ) const { return v[X] * v[X] + v[Y] * v[Y] + v[Z] * v[Z] + v[W] * v[W]; } //: l1 norm (sum of abs values of the components) T l1( void ) const { return T(fabs( v[X] ) + fabs( v[Y] ) + fabs( v[Z] ) + fabs( v[W] )); } //: l infinity norm (max of abs values of the components) T linfty( void ) const { T a = fabs( v[X] ); a = ::max( a, T(fabs( v[Y] )) ); a = ::max( a, T(fabs( v[Z] )) ); a = ::max( a, T(fabs( v[W] )) ); return a; } //: l infinity norm (sqrt of the sum of squares ) T l2( void ) const { return sqrt( dot() ); } T length( void ) const { return sqrt( dot() ); } //: for nonzero vectors, returns the normalized vector CVec4T dir( void ) const { T a = l2(); if ( a == T(0)) return *this; else return *this / a; } int normalize( void ) { T mag = l2(); return (mag == T(0)) ? 0 : ( *this /= mag, 1 ); } //: length |*this -c| T dist( const CVec4T& c ) const { return ( *this - c ).l2(); } CVec4T abs() { return CVec4T((T)fabs(v[X]), (T)fabs(v[Y]), (T)fabs(v[Z]), (T)fabs(v[W])); } //: conversion of different vectors // note that it is a template memeber function (parameterzed by G) of // the template class parameterized by T; not all compilers can handle this template CVec4T( const CVec4T& u ) { v[0] = u.x(); v[1] = u.y(); v[2] = u.z(); } private: T v[4]; }; #endif /* __CVEC4T_H__ */