commit 6111393aa6512bd135046590cafb5a75d48761e0
parent 1b0b3c87b211bf9c1f5f7262f8bb280feb18be5f
Author: amin <dev@aminmesbah.com>
Date: Sun, 23 Jun 2019 06:20:13 +0000
Merge branch 'features/replace-math-functions'
FossilOrigin-Name: 69e14fd6ae7d4c938fdbd60b860457d5f9e9411fab82fbef6f1858cd184de472
Diffstat:
M | Makefile | | | 2 | +- |
M | src/game.c | | | 67 | +++++++++---------------------------------------------------------- |
M | src/glmth.c | | | 66 | ++++++++++++++---------------------------------------------------- |
M | src/glmth.h | | | 112 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
4 files changed, 134 insertions(+), 113 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
CC = clang
CFLAGS = -std=c99 -Ilib -Wall -Wextra -Wshadow -Wswitch-enum -Wno-unused-parameter -Wno-missing-braces
-LDFLAGS = -ldl -lglfw -lGL -lm
+LDFLAGS = -ldl -lglfw -lGL
SRC_FILES = game.c glad.c glmth.c platform_linux.c shader.c
SRC = $(addprefix src/, $(SRC_FILES))
diff --git a/src/game.c b/src/game.c
@@ -1,7 +1,6 @@
#include "game.h"
#include <assert.h>
-#include <math.h>
// TODO: remove references to emscripten
#ifdef __EMSCRIPTEN__
@@ -48,56 +47,6 @@ float randf(float min, float max)
void game_init(struct GameState *game_state, uint32_t screen_width, uint32_t screen_height)
{
- // load pyramid vertex data
- {
- float edge_length = 1.0f;
- float height = 1.0f / sqrtf(2.0f) * edge_length;
- float half_length = edge_length / 2.0f;
- float half_height = height / 2.0f;
-
- GLfloat pyramid_vertices[] = {
- // positions
- -half_length, -half_height, -half_length,
- -half_length, -half_height, half_length,
- half_length, -half_height, half_length,
- half_length, -half_height, -half_length,
- 0.0f, half_height, 0.0f,
- };
-
- GLuint elements[] = {
- 0, 3, 2,
- 2, 1, 0,
- 0, 4, 3,
- 3, 4, 2,
- 2, 4, 1,
- 1, 4, 0,
- };
-
- GLuint pyramid_vao_id;
- glGenVertexArrays(1, &pyramid_vao_id);
- glBindVertexArray(pyramid_vao_id);
-
- GLuint pyramid_vbo_id;
- glGenBuffers(1, &pyramid_vbo_id);
- glBindBuffer(GL_ARRAY_BUFFER, pyramid_vbo_id);
- glBufferData(GL_ARRAY_BUFFER, sizeof(pyramid_vertices), pyramid_vertices, GL_STATIC_DRAW);
-
- // positions
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(*pyramid_vertices), (GLvoid*)0);
- glEnableVertexAttribArray(0);
-
- GLuint pyramid_ebo_id;
- glGenBuffers(1, &pyramid_ebo_id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pyramid_ebo_id);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
-
- glBindVertexArray(0);
-
- game_state->pyramid_vao_id = pyramid_vao_id;
- game_state->pyramid_vbo_id = pyramid_vbo_id;
- game_state->pyramid_ebo_id = pyramid_ebo_id;
- }
-
// load cube vertex data
{
GLfloat cube_vertices[] = {
@@ -187,9 +136,9 @@ void game_update_and_render(struct GameState *game_state, float dt, uint32_t scr
f32 color_freq = dt * 0.1f;
v3 pyramid_color = glmth_v3_init(
- sinf(color_freq),
- sinf(color_freq + (2 * M_PI / 3)),
- sinf(color_freq + (4 * M_PI / 3)));
+ glmth_sinf(color_freq),
+ glmth_sinf(color_freq + (2 * M_PI / 3)),
+ glmth_sinf(color_freq + (4 * M_PI / 3)));
shader_setm4(&game_state->pyramid_shader, "model", &model);
shader_setv3(&game_state->pyramid_shader, "pyramid_color", &pyramid_color);
@@ -216,11 +165,13 @@ void game_update_and_render(struct GameState *game_state, float dt, uint32_t scr
m4 model = glmth_m4_init_id();
f32 angle = 20.0f;
- model = glmth_rotate(model, dt * glmth_rad(angle), glmth_v3_init(1.0f, 0.0f, 0.0f));
- model = glmth_rotate(model, dt * glmth_rad(angle), glmth_v3_init(0.0f, 1.0f, 0.0f));
- model = glmth_rotate(model, dt * glmth_rad(angle), glmth_v3_init(0.0f, 0.0f, 1.0f));
+ // TODO: fmodf this so we don't get huge numbers eventually
+ f32 rot_rad = dt * glmth_rad(angle);
+ model = glmth_rotate(model, rot_rad, glmth_v3_init(1.0f, 0.0f, 0.0f));
+ model = glmth_rotate(model, rot_rad, glmth_v3_init(0.0f, 1.0f, 0.0f));
+ model = glmth_rotate(model, rot_rad, glmth_v3_init(0.0f, 0.0f, 1.0f));
- f32 alpha = 0.2f * (1.5f + sinf(0.5f * dt));
+ f32 alpha = 0.2f * (1.5f + glmth_sinf(0.5f * dt));
shader_setm4(&game_state->cube_shader, "model", &model);
shader_setf(&game_state->cube_shader, "alpha", alpha);
diff --git a/src/glmth.c b/src/glmth.c
@@ -115,11 +115,6 @@ 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 };
@@ -132,15 +127,6 @@ v3 glmth_v3_negate(v3 v)
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);
@@ -217,8 +203,8 @@ f32 glmth_rad(f32 deg)
m4 glmth_rotate_x(m4 m, f32 rad)
{
- f32 c = cosf(rad);
- f32 s = sinf(rad);
+ f32 c = glmth_cosf(rad);
+ f32 s = glmth_sinf(rad);
m4 r = glmth_m4_init_id();
@@ -234,8 +220,8 @@ m4 glmth_rotate_x(m4 m, f32 rad)
m4 glmth_rotate_y(m4 m, f32 rad)
{
- f32 c = cosf(rad);
- f32 s = sinf(rad);
+ f32 c = glmth_cosf(rad);
+ f32 s = glmth_sinf(rad);
m4 r = glmth_m4_init_id();
@@ -251,8 +237,8 @@ m4 glmth_rotate_y(m4 m, f32 rad)
m4 glmth_rotate_z(m4 m, f32 rad)
{
- f32 c = cosf(rad);
- f32 s = sinf(rad);
+ f32 c = glmth_cosf(rad);
+ f32 s = glmth_sinf(rad);
m4 r = glmth_m4_init_id();
@@ -265,27 +251,26 @@ m4 glmth_rotate_z(m4 m, f32 rad)
return glmth_m4m4_m(m, r);
}
-
-m4 glmth_rotate(m4 m, f32 rad, v3 axis)
+m4 glmth_rotate(m4 m, f32 rad, v3 normalized_axis)
{
- axis = glmth_v3_normalize(axis);
+ v3 axis = normalized_axis;
- f32 c = cosf(rad);
- f32 s = sinf(rad);
+ f32 c = glmth_cosf(rad);
+ f32 s = glmth_sinf(rad);
m4 r = glmth_m4_init_id();
- r.E[0][0] = c + (powf(axis.x, 2.0f) * (1 - c));
+ r.E[0][0] = c + ((axis.x * axis.x) * (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][1] = c + ((axis.y * axis.y) * (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));
+ r.E[2][2] = c + ((axis.z * axis.z) * (1 - c));
return glmth_m4m4_m(m, r);
}
@@ -377,7 +362,7 @@ m4 glmth_projection_perspective(f32 left, f32 right, f32 bottom, f32 top, f32 ne
m4 glmth_projection_perspective_fov(f32 fovy, f32 aspect, f32 near, f32 far)
{
- f32 half_height = tanf(fovy / 2.0f) * near;
+ f32 half_height = glmth_tanf(fovy / 2.0f) * near;
f32 half_width = half_height * aspect;
f32 left = -half_width;
f32 right = half_width;
@@ -386,26 +371,3 @@ m4 glmth_projection_perspective_fov(f32 fovy, f32 aspect, f32 near, f32 far)
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)));
-}
diff --git a/src/glmth.h b/src/glmth.h
@@ -2,7 +2,6 @@
#define GLMTH_H
#include <assert.h>
-#include <math.h>
#include <stdbool.h>
#include <stdint.h>
@@ -21,6 +20,116 @@ typedef int64_t s64;
typedef float f32;
typedef double r64;
+#define GLMTH_PI 3.14159265358979323846f
+#define GLMTH_M_2_PI 6.28318530717958647693f
+#define GLMTH_D_4_PI 1.27323954473516268615f
+#define GLMTH_D_PI_2 1.57079632679489661923f
+#define GLMTH_D_4_SQ_PI 0.40528473456935108578f
+
+static inline f32 glmth_floorf(f32 x)
+{
+ f32 result = (f32)((s32)x - (x < 0.0f));
+ return result;
+}
+
+
+// These Sine and Cosine approximations use a parabola adjusted to minimize
+// error. This lovely approximation was derived by "Nick" on the devmaster.net
+// forums:
+//
+// https://web.archive.org/web/20080228213915/http://www.devmaster.net/forums/showthread.php?t=5784
+static inline f32 glmth_sinf(f32 x)
+{
+
+ // wrap to range [0, 2PI]
+ f32 full_circles = glmth_floorf(x / GLMTH_M_2_PI);
+ f32 full_circle_radians = full_circles * GLMTH_M_2_PI;
+ x = x - full_circle_radians;
+
+ // TODO: remove branches
+ // wrap to range [-PI, PI]
+ if(x < -GLMTH_PI)
+ {
+ x += GLMTH_M_2_PI;
+ }
+ else if(x > GLMTH_PI)
+ {
+ x -= GLMTH_M_2_PI;
+ }
+
+ // fit parabola to sine
+ f32 f = 0.0f;
+ f32 g = 0.0f;
+ if(x < 0.0f)
+ {
+ f = (GLMTH_D_4_PI * x) + (GLMTH_D_4_SQ_PI * x * x);
+ g = f * -f;
+
+ }
+ else
+ {
+ f = (GLMTH_D_4_PI * x) - (GLMTH_D_4_SQ_PI * x * x);
+ g = f * f;
+ }
+
+ f32 h = g - f;
+ f32 i = h * 0.225f;
+ f = i + f;
+
+ return f;
+}
+
+static inline f32 glmth_cosf(f32 x)
+{
+ // wrap to range [0, 2PI]
+ f32 full_circles = glmth_floorf(x / GLMTH_M_2_PI);
+ f32 full_circle_radians = full_circles * GLMTH_M_2_PI;
+ x = x - full_circle_radians;
+
+ // TODO: remove branches
+ // wrap to range [-PI, PI]
+ if(x < -GLMTH_PI)
+ {
+ x += GLMTH_M_2_PI;
+ }
+ else if(x > GLMTH_PI)
+ {
+ x -= GLMTH_M_2_PI;
+ }
+
+ x += GLMTH_D_PI_2;
+ if(x > GLMTH_PI)
+ {
+ x -= GLMTH_M_2_PI;
+ }
+
+ // fit parabola to cosine
+ f32 f = 0.0f;
+ f32 g = 0.0f;
+ if(x < 0.0f)
+ {
+ f = (GLMTH_D_4_PI * x) + (GLMTH_D_4_SQ_PI * x * x);
+ g = f * -f;
+
+ }
+ else
+ {
+ f = (GLMTH_D_4_PI * x) - (GLMTH_D_4_SQ_PI * x * x);
+ g = f * f;
+ }
+
+ f32 h = g - f;
+ f32 i = h * 0.225f;
+ f = i + f;
+ return f;
+}
+
+static inline f32 glmth_tanf(f32 x)
+{
+ // TODO: make a proper approximation
+ return glmth_sinf(x)/glmth_cosf(x);
+}
+
typedef union
{
struct
@@ -124,5 +233,4 @@ m4 glmth_projection_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near, f3
m4 glmth_projection_perspective(f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far);
m4 glmth_projection_perspective_fov(f32 fovy, f32 aspect, f32 near, f32 far);
m4 glmth_camera_look_at(v3 camera_pos, v3 camera_target, v3 up);
-
#endif