From a00c0aab1eb5a7a55bef8ca08115bdd722ab5699 Mon Sep 17 00:00:00 2001
From: Matthew Kosarek <mattkae@protonmail.com>
Date: Sun, 16 May 2021 19:50:15 -0400
Subject: Moved the frontend directory up so that it no longer exists

---
 shared_cpp/MainLoop.cpp             |  31 +++++
 shared_cpp/MainLoop.h               |  29 +++++
 shared_cpp/OrthographicRenderer.cpp |  87 ++++++++++++++
 shared_cpp/OrthographicRenderer.h   |  43 +++++++
 shared_cpp/Shader.cpp               |  61 ++++++++++
 shared_cpp/Shader.h                 |  63 ++++++++++
 shared_cpp/WebglContext.h           |  39 +++++++
 shared_cpp/WebglHelper.h            |   6 +
 shared_cpp/mathlib.cpp              |  11 ++
 shared_cpp/mathlib.h                | 227 ++++++++++++++++++++++++++++++++++++
 shared_cpp/types.h                  |  18 +++
 11 files changed, 615 insertions(+)
 create mode 100644 shared_cpp/MainLoop.cpp
 create mode 100644 shared_cpp/MainLoop.h
 create mode 100644 shared_cpp/OrthographicRenderer.cpp
 create mode 100644 shared_cpp/OrthographicRenderer.h
 create mode 100644 shared_cpp/Shader.cpp
 create mode 100644 shared_cpp/Shader.h
 create mode 100644 shared_cpp/WebglContext.h
 create mode 100644 shared_cpp/WebglHelper.h
 create mode 100644 shared_cpp/mathlib.cpp
 create mode 100644 shared_cpp/mathlib.h
 create mode 100644 shared_cpp/types.h

(limited to 'shared_cpp')

