initial commit
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 29 Dec 2015 08:42:16 +0000 (10:42 +0200)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 29 Dec 2015 08:42:16 +0000 (10:42 +0200)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/gmath.h [new file with mode: 0644]
src/matrix.h [new file with mode: 0644]
src/quat.h [new file with mode: 0644]
src/ray.h [new file with mode: 0644]
src/swizzle.h [new file with mode: 0644]
src/vector.cc [new file with mode: 0644]
src/vector.h [new file with mode: 0644]
src/vector.inl [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..54ebde8
--- /dev/null
@@ -0,0 +1,6 @@
+*.o
+*.d
+*.swp
+*.so
+*.so.*
+*.a
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..315b7df
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,85 @@
+# build options
+PREFIX ?= /usr/local
+warn_flags = -pedantic -Wall
+opt_flags = -O0
+dbg_flags = -g
+# -------------
+name = gmath
+so_major = 0
+so_minor = 1
+
+rootdir ?= .
+ccsrc = $(wildcard $(rootdir)/src/*.cc)
+obj = $(ccsrc:.cc=.o) $(csrc:.c=.o)
+dep = $(obj:.o=.d)
+
+CFLAGS = $(warn_flags) $(opt_flags) $(dbg_flags) $(pic)
+CXXFLAGS = $(warn_flags) $(opt_flags) $(dbg_flags) $(pic)
+
+sys = $(shell uname -s | sed 's/MINGW.*/MINGW/')
+ifeq ($(sys), Darwin)
+       alib = lib$(name).a
+       solib = lib$(name).dylib
+       shared = -dynamiclib
+
+else ifeq ($(sys), MINGW)
+       alib = $(name).lib
+       solib = $(name).dll
+       shared = -shared
+
+else
+       alib = lib$(name).a
+       solib = lib$(name).so.$(so_major).$(so_minor)
+       soname = lib$(name).so.$(so_major)
+       ldname = lib$(name).so
+       shared = -shared -Wl,-soname=$(soname)
+       pic = -fPIC
+endif
+
+.PHONY: all
+all: $(alib) $(solib)
+
+$(alib): $(obj) Makefile
+       $(AR) rcs $@ $(obj)
+
+$(solib): $(obj) Makefile
+       $(CXX) -o $@ $(shared) $(obj) $(LDFLAGS)
+       [ -n "$(soname)" ] && \
+               rm -f $(soname) $(ldname) && \
+               ln -s $(solib) $(soname) && \
+               ln -s $(soname) $(ldname) || true
+
+-include $(dep)
+
+%.d: %.c
+       @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
+
+%.d: %.cc
+       @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(alib) $(solib)
+
+.PHONY: cleandep
+cleandep:
+       rm -f $(dep)
+
+.PHONY: install
+install: $(alib) $(solib)
+       mkdir -p $(DESTDIR)$(PREFIX)/include/$(name) $(DESTDIR)$(PREFIX)/lib
+       cp src/*.h src/*.inl $(DESTDIR)$(PREFIX)/include/$(name)/
+       cp $(alib) $(DESTDIR)$(PREFIX)/lib/$(alib)
+       cp $(solib) $(DESTDIR)$(PREFIX)/lib/$(solib)
+       [ -n "$(soname)" ] && \
+               rm -f $(DESTDIR)$(PREFIX)/lib/$(soname) $(DESTDIR)$(PREFIX)/lib/$(ldname) && \
+               cp $(soname) $(DESTDIR)$(PREFIX)/lib/$(soname) && \
+               cp $(ldname) $(DESTDIR)$(PREFIX)/lib/$(ldname) || true
+
+.PHONY: uninstall
+uninstall:
+       rm -f $(DESTDIR)$(PREFIX)/include/$(name)/*.h $(DESTDIR)$(PREFIX)/include/$(name)/*.inl
+       rm -f $(DESTDIR)$(PREFIX)/lib/$(solib)
+       [ -n "$(soname)" ] && \
+               rm -f $(DESTDIR)$(PREFIX)/lib/$(soname) && \
+               rm -f $(DESTDIR)$(PREFIX)/lib/$(ldname) || true
diff --git a/src/gmath.h b/src/gmath.h
new file mode 100644 (file)
index 0000000..6e1cde3
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef GMATH_H_
+#define GMATH_H_
+
+#include "vector.h"
+#include "matrix.h"
+
+#endif // GMATH_H_
diff --git a/src/matrix.h b/src/matrix.h
new file mode 100644 (file)
index 0000000..f5dbaa9
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef GMATH_MATRIX_H_
+#define GMATH_MATRIX_H_
+
+#include <string.h>
+#include "vector.h"
+
+namespace gph {
+
+class Matrix4x4 {
+private:
+       float m[4][4];
+
+public:
+       static Matrix4x4 identity;
+
+       Matrix4x4()
+       {
+               memcpy((float*)m, (const float*)identity.m, 16 * sizeof(float));
+       }
+
+       Matrix4x4(const float *m)
+       {
+               memcpy((float*)this->m, (const float*)m, 16 * sizeof(float));
+       }
+
+       Matrix4x4(float m00, float m01, float m02, float m03,
+                       float m10, float m11, float m12, float m13,
+                       float m20, float m21, float m22, float m23,
+                       float m30, float m31, float m32, float m33)
+       {
+               m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
+               m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
+               m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
+               m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
+       }
+
+       Matrix4x4(const Vector4 &v0, const Vector4 &v1, const Vector4 &v2, const Vector4 &v3)
+       {
+               m[0][0] = v0.x; m[0][1] = v0.y; m[0][2] = v0.z; m[0][3] = v0.w;
+               m[1][0] = v1.x; m[1][1] = v1.y; m[1][2] = v1.z; m[1][3] = v1.w;
+               m[2][0] = v2.x; m[2][1] = v2.y; m[2][2] = v2.z; m[2][3] = v2.w;
+               m[3][0] = v3.x; m[3][1] = v3.y; m[3][2] = v3.z; m[3][3] = v3.w;
+       }
+
+       float *operator [](int idx)
+       {
+               return m[idx];
+       }
+
+       const float *operator [](int idx) const
+       {
+               return m[idx];
+       }
+};
+
+}      // namespace gph
+
+#endif // GMATH_MATRIX_H_
diff --git a/src/quat.h b/src/quat.h
new file mode 100644 (file)
index 0000000..4b71c7c
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef QUATERNION_H_
+#define QUATERNION_H_
+
+namespace gph {
+
+class Quaternion {
+public:
+       float x, y, z, w;       // w + xi + yj + zk
+
+       Quaternion() : x(0), y(0), z(0), w(1) {}
+       Quaternion(float x_, float y_, float z_, float w_) : x(x_), y(y_), z(z_), w(w_) {}
+       Quaternion(const Vector3 &v, float s) : x(v.x), y(v.y), z(v.z), w(s) {}
+
+       // TODO more
+};
+
+}      // namespace gph
+
+#endif // QUATERNION_H_
diff --git a/src/ray.h b/src/ray.h
new file mode 100644 (file)
index 0000000..2574036
--- /dev/null
+++ b/src/ray.h
@@ -0,0 +1,54 @@
+#ifndef GMATH_RAY_H_
+#define GMATH_RAY_H_
+
+#include "vector.h"
+#include "matrix.h"
+
+namespace gph {
+
+class Ray {
+public:
+       Vector3 origin, dir;
+
+       Ray() : dir(0, 0, 1) {}
+       Ray(const Vector3 &o, const Vector3 &d) : o(origin), d(dir) {}
+};
+
+inline Ray operator *(const Ray &r, const Matrix4x4 &m)
+{
+       Matrix4x4 up = m;
+       up[0][3] = up[1][3] = up[2][3] = up[3][0] = up[3][1] = up[3][2] = 0.0;
+       up[3][3] = 1.0;
+
+       return Ray(origin * m, dir * up);
+}
+
+inline Ray operator *(const Matrix4x4 &m, const Ray &r)
+{
+       Matrix4x4 up = m;
+       up[0][3] = up[1][3] = up[2][3] = up[3][0] = up[3][1] = up[3][2] = 0.0;
+       up[3][3] = 1.0;
+
+       return Ray(m * origin, m * dir);
+}
+
+
+inline Ray reflect(const Ray &ray, const Vector3 &n)
+{
+       return Ray(ray.origin, reflect(ray.dir, n));
+}
+
+inline Ray refract(const Ray &ray, const Vector3 &n, float ior)
+{
+       return Ray(ray.origin, refract(ray.dir, n, ior));
+}
+
+inline Ray refract(const Ray &ray, const Vector3 &n, float from_ior, float to_ior)
+{
+       return Ray(ray.origin, refract(ray.dir, n, from_ior, to_ior));
+}
+
+
+}
+
+#endif // GMATH_RAY_H_
diff --git a/src/swizzle.h b/src/swizzle.h
new file mode 100644 (file)
index 0000000..66d27d5
--- /dev/null
@@ -0,0 +1,135 @@
+// the only function of this file is to hide the swizzle-macro eyesore
+
+// swizzle macros for Vector2
+#define GPH_VEC2_SWIZZLE       \
+       GPH_SWIZZLE2(Vector2, x, x) GPH_SWIZZLE2(Vector2, x, y) \
+       GPH_SWIZZLE2(Vector2, y, x) GPH_SWIZZLE2(Vector2, y, y)
+
+// swizzle macros for Vector3
+#define GPH_VEC3_SWIZZLE       \
+       GPH_SWIZZLE2(Vector3, x, x) GPH_SWIZZLE2(Vector3, x, y) GPH_SWIZZLE2(Vector3, x, z) \
+       GPH_SWIZZLE2(Vector3, y, x) GPH_SWIZZLE2(Vector3, y, y) GPH_SWIZZLE2(Vector3, y, z) \
+       GPH_SWIZZLE2(Vector3, z, x) GPH_SWIZZLE2(Vector3, z, y) GPH_SWIZZLE2(Vector3, z, z) \
+       GPH_SWIZZLE3(Vector3, x, x, x) GPH_SWIZZLE3(Vector3, x, x, y) GPH_SWIZZLE3(Vector3, x, x, z) \
+       GPH_SWIZZLE3(Vector3, x, y, x) GPH_SWIZZLE3(Vector3, x, y, y) GPH_SWIZZLE3(Vector3, x, y, z) \
+       GPH_SWIZZLE3(Vector3, x, z, x) GPH_SWIZZLE3(Vector3, x, z, y) GPH_SWIZZLE3(Vector3, x, z, z) \
+       GPH_SWIZZLE3(Vector3, y, x, x) GPH_SWIZZLE3(Vector3, y, x, y) GPH_SWIZZLE3(Vector3, y, x, z) \
+       GPH_SWIZZLE3(Vector3, y, y, x) GPH_SWIZZLE3(Vector3, y, y, y) GPH_SWIZZLE3(Vector3, y, y, z) \
+       GPH_SWIZZLE3(Vector3, y, z, x) GPH_SWIZZLE3(Vector3, y, z, y) GPH_SWIZZLE3(Vector3, y, z, z) \
+       GPH_SWIZZLE3(Vector3, z, x, x) GPH_SWIZZLE3(Vector3, z, x, y) GPH_SWIZZLE3(Vector3, z, x, z) \
+       GPH_SWIZZLE3(Vector3, z, y, x) GPH_SWIZZLE3(Vector3, z, y, y) GPH_SWIZZLE3(Vector3, z, y, z) \
+       GPH_SWIZZLE3(Vector3, z, z, x) GPH_SWIZZLE3(Vector3, z, z, y) GPH_SWIZZLE3(Vector3, z, z, z) \
+       GPH_SWIZZLE4(Vector3, x, x, x, x) GPH_SWIZZLE4(Vector3, x, x, x, y) GPH_SWIZZLE4(Vector3, x, x, x, z) \
+       GPH_SWIZZLE4(Vector3, x, x, y, x) GPH_SWIZZLE4(Vector3, x, x, y, y) GPH_SWIZZLE4(Vector3, x, x, y, z) \
+       GPH_SWIZZLE4(Vector3, x, x, z, x) GPH_SWIZZLE4(Vector3, x, x, z, y) GPH_SWIZZLE4(Vector3, x, x, z, z) \
+       GPH_SWIZZLE4(Vector3, x, y, x, x) GPH_SWIZZLE4(Vector3, x, y, x, y) GPH_SWIZZLE4(Vector3, x, y, x, z) \
+       GPH_SWIZZLE4(Vector3, x, y, y, x) GPH_SWIZZLE4(Vector3, x, y, y, y) GPH_SWIZZLE4(Vector3, x, y, y, z) \
+       GPH_SWIZZLE4(Vector3, x, y, z, x) GPH_SWIZZLE4(Vector3, x, y, z, y) GPH_SWIZZLE4(Vector3, x, y, z, z) \
+       GPH_SWIZZLE4(Vector3, x, z, x, x) GPH_SWIZZLE4(Vector3, x, z, x, y) GPH_SWIZZLE4(Vector3, x, z, x, z) \
+       GPH_SWIZZLE4(Vector3, x, z, y, x) GPH_SWIZZLE4(Vector3, x, z, y, y) GPH_SWIZZLE4(Vector3, x, z, y, z) \
+       GPH_SWIZZLE4(Vector3, x, z, z, x) GPH_SWIZZLE4(Vector3, x, z, z, y) GPH_SWIZZLE4(Vector3, x, z, z, z) \
+       GPH_SWIZZLE4(Vector3, y, x, x, x) GPH_SWIZZLE4(Vector3, y, x, x, y) GPH_SWIZZLE4(Vector3, y, x, x, z) \
+       GPH_SWIZZLE4(Vector3, y, x, y, x) GPH_SWIZZLE4(Vector3, y, x, y, y) GPH_SWIZZLE4(Vector3, y, x, y, z) \
+       GPH_SWIZZLE4(Vector3, y, x, z, x) GPH_SWIZZLE4(Vector3, y, x, z, y) GPH_SWIZZLE4(Vector3, y, x, z, z) \
+       GPH_SWIZZLE4(Vector3, y, y, x, x) GPH_SWIZZLE4(Vector3, y, y, x, y) GPH_SWIZZLE4(Vector3, y, y, x, z) \
+       GPH_SWIZZLE4(Vector3, y, y, y, x) GPH_SWIZZLE4(Vector3, y, y, y, y) GPH_SWIZZLE4(Vector3, y, y, y, z) \
+       GPH_SWIZZLE4(Vector3, y, y, z, x) GPH_SWIZZLE4(Vector3, y, y, z, y) GPH_SWIZZLE4(Vector3, y, y, z, z) \
+       GPH_SWIZZLE4(Vector3, y, z, x, x) GPH_SWIZZLE4(Vector3, y, z, x, y) GPH_SWIZZLE4(Vector3, y, z, x, z) \
+       GPH_SWIZZLE4(Vector3, y, z, y, x) GPH_SWIZZLE4(Vector3, y, z, y, y) GPH_SWIZZLE4(Vector3, y, z, y, z) \
+       GPH_SWIZZLE4(Vector3, y, z, z, x) GPH_SWIZZLE4(Vector3, y, z, z, y) GPH_SWIZZLE4(Vector3, y, z, z, z) \
+       GPH_SWIZZLE4(Vector3, z, x, x, x) GPH_SWIZZLE4(Vector3, z, x, x, y) GPH_SWIZZLE4(Vector3, z, x, x, z) \
+       GPH_SWIZZLE4(Vector3, z, x, y, x) GPH_SWIZZLE4(Vector3, z, x, y, y) GPH_SWIZZLE4(Vector3, z, x, y, z) \
+       GPH_SWIZZLE4(Vector3, z, x, z, x) GPH_SWIZZLE4(Vector3, z, x, z, y) GPH_SWIZZLE4(Vector3, z, x, z, z) \
+       GPH_SWIZZLE4(Vector3, z, y, x, x) GPH_SWIZZLE4(Vector3, z, y, x, y) GPH_SWIZZLE4(Vector3, z, y, x, z) \
+       GPH_SWIZZLE4(Vector3, z, y, y, x) GPH_SWIZZLE4(Vector3, z, y, y, y) GPH_SWIZZLE4(Vector3, z, y, y, z) \
+       GPH_SWIZZLE4(Vector3, z, y, z, x) GPH_SWIZZLE4(Vector3, z, y, z, y) GPH_SWIZZLE4(Vector3, z, y, z, z) \
+       GPH_SWIZZLE4(Vector3, z, z, x, x) GPH_SWIZZLE4(Vector3, z, z, x, y) GPH_SWIZZLE4(Vector3, z, z, x, z) \
+       GPH_SWIZZLE4(Vector3, z, z, y, x) GPH_SWIZZLE4(Vector3, z, z, y, y) GPH_SWIZZLE4(Vector3, z, z, y, z) \
+       GPH_SWIZZLE4(Vector3, z, z, z, x) GPH_SWIZZLE4(Vector3, z, z, z, y) GPH_SWIZZLE4(Vector3, z, z, z, z)
+
+// swizzle macros for Vector4 (oh shit...)
+#define GPH_VEC4_SWIZZLE       \
+       GPH_SWIZZLE2(Vector4, x, x) GPH_SWIZZLE2(Vector4, x, y) GPH_SWIZZLE2(Vector4, x, z) GPH_SWIZZLE2(Vector4, x, w) \
+       GPH_SWIZZLE2(Vector4, y, x) GPH_SWIZZLE2(Vector4, y, y) GPH_SWIZZLE2(Vector4, y, z) GPH_SWIZZLE2(Vector4, y, w) \
+       GPH_SWIZZLE2(Vector4, z, x) GPH_SWIZZLE2(Vector4, z, y) GPH_SWIZZLE2(Vector4, z, z) GPH_SWIZZLE2(Vector4, z, w) \
+       GPH_SWIZZLE2(Vector4, w, x) GPH_SWIZZLE2(Vector4, w, y) GPH_SWIZZLE2(Vector4, w, z) GPH_SWIZZLE2(Vector4, w, w) \
+       GPH_SWIZZLE3(Vector4, x, x, x) GPH_SWIZZLE3(Vector4, x, x, y) GPH_SWIZZLE3(Vector4, x, x, z) GPH_SWIZZLE3(Vector4, x, x, w) \
+       GPH_SWIZZLE3(Vector4, x, y, x) GPH_SWIZZLE3(Vector4, x, y, y) GPH_SWIZZLE3(Vector4, x, y, z) GPH_SWIZZLE3(Vector4, x, y, w) \
+       GPH_SWIZZLE3(Vector4, x, z, x) GPH_SWIZZLE3(Vector4, x, z, y) GPH_SWIZZLE3(Vector4, x, z, z) GPH_SWIZZLE3(Vector4, x, z, w) \
+       GPH_SWIZZLE3(Vector4, x, w, x) GPH_SWIZZLE3(Vector4, x, w, y) GPH_SWIZZLE3(Vector4, x, w, z) GPH_SWIZZLE3(Vector4, x, w, w) \
+       GPH_SWIZZLE3(Vector4, y, x, x) GPH_SWIZZLE3(Vector4, y, x, y) GPH_SWIZZLE3(Vector4, y, x, z) GPH_SWIZZLE3(Vector4, y, x, w) \
+       GPH_SWIZZLE3(Vector4, y, y, x) GPH_SWIZZLE3(Vector4, y, y, y) GPH_SWIZZLE3(Vector4, y, y, z) GPH_SWIZZLE3(Vector4, y, y, w) \
+       GPH_SWIZZLE3(Vector4, y, z, x) GPH_SWIZZLE3(Vector4, y, z, y) GPH_SWIZZLE3(Vector4, y, z, z) GPH_SWIZZLE3(Vector4, y, z, w) \
+       GPH_SWIZZLE3(Vector4, y, w, x) GPH_SWIZZLE3(Vector4, y, w, y) GPH_SWIZZLE3(Vector4, y, w, z) GPH_SWIZZLE3(Vector4, y, w, w) \
+       GPH_SWIZZLE3(Vector4, z, x, x) GPH_SWIZZLE3(Vector4, z, x, y) GPH_SWIZZLE3(Vector4, z, x, z) GPH_SWIZZLE3(Vector4, z, x, w) \
+       GPH_SWIZZLE3(Vector4, z, y, x) GPH_SWIZZLE3(Vector4, z, y, y) GPH_SWIZZLE3(Vector4, z, y, z) GPH_SWIZZLE3(Vector4, z, y, w) \
+       GPH_SWIZZLE3(Vector4, z, z, x) GPH_SWIZZLE3(Vector4, z, z, y) GPH_SWIZZLE3(Vector4, z, z, z) GPH_SWIZZLE3(Vector4, z, z, w) \
+       GPH_SWIZZLE3(Vector4, z, w, x) GPH_SWIZZLE3(Vector4, z, w, y) GPH_SWIZZLE3(Vector4, z, w, z) GPH_SWIZZLE3(Vector4, z, w, w) \
+       GPH_SWIZZLE3(Vector4, w, x, x) GPH_SWIZZLE3(Vector4, w, x, y) GPH_SWIZZLE3(Vector4, w, x, z) GPH_SWIZZLE3(Vector4, w, x, w) \
+       GPH_SWIZZLE3(Vector4, w, y, x) GPH_SWIZZLE3(Vector4, w, y, y) GPH_SWIZZLE3(Vector4, w, y, z) GPH_SWIZZLE3(Vector4, w, y, w) \
+       GPH_SWIZZLE3(Vector4, w, z, x) GPH_SWIZZLE3(Vector4, w, z, y) GPH_SWIZZLE3(Vector4, w, z, z) GPH_SWIZZLE3(Vector4, w, z, w) \
+       GPH_SWIZZLE3(Vector4, w, w, x) GPH_SWIZZLE3(Vector4, w, w, y) GPH_SWIZZLE3(Vector4, w, w, z) GPH_SWIZZLE3(Vector4, w, w, w) \
+       GPH_SWIZZLE4(Vector4, x, x, x, x) GPH_SWIZZLE4(Vector4, x, x, x, y) GPH_SWIZZLE4(Vector4, x, x, x, z) GPH_SWIZZLE4(Vector4, x, x, x, w) \
+       GPH_SWIZZLE4(Vector4, x, x, y, x) GPH_SWIZZLE4(Vector4, x, x, y, y) GPH_SWIZZLE4(Vector4, x, x, y, z) GPH_SWIZZLE4(Vector4, x, x, y, w) \
+       GPH_SWIZZLE4(Vector4, x, x, z, x) GPH_SWIZZLE4(Vector4, x, x, z, y) GPH_SWIZZLE4(Vector4, x, x, z, z) GPH_SWIZZLE4(Vector4, x, x, z, w) \
+       GPH_SWIZZLE4(Vector4, x, x, w, x) GPH_SWIZZLE4(Vector4, x, x, w, y) GPH_SWIZZLE4(Vector4, x, x, w, z) GPH_SWIZZLE4(Vector4, x, x, w, w) \
+       GPH_SWIZZLE4(Vector4, x, y, x, x) GPH_SWIZZLE4(Vector4, x, y, x, y) GPH_SWIZZLE4(Vector4, x, y, x, z) GPH_SWIZZLE4(Vector4, x, y, x, w) \
+       GPH_SWIZZLE4(Vector4, x, y, y, x) GPH_SWIZZLE4(Vector4, x, y, y, y) GPH_SWIZZLE4(Vector4, x, y, y, z) GPH_SWIZZLE4(Vector4, x, y, y, w) \
+       GPH_SWIZZLE4(Vector4, x, y, z, x) GPH_SWIZZLE4(Vector4, x, y, z, y) GPH_SWIZZLE4(Vector4, x, y, z, z) GPH_SWIZZLE4(Vector4, x, y, z, w) \
+       GPH_SWIZZLE4(Vector4, x, y, w, x) GPH_SWIZZLE4(Vector4, x, y, w, y) GPH_SWIZZLE4(Vector4, x, y, w, z) GPH_SWIZZLE4(Vector4, x, y, w, w) \
+       GPH_SWIZZLE4(Vector4, x, z, x, x) GPH_SWIZZLE4(Vector4, x, z, x, y) GPH_SWIZZLE4(Vector4, x, z, x, z) GPH_SWIZZLE4(Vector4, x, z, x, w) \
+       GPH_SWIZZLE4(Vector4, x, z, y, x) GPH_SWIZZLE4(Vector4, x, z, y, y) GPH_SWIZZLE4(Vector4, x, z, y, z) GPH_SWIZZLE4(Vector4, x, z, y, w) \
+       GPH_SWIZZLE4(Vector4, x, z, z, x) GPH_SWIZZLE4(Vector4, x, z, z, y) GPH_SWIZZLE4(Vector4, x, z, z, z) GPH_SWIZZLE4(Vector4, x, z, z, w) \
+       GPH_SWIZZLE4(Vector4, x, z, w, x) GPH_SWIZZLE4(Vector4, x, z, w, y) GPH_SWIZZLE4(Vector4, x, z, w, z) GPH_SWIZZLE4(Vector4, x, z, w, w) \
+       GPH_SWIZZLE4(Vector4, x, w, x, x) GPH_SWIZZLE4(Vector4, x, w, x, y) GPH_SWIZZLE4(Vector4, x, w, x, z) GPH_SWIZZLE4(Vector4, x, w, x, w) \
+       GPH_SWIZZLE4(Vector4, x, w, y, x) GPH_SWIZZLE4(Vector4, x, w, y, y) GPH_SWIZZLE4(Vector4, x, w, y, z) GPH_SWIZZLE4(Vector4, x, w, y, w) \
+       GPH_SWIZZLE4(Vector4, x, w, z, x) GPH_SWIZZLE4(Vector4, x, w, z, y) GPH_SWIZZLE4(Vector4, x, w, z, z) GPH_SWIZZLE4(Vector4, x, w, z, w) \
+       GPH_SWIZZLE4(Vector4, x, w, w, x) GPH_SWIZZLE4(Vector4, x, w, w, y) GPH_SWIZZLE4(Vector4, x, w, w, z) GPH_SWIZZLE4(Vector4, x, w, w, w) \
+       GPH_SWIZZLE4(Vector4, y, x, x, x) GPH_SWIZZLE4(Vector4, y, x, x, y) GPH_SWIZZLE4(Vector4, y, x, x, z) GPH_SWIZZLE4(Vector4, y, x, x, w) \
+       GPH_SWIZZLE4(Vector4, y, x, y, x) GPH_SWIZZLE4(Vector4, y, x, y, y) GPH_SWIZZLE4(Vector4, y, x, y, z) GPH_SWIZZLE4(Vector4, y, x, y, w) \
+       GPH_SWIZZLE4(Vector4, y, x, z, x) GPH_SWIZZLE4(Vector4, y, x, z, y) GPH_SWIZZLE4(Vector4, y, x, z, z) GPH_SWIZZLE4(Vector4, y, x, z, w) \
+       GPH_SWIZZLE4(Vector4, y, x, w, x) GPH_SWIZZLE4(Vector4, y, x, w, y) GPH_SWIZZLE4(Vector4, y, x, w, z) GPH_SWIZZLE4(Vector4, y, x, w, w) \
+       GPH_SWIZZLE4(Vector4, y, y, x, x) GPH_SWIZZLE4(Vector4, y, y, x, y) GPH_SWIZZLE4(Vector4, y, y, x, z) GPH_SWIZZLE4(Vector4, y, y, x, w) \
+       GPH_SWIZZLE4(Vector4, y, y, y, x) GPH_SWIZZLE4(Vector4, y, y, y, y) GPH_SWIZZLE4(Vector4, y, y, y, z) GPH_SWIZZLE4(Vector4, y, y, y, w) \
+       GPH_SWIZZLE4(Vector4, y, y, z, x) GPH_SWIZZLE4(Vector4, y, y, z, y) GPH_SWIZZLE4(Vector4, y, y, z, z) GPH_SWIZZLE4(Vector4, y, y, z, w) \
+       GPH_SWIZZLE4(Vector4, y, y, w, x) GPH_SWIZZLE4(Vector4, y, y, w, y) GPH_SWIZZLE4(Vector4, y, y, w, z) GPH_SWIZZLE4(Vector4, y, y, w, w) \
+       GPH_SWIZZLE4(Vector4, y, z, x, x) GPH_SWIZZLE4(Vector4, y, z, x, y) GPH_SWIZZLE4(Vector4, y, z, x, z) GPH_SWIZZLE4(Vector4, y, z, x, w) \
+       GPH_SWIZZLE4(Vector4, y, z, y, x) GPH_SWIZZLE4(Vector4, y, z, y, y) GPH_SWIZZLE4(Vector4, y, z, y, z) GPH_SWIZZLE4(Vector4, y, z, y, w) \
+       GPH_SWIZZLE4(Vector4, y, z, z, x) GPH_SWIZZLE4(Vector4, y, z, z, y) GPH_SWIZZLE4(Vector4, y, z, z, z) GPH_SWIZZLE4(Vector4, y, z, z, w) \
+       GPH_SWIZZLE4(Vector4, y, z, w, x) GPH_SWIZZLE4(Vector4, y, z, w, y) GPH_SWIZZLE4(Vector4, y, z, w, z) GPH_SWIZZLE4(Vector4, y, z, w, w) \
+       GPH_SWIZZLE4(Vector4, y, w, x, x) GPH_SWIZZLE4(Vector4, y, w, x, y) GPH_SWIZZLE4(Vector4, y, w, x, z) GPH_SWIZZLE4(Vector4, y, w, x, w) \
+       GPH_SWIZZLE4(Vector4, y, w, y, x) GPH_SWIZZLE4(Vector4, y, w, y, y) GPH_SWIZZLE4(Vector4, y, w, y, z) GPH_SWIZZLE4(Vector4, y, w, y, w) \
+       GPH_SWIZZLE4(Vector4, y, w, z, x) GPH_SWIZZLE4(Vector4, y, w, z, y) GPH_SWIZZLE4(Vector4, y, w, z, z) GPH_SWIZZLE4(Vector4, y, w, z, w) \
+       GPH_SWIZZLE4(Vector4, y, w, w, x) GPH_SWIZZLE4(Vector4, y, w, w, y) GPH_SWIZZLE4(Vector4, y, w, w, z) GPH_SWIZZLE4(Vector4, y, w, w, w) \
+       GPH_SWIZZLE4(Vector4, z, x, x, x) GPH_SWIZZLE4(Vector4, z, x, x, y) GPH_SWIZZLE4(Vector4, z, x, x, z) GPH_SWIZZLE4(Vector4, z, x, x, w) \
+       GPH_SWIZZLE4(Vector4, z, x, y, x) GPH_SWIZZLE4(Vector4, z, x, y, y) GPH_SWIZZLE4(Vector4, z, x, y, z) GPH_SWIZZLE4(Vector4, z, x, y, w) \
+       GPH_SWIZZLE4(Vector4, z, x, z, x) GPH_SWIZZLE4(Vector4, z, x, z, y) GPH_SWIZZLE4(Vector4, z, x, z, z) GPH_SWIZZLE4(Vector4, z, x, z, w) \
+       GPH_SWIZZLE4(Vector4, z, x, w, x) GPH_SWIZZLE4(Vector4, z, x, w, y) GPH_SWIZZLE4(Vector4, z, x, w, z) GPH_SWIZZLE4(Vector4, z, x, w, w) \
+       GPH_SWIZZLE4(Vector4, z, y, x, x) GPH_SWIZZLE4(Vector4, z, y, x, y) GPH_SWIZZLE4(Vector4, z, y, x, z) GPH_SWIZZLE4(Vector4, z, y, x, w) \
+       GPH_SWIZZLE4(Vector4, z, y, y, x) GPH_SWIZZLE4(Vector4, z, y, y, y) GPH_SWIZZLE4(Vector4, z, y, y, z) GPH_SWIZZLE4(Vector4, z, y, y, w) \
+       GPH_SWIZZLE4(Vector4, z, y, z, x) GPH_SWIZZLE4(Vector4, z, y, z, y) GPH_SWIZZLE4(Vector4, z, y, z, z) GPH_SWIZZLE4(Vector4, z, y, z, w) \
+       GPH_SWIZZLE4(Vector4, z, y, w, x) GPH_SWIZZLE4(Vector4, z, y, w, y) GPH_SWIZZLE4(Vector4, z, y, w, z) GPH_SWIZZLE4(Vector4, z, y, w, w) \
+       GPH_SWIZZLE4(Vector4, z, z, x, x) GPH_SWIZZLE4(Vector4, z, z, x, y) GPH_SWIZZLE4(Vector4, z, z, x, z) GPH_SWIZZLE4(Vector4, z, z, x, w) \
+       GPH_SWIZZLE4(Vector4, z, z, y, x) GPH_SWIZZLE4(Vector4, z, z, y, y) GPH_SWIZZLE4(Vector4, z, z, y, z) GPH_SWIZZLE4(Vector4, z, z, y, w) \
+       GPH_SWIZZLE4(Vector4, z, z, z, x) GPH_SWIZZLE4(Vector4, z, z, z, y) GPH_SWIZZLE4(Vector4, z, z, z, z) GPH_SWIZZLE4(Vector4, z, z, z, w) \
+       GPH_SWIZZLE4(Vector4, z, z, w, x) GPH_SWIZZLE4(Vector4, z, z, w, y) GPH_SWIZZLE4(Vector4, z, z, w, z) GPH_SWIZZLE4(Vector4, z, z, w, w) \
+       GPH_SWIZZLE4(Vector4, z, w, x, x) GPH_SWIZZLE4(Vector4, z, w, x, y) GPH_SWIZZLE4(Vector4, z, w, x, z) GPH_SWIZZLE4(Vector4, z, w, x, w) \
+       GPH_SWIZZLE4(Vector4, z, w, y, x) GPH_SWIZZLE4(Vector4, z, w, y, y) GPH_SWIZZLE4(Vector4, z, w, y, z) GPH_SWIZZLE4(Vector4, z, w, y, w) \
+       GPH_SWIZZLE4(Vector4, z, w, z, x) GPH_SWIZZLE4(Vector4, z, w, z, y) GPH_SWIZZLE4(Vector4, z, w, z, z) GPH_SWIZZLE4(Vector4, z, w, z, w) \
+       GPH_SWIZZLE4(Vector4, z, w, w, x) GPH_SWIZZLE4(Vector4, z, w, w, y) GPH_SWIZZLE4(Vector4, z, w, w, z) GPH_SWIZZLE4(Vector4, z, w, w, w) \
+       GPH_SWIZZLE4(Vector4, w, x, x, x) GPH_SWIZZLE4(Vector4, w, x, x, y) GPH_SWIZZLE4(Vector4, w, x, x, z) GPH_SWIZZLE4(Vector4, w, x, x, w) \
+       GPH_SWIZZLE4(Vector4, w, x, y, x) GPH_SWIZZLE4(Vector4, w, x, y, y) GPH_SWIZZLE4(Vector4, w, x, y, z) GPH_SWIZZLE4(Vector4, w, x, y, w) \
+       GPH_SWIZZLE4(Vector4, w, x, z, x) GPH_SWIZZLE4(Vector4, w, x, z, y) GPH_SWIZZLE4(Vector4, w, x, z, z) GPH_SWIZZLE4(Vector4, w, x, z, w) \
+       GPH_SWIZZLE4(Vector4, w, x, w, x) GPH_SWIZZLE4(Vector4, w, x, w, y) GPH_SWIZZLE4(Vector4, w, x, w, z) GPH_SWIZZLE4(Vector4, w, x, w, w) \
+       GPH_SWIZZLE4(Vector4, w, y, x, x) GPH_SWIZZLE4(Vector4, w, y, x, y) GPH_SWIZZLE4(Vector4, w, y, x, z) GPH_SWIZZLE4(Vector4, w, y, x, w) \
+       GPH_SWIZZLE4(Vector4, w, y, y, x) GPH_SWIZZLE4(Vector4, w, y, y, y) GPH_SWIZZLE4(Vector4, w, y, y, z) GPH_SWIZZLE4(Vector4, w, y, y, w) \
+       GPH_SWIZZLE4(Vector4, w, y, z, x) GPH_SWIZZLE4(Vector4, w, y, z, y) GPH_SWIZZLE4(Vector4, w, y, z, z) GPH_SWIZZLE4(Vector4, w, y, z, w) \
+       GPH_SWIZZLE4(Vector4, w, y, w, x) GPH_SWIZZLE4(Vector4, w, y, w, y) GPH_SWIZZLE4(Vector4, w, y, w, z) GPH_SWIZZLE4(Vector4, w, y, w, w) \
+       GPH_SWIZZLE4(Vector4, w, z, x, x) GPH_SWIZZLE4(Vector4, w, z, x, y) GPH_SWIZZLE4(Vector4, w, z, x, z) GPH_SWIZZLE4(Vector4, w, z, x, w) \
+       GPH_SWIZZLE4(Vector4, w, z, y, x) GPH_SWIZZLE4(Vector4, w, z, y, y) GPH_SWIZZLE4(Vector4, w, z, y, z) GPH_SWIZZLE4(Vector4, w, z, y, w) \
+       GPH_SWIZZLE4(Vector4, w, z, z, x) GPH_SWIZZLE4(Vector4, w, z, z, y) GPH_SWIZZLE4(Vector4, w, z, z, z) GPH_SWIZZLE4(Vector4, w, z, z, w) \
+       GPH_SWIZZLE4(Vector4, w, z, w, x) GPH_SWIZZLE4(Vector4, w, z, w, y) GPH_SWIZZLE4(Vector4, w, z, w, z) GPH_SWIZZLE4(Vector4, w, z, w, w) \
+       GPH_SWIZZLE4(Vector4, w, w, x, x) GPH_SWIZZLE4(Vector4, w, w, x, y) GPH_SWIZZLE4(Vector4, w, w, x, z) GPH_SWIZZLE4(Vector4, w, w, x, w) \
+       GPH_SWIZZLE4(Vector4, w, w, y, x) GPH_SWIZZLE4(Vector4, w, w, y, y) GPH_SWIZZLE4(Vector4, w, w, y, z) GPH_SWIZZLE4(Vector4, w, w, y, w) \
+       GPH_SWIZZLE4(Vector4, w, w, z, x) GPH_SWIZZLE4(Vector4, w, w, z, y) GPH_SWIZZLE4(Vector4, w, w, z, z) GPH_SWIZZLE4(Vector4, w, w, z, w) \
+       GPH_SWIZZLE4(Vector4, w, w, w, x) GPH_SWIZZLE4(Vector4, w, w, w, y) GPH_SWIZZLE4(Vector4, w, w, w, z) GPH_SWIZZLE4(Vector4, w, w, w, w)
diff --git a/src/vector.cc b/src/vector.cc
new file mode 100644 (file)
index 0000000..4af8dab
--- /dev/null
@@ -0,0 +1,37 @@
+#include "vector.h"
+#include "matrix.h"
+
+namespace gph {
+
+Vector2::Vector2(const Vector3 &v)
+       : x(v.x), y(v.y)
+{
+}
+
+Vector3::Vector3(const Vector4 &v)
+       : x(v.x), y(v.y), z(v.z)
+{
+}
+
+Vector3 operator *(const Vector3 &v, const Matrix4x4 &m)
+{
+       float x = v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0];
+       float y = v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1];
+       float z = v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2];
+       return Vector3(x, y, z);
+}
+
+Vector3 operator *(const Matrix4x4 &m, const Vector3 &v)
+{
+       float x = m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3];
+       float y = m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3];
+       float z = m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3];
+       return Vector3(x, y, z);
+}
+
+Vector4::Vector4(const Vector3 &v)
+       : x(v.x), y(v.y), z(v.z), w(1.0f)
+{
+}
+
+}      // namespace gph
diff --git a/src/vector.h b/src/vector.h
new file mode 100644 (file)
index 0000000..02aeddf
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef GMATH_VEC_H_
+#define GMATH_VEC_H_
+
+#include <math.h>
+#include "swizzle.h"
+
+namespace gph {
+
+#define GPH_SWIZZLE2(T, a, b)          inline Vector2 a##b() const;
+#define GPH_SWIZZLE3(T, a, b, c)       inline Vector3 a##b##c() const;
+#define GPH_SWIZZLE4(T, a, b, c, d)    inline Vector4 a##b##c##d() const;
+
+class Vector3;
+class Vector4;
+class Matrix4x4;
+class Quaternion;
+
+class Vector2 {
+public:
+       float x, y;
+
+       Vector2() : x(0), y(0) {}
+       Vector2(float x_, float y_) : x(x_), y(y_) {}
+       Vector2(const Vector3 &v);
+
+       inline void normalize();
+       inline float &operator[] (int idx);
+       inline const float &operator[] (int idx) const;
+
+       GPH_VEC2_SWIZZLE
+};
+
+class Vector3 {
+public:
+       float x, y, z;
+
+       Vector3() : x(0), y(0), z(0) {}
+       Vector3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {}
+       Vector3(const Vector4 &v);
+
+       inline void normalize();
+       inline float &operator[] (int idx);
+       inline const float &operator[] (int idx) const;
+
+       GPH_VEC3_SWIZZLE
+};
+
+
+class Vector4 {
+public:
+       float x, y, z, w;
+
+       Vector4() : x(0), y(0), z(0), w(0) {}
+       Vector4(float x_, float y_, float z_, float w_) : x(x_), y(y_), z(z_), w(w_) {}
+       Vector4(const Vector3 &v);
+
+       inline void normalize();
+       inline float &operator[] (int idx);
+       inline const float &operator[] (int idx) const;
+
+       GPH_VEC4_SWIZZLE
+};
+
+// ---- Vector3 functions ----
+inline Vector3 operator -(const Vector3 &v);
+inline Vector3 operator +(const Vector3 &a, const Vector3 &b);
+inline Vector3 operator -(const Vector3 &a, const Vector3 &b);
+inline Vector3 operator *(const Vector3 &a, const Vector3 &b);
+inline Vector3 operator /(const Vector3 &a, const Vector3 &b);
+inline Vector3 operator *(const Vector3 &v, float s);
+inline Vector3 operator *(float s, const Vector3 &v);
+inline Vector3 operator /(const Vector3 &v, float s);
+inline Vector3 operator /(float s, const Vector3 &v);
+inline Vector3 &operator +=(Vector3 &a, const Vector3 &b);
+inline Vector3 &operator -=(Vector3 &a, const Vector3 &b);
+inline Vector3 &operator *=(Vector3 &a, const Vector3 &b);
+inline Vector3 &operator /=(Vector3 &a, const Vector3 &b);
+inline Vector3 &operator *=(Vector3 &v, float s);
+inline Vector3 &operator /=(Vector3 &v, float s);
+
+Vector3 operator *(const Vector3 &v, const Matrix4x4 &m);
+Vector3 operator *(const Matrix4x4 &m, const Vector3 &v);
+
+inline bool operator ==(const Vector3 &a, const Vector3 &b);
+inline bool operator !=(const Vector3 &a, const Vector3 &b);
+
+inline float dot(const Vector3 &a, const Vector3 &b);
+inline Vector3 cross(const Vector3 &a, const Vector3 &b);
+inline float length(const Vector3 &v);
+inline float length_sq(const Vector3 &v);
+inline Vector3 normalize(const Vector3 &v);
+
+inline Vector3 reflect(const Vector3 &v, const Vector3 &n);
+inline Vector3 refract(const Vector3 &v, const Vector3 &n, float ior);
+inline Vector3 refract(const Vector3 &v, const Vector3 &n, float from_ior, float to_ior);
+
+inline float distance(const Vector3 &a, const Vector3 &b);
+inline float distance_sq(const Vector3 &a, const Vector3 &b);
+inline Vector3 faceforward(const Vector3 &n, const Vector3 &vi, const Vector3 &ng);
+
+inline Vector3 major(const Vector3 &v);
+inline int major_idx(const Vector3 &v);
+inline Vector3 proj_axis(const Vector3 &v, const Vector3 &axis);
+
+inline Vector3 rotate(const Vector3 &v, const Quaternion &q);
+inline Vector3 rotate(const Vector3 &v, const Vector3 &axis, float angle);
+inline Vector3 rotate(const Vector3 &v, const Vector3 &euler);
+
+}
+
+#include "vector.inl"
+
+#endif /* GMATH_VEC_H_ */
diff --git a/src/vector.inl b/src/vector.inl
new file mode 100644 (file)
index 0000000..1aeae0f
--- /dev/null
@@ -0,0 +1,292 @@
+#include <math.h>
+
+namespace gph {
+
+#undef GPH_SWIZZLE2
+#undef GPH_SWIZZLE3
+#undef GPH_SWIZZLE4
+#define GPH_SWIZZLE2(T, a, b)          inline Vector2 T::a##b() const { return Vector2(a, b); }
+#define GPH_SWIZZLE3(T, a, b, c)       inline Vector3 T::a##b##c() const { return Vector3(a, b, c); }
+#define GPH_SWIZZLE4(T, a, b, c, d)    inline Vector4 T::a##b##c##d() const { return Vector4(a, b, c, d); }
+
+// ---- Vector3 ----
+
+inline void Vector3::normalize()
+{
+       float len = (float)sqrt(x * x + y * y + z * z);
+       if(len != 0.0f) {
+               x /= len;
+               y /= len;
+               z /= len;
+       }
+}
+
+inline float &Vector3::operator[] (int idx)
+{
+       return idx == 0 ? x : (idx == 1 ? y : z);
+}
+
+inline const float &Vector3::operator[] (int idx) const
+{
+       return idx == 0 ? x : (idx == 1 ? y : z);
+}
+
+inline Vector3 operator -(const Vector3 &v)
+{
+       return Vector3(-v.x, -v.y, -v.z);
+}
+
+inline Vector3 operator +(const Vector3 &a, const Vector3 &b)
+{
+       return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
+}
+
+inline Vector3 operator -(const Vector3 &a, const Vector3 &b)
+{
+       return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
+}
+
+inline Vector3 operator *(const Vector3 &a, const Vector3 &b)
+{
+       return Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
+}
+
+inline Vector3 operator /(const Vector3 &a, const Vector3 &b)
+{
+       return Vector3(a.x / b.x, a.y / b.y, a.z / b.z);
+}
+
+inline Vector3 operator *(const Vector3 &v, float s)
+{
+       return Vector3(v.x * s, v.y * s, v.z * s);
+}
+
+inline Vector3 operator *(float s, const Vector3 &v)
+{
+       return Vector3(s * v.x, s * v.y, s * v.z);
+}
+
+inline Vector3 operator /(const Vector3 &v, float s)
+{
+       return Vector3(v.x / s, v.y / s, v.z / s);
+}
+
+inline Vector3 operator /(float s, const Vector3 &v)
+{
+       return Vector3(s / v.x, s / v.y, s / v.z);
+}
+
+inline Vector3 &operator +=(Vector3 &a, const Vector3 &b)
+{
+       a.x += b.x;
+       a.y += b.y;
+       a.z += b.z;
+       return a;
+}
+
+inline Vector3 &operator -=(Vector3 &a, const Vector3 &b)
+{
+       a.x -= b.x;
+       a.y -= b.y;
+       a.z -= b.z;
+       return a;
+}
+
+inline Vector3 &operator *=(Vector3 &a, const Vector3 &b)
+{
+       a.x *= b.x;
+       a.y *= b.y;
+       a.z *= b.z;
+       return a;
+}
+
+inline Vector3 &operator /=(Vector3 &a, const Vector3 &b)
+{
+       a.x /= b.x;
+       a.y /= b.y;
+       a.z /= b.z;
+       return a;
+}
+
+inline Vector3 &operator *=(Vector3 &v, float s)
+{
+       v.x *= s;
+       v.y *= s;
+       v.z *= s;
+       return v;
+}
+
+inline Vector3 &operator /=(Vector3 &v, float s)
+{
+       v.x /= s;
+       v.y /= s;
+       v.z /= s;
+       return v;
+}
+
+inline bool operator ==(const Vector3 &a, const Vector3 &b)
+{
+       return a.x == b.x && a.y == b.y && a.z == b.z;
+}
+
+inline bool operator !=(const Vector3 &a, const Vector3 &b)
+{
+       return !(a == b);
+}
+
+inline float dot(const Vector3 &a, const Vector3 &b)
+{
+       return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+inline Vector3 cross(const Vector3 &a, const Vector3 &b)
+{
+       return Vector3(a.y * b.z - a.z * b.y,
+                       a.z * b.x - a.x * b.z,
+                       a.x * b.y - a.y * b.x);
+}
+
+inline float length(const Vector3 &v)
+{
+       return (float)sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
+}
+
+inline float length_sq(const Vector3 &v)
+{
+       return v.x * v.x + v.y * v.y + v.z * v.z;
+}
+
+inline Vector3 normalize(const Vector3 &v)
+{
+       float len = length(v);
+       if(len == 0.0f) {
+               return v;
+       }
+
+       return Vector3(v.x / len, v.y / len, v.z / len);
+}
+
+inline Vector3 reflect(const Vector3 &v, const Vector3 &n)
+{
+       return v - n * dot(n, v) * 2.0;
+}
+
+inline Vector3 refract(const Vector3 &v, const Vector3 &n, float ior)
+{
+       float ndotv = dot(n, v);
+       float k = 1.0f - ior * ior * (1.0f - ndotv * ndotv);
+       if(k < 0.0f) {
+               return Vector3();
+       }
+       return ior * v - (ior * ndotv + sqrt(k)) * n;
+}
+
+inline Vector3 refract(const Vector3 &v, const Vector3 &n, float from_ior, float to_ior)
+{
+       if(to_ior == 0.0f) to_ior = 1.0f;
+       return refract(v, n, from_ior / to_ior);
+}
+
+inline float distance(const Vector3 &a, const Vector3 &b)
+{
+       return length(a - b);
+}
+
+inline float distance_sq(const Vector3 &a, const Vector3 &b)
+{
+       return length_sq(a - b);
+}
+
+inline Vector3 faceforward(const Vector3 &n, const Vector3 &vi, const Vector3 &ng)
+{
+       return dot(ng, vi) < 0.0f ? n : -n;
+}
+
+inline Vector3 major(const Vector3 &v)
+{
+       int m = major_idx(v);
+       Vector3 res;
+       res[m] = v[m];
+       return res;
+}
+
+inline int major_idx(const Vector3 &v)
+{
+       return fabs(v.x) >= fabs(v.y) && fabs(v.x) > fabs(v.z) ? 0 :
+               (fabs(v.y) >= fabs(v.z) ? 1 : 2);
+}
+
+inline Vector3 proj_axis(const Vector3 &v, const Vector3 &axis)
+{
+       return axis * dot(v, axis);
+}
+
+
+inline Vector3 rotate(const Vector3 &v, const Quaternion &q)
+{
+       return v;       // TODO
+}
+
+inline Vector3 rotate(const Vector3 &v, const Vector3 &axis, float angle)
+{
+       return v;       // TODO
+}
+
+inline Vector3 rotate(const Vector3 &v, const Vector3 &euler)
+{
+       return v;       // TODO
+}
+
+
+GPH_VEC3_SWIZZLE
+
+// ---- Vector4 ----
+
+
+inline void Vector4::normalize()
+{
+       float len = (float)sqrt(x * x + y * y + z * z + w * w);
+       if(len != 0.0f) {
+               x /= len;
+               y /= len;
+               z /= len;
+               w /= len;
+       }
+}
+
+inline float &Vector4::operator[] (int idx)
+{
+       return idx == 0 ? x : (idx == 1 ? y : (idx == 2 ? z : w));
+}
+
+inline const float &Vector4::operator[] (int idx) const
+{
+       return idx == 0 ? x : (idx == 1 ? y : (idx == 2 ? z : w));
+}
+
+GPH_VEC4_SWIZZLE
+
+// ---- Vector2 ----
+
+inline void Vector2::normalize()
+{
+       float len = (float)sqrt(x * x + y * y);
+       if(len != 0.0f) {
+               x /= len;
+               y /= len;
+       }
+}
+
+inline float &Vector2::operator[] (int idx)
+{
+       return idx == 0 ? x : y;
+}
+
+inline const float &Vector2::operator[] (int idx) const
+{
+       return idx == 0 ? x : y;
+}
+
+GPH_VEC2_SWIZZLE
+
+}      // namespace gph