about summary refs log tree commit diff
path: root/src/base
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2009-10-29 12:14:31 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2009-10-29 12:14:31 +0000
commite56feb597bc743677633432f77513b02907fd169 (patch)
tree5b6bbb983fcf33cfe5eef8aec1298608257036b5 /src/base
parent878ede3080ab2cfb627aca505c397d9765052996 (diff)
downloadzcatch-e56feb597bc743677633432f77513b02907fd169.tar.gz
zcatch-e56feb597bc743677633432f77513b02907fd169.zip
added missing headers
Diffstat (limited to 'src/base')
-rw-r--r--src/base/tl/math.hpp45
-rw-r--r--src/base/tl/matrix.hpp163
-rw-r--r--src/base/tl/quat.hpp211
-rw-r--r--src/base/tl/stream.hpp65
-rw-r--r--src/base/tl/vector.hpp198
5 files changed, 682 insertions, 0 deletions
diff --git a/src/base/tl/math.hpp b/src/base/tl/math.hpp
new file mode 100644
index 00000000..b323dea8
--- /dev/null
+++ b/src/base/tl/math.hpp
@@ -0,0 +1,45 @@
+/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#ifndef BASE_MATH_H
+#define BASE_MATH_H
+
+#include <stdlib.h>
+
+template <typename T>
+inline T clamp(T val, T min, T max)
+{
+	if(val < min)
+		return min;
+	if(val > max)
+		return max;
+	return val;
+}
+
+inline float sign(float f)
+{
+	return f<0.0f?-1.0f:1.0f;
+}
+
+inline int round(float f)
+{
+	if(f > 0)
+		return (int)(f+0.5f);
+	return (int)(f-0.5f);
+}
+
+template<typename T, typename TB>
+inline T mix(const T a, const T b, TB amount)
+{
+	return a + (b-a)*amount;
+}
+
+inline float frandom() { return rand()/(float)(RAND_MAX); }
+
+const float pi = 3.1415926535897932384626433f;
+
+template <typename T> inline T min(T a, T b) { return a<b?a:b; }
+template <typename T> inline T max(T a, T b) { return a>b?a:b; }
+
+template <typename T> inline T min(T a, T b, T c) { return min(min(a,b),c); }
+template <typename T> inline T max(T a, T b, T c) { return max(max(a,b),c); }
+
+#endif // BASE_MATH_H
diff --git a/src/base/tl/matrix.hpp b/src/base/tl/matrix.hpp
new file mode 100644
index 00000000..b723eaa7
--- /dev/null
+++ b/src/base/tl/matrix.hpp
@@ -0,0 +1,163 @@
+#ifndef TL_FILE_MATRIX_HPP
+#define TL_FILE_MATRIX_HPP
+
+/*
+ 
+ Looks like OpenGL 
+ 
+ Column Major
+
+        / m[0][0]  m[1][0]  m[2][0]  m[3][0] \     / v[0] \
+        |                                    |     |      |
+		| m[0][1]  m[1][1]  m[2][1]  m[3][1] |     | v[1] |
+        |                                    |     |      |
+ M(v) = | m[0][2]  m[1][2]  m[2][2]  m[3][2] |  X  | v[2] |
+        |                                    |     |      |
+        \ m[0][3]  m[1][3]  m[2][3]  m[3][3] /     \ v[3] /
+ 
+ v[0] = x
+ v[1] = y
+ v[2] = z
+ v[3] = w or 1
+ 
+   +y
+   |
+   |
+   |_____ +x
+   /
+  /
+ +z
+ 
+ right = +x
+ up = +y
+ forward = -z
+
+*/
+
+template<class T>
+class matrix4_base
+{
+public:
+	// [col][row]
+	T m[4][4];
+
+	//
+	inline matrix4_base()
+	{}
+
+	inline vector3_base<T> get_column3(const int i) const { return vector3_base<T>(m[i][0], m[i][1], m[i][2]); }
+	inline vector3_base<T> get_column4(const int i) const { return vector4_base<T>(m[i][0], m[i][1], m[i][2], m[i][3]); }
+	inline vector3_base<T> get_row3(const int i) const { return vector3_base<T>(m[0][i], m[1][i], m[2][i]); }
+	inline vector4_base<T> get_row4(const int i) const { return vector4_base<T>(m[0][i], m[1][i], m[2][i], m[3][i]); }
+
+	inline vector3_base<T> get_right() const { return get_row3(0); }
+	inline vector3_base<T> get_up() const { return get_row3(1); }
+	inline vector3_base<T> get_forward() const { return -get_row3(2); }
+	inline vector3_base<T> get_translation() const { return get_column3(3); }
+
+	//
+	void unit()
+	{
+		m[0][1] = m[0][2] = m[0][3] = 0;
+		m[1][0] = m[1][2] = m[1][3] = 0;
+		m[2][0] = m[2][1] = m[2][3] = 0;
+		m[3][0] = m[3][1] = m[3][2] = 0;
+
+		m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1;
+	}
+
+	//
+	vector3_base<T> operator *(const vector3_base<T> &v) const
+	{
+		vector3_base<T> r(0,0,0);
+
+		r.x += v.x*m[0][0] + v.y*m[1][0] + v.z*m[2][0] + m[3][0];
+		r.y += v.x*m[0][1] + v.y*m[1][1] + v.z*m[2][1] + m[3][1];
+		r.z += v.x*m[0][2] + v.y*m[1][2] + v.z*m[2][2] + m[3][2];
+		return r;
+	}
+
+	//
+	vector4_base<T> operator *(const vector4_base<T> &v) const
+	{
+		vector4_base<T> r(0,0,0,0);
+
+		r.x += v.x*m[0][0] + v.y*m[1][0] + v.z*m[2][0] + v.w*m[3][0];
+		r.y += v.x*m[0][1] + v.y*m[1][1] + v.z*m[2][1] + v.w*m[3][1];
+		r.z += v.x*m[0][2] + v.y*m[1][2] + v.z*m[2][2] + v.w*m[3][2];
+		r.w += v.x*m[0][3] + v.y*m[1][3] + v.z*m[2][3] + v.w*m[3][3];
+		return r;
+	}
+	//
+	matrix4_base operator *(const matrix4_base &other) const
+	{
+		matrix4_base r;
+
+		for(int i = 0; i < 4; i++)
+			for(int j = 0; j < 4; j++)
+			{
+				r.m[i][j] = 0;
+				for(int a = 0; a < 4; a++)
+					r.m[i][j] += m[a][j] * other.m[i][a];
+			}
+		return r;
+	}
+	
+	
+	//
+	// THIS PART IS KINDA UGLY BECAUSE MAT4 IS NOT IMMUTABLE
+	//
+	
+	inline void set_row(const vector3_base<T>& v, const int row)
+	{
+		m[0][row] = v.x;
+		m[1][row] = v.y;
+		m[2][row] = v.z;
+	}
+
+	inline void set_column(const vector3_base<T>& v, const int col)
+	{
+		m[col][0] = v.x;
+		m[col][1] = v.y;
+		m[col][2] = v.z;
+	}
+
+	inline void set_translation(const vector3_base<T>& v) { set_column(v,3); }	
+
+	//
+	void rot_x(T angle)
+	{
+		T sina = (T)sin(angle);
+		T cosa = (T)cos(angle);
+
+		unit();
+		m[1][1] = cosa; m[2][1] =-sina;
+		m[1][2] = sina; m[2][2] = cosa;
+	}
+
+	//
+	void rot_y(T angle)
+	{
+		T sina = (T)sin(-angle);
+		T cosa = (T)cos(-angle);
+
+		unit();
+		m[0][0] = cosa; m[2][0] =-sina;
+		m[0][2] = sina; m[2][2] = cosa;
+	}
+
+	//
+	void rot_z(T angle)
+	{
+		T sina = (T)sin(angle);
+		T cosa = (T)cos(angle);
+
+		unit();
+		m[0][0] = cosa; m[1][0] =-sina;
+		m[0][1] = sina; m[1][1] = cosa;
+	}
+};
+
+typedef matrix4_base<float> mat4;
+
+#endif
diff --git a/src/base/tl/quat.hpp b/src/base/tl/quat.hpp
new file mode 100644
index 00000000..2f381e11
--- /dev/null
+++ b/src/base/tl/quat.hpp
@@ -0,0 +1,211 @@
+
+
+template<class T>
+class quaternion_base
+{
+public:
+	T k[4];
+
+	/*void Unit()
+	{
+		k[0] = 0;
+		k[1] = 0;
+		k[2] = 0;
+		k[3] = 1;
+	}*/
+	
+	inline quaternion_base(){}
+
+	inline quaternion_base(T x, T y, T z, T w)
+	{
+		k[0] = x;
+		k[1] = y;
+		k[2] = z;
+		k[3] = w;
+	}
+	
+	inline quaternion_base(vector3_base<T> axis, T angle)
+	{
+		T sin_angle = sin(angle * (T)0.5);
+		T cos_angle = cos(angle * (T)0.5);
+		k[0] = axis.x * sin_angle;
+		k[1] = axis.y * sin_angle;
+		k[2] = axis.z * sin_angle;
+		k[3] = cos_angle;
+	}
+	
+
+	T magnitude()
+	{
+		return sqrt(k[0] * k[0] + k[1] * k[1] + k[2] * k[2] + k[3] * k[3]);
+	}
+
+	matrix4_base<T> create_matrix() const
+	{
+		matrix4_base<T> mat;
+		
+		T xx = k[0] * k[0];
+		T xy = k[0] * k[1];
+		T xz = k[0] * k[2];
+		T xw = k[0] * k[3];
+		T yy = k[1] * k[1];
+		T yz = k[1] * k[2];
+		T yw = k[1] * k[3];
+		T zz = k[2] * k[2];
+		T zw = k[2] * k[3];
+		
+		mat.k[0][0] = 1 - 2 * (yy + zz);
+		mat.k[0][1] = 2 * (xy + zw);
+		mat.k[0][2] = 2 * (xz - yw);
+		mat.k[0][3] = 0;
+		
+		mat.k[1][0] = 2 * (xy - zw);
+		mat.k[1][1] = 1 - 2 * (xx + zz);
+		mat.k[1][2] = 2 * (yz + xw);
+		mat.k[1][3] = 0;
+
+		mat.k[2][0] = 2 * (xz + yw);
+		mat.k[2][1] = 2 * (yz - xw);
+		mat.k[2][2] = 1 - 2 * (xx + yy);
+		mat.k[2][3] = 0;
+
+		mat.k[3][0] = 0;
+		mat.k[3][1] = 0;
+		mat.k[3][2] = 0;
+		mat.k[3][3] = 1;
+	}
+
+	/*
+	void CreateDOOM(T x, T y, T z)
+	{
+		k[0] = x;
+		k[1] = y;
+		k[2] = z;
+		T Term = 1 - (x * x) - (y * y) - (z * z);
+		if (Term < 0)
+			k[3] = 0;
+		else
+			k[3] = -sqrt(Term);
+
+		Normalize();
+	}
+	
+	T DotProd(const TQuaternion<T>& Quat) const
+	{
+		return (k[0] * Quat.k[0] + k[1] * Quat.k[1] + k[2] * Quat.k[2] + k[3] * Quat.k[3]);
+	}
+
+	void Interpolate(const TQuaternion<T>& Quat, TQuaternion& Dest, T Scale)
+	{
+		T Separation = k[0] * Quat.k[0] + k[1] * Quat.k[1] + k[2] * Quat.k[2] + k[3] * Quat.k[3];
+		T Factor1,Factor2;
+
+		if (Separation > 1)
+			Separation = 1;
+		if (Separation < -1)
+			Separation = -1;
+		Separation = acos(Separation);
+		if (Separation == 0 || Separation == pi)
+		{
+			Factor1 = 1;
+			Factor2 = 0;
+		}
+		else
+		{
+			Factor1 = sin((1 - Scale)*Separation) / sin(Separation);
+			Factor2 = sin(Scale * Separation) / sin(Separation);
+		}
+		
+		Dest.k[0] = k[0] * Factor1 + Quat.k[0] * Factor2;
+		Dest.k[1] = k[1] * Factor1 + Quat.k[1] * Factor2;
+		Dest.k[2] = k[2] * Factor1 + Quat.k[2] * Factor2;
+		Dest.k[3] = k[3] * Factor1 + Quat.k[3] * Factor2;
+	}
+
+	void Slerp(const TQuaternion<T>& Quat, TQuaternion& Dest, T Scale) const
+	{
+		T Sq1,Sq2;
+		T Dot = DotProd(Quat);
+
+		TQuaternion Temp;
+
+		if (Dot < 0.0f)
+		{
+			Dot = -Dot;
+			Temp.k[0] = -Quat.k[0];
+			Temp.k[1] = -Quat.k[1];
+			Temp.k[2] = -Quat.k[2];
+			Temp.k[3] = -Quat.k[3];
+		}
+		else
+		{
+			Temp = Quat;
+		}
+
+		if ((1.0 + Dot) > 0.00001)
+		{
+			if ((1.0 - Dot) > 0.00001)
+			{
+				T om = (T)acos(Dot);
+				T rsinom = (T)(1.0f / sin(om));
+				Sq1 = (T)sin(((T)1.0 - Scale) * om) * rsinom;
+				Sq2 = (T)sin(Scale * om) * rsinom;
+			}
+			else
+			{
+				Sq1 = (T)(1.0 - Scale);
+				Sq2 = Scale;
+			}
+			Dest.k[0] = Sq1 * k[0] + Sq2 * Temp[0];
+			Dest.k[1] = Sq1 * k[1] + Sq2 * Temp[1];
+			Dest.k[2] = Sq1 * k[2] + Sq2 * Temp[2];
+			Dest.k[3] = Sq1 * k[3] + Sq2 * Temp[3];
+		}
+		else
+		{
+			Sq1 = (T)sin(((T)1.0 - Scale) * (T)0.5 * pi);
+			Sq2 = (T)sin(Scale * (T)0.5 * pi);
+
+			Dest.k[0] = Sq1 * k[0] + Sq2 * Temp[1];
+			Dest.k[1] = Sq1 * k[1] + Sq2 * Temp[0];
+			Dest.k[2] = Sq1 * k[2] + Sq2 * Temp[3];
+			Dest.k[3] = Sq1 * k[3] + Sq2 * Temp[2];
+		}
+	}*/
+
+	// perators
+	T& operator [] (int i) { return k[i]; }
+
+	// quaternion multiply
+	quaternion_base operator *(const quaternion_base& other) const
+	{
+		// (w1 dot w2 - v1 dot v2, w1 dot v2 + w2 dot v1 + v1 cross v2)
+		quaternion_base r;
+		r.k[0] = k[3] * other.k[0] + k[0] * other.k[3] + k[1] * other.k[2] - k[2] * other.k[1];
+		r.k[1] = k[3] * other.k[1] + k[1] * other.k[3] + k[2] * other.k[0] - k[0] * other.k[2];
+		r.k[2] = k[3] * other.k[2] + k[2] * other.k[3] + k[0] * other.k[1] - k[1] * other.k[0];
+		r.k[3] = k[3] * other.k[3] - k[0] * other.k[0] - k[1] * other.k[1] - k[2] * other.k[2];
+
+		return normalize(r);
+	}
+	
+	/*
+	bool operator == (const quaternion_base<T>& t) const { return ((k[0] == t.k[0]) && (k[1] == t.k[1]) && (k[2] == t.k[2]) && (k[3] == t.k[3])); }
+	bool operator != (const quaternion_base<T>& t) const { return ((k[0] != t.k[0]) || (k[1] != t.k[1]) || (k[2] != t.k[2]) || (k[3] != t.k[3])); }
+
+	void operator = (const quaternion_base<T>& other) { k[0] = other.k[0]; k[1] = other.k[1]; k[2] = other.k[2]; k[3] = other.k[3]; }
+	*/
+	
+	/*void operator *= (const TQuaternion<T>& t) 				{ TQuaternion Temp = Multiply(t); *this = Temp; }
+	TQuaternion operator * (const TQuaternion<T>& t)		const	{ return Multiply(t); }
+	*/
+};
+
+template<typename T>
+inline quaternion_base<T> normalize(const quaternion_base<T> &v)
+{
+	T factor = 1.0f/v.magnitude();
+	return quaternion_base<T>(v.k[0]*factor, v.k[1]*factor,v. k[2]*factor,v. k[3]*factor);
+}
+
+
diff --git a/src/base/tl/stream.hpp b/src/base/tl/stream.hpp
new file mode 100644
index 00000000..c307b968
--- /dev/null
+++ b/src/base/tl/stream.hpp
@@ -0,0 +1,65 @@
+#ifndef TL_FILE_STREAM_HPP
+#define TL_FILE_STREAM_HPP
+
+class input_stream
+{
+public:	
+	virtual ~input_stream() {}
+	virtual size_t read(void *data, size_t size) = 0;
+	virtual size_t size() = 0;
+};
+
+class output_stream
+{
+public:	
+	virtual ~output_stream() {}
+	virtual size_t write(const void *data, size_t size) = 0;
+};
+
+
+// input wrapping
+// RAII style
+class file_backend
+{
+private:
+	file_backend(const file_backend &other) { /* no copy allowed */ }
+protected:
+	IOHANDLE file_handle;
+	
+	explicit file_backend(const char *filename, int flags)
+	{
+		file_handle = io_open(filename, flags);
+	}
+	
+	~file_backend()
+	{
+		if(file_handle)
+			io_close(file_handle);
+	}
+public:
+	bool is_open() const { return file_handle != 0; }
+};
+
+class file_reader : public input_stream, public file_backend
+{
+public:	
+	explicit file_reader(const char *filename)
+	: file_backend(filename, IOFLAG_READ)
+	{}
+	
+	virtual size_t read(void *data, size_t size) { return io_read(file_handle, data, size); }
+	virtual size_t size() { return io_length(file_handle); }
+};
+
+
+class file_writer : public output_stream, public file_backend
+{
+public:	
+	explicit file_writer(const char *filename)
+	: file_backend(filename, IOFLAG_WRITE)
+	{}
+	
+	virtual size_t write(const void *data, size_t size) { return io_write(file_handle, data, size); }
+};
+
+#endif
diff --git a/src/base/tl/vector.hpp b/src/base/tl/vector.hpp
new file mode 100644
index 00000000..1c1bb804
--- /dev/null
+++ b/src/base/tl/vector.hpp
@@ -0,0 +1,198 @@
+/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#ifndef TL_FILE_VECTOR_HPP
+#define TL_FILE_VECTOR_HPP
+
+#include <math.h>
+
+// ------------------------------------
+
+template<typename T>
+class vector2_base
+{
+public:
+	union { T x,u; };
+	union { T y,v; };
+	
+	vector2_base() {}
+	vector2_base(float nx, float ny)
+	{
+		x = nx;
+		y = ny;
+	}
+	
+	vector2_base operator -() const { return vector2_base(-x, -y); }
+	vector2_base operator -(const vector2_base &v) const { return vector2_base(x-v.x, y-v.y); }
+	vector2_base operator +(const vector2_base &v) const { return vector2_base(x+v.x, y+v.y); }
+	vector2_base operator *(const T v) const { return vector2_base(x*v, y*v); }
+	
+	const vector2_base &operator =(const vector2_base &v) { x = v.x; y = v.y; return *this; }
+
+	const vector2_base &operator +=(const vector2_base &v) { x += v.x; y += v.y; return *this; }
+	const vector2_base &operator -=(const vector2_base &v) { x -= v.x; y -= v.y; return *this; }
+	const vector2_base &operator *=(const T v) { x *= v; y *= v; return *this;	}
+
+	bool operator ==(const vector2_base &v) const { return x == v.x && y == v.y; } //TODO: do this with an eps instead
+
+	operator const T* () { return &x; }
+};
+
+
+template<typename T>
+inline T length(const vector2_base<T> &a)
+{
+	return sqrtf(a.x*a.x + a.y*a.y);
+}
+
+template<typename T>
+inline T distance(const vector2_base<T> a, const vector2_base<T> &b)
+{
+	return length(a-b);
+}
+
+template<typename T>
+inline T dot(const vector2_base<T> a, const vector2_base<T> &b)
+{
+	return a.x*b.x + a.y*b.y;
+}
+
+template<typename T>
+inline vector2_base<T> normalize(const vector2_base<T> &v)
+{
+	T l = (T)(1.0f/sqrtf(v.x*v.x + v.y*v.y));
+	return vector2_base<T>(v.x*l, v.y*l);
+}
+
+typedef vector2_base<float> vec2;
+typedef vector2_base<bool> bvec2;
+typedef vector2_base<int> ivec2;
+
+template<typename T>
+inline vector2_base<T> closest_point_on_line(vector2_base<T> line_point0, vector2_base<T> line_point1, vector2_base<T> target_point)
+{
+	vector2_base<T> c = target_point - line_point0;
+	vector2_base<T> v = (line_point1 - line_point0);
+	v = normalize(v);
+	T d = length(line_point0-line_point1);
+	T t = dot(v, c)/d;
+	return mix(line_point0, line_point1, clamp(t, (T)0, (T)1));
+	/*
+	if (t < 0) t = 0;
+	if (t > 1.0f) return 1.0f;
+	return t;*/
+}
+	
+// ------------------------------------
+template<typename T>
+class vector3_base
+{
+public:
+	union { T x,r,h; };
+	union { T y,g,s; };
+	union { T z,b,v,l; };
+
+	vector3_base() {}
+	vector3_base(float nx, float ny, float nz)
+	{
+		x = nx;
+		y = ny;
+		z = nz;
+	}
+	
+	const vector3_base &operator =(const vector3_base &v) { x = v.x; y = v.y; z = v.z; return *this; }
+
+	vector3_base operator -(const vector3_base &v) const { return vector3_base(x-v.x, y-v.y, z-v.z); }
+	vector3_base operator -() const { return vector3_base(-x, -y, -z); }
+	vector3_base operator +(const vector3_base &v) const { return vector3_base(x+v.x, y+v.y, z+v.z); }
+	vector3_base operator *(const T v) const { return vector3_base(x*v, y*v, z*v); }
+	vector3_base operator *(const vector3_base &v) const { return vector3_base(x*v.x, y*v.y, z*v.z); }
+	vector3_base operator /(const T v) const { return vector3_base(x/v, y/v, z/v); }
+	
+	const vector3_base &operator +=(const vector3_base &v) { x += v.x; y += v.y; z += v.z; return *this; }
+	const vector3_base &operator -=(const vector3_base &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
+	const vector3_base &operator *=(const T v) { x *= v; y *= v; z *= v; return *this;	}
+
+	bool operator ==(const vector3_base &v) const { return x == v.x && y == v.y && z == v.z; } //TODO: do this with an eps instead
+
+	operator const T* () { return &x; }
+};
+
+template<typename T>
+inline T length(const vector3_base<T> &a)
+{
+	return sqrtf(a.x*a.x + a.y*a.y + a.z*a.z);
+}
+
+template<typename T>
+inline T distance(const vector3_base<T> &a, const vector3_base<T> &b)
+{
+	return length(a-b);
+}
+
+template<typename T>
+inline T dot(const vector3_base<T> &a, const vector3_base<T> &b)
+{
+	return a.x*b.x + a.y*b.y + a.z*b.z;
+}
+
+template<typename T>
+inline vector3_base<T> normalize(const vector3_base<T> &v)
+{
+	T l = (T)(1.0f/sqrtf(v.x*v.x + v.y*v.y + v.z*v.z));
+	return vector3_base<T>(v.x*l, v.y*l, v.z*l);
+}
+
+template<typename T>
+inline vector3_base<T> cross(const vector3_base<T> &a, const vector3_base<T> &b)
+{
+	return vector3_base<T>(
+		a.y*b.z - a.z*b.y,
+		a.z*b.x - a.x*b.z,
+		a.x*b.y - a.y*b.x);
+}
+
+typedef vector3_base<float> vec3;
+typedef vector3_base<bool> bvec3;
+typedef vector3_base<int> ivec3;
+
+// ------------------------------------
+
+template<typename T>
+class vector4_base
+{
+public:
+	union { T x,r; };
+	union { T y,g; };
+	union { T z,b; };
+	union { T w,a; };
+
+	vector4_base() {}
+	vector4_base(float nx, float ny, float nz, float nw)
+	{
+		x = nx;
+		y = ny;
+		z = nz;
+		w = nw;
+	}
+	
+	vector4_base operator +(const vector4_base &v) const { return vector4_base(x+v.x, y+v.y, z+v.z, w+v.w); }
+	vector4_base operator -(const vector4_base &v) const { return vector4_base(x-v.x, y-v.y, z-v.z, w-v.w); }
+	vector4_base operator -() const { return vector4_base(-x, -y, -z, -w); }
+	vector4_base operator *(const vector4_base &v) const { return vector4_base(x*v.x, y*v.y, z*v.z, w*v.w); }
+	vector4_base operator *(const T v) const { return vector4_base(x*v, y*v, z*v, w*v); }
+	
+	const vector4_base &operator =(const vector4_base &v) { x = v.x; y = v.y; z = v.z; w = v.w; return *this; }
+
+	const vector4_base &operator +=(const vector4_base &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
+	const vector4_base &operator -=(const vector4_base &v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
+	const vector4_base &operator *=(const T v) { x *= v; y *= v; z *= v; w *= v; return *this;	}
+
+	bool operator ==(const vector4_base &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; } //TODO: do this with an eps instead
+
+	operator const T* () { return &x; }
+};
+
+typedef vector4_base<float> vec4;
+typedef vector4_base<bool> bvec4;
+typedef vector4_base<int> ivec4;
+
+#endif