// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_vec4 #define tools_vec4 #include //size_t namespace tools { template class vec4 { protected: static T zero() {return T();} static T minus_one() {return T(-1);} public: typedef T elem_t; unsigned int dimension() const {return 4;} public: vec4(){ m_data[0] = T(); m_data[1] = T(); m_data[2] = T(); m_data[3] = T(); } vec4(const T a_vec[4]) { m_data[0] = a_vec[0]; m_data[1] = a_vec[1]; m_data[2] = a_vec[2]; m_data[3] = a_vec[3]; } vec4(const T& a0,const T& a1,const T& a2,const T& a3) { m_data[0] = a0; m_data[1] = a1; m_data[2] = a2; m_data[3] = a3; } virtual ~vec4() { } public: vec4(const vec4& a_from){ m_data[0] = a_from.m_data[0]; m_data[1] = a_from.m_data[1]; m_data[2] = a_from.m_data[2]; m_data[3] = a_from.m_data[3]; } vec4& operator=(const vec4& a_from) { m_data[0] = a_from.m_data[0]; m_data[1] = a_from.m_data[1]; m_data[2] = a_from.m_data[2]; m_data[3] = a_from.m_data[3]; return *this; } public: const T& v0() const { return m_data[0];} const T& v1() const { return m_data[1];} const T& v2() const { return m_data[2];} const T& v3() const { return m_data[3];} void v0(const T& a_value) { m_data[0] = a_value;} void v1(const T& a_value) { m_data[1] = a_value;} void v2(const T& a_value) { m_data[2] = a_value;} void v3(const T& a_value) { m_data[3] = a_value;} const T& x() const { return m_data[0];} const T& y() const { return m_data[1];} const T& z() const { return m_data[2];} const T& t() const { return m_data[3];} void set_value(const T& a0,const T& a1,const T& a2,const T& a3) { m_data[0] = a0; m_data[1] = a1; m_data[2] = a2; m_data[3] = a3; } void set_value(const T aV[4]) { m_data[0] = aV[0]; m_data[1] = aV[1]; m_data[2] = aV[2]; m_data[3] = aV[3]; } void value(T& a0,T& a1,T& a2,T& a3) const { a0 = m_data[0]; a1 = m_data[1]; a2 = m_data[2]; a3 = m_data[3]; } bool set_value(unsigned int a_index,const T& a_value) { if(a_index>=4) return false; m_data[a_index] = a_value; return true; } T length(T(*a_sqrt)(T)) const { return a_sqrt(m_data[0]*m_data[0]+m_data[1]*m_data[1]+m_data[2]*m_data[2]+m_data[3]*m_data[3]); } T normalize(T(*a_sqrt)(T)) { T norme = length(a_sqrt); if(norme==T()) return T(); divide(norme); return norme; } bool equal(const vec4& a_vec) const { if(m_data[0]!=a_vec.m_data[0]) return false; if(m_data[1]!=a_vec.m_data[1]) return false; if(m_data[2]!=a_vec.m_data[2]) return false; if(m_data[3]!=a_vec.m_data[3]) return false; return true; } bool equal(const vec4& a_vec,const T& a_epsil) const { T* tp = (T*)m_data; T* ap = (T*)a_vec.m_data; for(unsigned int i=0;i<4;i++,tp++,ap++) { T diff = (*tp) - (*ap); if(diff=a_epsil) return false; } return true; } bool is_proportional(const vec4& a_vec,T& a_factor) const { // If true, then : a_vec = a_factor * this. a_factor = zero(); bool first = true; T* tp = (T*)m_data; T* ap = (T*)a_vec.m_data; for(unsigned int i=0;i<4;i++,tp++,ap++) { if( ((*tp)==zero()) && ((*ap)==zero())) { continue; } else if( ((*tp)!=zero()) && ((*ap)==zero())) { return false; } else if( ((*tp)==zero()) && ((*ap)!=zero())) { return false; } else { if(first) { a_factor = (*ap)/(*tp); first = false; } else { if((*ap)!=(*tp)*a_factor) return false; } } } return true; } void multiply(const T& a_T) { m_data[0] *= a_T; m_data[1] *= a_T; m_data[2] *= a_T; m_data[3] *= a_T; } bool divide(const T& a_T) { if(a_T==T()) return false; m_data[0] /= a_T; m_data[1] /= a_T; m_data[2] /= a_T; m_data[3] /= a_T; return true; } void add(const vec4& a_v) { m_data[0] += a_v.m_data[0]; m_data[1] += a_v.m_data[1]; m_data[2] += a_v.m_data[2]; m_data[3] += a_v.m_data[3]; } void add(const T& a0,const T& a1,const T& a2,const T& a3) { m_data[0] += a0; m_data[1] += a1; m_data[2] += a2; m_data[3] += a3; } void subtract(const vec4& a_v) { m_data[0] -= a_v.m_data[0]; m_data[1] -= a_v.m_data[1]; m_data[2] -= a_v.m_data[2]; m_data[3] -= a_v.m_data[3]; } void subtract(const T& a0,const T& a1,const T& a2,const T& a3) { m_data[0] -= a0; m_data[1] -= a1; m_data[2] -= a2; m_data[3] -= a3; } public: //operators T& operator[](size_t a_index) { //WARNING : no check on a_index. return m_data[a_index]; } const T& operator[](size_t a_index) const { //WARNING : no check on a_index. return m_data[a_index]; } vec4 operator+(const vec4& a_v) const { return vec4(m_data[0]+a_v.m_data[0], m_data[1]+a_v.m_data[1], m_data[2]+a_v.m_data[2], m_data[3]+a_v.m_data[3]); } vec4 operator-(const vec4& a_v) const { return vec4(m_data[0]-a_v.m_data[0], m_data[1]-a_v.m_data[1], m_data[2]-a_v.m_data[2], m_data[3]-a_v.m_data[3]); } vec4 operator*(const T& a_v) const { return vec4(m_data[0]*a_v, m_data[1]*a_v, m_data[2]*a_v, m_data[3]*a_v); } bool operator==(const vec4& a_v) const {return equal(a_v);} bool operator!=(const vec4& a_v) const {return !operator==(a_v);} public: //for tools/sg/sf_vec typedef unsigned int size_type; size_type size() const {return 4;} const T* data() const {return m_data;} protected: T m_data[4]; private:static void check_instantiation() {vec4 v;} }; //for sf, mf : template inline const T* get_data(const vec4& a_v) {return a_v.data();} } #include namespace tools { // for sf_vec::dump(). template inline std::ostream& operator<<(std::ostream& a_out,const vec4& a_this){ a_out << "x = " << a_this.v0() << ",y = " << a_this.v1() << ",z = " << a_this.v2() << ",t = " << a_this.v3(); return a_out; } } #endif