diff --git a/shared_cpp/MainLoop.cpp b/shared_cpp/MainLoop.cpp
new file mode 100644
index 0000000..09aa643
--- /dev/null
+++ b/shared_cpp/MainLoop.cpp
@@ -0,0 +1,31 @@
+#include "MainLoop.h"
+#include <cstdio>
+#include <cstdlib>
+
+EM_BOOL loop(double time, void* loop) {
+    MainLoop* mainLoop = (MainLoop*) loop;
+    if (!mainLoop->isRunning) {
+        return false;
+    }
+    
+    if (mainLoop->lastTime == 0) {
+        mainLoop->lastTime = time;
+        return true;
+    }
+
+    long deltaTime = time - mainLoop->lastTime;
+    mainLoop->lastTime = time;
+    mainLoop->elapsedTime += deltaTime;
+    mainLoop->numFrames++;
+    float deltaTimeSeconds = static_cast<float>(deltaTime) / 1000.f;
+
+    if (mainLoop->elapsedTime >= 1000.0) {
+        printf("FPS: %d\n", mainLoop->numFrames);
+
+        mainLoop->elapsedTime = 0.0;
+        mainLoop->numFrames = 0;
+    }
+
+    mainLoop->updateFunc(deltaTimeSeconds, NULL);
+    return true;
+}
\ No newline at end of file
diff --git a/shared_cpp/MainLoop.h b/shared_cpp/MainLoop.h
new file mode 100644
index 0000000..2573bb8
--- /dev/null
+++ b/shared_cpp/MainLoop.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+EM_BOOL loop(double time, void* loop);
+
+struct MainLoop {
+    bool isRunning = false;
+	double lastTime = 0, elapsedTime = 0;
+	int numFrames = 0;
+	void (*updateFunc)(float dtSeconds, void *userData);
+
+    void run(void (*cb)(float dtSeconds, void *userData)) {
+		isRunning = true;
+		lastTime = 0;
+		elapsedTime = 0;
+		numFrames = 0;
+		updateFunc = cb;
+
+		emscripten_request_animation_frame_loop(loop, this);
+	}
+
+    void stop() {
+        isRunning = false;
+    }
+};
\ No newline at end of file
diff --git a/shared_cpp/OrthographicRenderer.cpp b/shared_cpp/OrthographicRenderer.cpp
new file mode 100644
index 0000000..21c13a1
--- /dev/null
+++ b/shared_cpp/OrthographicRenderer.cpp
@@ -0,0 +1,87 @@
+#include "OrthographicRenderer.h"
+#include "WebglContext.h"
+#include "mathlib.h"
+
+const char* orthographicVertex = 
+"attribute vec2 position; \n"
+"attribute vec4 color; \n"
+"uniform mat4 projection; \n"
+"uniform mat4 model; \n"
+"varying lowp vec4 VertexColor; \n"
+"void main() { \n"
+"    vec4 fragmentPosition = projection * model * vec4(position, 1, 1); \n"
+"    gl_Position = fragmentPosition; \n"
+"    VertexColor = color; \n"
+"}";
+
+const char* orthographicFragment = 
+"varying lowp vec4 VertexColor; \n"
+"void main() { \n"
+"    gl_FragColor = VertexColor; \n"
+"}";
+
+void OrthographicRenderer::load(WebglContext* context) {
+	printf("Compiling orthographic shader...\n");
+	shader = loadShader(orthographicVertex, orthographicFragment);
+
+	useShader(shader);
+	attributes.position = getShaderAttribute(shader, "position");
+	attributes.color = getShaderAttribute(shader, "color");
+	uniforms.projection = getShaderUniform(shader, "projection");
+	uniforms.model = getShaderUniform(shader, "model");
+	projection = Mat4x4().getOrthographicMatrix(0, context->width, 0, context->height);
+
+	printf("Orthographic shader compiled.\n");
+}
+	
+void OrthographicRenderer::render() {
+	glEnable(GL_DEPTH_TEST);
+	glDepthFunc(GL_LEQUAL);
+	glDepthMask(GL_TRUE);
+	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+	glClearDepth(1.0f);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+	useShader(shader);
+	setShaderMat4(uniforms.projection, projection);
+}
+
+void OrthographicRenderer::unload() {
+	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+	glDeleteProgram(shader);
+}
+
+
+void OrthographicShape::load(OrthographicVertex* inVertices, uint32 inNumVertices, OrthographicRenderer* renderer) {
+	numVertices = inNumVertices;
+	useShader(renderer->shader);
+
+	glGenVertexArrays(1, &vao);
+	glBindVertexArray(vao);
+
+	glGenBuffers(1, &vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, vbo);
+	glBufferData(GL_ARRAY_BUFFER, inNumVertices * sizeof(OrthographicVertex), &inVertices[0], GL_STATIC_DRAW);
+
+	glEnableVertexAttribArray(renderer->attributes.position);
+	glVertexAttribPointer(renderer->attributes.position, 2, GL_FLOAT, GL_FALSE, sizeof(OrthographicVertex), (GLvoid *)0);
+
+	glEnableVertexAttribArray(renderer->attributes.color);
+	glVertexAttribPointer(renderer->attributes.color, 4, GL_FLOAT, GL_FALSE, sizeof(OrthographicVertex), (GLvoid *)offsetof(OrthographicVertex, color));
+
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+	glBindVertexArray(0);
+}
+
+void OrthographicShape::render(OrthographicRenderer* renderer, GLenum drawType) {
+	setShaderMat4(renderer->uniforms.model, model);
+
+	glBindVertexArray(vao);
+	glDrawArrays(drawType, 0, numVertices);
+	glBindVertexArray(0);
+}
+
+void OrthographicShape::unload() {
+	glDeleteVertexArrays(1, &vao);
+	glDeleteBuffers(1, &vbo);
+}
\ No newline at end of file
diff --git a/shared_cpp/OrthographicRenderer.h b/shared_cpp/OrthographicRenderer.h
new file mode 100644
index 0000000..cef5305
--- /dev/null
+++ b/shared_cpp/OrthographicRenderer.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "WebglContext.h"
+#include "types.h"
+#include "Shader.h"
+#include "mathlib.h"
+
+struct WebglContext;
+
+struct OrthographicRenderer {
+	Mat4x4 projection;
+	uint32 shader;
+
+	struct {
+		int32 position;
+		int32 color;
+	} attributes;
+
+	struct {
+		int32 projection;
+		int32 model;
+	} uniforms;
+
+	void load(WebglContext* context);
+	void render();
+	void unload();
+};
+
+struct OrthographicVertex {
+	Vector2 position;
+	Vector4 color;
+};
+
+struct OrthographicShape {
+	uint32 vao;
+	uint32 vbo;
+	uint32 numVertices = 0;
+	Mat4x4 model;
+
+	void load(OrthographicVertex* vertices, uint32 numVertices, OrthographicRenderer* renderer);
+	void render(OrthographicRenderer* renderer, GLenum drawType = GL_TRIANGLES);
+	void unload();
+};
\ No newline at end of file
diff --git a/shared_cpp/Shader.cpp b/shared_cpp/Shader.cpp
new file mode 100644
index 0000000..5f2b00e
--- /dev/null
+++ b/shared_cpp/Shader.cpp
@@ -0,0 +1,61 @@
+#include "Shader.h"
+#include <string>
+
+GLuint loadIndividualShader(GLenum shaderType, const GLchar* cCode) {
+    GLuint shader = glCreateShader(shaderType);
+    glShaderSource(shader, 1, &cCode, 0);
+    glCompileShader(shader);
+    GLint success;
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+    if (!success) {
+        GLchar infoLog[512];
+        glGetShaderInfoLog(shader, 512, 0, infoLog);
+		printf("Failed to load shader: %s, Shader =%s\n", infoLog, cCode);
+        return 0;
+    }
+    
+    return shader;
+}
+
+void attachShaders(Shader& retVal, const GLchar* vertexShader, const GLchar* fragmentShader) {
+    GLuint vertex = 0, fragment = 0, geometry = 0;
+    if (vertexShader) {
+        vertex = loadIndividualShader(GL_VERTEX_SHADER, vertexShader);
+        glAttachShader(retVal, vertex);
+    }
+
+    if (fragmentShader) {
+        fragment = loadIndividualShader(GL_FRAGMENT_SHADER, fragmentShader);
+        glAttachShader(retVal, fragment);
+    }
+
+    glLinkProgram(retVal);
+    GLint isLinked = 0;
+    glGetProgramiv(retVal, GL_LINK_STATUS, (int*)&isLinked);
+    if (isLinked == GL_FALSE) {
+        GLint maxLength = 0;
+        glGetProgramiv(retVal, GL_INFO_LOG_LENGTH, &maxLength);
+
+        // The maxLength includes the NULL character
+        GLchar* infoLog = new GLchar[maxLength];
+        glGetProgramInfoLog(retVal, maxLength, &maxLength, infoLog);
+        glDeleteProgram(retVal);
+        printf("Error. Could not initialize shader with vertex=%s, error=%s\n", vertexShader, infoLog);
+        delete []infoLog;
+    }
+
+    if (vertexShader)
+        glDeleteShader(vertex);
+    if (fragmentShader)
+        glDeleteShader(fragment);
+}
+
+Shader loadShader(const GLchar* vertexShader, const GLchar* fragmentShader) {
+    Shader retVal;
+    retVal = glCreateProgram();
+
+    attachShaders(retVal, vertexShader, fragmentShader);
+    useShader(retVal);
+
+    return retVal;
+}
diff --git a/shared_cpp/Shader.h b/shared_cpp/Shader.h
new file mode 100644
index 0000000..6ee9981
--- /dev/null
+++ b/shared_cpp/Shader.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <GL/glew.h>
+#include <string>
+#include <vector>
+#include "mathlib.h"
+
+typedef GLuint Shader;
+
+Shader loadShader(const GLchar* vertexShader, const GLchar* fragmentShader);
+
+inline GLint getShaderUniform(const Shader& shader, const GLchar *name) {
+    GLint uid = glGetUniformLocation(shader, name);
+	if (uid < 0) {
+		return -1;
+	}
+	return uid;
+}
+
+inline GLint getShaderAttribute(const Shader& shader, const GLchar *name) {
+	printf("Getting attribute for shader, name: %d, %s\n", shader, name);
+    GLint uid = glGetAttribLocation(shader, name);
+	if (uid < 0) {
+		return -1;
+	}
+	return uid;
+}
+
+inline void useShader(const Shader& shader) {
+	glUseProgram(shader);
+}
+
+inline void setShaderFloat(GLint location, GLfloat value) {
+    glUniform1f(location, value);
+}
+
+inline void setShaderInt(GLint location, GLint value) {
+	glUniform1i(location, value);
+}
+
+inline void setShaderUint(GLint location, GLuint value) {
+	glUniform1ui(location, value);
+}
+
+inline void setShaderVec2(GLint location, const Vector2& value) {
+	glUniform2f(location, value.x, value.y);
+}
+
+inline void setShaderMat4(GLint location, const Mat4x4& matrix) {
+	glUniformMatrix4fv(location, 1, GL_FALSE, matrix.m);
+}
+
+inline void setShaderBVec3(GLint location, bool first, bool second, bool third) {
+	glUniform3i(location, first, second, third);
+}
+
+inline void setShaderBVec4(GLint location, bool first, bool second, bool third, bool fourth) {
+	glUniform4i(location, first, second, third, fourth);
+}
+
+inline void setShaderBool(GLint location, bool value) {
+	glUniform1i(location, value);
+}
\ No newline at end of file
diff --git a/shared_cpp/WebglContext.h b/shared_cpp/WebglContext.h
new file mode 100644
index 0000000..017498f
--- /dev/null
+++ b/shared_cpp/WebglContext.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "types.h"
+#include <emscripten.h>
+#include <emscripten/html5.h>
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+struct WebglContext {
+	EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context;
+	int width = 640;
+	int height = 480;
+
+	void init(const char* query, int inWidth = 640, int inHeight = 480) {
+		width = inWidth;
+		height = inHeight;
+		emscripten_set_canvas_element_size( query, width, height);
+		
+		EmscriptenWebGLContextAttributes attrs;
+		emscripten_webgl_init_context_attributes(&attrs);
+
+		attrs.enableExtensionsByDefault = 1;
+		attrs.majorVersion = 3;
+		attrs.minorVersion = 0;
+
+		context = emscripten_webgl_create_context(query, &attrs);
+		makeCurrentContext();
+
+		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
+		glClear(GL_COLOR_BUFFER_BIT);	
+	};
+	
+	void makeCurrentContext() {
+		emscripten_webgl_make_context_current(context);
+	};
+	
+	void destroy() {
+		emscripten_webgl_destroy_context(context);
+	}
+};
\ No newline at end of file
diff --git a/shared_cpp/WebglHelper.h b/shared_cpp/WebglHelper.h
new file mode 100644
index 0000000..dbdb23f
--- /dev/null
+++ b/shared_cpp/WebglHelper.h
@@ -0,0 +1,6 @@
+#pragma once
+#include "mathlib.h"
+
+struct OrthographicRenderer;
+
+void render2DArrow(Vector2 start, Vector2 end, OrthographicRenderer* renderer);
diff --git a/shared_cpp/mathlib.cpp b/shared_cpp/mathlib.cpp
new file mode 100644
index 0000000..8222d00
--- /dev/null
+++ b/shared_cpp/mathlib.cpp
@@ -0,0 +1,11 @@
+#include "mathlib.h"
+#include <cstdlib>
+
+Vector2 getRandomNormalVector2() {
+    Vector2 retval = {
+		static_cast<float>(rand()) / static_cast<float>(RAND_MAX),
+		static_cast<float>(rand()) / static_cast<float>(RAND_MAX) 
+	};
+
+	return retval.normalize();
+}
diff --git a/shared_cpp/mathlib.h b/shared_cpp/mathlib.h
new file mode 100644
index 0000000..3ed61cd
--- /dev/null
+++ b/shared_cpp/mathlib.h
@@ -0,0 +1,227 @@
+#pragma once
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cmath>
+
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define ABS(x) (x < 0 ? -x : x)
+
+struct Vector2 {
+    float x = 0;
+    float y = 0;
+
+    Vector2 operator+(Vector2 other) {
+        return { x + other.x, y + other.y };
+    }
+
+    Vector2& operator+=(Vector2 other) {
+        x += other.x;
+        y += other.y;
+        return *this;
+    }
+
+    Vector2 operator-(Vector2 other) {
+        return { x - other.x, y - other.y };
+    }
+
+    Vector2 operator*(float s) {
+        return { x * s, y * s };
+    }
+
+    Vector2 operator/(float s) {
+        return { x / s, y / s };
+    }
+
+    float dot(Vector2 other) {
+        return x * other.x + y * other.y;
+    }
+
+    float length() {
+        return sqrtf(x * x + y * y);
+    }
+
+    Vector2 normalize() {
+        float len = length();
+        float inverseLength = len == 0 ? 1.0 : 1.0 / len;
+
+        return { x * inverseLength, y * inverseLength };
+    }
+
+    Vector2 negate() {
+        return { -x, -y };
+    }
+
+    Vector2 getPerp() {
+        return { y, -x };
+    }
+
+    Vector2 rotate(float angle) {
+        return {
+            x * cosf(angle) - y * sinf(angle),
+            x * sinf(angle) + y * cosf(angle)
+        };
+    }
+
+    void printDebug(const char* name) {
+        printf("%s=Vector2(%f, %f)\n", name, x, y);
+    }
+
+    float determinant(Vector2 other) {
+        //
+        // [ a b ]
+        // [ c d ]
+        //
+        // [ x other.x ]
+        // [ y other.y ]
+        //
+        // det = a * d - b * c
+        // det = x * other.y - other.x * y
+        //
+        return x * other.y - other.x * y;
+    }
+};
+
+struct Vector3 {
+    float x = 0.f;
+    float y = 0.f;
+    float z = 0.f;
+};
+
+struct Vector4 {
+    float x = 0.f;
+    float y = 0.f;
+    float z = 0.f;
+    float w = 0.f;
+
+    float length() {
+        return sqrtf(x * x + y * y + z * z + w * w);
+    }
+
+    Vector4 normalize() {
+        float len = length();
+        float inverseLength = len == 0 ? 1.0 : 1.0 / len;
+
+        return { x * inverseLength, y * inverseLength, z * inverseLength, w * inverseLength };
+    }
+
+    Vector4 fromColor(float r, float g, float b, float a) {
+        float scale = 1.f / 255.f;
+        return { r * scale, g * scale, b * scale, a * scale };
+    }
+
+	Vector4 toNormalizedColor() {
+		return fromColor(x, y, z, w);
+	}
+};
+
+struct Mat4x4 {
+    float m[16] = {
+        1, 0, 0, 0,
+        0, 1, 0, 0,
+        0, 0, 1, 0,
+        0, 0, 0, 1
+    };
+
+    Mat4x4 copy() {
+        Mat4x4 result;
+        memcpy(result.m, m, sizeof(float) * 16);
+        return result;
+    }
+
+    Mat4x4 scale(Vector3 v) {
+        Mat4x4 result = copy();
+        result.m[0] = result.m[0] * v.x;
+        result.m[5] = result.m[5] *v.y;
+        result.m[10] = result.m[10] * v.z;
+        return result;
+    }
+
+    Mat4x4 translate(Vector3 v) {
+        Mat4x4 result = copy();
+        result.m[12] += v.x;
+        result.m[13] += v.y;
+        result.m[14] += v.z;
+        return result;
+    }
+
+	Mat4x4 translateByVec2(Vector2 v) {
+        Mat4x4 result = copy();
+        result.m[12] += v.x;
+        result.m[13] += v.y;
+        return result;
+    }
+
+    Mat4x4 rotate2D(float angle) {
+        Mat4x4 result = copy();
+        result.m[0] = cos(angle);
+        result.m[1] = -sin(angle);
+        result.m[4] = sin(angle);
+        result.m[5] = cos(angle);
+        return result;
+    }
+
+    Vector2 multByVec2(Vector2 v) {
+        Vector4 vec4 = { v.x, v.y, 0.0, 1.0 };
+        return {
+            vec4.x * m[0] + vec4.y * m[4] + vec4.z * m[8] + vec4.w * m[12],
+            vec4.x * m[1] + vec4.y * m[5] + vec4.z * m[9] + vec4.w * m[13]
+        };
+    }
+
+    Vector2 operator*(Vector2 v) {
+        return multByVec2(v);
+    }
+
+    Mat4x4 getOrthographicMatrix(float left, float right, float bottom, float top) {
+        Mat4x4 result;
+        result.m[0] = 2.0 / (right - left);
+        result.m[5] = 2.0 / (top - bottom);
+        result.m[10] = 1.0;
+        result.m[12] = -(right + left) / (right - left);
+        result.m[13] = -(top + bottom) / (top - bottom);
+        return result;
+    }
+
+    Mat4x4 inverse() {
+        Mat4x4 inv;
+
+        inv.m[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
+        inv.m[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
+        inv.m[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
+        inv.m[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
+        inv.m[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
+        inv.m[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
+        inv.m[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
+        inv.m[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
+        inv.m[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
+        inv.m[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
+        inv.m[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
+        inv.m[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
+        inv.m[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
+        inv.m[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
+        inv.m[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
+        inv.m[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];
+
+        float det = m[0] * inv.m[0] + m[1] * inv.m[4] + m[2] * inv.m[8] + m[3] * inv.m[12];
+
+        if (det == 0)
+            return Mat4x4();
+
+        det = 1.f / det;
+
+        for (int i = 0; i < 16; i++)
+            inv.m[i] = inv.m[i] * det;
+
+        return inv;
+    }
+
+	void print() {
+		printf("[ ");
+		for (int idx = 0; idx < 16; idx++) {
+			printf("%f, ", m[idx]);
+		}
+		printf(" ]\n");
+	}
+};
diff --git a/shared_cpp/types.h b/shared_cpp/types.h
new file mode 100644
index 0000000..3739699
--- /dev/null
+++ b/shared_cpp/types.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <cstdint>
+
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef unsigned long uint64;
+
+typedef float float32;
+typedef double float64;
+
+#define PI 3.14159265358979323846
\ No newline at end of file
-- 
cgit v1.2.1