commit 43f32142a00cb8886f0c525c8e4e66a6e7e86105
parent 539713663796d1162978cef7631ca1fe4c7f783c
Author: amin <dev@aminmesbah.com>
Date: Sun, 23 Jun 2019 06:19:24 +0000
Implement sine and cosine
Compile and run without math.h.
FossilOrigin-Name: a5c7f1aa1e2e5fdddfd19823a77e2328a5deb842a1b9f17dcf3207bee5b0dcfc
Diffstat:
4 files changed, 103 insertions(+), 10 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
@@ -165,9 +165,11 @@ 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 + glmth_sinf(0.5f * dt));
shader_setm4(&game_state->cube_shader, "model", &model);
diff --git a/src/glmth.c b/src/glmth.c
@@ -251,7 +251,6 @@ m4 glmth_rotate_z(m4 m, f32 rad)
return glmth_m4m4_m(m, r);
}
-
m4 glmth_rotate(m4 m, f32 rad, v3 normalized_axis)
{
v3 axis = normalized_axis;
diff --git a/src/glmth.h b/src/glmth.h
@@ -20,21 +20,114 @@ typedef int64_t s64;
typedef float f32;
typedef double r64;
-#include <math.h>
+#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)
{
- return sinf(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)
{
- return cosf(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)
{
- return tanf(x);
+ // TODO: make a proper approximation
+ return glmth_sinf(x)/glmth_cosf(x);
}
typedef union
@@ -140,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