286 lines
6.7 KiB
Plaintext
286 lines
6.7 KiB
Plaintext
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
|
// See the file tools.license for terms.
|
|
|
|
#ifndef tools_vec4
|
|
#define tools_vec4
|
|
|
|
#include <cstddef> //size_t
|
|
|
|
#ifdef TOOLS_MEM
|
|
#include "../mem"
|
|
#endif
|
|
|
|
namespace tools {
|
|
|
|
template <class T>
|
|
class vec4 {
|
|
#ifdef TOOLS_MEM
|
|
public:
|
|
static const std::string& s_class() {
|
|
static const std::string s_v("tools::vec4");
|
|
return s_v;
|
|
}
|
|
#endif
|
|
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(){
|
|
#ifdef TOOLS_MEM
|
|
mem::increment(s_class().c_str());
|
|
#endif
|
|
m_data[0] = T();
|
|
m_data[1] = T();
|
|
m_data[2] = T();
|
|
m_data[3] = T();
|
|
}
|
|
vec4(const T a_vec[4]) {
|
|
#ifdef TOOLS_MEM
|
|
mem::increment(s_class().c_str());
|
|
#endif
|
|
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,bool a_inc = true) {
|
|
#ifdef TOOLS_MEM
|
|
if(a_inc) mem::increment(s_class().c_str());
|
|
#else
|
|
(void)a_inc;
|
|
#endif
|
|
m_data[0] = a0;
|
|
m_data[1] = a1;
|
|
m_data[2] = a2;
|
|
m_data[3] = a3;
|
|
}
|
|
virtual ~vec4() {
|
|
#ifdef TOOLS_MEM
|
|
mem::decrement(s_class().c_str());
|
|
#endif
|
|
}
|
|
public:
|
|
vec4(const vec4& a_from){
|
|
#ifdef TOOLS_MEM
|
|
mem::increment(s_class().c_str());
|
|
#endif
|
|
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;}
|
|
|
|
//T x() const {return m_data[0];}
|
|
//T y() const {return m_data[1];}
|
|
//T z() const {return m_data[2];}
|
|
|
|
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<zero()) diff *= minus_one();
|
|
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 inlib/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<float> v;}
|
|
};
|
|
|
|
//for sf, mf :
|
|
template <class T>
|
|
inline const T* get_data(const vec4<T>& a_v) {return a_v.data();}
|
|
|
|
}
|
|
|
|
#include <ostream>
|
|
|
|
namespace tools {
|
|
|
|
// for sf_vec::dump().
|
|
template <class T>
|
|
inline std::ostream& operator<<(std::ostream& a_out,const vec4<T>& a_this){
|
|
a_out << "x = " << a_this.v0()
|
|
<< ",y = " << a_this.v1()
|
|
<< ",z = " << a_this.v2()
|
|
<< ",t = " << a_this.v3();
|
|
return a_out;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|