commit cf9499da4a0512a2c0de111c9d584c5001bee60e
parent c616c3d7deb7b976ab893b8b7455fd034fea0d93
Author: amin <dev@aminmesbah.com>
Date: Wed, 16 May 2018 06:46:12 +0000
Add math and shader libs
FossilOrigin-Name: 713a9f02e95d0203ccc69eb63f67829a2d57dc0112b8dd8db7a7031575a72c1e
Diffstat:
A | src/glmth.h | | | 503 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/shader.h | | | 203 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 706 insertions(+), 0 deletions(-)
diff --git a/src/glmth.h b/src/glmth.h
@@ -0,0 +1,503 @@
+#ifndef GLMTH_H
+#define GLMTH_H
+
+#include <assert.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265359f
+#endif
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+typedef float f32;
+typedef double r64;
+
+typedef union
+{
+ struct
+ {
+ f32 x, y;
+ }
+ E[2];
+} v2;
+
+typedef union
+{
+ struct
+ {
+ f32 x, y, z;
+ };
+ struct
+ {
+ v2 xy;
+ f32 ignored_z;
+ };
+ struct
+ {
+ f32 ignored_x;
+ v2 yz;
+ };
+ f32 E[3];
+} v3;
+
+typedef union
+{
+ struct
+ {
+ union
+ {
+ v3 xyz;
+ struct
+ {
+ f32 x, y, z;
+ };
+ };
+ f32 w;
+ };
+ struct
+ {
+ v2 xy;
+ f32 ignored_z_xy;
+ f32 ignored_w_xy;
+ };
+ struct
+ {
+ f32 ignored_x_yz;
+ v2 yz;
+ f32 ignored_w_yz;
+ };
+ struct
+ {
+ f32 ignored_x_zw;
+ f32 ignored_y_zw;
+ v2 zw;
+ };
+ f32 E[4];
+} v4;
+
+typedef struct
+{
+ // row-major, so you probably want to transpose before passing to opengl,
+ // which uses column-major matrices
+ f32 E[4][4]; // E[row][column]
+} m4;
+
+
+m4 glmth_m4_init_id()
+{
+ m4 m = { 0 };
+ m.E[0][0] = 1.0f;
+ m.E[1][1] = 1.0f;
+ m.E[2][2] = 1.0f;
+ m.E[3][3] = 1.0f;
+ return m;
+}
+
+
+void glmth_m4_print(m4 m)
+{
+ printf("[\n");
+ printf(" %f, %f, %f, %f\n", m.E[0][0], m.E[0][1], m.E[0][2], m.E[0][3]);
+ printf(" %f, %f, %f, %f\n", m.E[1][0], m.E[1][1], m.E[1][2], m.E[1][3]);
+ printf(" %f, %f, %f, %f\n", m.E[2][0], m.E[2][1], m.E[2][2], m.E[2][3]);
+ printf(" %f, %f, %f, %f\n", m.E[3][0], m.E[3][1], m.E[3][2], m.E[3][3]);
+ printf("]\n");
+}
+
+
+f32 *glmth_m4_valueptr(m4 m)
+{
+ f32 *values = malloc(sizeof(m4));
+ for (u8 v = 0; v < 16; ++v)
+ {
+ u8 row = v / 4;
+ u8 col = v % 4;
+ values[v] = m.E[row][col];
+ }
+ return values;
+}
+
+
+bool glmth_m4m4_eq(m4 mat1, m4 mat2)
+{
+ for (u8 i = 0; i < 4; ++i)
+ {
+ for (u8 j = 0; j < 4; ++j)
+ {
+ if (mat1.E[i][j] != mat2.E[i][j])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
+m4 glmth_m4m4_m(m4 mat1, m4 mat2)
+{
+ m4 r = {
+ .E[0][0] = (mat1.E[0][0] * mat2.E[0][0]) + (mat1.E[0][1] * mat2.E[1][0]) + (mat1.E[0][2] * mat2.E[2][0]) + (mat1.E[0][3] * mat2.E[3][0]),
+ .E[0][1] = (mat1.E[0][0] * mat2.E[0][1]) + (mat1.E[0][1] * mat2.E[1][1]) + (mat1.E[0][2] * mat2.E[2][1]) + (mat1.E[0][3] * mat2.E[3][1]),
+ .E[0][2] = (mat1.E[0][0] * mat2.E[0][2]) + (mat1.E[0][1] * mat2.E[1][2]) + (mat1.E[0][2] * mat2.E[2][2]) + (mat1.E[0][3] * mat2.E[3][2]),
+ .E[0][3] = (mat1.E[0][0] * mat2.E[0][3]) + (mat1.E[0][1] * mat2.E[1][3]) + (mat1.E[0][2] * mat2.E[2][3]) + (mat1.E[0][3] * mat2.E[3][3]),
+
+ .E[1][0] = (mat1.E[1][0] * mat2.E[0][0]) + (mat1.E[1][1] * mat2.E[1][0]) + (mat1.E[1][2] * mat2.E[2][0]) + (mat1.E[1][3] * mat2.E[3][0]),
+ .E[1][1] = (mat1.E[1][0] * mat2.E[0][1]) + (mat1.E[1][1] * mat2.E[1][1]) + (mat1.E[1][2] * mat2.E[2][1]) + (mat1.E[1][3] * mat2.E[3][1]),
+ .E[1][2] = (mat1.E[1][0] * mat2.E[0][2]) + (mat1.E[1][1] * mat2.E[1][2]) + (mat1.E[1][2] * mat2.E[2][2]) + (mat1.E[1][3] * mat2.E[3][2]),
+ .E[1][3] = (mat1.E[1][0] * mat2.E[0][3]) + (mat1.E[1][1] * mat2.E[1][3]) + (mat1.E[1][2] * mat2.E[2][3]) + (mat1.E[1][3] * mat2.E[3][3]),
+
+ .E[2][0] = (mat1.E[2][0] * mat2.E[0][0]) + (mat1.E[2][1] * mat2.E[1][0]) + (mat1.E[2][2] * mat2.E[2][0]) + (mat1.E[2][3] * mat2.E[3][0]),
+ .E[2][1] = (mat1.E[2][0] * mat2.E[0][1]) + (mat1.E[2][1] * mat2.E[1][1]) + (mat1.E[2][2] * mat2.E[2][1]) + (mat1.E[2][3] * mat2.E[3][1]),
+ .E[2][2] = (mat1.E[2][0] * mat2.E[0][2]) + (mat1.E[2][1] * mat2.E[1][2]) + (mat1.E[2][2] * mat2.E[2][2]) + (mat1.E[2][3] * mat2.E[3][2]),
+ .E[2][3] = (mat1.E[2][0] * mat2.E[0][3]) + (mat1.E[2][1] * mat2.E[1][3]) + (mat1.E[2][2] * mat2.E[2][3]) + (mat1.E[2][3] * mat2.E[3][3]),
+
+ .E[3][0] = (mat1.E[3][0] * mat2.E[0][0]) + (mat1.E[3][1] * mat2.E[1][0]) + (mat1.E[3][2] * mat2.E[2][0]) + (mat1.E[3][3] * mat2.E[3][0]),
+ .E[3][1] = (mat1.E[3][0] * mat2.E[0][1]) + (mat1.E[3][1] * mat2.E[1][1]) + (mat1.E[3][2] * mat2.E[2][1]) + (mat1.E[3][3] * mat2.E[3][1]),
+ .E[3][2] = (mat1.E[3][0] * mat2.E[0][2]) + (mat1.E[3][1] * mat2.E[1][2]) + (mat1.E[3][2] * mat2.E[2][2]) + (mat1.E[3][3] * mat2.E[3][2]),
+ .E[3][3] = (mat1.E[3][0] * mat2.E[0][3]) + (mat1.E[3][1] * mat2.E[1][3]) + (mat1.E[3][2] * mat2.E[2][3]) + (mat1.E[3][3] * mat2.E[3][3]),
+ };
+ return r;
+}
+
+
+v4 glmth_m4v4_m(m4 m, v4 v)
+{
+ v4 r = {
+ .x = (m.E[0][0] * v.x) + (m.E[0][1] * v.y) + (m.E[0][2] * v.z) + (m.E[0][3] * v.w),
+ .y = (m.E[1][0] * v.x) + (m.E[1][1] * v.y) + (m.E[1][2] * v.z) + (m.E[1][3] * v.w),
+ .z = (m.E[2][0] * v.x) + (m.E[2][1] * v.y) + (m.E[2][2] * v.z) + (m.E[2][3] * v.w),
+ .w = (m.E[3][0] * v.x) + (m.E[3][1] * v.y) + (m.E[3][2] * v.z) + (m.E[3][3] * v.w),
+ };
+ return r;
+}
+
+
+v3 glmth_v3_cross(v3 vec1, v3 vec2)
+{
+ v3 r = {
+ .x = (vec1.y * vec2.z) - (vec1.z * vec2.y),
+ .y = (vec1.z * vec2.x) - (vec1.x * vec2.z),
+ .z = (vec1.x * vec2.y) - (vec1.y * vec2.x),
+ };
+ return r;
+}
+
+
+v3 glmth_v3_init(f32 x, f32 y, f32 z)
+{
+ v3 v = { .x = x, .y = y, .z = z };
+ return v;
+}
+
+v3 glmth_v3_init_f(f32 f)
+{
+ return glmth_v3_init(f, f, f);
+}
+
+f32 glmth_v3_length(v3 v)
+{
+ return sqrtf((v.x * v.x) + (v.y * v.y) + (v.z * v.z));
+}
+
+v3 glmth_v3f_m(v3 v, f32 s)
+{
+ v3 r = { .x = v.x * s, .y = v.y * s, .z = v.z * s };
+ return r;
+}
+
+v3 glmth_v3_negate(v3 v)
+{
+ v3 r = { .x = -v.x, .y = -v.y, .z = -v.z };
+ return r;
+}
+
+
+v3 glmth_v3_normalize(v3 v)
+{
+ f32 l = glmth_v3_length(v);
+ v3 r = glmth_v3_init(v.x / l, v.y / l, v.z / l);
+ return r;
+}
+
+
+void glmth_v3_print(v3 v)
+{
+ printf("( %f, %f, %f )\n", v.x, v.y, v.z);
+}
+
+
+v3 glmth_v3_a(v3 vec1, v3 vec2)
+{
+ v3 r = {
+ .x = vec1.x + vec2.x,
+ .y = vec1.y + vec2.y,
+ .z = vec1.z + vec2.z
+ };
+ return r;
+}
+
+
+v3 glmth_v3_s(v3 vec1, v3 vec2)
+{
+ return glmth_v3_a(vec1, glmth_v3_negate(vec2));
+}
+
+
+void glmth_v4_print(v4 v)
+{
+ printf("( %f, %f, %f, %f )\n", v.x, v.y, v.z, v.w);
+}
+
+
+bool glmth_v4v4_eq(v4 vec1, v4 vec2)
+{
+ for (u8 i = 0; i < 4; ++i)
+ {
+ if (vec1.E[i] != vec2.E[i])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+void glmth_clampf(float *f, float min, float max)
+{
+ if (*f < min)
+ {
+ *f = min;
+ }
+ else if (*f > max)
+ {
+ *f = max;
+ }
+}
+
+
+f32 glmth_deg(f32 rad)
+{
+ return rad * (180.0f / M_PI);
+}
+
+
+float glmth_lerpf(float f, float min, float max)
+{
+ assert(f >= 0.0f && f <= 1.0f);
+ return (1.0f - f) * min + f * max;
+}
+
+
+f32 glmth_rad(f32 deg)
+{
+ return deg * (M_PI / 180.0f);
+}
+
+
+m4 glmth_rotate_x(m4 m, f32 rad)
+{
+ f32 c = cosf(rad);
+ f32 s = sinf(rad);
+
+ m4 r = glmth_m4_init_id();
+
+ r.E[1][1] = c;
+ r.E[1][2] = -s;
+
+ r.E[2][1] = s;
+ r.E[2][2] = c;
+
+ return glmth_m4m4_m(m, r);
+}
+
+
+m4 glmth_rotate_y(m4 m, f32 rad)
+{
+ f32 c = cosf(rad);
+ f32 s = sinf(rad);
+
+ m4 r = glmth_m4_init_id();
+
+ r.E[0][0] = c;
+ r.E[0][2] = s;
+
+ r.E[2][0] = -s;
+ r.E[2][2] = c;
+
+ return glmth_m4m4_m(m, r);
+}
+
+
+m4 glmth_rotate_z(m4 m, f32 rad)
+{
+ f32 c = cosf(rad);
+ f32 s = sinf(rad);
+
+ m4 r = glmth_m4_init_id();
+
+ r.E[0][0] = c;
+ r.E[0][1] = -s;
+
+ r.E[1][0] = s;
+ r.E[1][1] = c;
+
+ return glmth_m4m4_m(m, r);
+}
+
+
+m4 glmth_rotate(m4 m, f32 rad, v3 axis)
+{
+ axis = glmth_v3_normalize(axis);
+
+ f32 c = cosf(rad);
+ f32 s = sinf(rad);
+
+ m4 r = glmth_m4_init_id();
+
+ r.E[0][0] = c + (powf(axis.x, 2.0f) * (1 - c));
+ r.E[0][1] = (axis.x * axis.y * (1 - c)) - (axis.z * s);
+ r.E[0][2] = (axis.x * axis.z * (1 - c)) + (axis.y * s);
+
+ r.E[1][0] = (axis.y * axis.x * (1 - c)) + (axis.z * s);
+ r.E[1][1] = c + (powf(axis.y, 2.0f) * (1 - c));
+ r.E[1][2] = (axis.y * axis.z * (1 - c)) - (axis.x * s);
+
+ r.E[2][0] = (axis.z * axis.x * (1 - c)) - (axis.y * s);
+ r.E[2][1] = (axis.z * axis.y * (1 - c)) + (axis.x * s);
+ r.E[2][2] = c + (powf(axis.z, 2.0f) * (1 - c));
+
+ return glmth_m4m4_m(m, r);
+}
+
+
+m4 glmth_scale(m4 m, v3 v)
+{
+ m4 r = glmth_m4_init_id();
+ r.E[0][0] = v.x;
+ r.E[1][1] = v.y;
+ r.E[2][2] = v.z;
+ return glmth_m4m4_m(m, r);
+}
+
+
+m4 glmth_translate(m4 m, v3 v)
+{
+ m4 r = glmth_m4_init_id();
+ r.E[0][3] = v.x;
+ r.E[1][3] = v.y;
+ r.E[2][3] = v.z;
+ return glmth_m4m4_m(m, r);
+}
+
+
+m4 glmth_projection_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far)
+{
+ assert(left != right);
+ assert(bottom != top);
+ assert(near != far);
+
+ m4 r = glmth_m4_init_id();
+
+ r.E[0][0] = 2.0f / (right - left);
+ r.E[0][1] = 0.0f;
+ r.E[0][2] = 0.0f;
+ r.E[0][3] = -(right + left) / (right - left);
+
+ r.E[1][0] = 0.0f;
+ r.E[1][1] = 2.0f / (top - bottom);
+ r.E[1][2] = 0.0f;
+ r.E[1][3] = -(top + bottom) / (top - bottom);
+
+ r.E[2][0] = 0.0f;
+ r.E[2][1] = 0.0f;
+ r.E[2][2] = -2.0f / (far - near);
+ r.E[2][3] = -(far + near) / (far - near);
+
+ r.E[3][0] = 0.0f;
+ r.E[3][1] = 0.0f;
+ r.E[3][2] = 0.0f;
+ r.E[3][3] = 1.0f;
+
+ return r;
+}
+
+
+m4 glmth_projection_perspective(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far)
+{
+ assert(left != right);
+ assert(bottom != top);
+ assert(near != far);
+
+ m4 r = glmth_m4_init_id();
+
+ r.E[0][0] = (2.0f * near) / (right - left);
+ r.E[0][1] = 0.0f;
+ r.E[0][2] = (right + left) / (right - left);
+ r.E[0][3] = 0.0f;
+
+ r.E[1][0] = 0.0f;
+ r.E[1][1] = (2.0f * near) / (top - bottom);
+ r.E[1][2] = (top + bottom) / (top - bottom);
+ r.E[1][3] = 0.0f;
+
+ r.E[2][0] = 0.0f;
+ r.E[2][1] = 0.0f;
+ r.E[2][2] = -(far + near) / (far - near);
+ r.E[2][3] = (-2.0f * far * near) / (far - near);
+
+ r.E[3][0] = 0.0f;
+ r.E[3][1] = 0.0f;
+ r.E[3][2] = -1.0f;
+ r.E[3][3] = 0.0f;
+
+ return r;
+}
+
+
+m4 glmth_projection_perspective_fov(f32 fovy, f32 aspect, f32 near, f32 far)
+{
+ f32 half_height = tanf(fovy / 2.0f) * near;
+ f32 half_width = half_height * aspect;
+ f32 left = -half_width;
+ f32 right = half_width;
+ f32 bottom = -half_height;
+ f32 top = half_height;
+
+ return glmth_projection_perspective(left, right, bottom, top, near, far);
+}
+
+
+m4 glmth_camera_look_at(v3 camera_pos, v3 camera_target, v3 up)
+{
+ v3 camera_direction = glmth_v3_normalize(glmth_v3_s(camera_pos, camera_target));
+ v3 camera_right = glmth_v3_normalize(glmth_v3_cross(up, camera_direction));
+ v3 camera_up = glmth_v3_cross(camera_direction, camera_right);
+
+ m4 look = glmth_m4_init_id();
+ look.E[0][0] = camera_right.x;
+ look.E[0][1] = camera_right.y;
+ look.E[0][2] = camera_right.z;
+
+ look.E[1][0] = camera_up.x;
+ look.E[1][1] = camera_up.y;
+ look.E[1][2] = camera_up.z;
+
+ look.E[2][0] = camera_direction.x;
+ look.E[2][1] = camera_direction.y;
+ look.E[2][2] = camera_direction.z;
+
+ return glmth_m4m4_m(look, glmth_translate(glmth_m4_init_id(), glmth_v3_negate(camera_pos)));
+}
+
+
+#endif
diff --git a/src/shader.h b/src/shader.h
@@ -0,0 +1,203 @@
+#ifndef SHADER_H
+#define SHADER_H
+
+#include <glad/glad.h> // get opengl headers
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "glmth.h"
+
+struct Shader
+{
+ uint32_t program;
+};
+
+
+char *read_file(char *file_path)
+{
+ FILE *handle = fopen(file_path, "r");
+ char *buffer = NULL;
+
+ if (handle)
+ {
+ // get file size
+ fseek(handle, 0, SEEK_END);
+ uint32_t num_bytes_in_file = ftell(handle);
+ rewind(handle);
+
+ buffer = (char*) malloc(sizeof(char) * (num_bytes_in_file + 1) );
+
+ uint32_t bytes_read = fread(buffer, sizeof(char), num_bytes_in_file, handle);
+ // IMPORTANT! fread() doesn't add the '\0'
+ buffer[num_bytes_in_file] = '\0';
+
+ if (num_bytes_in_file != bytes_read)
+ {
+ free(buffer);
+ buffer = NULL;
+ }
+
+ fclose(handle);
+ }
+ else
+ {
+ printf("Error: Couldn't open file at path: %s", file_path);
+ }
+
+ return buffer;
+}
+
+
+struct Shader shader_compile(GLchar *vertex_path, GLchar *fragment_path)
+{
+ const GLchar *vertex_shader_source = read_file(vertex_path);
+ const GLchar *fragment_shader_source = read_file(fragment_path);
+
+ GLint success;
+ GLchar info_log[512];
+
+ GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
+ glCompileShader(vertex_shader);
+ glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
+ if (!success)
+ {
+ glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
+ printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n %s\n", info_log);
+ }
+
+ GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
+ glCompileShader(fragment_shader);
+ glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
+ if (!success)
+ {
+ glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
+ printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n %s\n", info_log);
+ }
+
+ struct Shader s;
+ s.program = glCreateProgram();
+ glAttachShader(s.program, vertex_shader);
+ glAttachShader(s.program, fragment_shader);
+ glLinkProgram(s.program);
+ glGetProgramiv(s.program, GL_LINK_STATUS, &success);
+ if (!success)
+ {
+ glGetShaderInfoLog(s.program, 512, NULL, info_log);
+ printf("ERROR::SHADER::LINKING_FAILED\n %s\n", info_log);
+ }
+
+ glDeleteShader(fragment_shader);
+ glDeleteShader(vertex_shader);
+
+ return s;
+}
+
+
+void shader_use(struct Shader *s)
+{
+ if (s)
+ {
+ glUseProgram(s->program);
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+void shader_setb(struct Shader *s, char *name, bool value)
+{
+ if (s)
+ {
+ glUniform1i(glGetUniformLocation(s->program, name), (int)value);
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+void shader_seti(struct Shader *s, char *name, int value)
+{
+ if (s)
+ {
+ glUniform1i(glGetUniformLocation(s->program, name), value);
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+void shader_setf(struct Shader *s, char *name, f32 value)
+{
+ if (s)
+ {
+ glUniform1f(glGetUniformLocation(s->program, name), value);
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+void shader_setm4(struct Shader *s, char *name, m4 *mat)
+{
+ if (s)
+ {
+ glUniformMatrix4fv(glGetUniformLocation(s->program, name), 1, GL_TRUE, glmth_m4_valueptr(*mat));
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+void shader_setf3(struct Shader *s, char *name, f32 x, f32 y, f32 z)
+{
+ if (s)
+ {
+ glUniform3f(glGetUniformLocation(s->program, name), x, y, z);
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+void shader_setf3_1(struct Shader *s, char *name, f32 f)
+{
+ if (s)
+ {
+ shader_setf3(s, name, f, f, f);
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+void shader_setv3(struct Shader *s, char *name, v3 *v)
+{
+ if (s)
+ {
+ shader_setf3(s, name, v->x, v->y, v->z);
+ }
+ else
+ {
+ printf("Error: invalid Shader pointer\n");
+ }
+}
+
+
+#endif