diff --git a/apps/testgame/scenes/ingame.c b/apps/testgame/scenes/ingame.c index 926d2fe..022b909 100644 --- a/apps/testgame/scenes/ingame.c +++ b/apps/testgame/scenes/ingame.c @@ -11,14 +11,14 @@ static void ingame_tick(struct state *state) { world_drawdef(scn->world); player_calc(scn->player); - static t_camera cam = { .pos = { 0 }, .target = { 0, 0, -1 }, .up = { 0, -1, 0 }, .fov = (float)M_PI_2 }; + static t_camera cam = { .pos = { 0, 0, 1 }, .target = { 0, 0, -1 }, .up = { 0, 1, 0 }, .fov = (float)M_PI_2 }; if (input_is_action_pressed(&ctx.input, "player_left")) cam.pos.x -= 0.01f; if (input_is_action_pressed(&ctx.input, "player_right")) cam.pos.x += 0.01f; if (input_is_action_pressed(&ctx.input, "player_jump")) - cam.pos.z -= 0.01f; + cam.pos.z += 0.01f; m_sprite(m_set(path, "/assets/light.png"), m_set(rect, ((t_frect){ 48, 64, 64, 64 })), diff --git a/src/camera.c b/src/camera.c index f15a522..adea359 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,27 +1,52 @@ #include "camera.h" +#include "context.h" + +#include + + +#define CAMERA_NEAR_Z 0.1f +#define CAMERA_FAR_Z 100.0f + t_matrix4 camera_look_at(const t_camera *const camera) { /* from cglm */ - const t_fvec3 f = m_vec_norm(m_vec_sub(camera->pos, camera->target)); - const t_fvec3 r = m_vec_norm(m_vec_cross(f, camera->up)); - const t_fvec3 u = m_vec_cross(f, r); + const t_fvec3 r = m_vec_norm(m_vec_cross(camera->target, camera->up)); + const t_fvec3 u = m_vec_cross(r, camera->target); t_matrix4 result; - result.row[0].x = r.x; - result.row[0].y = u.x; - result.row[0].z =-f.x; - result.row[1].x = r.y; - result.row[1].y = u.y; - result.row[1].z =-f.y; - result.row[2].x = r.z; - result.row[2].y = u.z; - result.row[2].z =-f.z; - result.row[3].x =-m_vec_dot(r, camera->pos); - result.row[3].y =-m_vec_dot(u, camera->pos); - result.row[3].z = m_vec_dot(f, camera->pos); - result.row[0].w = result.row[1].w = result.row[2].w = 0.0f; - result.row[3].w = 1.0f; + result.row[0].x = r.x; + result.row[0].y = u.x; + result.row[0].z = -camera->target.x; + result.row[1].x = r.y; + result.row[1].y = u.y; + result.row[1].z = -camera->target.y; + result.row[2].x = r.z; + result.row[2].y = u.z; + result.row[2].z = -camera->target.z; + result.row[3].x = -m_vec_dot(r, camera->pos); + result.row[3].y = -m_vec_dot(u, camera->pos); + result.row[3].z = m_vec_dot(camera->target, camera->pos); + result.row[0].w = result.row[1].w = result.row[2].w = 0.0f; + result.row[3].w = 1.0f; + + return result; +} + +t_matrix4 camera_perspective(const t_camera *const camera) { + /* from cglm */ + t_matrix4 result = {0}; + + const float aspect = RENDER_BASE_RATIO; + + const float f = 1.0f / tanf(camera->fov * 0.5f); + const float fn = 1.0f / (CAMERA_NEAR_Z - CAMERA_FAR_Z); + + result.row[0].x = f / aspect; + result.row[1].y = f; + result.row[2].z = (CAMERA_NEAR_Z + CAMERA_FAR_Z) * fn; + result.row[2].w = -1.0f; + result.row[3].z = 2.0f * CAMERA_NEAR_Z * CAMERA_FAR_Z * fn; return result; } diff --git a/src/camera.h b/src/camera.h index 128db62..0d2f0f9 100644 --- a/src/camera.h +++ b/src/camera.h @@ -3,13 +3,19 @@ #include "util.h" +/* TODO: make it cached */ +/* for example, perspective matrix only needs recaluclation on FOV change */ + /* first person camera class */ typedef struct camera { - t_fvec3 pos; /* eye position */ - t_fvec3 target; /* target point */ - t_fvec3 up; /* normalized up vector */ + t_fvec3 pos; /* eye position */ + t_fvec3 target; /* normalized target vector */ + t_fvec3 up; /* normalized up vector */ + float fov; /* field of view, in radians */ } t_camera; t_matrix4 camera_look_at(const t_camera *camera); +t_matrix4 camera_perspective(const t_camera *const camera); + #endif diff --git a/src/rendering.c b/src/rendering.c index 887b23b..e561e7b 100644 --- a/src/rendering.c +++ b/src/rendering.c @@ -14,7 +14,8 @@ /* TODO: have a default initialized one */ -static t_matrix4 camera_projection; +static t_matrix4 camera_projection_matrix; +static t_matrix4 camera_look_at_matrix; void render_queue_clear(void) { @@ -164,10 +165,10 @@ void render(void) { { glMatrixMode(GL_PROJECTION); - glLoadMatrixf(&camera_projection.row[0].x); + glLoadMatrixf(&camera_projection_matrix.row[0].x); glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + glLoadMatrixf(&camera_look_at_matrix.row[0].x); render_space(); } @@ -189,7 +190,8 @@ void render(void) { SDL_GL_SwapWindow(ctx.window); } -void push_camera(const t_camera *const camera) { +void set_camera(const t_camera *const camera) { /* TODO: skip recaulculating if it's the same? */ - camera_projection = camera_look_at(camera); + camera_projection_matrix = camera_perspective(camera); + camera_look_at_matrix = camera_look_at(camera); }