aboutsummaryrefslogtreecommitdiff
path: root/09-september/tomcat/math
diff options
context:
space:
mode:
Diffstat (limited to '09-september/tomcat/math')
-rw-r--r--09-september/tomcat/math/math_util.c10
-rw-r--r--09-september/tomcat/math/math_util.h8
-rw-r--r--09-september/tomcat/math/matrix4x4.c326
-rw-r--r--09-september/tomcat/math/matrix4x4.h39
-rw-r--r--09-september/tomcat/math/vector.c177
-rw-r--r--09-september/tomcat/math/vector.h47
6 files changed, 607 insertions, 0 deletions
diff --git a/09-september/tomcat/math/math_util.c b/09-september/tomcat/math/math_util.c
new file mode 100644
index 0000000..1285f3d
--- /dev/null
+++ b/09-september/tomcat/math/math_util.c
@@ -0,0 +1,10 @@
+#include "math_util.h"
+
+float baryCentric(Vec3 *p1, Vec3 *p2, Vec3 *p3, Vec2 *pos)
+{
+ float det = (p2->z - p3->z) * (p1->x - p3->x) + (p3->x - p2->x) * (p1->z - p3->z);
+ float l1 = ((p2->z - p3->z) * (pos->x - p3->x) + (p3->x - p2->x) * (pos->y - p3->z)) / det;
+ float l2 = ((p3->z - p1->z) * (pos->x - p3->x) + (p1->x - p3->x) * (pos->y - p3->z)) / det;
+ float l3 = 1.0f - l1 - l2;
+ return l1 * p1->y + l2 * p2->y + l3 * p3->y;
+}
diff --git a/09-september/tomcat/math/math_util.h b/09-september/tomcat/math/math_util.h
new file mode 100644
index 0000000..5582dc7
--- /dev/null
+++ b/09-september/tomcat/math/math_util.h
@@ -0,0 +1,8 @@
+#ifndef MATH_UTIL_H
+#define MATH_UTIL_H
+
+#include "vector.h"
+
+extern float baryCentric(Vec3 *p1, Vec3 *p2, Vec3 *p3, Vec2 *pos);
+
+#endif // MATH_UTIL_H
diff --git a/09-september/tomcat/math/matrix4x4.c b/09-september/tomcat/math/matrix4x4.c
new file mode 100644
index 0000000..d4bea71
--- /dev/null
+++ b/09-september/tomcat/math/matrix4x4.c
@@ -0,0 +1,326 @@
+#include "matrix4x4.h"
+#include "../util/util.h"
+#include <SDL2/SDL.h>
+
+void mat4_identity(Mat4 *a)
+{
+ int i;
+ for(i = 0; i < 4*4; i++)
+ {
+ a->data[i] = 0.0f;
+ }
+ a->data[0 + 0 * 4] = 1.0f;
+ a->data[1 + 1 * 4] = 1.0f;
+ a->data[2 + 2 * 4] = 1.0f;
+ a->data[3 + 3 * 4] = 1.0f;
+}
+
+/** TODO: Preprocess these operation (1 + 1 * 4) -> 5 **/
+Mat4 mat4_inverse(const Mat4 *a)
+{
+ Mat4 inv;
+ int i;
+
+ /** Remember that inverted matrix is (1/det) * cofactor(transposed) **/
+ inv.data[0 + 0 * 4] = (a->data[1 + 1 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] +
+ a->data[2 + 1 * 4] * a->data[3 + 2 * 4] * a->data[1 + 3 * 4] +
+ a->data[3 + 1 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] -
+ a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 1 * 4] -
+ a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[1 + 1 * 4] -
+ a->data[3 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 1 * 4]);
+
+ inv.data[0 + 1 * 4] = -(a->data[0 + 1 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] +
+ a->data[2 + 1 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] +
+ a->data[3 + 1 * 4] * a->data[0 + 2 * 4] * a->data[2 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 1 * 4] -
+ a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 1 * 4] -
+ a->data[3 + 3 * 4] * a->data[0 + 2 * 4] * a->data[2 + 1 * 4]);
+
+ inv.data[0 + 2 * 4] = (a->data[0 + 1 * 4] * a->data[1 + 2 * 4] * a->data[3 + 3 * 4] +
+ a->data[1 + 1 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] +
+ a->data[3 + 1 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[3 + 1 * 4] -
+ a->data[1 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 1 * 4] -
+ a->data[3 + 3 * 4] * a->data[0 + 2 * 4] * a->data[1 + 1 * 4]);
+
+ inv.data[0 + 3 * 4] = -(a->data[0 + 1 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] +
+ a->data[1 + 1 * 4] * a->data[2 + 2 * 4] * a->data[0 + 3 * 4] +
+ a->data[2 + 1 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 1 * 4] -
+ a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[0 + 1 * 4] -
+ a->data[2 + 3 * 4] * a->data[0 + 2 * 4] * a->data[1 + 1 * 4]);
+
+ inv.data[1 + 0 * 4] = -(a->data[1 + 0 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] +
+ a->data[2 + 0 * 4] * a->data[3 + 2 * 4] * a->data[1 + 3 * 4] +
+ a->data[3 + 0 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] -
+ a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 0 * 4] -
+ a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[1 + 0 * 4] -
+ a->data[3 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 0 * 4]);
+
+ inv.data[1 + 1 * 4] = (a->data[0 + 0 * 4] * a->data[2 + 2 * 4] * a->data[3 + 3 * 4] +
+ a->data[2 + 0 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] +
+ a->data[3 + 0 * 4] * a->data[0 + 2 * 4] * a->data[2 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[2 + 2 * 4] * a->data[3 + 0 * 4] -
+ a->data[2 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 0 * 4] -
+ a->data[3 + 3 * 4] * a->data[0 + 2 * 4] * a->data[2 + 0 * 4]);
+
+ inv.data[1 + 2 * 4] = -(a->data[0 + 0 * 4] * a->data[1 + 2 * 4] * a->data[3 + 3 * 4] +
+ a->data[1 + 0 * 4] * a->data[3 + 2 * 4] * a->data[0 + 3 * 4] +
+ a->data[3 + 0 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[3 + 0 * 4] -
+ a->data[1 + 3 * 4] * a->data[3 + 2 * 4] * a->data[0 + 0 * 4] -
+ a->data[3 + 3 + 4] * a->data[0 + 2 * 4] * a->data[1 + 0 * 4]);
+
+ inv.data[1 + 3 * 4] = (a->data[0 + 0 * 4] * a->data[1 + 2 * 4] * a->data[2 + 3 * 4] +
+ a->data[1 + 0 * 4] * a->data[2 + 2 * 4] * a->data[0 + 3 * 4] +
+ a->data[2 + 0 * 4] * a->data[0 + 2 * 4] * a->data[1 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[1 + 2 * 4] * a->data[2 + 0 * 4] -
+ a->data[1 + 3 * 4] * a->data[2 + 2 * 4] * a->data[0 + 0 * 4] -
+ a->data[2 + 3 * 4] * a->data[0 + 2 * 4] * a->data[1 + 0 * 4]);
+
+ inv.data[2 + 0 * 4] = (a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 3 * 4] +
+ a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[1 + 3 * 4] +
+ a->data[3 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 3 * 4] -
+ a->data[1 + 3 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] -
+ a->data[2 + 3 * 4] * a->data[3 + 1 * 4] * a->data[1 + 0 * 4] -
+ a->data[3 + 3 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4]);
+
+ inv.data[2 + 1 * 4] = -(a->data[0 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 3 * 4] +
+ a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 3 * 4] +
+ a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[2 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] -
+ a->data[2 + 3 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] -
+ a->data[3 + 3 * 4] * a->data[0 + 1 * 4] * a->data[2 + 0 * 4]);
+
+ inv.data[2 + 2 * 4] = (a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[3 + 3 * 4] +
+ a->data[1 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 3 * 4] +
+ a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[1 + 1 * 4] * a->data[3 + 0 * 4] -
+ a->data[1 + 3 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] -
+ a->data[3 + 3 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]);
+
+ inv.data[2 + 3 * 4] = -(a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 3 * 4] +
+ a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[0 + 3 * 4] +
+ a->data[2 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 3 * 4] -
+ a->data[0 + 3 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4] -
+ a->data[1 + 3 * 4] * a->data[2 + 1 * 4] * a->data[0 + 0 * 4] -
+ a->data[2 + 3 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]);
+
+ inv.data[3 + 0 * 4] = -(a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 2 * 4] +
+ a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[1 + 2 * 4] +
+ a->data[3 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 2 * 4] -
+ a->data[1 + 2 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] -
+ a->data[2 + 2 * 4] * a->data[3 + 1 * 4] * a->data[1 + 0 * 4] -
+ a->data[3 + 2 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4]);
+
+ inv.data[3 + 1 * 4] = (a->data[0 + 0 * 4] * a->data[2 + 1 * 4] * a->data[3 + 2 * 4] +
+ a->data[2 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 2 * 4] +
+ a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[2 + 2 * 4] -
+ a->data[0 + 2 * 4] * a->data[2 + 1 * 4] * a->data[3 + 0 * 4] -
+ a->data[2 + 2 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] -
+ a->data[3 + 2 * 4] * a->data[0 + 1 * 4] * a->data[2 + 0 * 4]);
+
+ inv.data[3 + 2 * 4] = -(a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[3 + 2 * 4] +
+ a->data[1 + 0 * 4] * a->data[3 + 1 * 4] * a->data[0 + 2 * 4] +
+ a->data[3 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 2 * 4] -
+ a->data[0 + 2 * 4] * a->data[1 + 1 * 4] * a->data[3 + 0 * 4] -
+ a->data[1 + 2 * 4] * a->data[3 + 1 * 4] * a->data[0 + 0 * 4] -
+ a->data[3 + 2 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]);
+
+ inv.data[3 + 3 * 4] = (a->data[0 + 0 * 4] * a->data[1 + 1 * 4] * a->data[2 + 2 * 4] +
+ a->data[1 + 0 * 4] * a->data[2 + 1 * 4] * a->data[0 + 2 * 4] +
+ a->data[2 + 0 * 4] * a->data[0 + 1 * 4] * a->data[1 + 2 * 4] -
+ a->data[0 + 2 * 4] * a->data[1 + 1 * 4] * a->data[2 + 0 * 4] -
+ a->data[1 + 2 * 4] * a->data[2 + 1 * 4] * a->data[0 + 0 * 4] -
+ a->data[2 + 2 * 4] * a->data[0 + 1 * 4] * a->data[1 + 0 * 4]);
+
+ /** Remember that our matrix is already transposed and we also got the minors(inside each "inv" entry),
+ so we just use them. We use a->data[0 + 1 * 4] * inv.data[1 + 0 * 4] becouse inv.data is transposed **/
+ float det = a->data[0 + 0 * 4] * inv.data[0 + 0 * 4] + a->data[0 + 1 * 4] * inv.data[1 + 0 * 4] +
+ a->data[0 + 2 * 4] * inv.data[2 + 0 * 4] + a->data[0 + 3 * 4] * inv.data[3 + 0 * 4];
+
+ if(det == 0.0f)
+ return *a;
+
+ det = 1.0f / det;
+
+ for(i = 0; i < 16; i++)
+ inv.data[i] *= det;
+
+ return inv;
+}
+
+Mat4 mat4_mul(const Mat4 *a, const Mat4 *b)
+{
+ int i, j, k;
+ GLfloat sum = 0.0f;
+ Mat4 c;
+ mat4_identity(&c);
+ for(i = 0; i < 4; i++)
+ for(j = 0; j < 4; j++){
+ for(k = 0; k < 4; k++){
+ sum += a->data[i + k * 4] * b->data[k + j * 4];
+ }
+ c.data[i + j * 4] = sum;
+ sum = 0.0f;
+ }
+
+ return c;
+}
+
+Mat4 mat4_translate(const Vec3 *a)
+{
+ Mat4 b;
+ mat4_identity(&b);
+ b.data[0 + 3 * 4] = a->x;
+ b.data[1 + 3 * 4] = a->y;
+ b.data[2 + 3 * 4] = a->z;
+ return b;
+}
+
+Mat4 mat4_scale(GLfloat x, GLfloat y, GLfloat z)
+{
+ Mat4 b;
+ mat4_identity(&b);
+ b.data[0 + 0 * 4] = x;
+ b.data[1 + 1 * 4] = y;
+ b.data[2 + 2 * 4] = z;
+ return b;
+}
+
+Mat4 mat4_rotate(GLfloat degrees, const Vec3 *a)
+{
+ Mat4 b;
+ mat4_identity(&b);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees)), o = 1-c;
+ b.data[0 + 0 * 4] = a->x * a->x * o + c;
+ b.data[0 + 1 * 4] = a->x * a->y * o - a->z * s;
+ b.data[0 + 2 * 4] = a->x * a->z * o + a->y * s;
+
+ b.data[1 + 0 * 4] = a->x * a->y * o + a->z * s;
+ b.data[1 + 1 * 4] = a->y * a->y * o + c;
+ b.data[1 + 2 * 4] = a->y * a->z * o - a->x * s;
+
+ b.data[2 + 0 * 4] = a->x * a->z * o - a->y * s;
+ b.data[2 + 1 * 4] = a->y * a->z * o + a->x * s;
+ b.data[2 + 2 * 4] = a->z * a->z * o + c;
+ return b;
+}
+
+Mat4 mat4_rotate_x(GLfloat degrees)
+{
+ Mat4 a;
+ mat4_identity(&a);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees));
+ a.data[1 + 1 * 4] = c;
+ a.data[2 + 1 * 4] = s;
+ a.data[1 + 2 * 4] = -s;
+ a.data[2 + 2 * 4] = c;
+ return a;
+}
+
+Mat4 mat4_rotate_y(GLfloat degrees)
+{
+ Mat4 a;
+ mat4_identity(&a);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees));
+ a.data[0 + 0 * 4] = c;
+ a.data[2 + 0 * 4] = -s;
+ a.data[0 + 2 * 4] = s;
+ a.data[2 + 2 * 4] = c;
+ return a;
+}
+
+Mat4 mat4_rotate_z(GLfloat degrees)
+{
+ Mat4 a;
+ mat4_identity(&a);
+ GLfloat c = SDL_cosf(toRadians(degrees)), s = SDL_sinf(toRadians(degrees));
+ a.data[0 + 0 * 4] = c;
+ a.data[1 + 0 * 4] = s;
+ a.data[0 + 1 * 4] = -s;
+ a.data[1 + 1 * 4] = c;
+ return a;
+}
+
+Mat4 mat4_perspective(GLfloat fov, GLfloat aspect, GLfloat zNear, GLfloat zFar)
+{
+ Mat4 a;
+ GLubyte i, j;
+ for(i = 0; i < 4; i++)
+ for(j = 0; j < 4; j++)
+ a.data[i + j * 4] = 0.0f;
+ fov = toRadians(fov); // To radians
+
+ a.data[0 + 0 * 4] = ( (1.0f / SDL_tanf( fov/2.0f )) / aspect);
+ a.data[1 + 1 * 4] = (1.0f / SDL_tanf( fov/2.0f ));
+ a.data[2 + 2 * 4] = -( (zFar + zNear) / (zFar - zNear) );
+ a.data[2 + 3 * 4] = -( ( 2.0f * zFar * zNear) / (zFar - zNear) );
+ a.data[3 + 2 * 4] = -1.0f;
+
+ return a;
+}
+
+Mat4
+mat4_orthographic(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
+{
+ Mat4 a;
+ mat4_identity(&a);
+ a.data[0 + 0 * 4] = 2.0f / (right - left);
+ a.data[1 + 1 * 4] = 2.0f / (top - bottom);
+ a.data[2 + 2 * 4] = 2.0f / (near - far);
+
+ a.data[0 + 3 * 4] = (left + right) / (left - right);
+ a.data[1 + 3 * 4] = (bottom + top) / (bottom - top);
+ a.data[2 + 3 * 4] = (far + near) / (far - near);
+
+ return a;
+}
+
+Mat4 mat4_lookAt(Vec3 *eye, Vec3 *center, Vec3 *up)
+{
+ Vec3 temp = vec3_sub(center, eye);
+
+ Vec3 f = vec3_normalize(&temp);
+ Vec3 u = vec3_normalize(up);
+ temp = vec3_cross_mul(&f, &u);
+ Vec3 s = vec3_normalize(&temp);
+ u = vec3_cross_mul(&s, &f);
+
+ Mat4 a;
+ mat4_identity(&a);
+
+ a.data[0 + 0 * 4] = s.x;
+ a.data[0 + 1 * 4] = s.y;
+ a.data[0 + 2 * 4] = s.z;
+ a.data[1 + 0 * 4] = u.x;
+ a.data[1 + 1 * 4] = u.y;
+ a.data[1 + 2 * 4] = u.z;
+ a.data[2 + 0 * 4] =-f.x;
+ a.data[2 + 1 * 4] =-f.y;
+ a.data[2 + 2 * 4] =-f.z;
+ a.data[0 + 3 * 4] =-vec3_dot_mul(&s, eye);
+ a.data[1 + 3 * 4] =-vec3_dot_mul(&u, eye);
+ a.data[2 + 3 * 4] = vec3_dot_mul(&f, eye);
+
+ return a;
+}
+
+Vec3 mat4_mul_vec3(const Mat4 *a, const Vec3 *b)
+{
+ Vec3 c;
+ c.x = a->data[0 + 0 * 4] * b->x + a->data[0 + 1 * 4] * b->y + a->data[0 + 2 * 4] * b->z + a->data[0 + 3 * 4];
+ c.y = a->data[1 + 0 * 4] * b->x + a->data[1 + 1 * 4] * b->y + a->data[1 + 2 * 4] * b->z + a->data[1 + 3 * 4];
+ c.z = a->data[2 + 0 * 4] * b->x + a->data[2 + 1 * 4] * b->y + a->data[2 + 2 * 4] * b->z + a->data[2 + 3 * 4];
+ return c;
+}
+
+Vec4 mat4_mul_vec4(const Mat4 *a, const Vec4 *b)
+{
+ Vec4 c;
+ c.x = a->data[0 + 0 * 4] * b->x + a->data[0 + 1 * 4] * b->y + a->data[0 + 2 * 4] * b->z + a->data[0 + 3 * 4] * b->w;
+ c.y = a->data[1 + 0 * 4] * b->x + a->data[1 + 1 * 4] * b->y + a->data[1 + 2 * 4] * b->z + a->data[1 + 3 * 4] * b->w;
+ c.z = a->data[2 + 0 * 4] * b->x + a->data[2 + 1 * 4] * b->y + a->data[2 + 2 * 4] * b->z + a->data[2 + 3 * 4] * b->w;
+ c.w = a->data[3 + 0 * 4] * b->x + a->data[3 + 1 * 4] * b->y + a->data[3 + 2 * 4] * b->z + a->data[3 + 3 * 4] * b->w;
+ return c;
+}
diff --git a/09-september/tomcat/math/matrix4x4.h b/09-september/tomcat/math/matrix4x4.h
new file mode 100644
index 0000000..74918fe
--- /dev/null
+++ b/09-september/tomcat/math/matrix4x4.h
@@ -0,0 +1,39 @@
+#ifndef MATRIX4X4_H
+#define MATRIX4X4_H
+
+#include <GL/glew.h>
+#include "vector.h"
+
+/* accesing data: row + column * width */
+typedef struct
+{
+ GLfloat data[16];
+} Mat4;
+
+extern void mat4_identity(Mat4 *a);
+extern Mat4 mat4_inverse(const Mat4 *a);
+extern Mat4 mat4_mul(const Mat4 *a, const Mat4 *b);
+
+extern Mat4 mat4_translate(const Vec3 *a);
+extern Mat4 mat4_scale(GLfloat x, GLfloat y, GLfloat z);
+extern Mat4 mat4_rotate_x(GLfloat degrees);
+extern Mat4 mat4_rotate_y(GLfloat degrees);
+extern Mat4 mat4_rotate_z(GLfloat degrees);
+extern Mat4 mat4_rotate(GLfloat degrees, const Vec3 *a);
+
+extern Mat4
+mat4_perspective(GLfloat fov, GLfloat aspect, GLfloat zNear, GLfloat zFar);
+
+extern Mat4
+mat4_orthographic(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far);
+
+extern Mat4
+mat4_lookAt(Vec3 *eye, Vec3 *center, Vec3 *up);
+
+extern Vec3
+mat4_mul_vec3(const Mat4 *a, const Vec3 *b);
+
+extern Vec4
+mat4_mul_vec4(const Mat4 *a, const Vec4 *b);
+
+#endif // MATRIX4X4_H
diff --git a/09-september/tomcat/math/vector.c b/09-september/tomcat/math/vector.c
new file mode 100644
index 0000000..230de51
--- /dev/null
+++ b/09-september/tomcat/math/vector.c
@@ -0,0 +1,177 @@
+#include "vector.h"
+#include <SDL2/SDL.h>
+
+Vec4 vec4_add(const Vec4 *a, const Vec4 *b)
+{
+ Vec4 c;
+ c.x = a->x + b->x;
+ c.y = a->y + b->y;
+ c.z = a->z + b->z;
+ c.w = a->w + b->w;
+ return c;
+}
+
+Vec4 vec4_sub(const Vec4 *a, const Vec4 *b)
+{
+ Vec4 c;
+ c.x = a->x - b->x;
+ c.y = a->y - b->y;
+ c.z = a->z - b->z;
+ c.w = a->w - b->w;
+ return c;
+}
+
+Vec4 vec4_scalar_mul(const Vec4 *a, GLfloat scalar)
+{
+ Vec4 c;
+ c.x = a->x * scalar;
+ c.y = a->y * scalar;
+ c.z = a->z * scalar;
+ c.w = a->w * scalar;
+ return c;
+}
+
+GLfloat vec4_dot_mul(const Vec4 *a, const Vec4 *b)
+{
+ return ( (a->x * b->x) + (a->y * b->y) + (a->z * b->z) + (a->w * b->w) );
+}
+
+GLfloat vec4_length(Vec4 *a)
+{
+ return SDL_sqrtf(SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) + SDL_pow(a->z, 2.0f) + SDL_pow(a->w, 2.0f) );
+}
+
+GLfloat vec4_length2(Vec4 *a)
+{
+ return ( SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) + SDL_pow(a->z, 2.0f) + SDL_pow(a->w, 2.0f) );
+}
+
+Vec4 vec4_normalize(Vec4 *a)
+{
+ Vec4 b;
+ GLfloat length = vec4_length(a);
+ b.x = a->x / length;
+ b.y = a->y / length;
+ b.z = a->z / length;
+ b.w = a->w / length;
+ return b;
+}
+
+Vec3 vec3_add(const Vec3 *a, const Vec3 *b)
+{
+ Vec3 c;
+ c.x = a->x + b->x;
+ c.y = a->y + b->y;
+ c.z = a->z + b->z;
+ return c;
+}
+
+Vec3 vec3_sub(const Vec3 *a, const Vec3 *b)
+{
+ Vec3 c;
+ c.x = a->x - b->x;
+ c.y = a->y - b->y;
+ c.z = a->z - b->z;
+ return c;
+}
+
+Vec3 vec3_scalar_mul(const Vec3 *a, GLfloat scalar)
+{
+ Vec3 c;
+ c.x = a->x * scalar;
+ c.y = a->y * scalar;
+ c.z = a->z * scalar;
+ return c;
+}
+
+GLfloat vec3_dot_mul(const Vec3 *a, const Vec3 *b)
+{
+ return ( (a->x * b->x) + (a->y * b->y) + (a->z * b->z) );
+}
+
+
+Vec3 vec3_cross_mul(const Vec3 *a, const Vec3 *b)
+{
+ Vec3 c;
+ c.x = (a->y * b->z) - (a->z * b->y);
+ c.y = (a->z * b->x) - (a->x * b->z);
+ c.z = (a->x * b->y) - (a->y * b->x);
+ return c;
+}
+
+GLfloat vec3_length(Vec3 *a)
+{
+ return SDL_sqrtf(SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) + SDL_pow(a->z, 2.0f));
+}
+
+GLfloat vec3_length2(Vec3 *a)
+{
+ return ( SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) + SDL_pow(a->z, 2.0f) );
+}
+
+Vec3 vec3_normalize(Vec3 *a)
+{
+ Vec3 b;
+ GLfloat length = vec3_length(a);
+ b.x = a->x / length;
+ b.y = a->y / length;
+ b.z = a->z / length;
+ return b;
+}
+
+Vec2 vec2_add(const Vec2 *a, const Vec2 *b)
+{
+ Vec2 c;
+ c.x = a->x + b->x;
+ c.y = a->y + b->y;
+ return c;
+}
+
+Vec2 vec2_sub(const Vec2 *a, const Vec2 *b)
+{
+ Vec2 c;
+ c.x = a->x - b->x;
+ c.y = a->y - b->y;
+ return c;
+}
+
+Vec2 vec2_scalar_mul(const Vec2 *a, GLfloat scalar)
+{
+ Vec2 c;
+ c.x = a->x * scalar;
+ c.y = a->y * scalar;
+ return c;
+}
+
+GLfloat vec2_dot_mul(const Vec2 *a, const Vec2 *b)
+{
+ return ( (a->x * b->x) + (a->y * b->y) );
+}
+
+
+Vec2 vec2_cross_mul(const Vec2 *a, const Vec2 *b)
+{
+ Vec2 c;
+ c.x = (a->x * b->y) - (a->y * b->x);
+ c.y = (a->y * b->x) - (a->x * b->y);
+ return c;
+}
+
+GLfloat vec2_length(Vec2 *a)
+{
+ return SDL_sqrtf(SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) );
+}
+
+GLfloat vec2_length2(Vec2 *a)
+{
+ return ( SDL_pow(a->x, 2.0f) + SDL_pow(a->y, 2.0f) );
+}
+
+Vec2 vec2_normalize(Vec2 *a)
+{
+ Vec2 b;
+ GLfloat length = vec2_length(a);
+ b.x = a->x / length;
+ b.y = a->y / length;
+ return b;
+}
diff --git a/09-september/tomcat/math/vector.h b/09-september/tomcat/math/vector.h
new file mode 100644
index 0000000..173fc11
--- /dev/null
+++ b/09-september/tomcat/math/vector.h
@@ -0,0 +1,47 @@
+#ifndef VECTOR4F_H
+#define VECTOR4F_H
+
+#include <GL/glew.h>
+
+typedef struct _Vec4
+{
+ GLfloat x, y, z, w;
+} Vec4;
+
+extern Vec4 vec4_add(const Vec4 *a, const Vec4 *b);
+extern Vec4 vec4_sub(const Vec4 *a, const Vec4 *b);
+extern Vec4 vec4_scalar_mul(const Vec4 *a, GLfloat scalar);
+extern GLfloat vec4_dot_mul(const Vec4 *a, const Vec4 *b);
+extern GLfloat vec4_length(Vec4 *a);
+extern GLfloat vec4_length2(Vec4 *a);
+extern Vec4 vec4_normalize(Vec4 *a);
+
+typedef struct _Vec3
+{
+ GLfloat x, y, z;
+} Vec3;
+
+extern Vec3 vec3_add(const Vec3 *a, const Vec3 *b);
+extern Vec3 vec3_sub(const Vec3 *a, const Vec3 *b);
+extern Vec3 vec3_scalar_mul(const Vec3 *a, GLfloat scalar);
+extern GLfloat vec3_dot_mul(const Vec3 *a, const Vec3 *b);
+extern Vec3 vec3_cross_mul(const Vec3 *a, const Vec3 *b);
+extern GLfloat vec3_length(Vec3 *a);
+extern GLfloat vec3_length2(Vec3 *a);
+extern Vec3 vec3_normalize(Vec3 *a);
+
+typedef struct _Vec2
+{
+ GLfloat x, y;
+} Vec2;
+
+extern Vec2 vec2_add(const Vec2 *a, const Vec2 *b);
+extern Vec2 vec2_sub(const Vec2 *a, const Vec2 *b);
+extern Vec2 vec2_scalar_mul(const Vec2 *a, GLfloat scalar);
+extern GLfloat vec2_dot_mul(const Vec2 *a, const Vec2 *b);
+extern Vec2 vec2_cross_mul(const Vec2 *a, const Vec2 *b);
+extern GLfloat vec2_length(Vec2 *a);
+extern GLfloat vec2_length2(Vec2 *a);
+extern Vec2 vec2_normalize(Vec2 *a);
+
+#endif // VECTOR4F_H