From d11143ac8659d573c9735e0708751e7a6bac34eb Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Mon, 28 Oct 2024 12:34:48 +0300 Subject: [PATCH] twn_draw.h: new camera api --- apps/demos/scenery/scenes/ingame.c | 37 ++++++++----------- apps/demos/scenery/scenes/ingame.h | 4 +-- include/twn_draw.h | 18 ++++++++-- src/rendering/twn_draw.c | 42 +++++++++++++++++++--- src/twn_camera.c | 2 +- include/twn_camera.h => src/twn_camera_c.h | 7 ++-- src/twn_textures_c.h | 4 +-- 7 files changed, 73 insertions(+), 41 deletions(-) rename include/twn_camera.h => src/twn_camera_c.h (66%) diff --git a/apps/demos/scenery/scenes/ingame.c b/apps/demos/scenery/scenes/ingame.c index 464dbfc..fdeda70 100644 --- a/apps/demos/scenery/scenes/ingame.c +++ b/apps/demos/scenery/scenes/ingame.c @@ -24,40 +24,34 @@ static void ingame_tick(State *state) { input_bind_action_control("mouse_capture_toggle", CONTROL_ESCAPE); if (scn->mouse_captured) { - const float sensitivity = 0.6f; /* TODO: put this in a better place */ + const float sensitivity = 0.4f * (float)DEG2RAD; /* TODO: put this in a better place */ scn->yaw += (float)ctx.mouse_movement.x * sensitivity; scn->pitch -= (float)ctx.mouse_movement.y * sensitivity; - scn->pitch = clampf(scn->pitch, -89.0f, 89.0f); - - const float yaw_rad = scn->yaw * (float)DEG2RAD; - const float pitch_rad = scn->pitch * (float)DEG2RAD; - - scn->cam.target = m_vec_norm(((Vec3){ - cosf(yaw_rad) * cosf(pitch_rad), - sinf(pitch_rad), - sinf(yaw_rad) * cosf(pitch_rad) - })); + scn->pitch = clampf(scn->pitch, (float)-M_PI * 0.49f, (float)M_PI * 0.49f); } - const Vec3 right = m_vec_norm(m_vec_cross(scn->cam.target, scn->cam.up)); + DrawCameraFromPrincipalAxesResult dir_and_up = + draw_camera_from_principal_axes(scn->pos, (float)M_PI_2, scn->roll, scn->pitch, scn->yaw); + + const Vec3 right = m_vec_norm(m_vec_cross(dir_and_up.direction, dir_and_up.up)); const float speed = 0.04f; /* TODO: put this in a better place */ if (input_is_action_pressed("player_left")) - scn->cam.pos = vec3_sub(scn->cam.pos, m_vec_scale(right, speed)); + scn->pos = vec3_sub(scn->pos, m_vec_scale(right, speed)); if (input_is_action_pressed("player_right")) - scn->cam.pos = vec3_add(scn->cam.pos, m_vec_scale(right, speed)); + scn->pos = vec3_add(scn->pos, m_vec_scale(right, speed)); if (input_is_action_pressed("player_forward")) - scn->cam.pos = vec3_add(scn->cam.pos, m_vec_scale(scn->cam.target, speed)); + scn->pos = vec3_add(scn->pos, m_vec_scale(dir_and_up.direction, speed)); if (input_is_action_pressed("player_backward")) - scn->cam.pos = vec3_sub(scn->cam.pos, m_vec_scale(scn->cam.target, speed)); + scn->pos = vec3_sub(scn->pos, m_vec_scale(dir_and_up.direction, speed)); if (input_is_action_pressed("player_jump")) - scn->cam.pos.y += speed; + scn->pos.y += speed; if (input_is_action_pressed("player_run")) - scn->cam.pos.y -= speed; + scn->pos.y -= speed; /* toggle mouse capture with end key */ if (input_is_action_just_pressed("mouse_capture_toggle")) @@ -65,14 +59,12 @@ static void ingame_tick(State *state) { input_set_mouse_captured(scn->mouse_captured); - draw_camera(&scn->cam); - #define TERRAIN_FREQUENCY 0.1f for (int ly = 64; ly--;) { for (int lx = 64; lx--;) { - float x = SDL_truncf(scn->cam.pos.x + 32 - (float)lx); - float y = SDL_truncf(scn->cam.pos.z + 32 - (float)ly); + float x = SDL_truncf(scn->pos.x + 32 - (float)lx); + float y = SDL_truncf(scn->pos.z + 32 - (float)ly); float d0 = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6; float d1 = stb_perlin_noise3((float)(x + 1) * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6; @@ -114,7 +106,6 @@ Scene *ingame_scene(State *state) { new_scene->base.tick = ingame_tick; new_scene->base.end = ingame_end; - new_scene->cam = (Camera){ .pos = { 32, 0, 1 }, .up = { 0, 1, 0 }, .fov = (float)M_PI_2 }; new_scene->mouse_captured = true; m_audio(m_set(path, "music/mod65.xm"), diff --git a/apps/demos/scenery/scenes/ingame.h b/apps/demos/scenery/scenes/ingame.h index 8eece6e..a553971 100644 --- a/apps/demos/scenery/scenes/ingame.h +++ b/apps/demos/scenery/scenes/ingame.h @@ -12,9 +12,7 @@ typedef struct SceneIngame { Scene base; - Camera cam; - - /* TODO: put this in a better place */ + Vec3 pos; float yaw; float pitch; float roll; diff --git a/include/twn_draw.h b/include/twn_draw.h index 161dfdb..8566ab3 100644 --- a/include/twn_draw.h +++ b/include/twn_draw.h @@ -3,7 +3,6 @@ #include "twn_types.h" #include "twn_option.h" -#include "twn_camera.h" #include "twn_engine_api.h" #include @@ -76,8 +75,21 @@ TWN_API void draw_triangle(char const *path, // Vec2 scaling, // Rect uvs); -/* pushes a camera state to be used for all future unfurl_* commands */ -TWN_API void draw_camera(const Camera *camera); +/* sets a perspective 3d camera to be used for all 3d commands */ +TWN_API void draw_camera(Vec3 position, float fov, Vec3 up, Vec3 direction); + +/* same as draw_camera(), but with specific use case */ +/* direction and up vectors are inferred from roll, pitch and yaw parameters (in radians) */ +/* return value is direction and up vectors, so that you can use them in logic (such as controllers) */ +typedef struct DrawCameraFromPrincipalAxesResult { + Vec3 direction; + Vec3 up; +} DrawCameraFromPrincipalAxesResult; +DrawCameraFromPrincipalAxesResult TWN_API draw_camera_from_principal_axes(Vec3 position, + float fov, + float roll, + float pitch, + float yaw); /* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */ TWN_API void draw_skybox(const char *paths); diff --git a/src/rendering/twn_draw.c b/src/rendering/twn_draw.c index 80489ec..08fbce6 100644 --- a/src/rendering/twn_draw.c +++ b/src/rendering/twn_draw.c @@ -1,8 +1,9 @@ #include "twn_draw_c.h" #include "twn_draw.h" #include "twn_engine_context_c.h" -#include "twn_camera.h" +#include "twn_camera_c.h" #include "twn_types.h" +#include "twn_vec.h" #include #include @@ -382,8 +383,39 @@ void render(void) { } -void draw_camera(const Camera *const camera) { - /* TODO: skip recaulculating if it's the same? */ - camera_projection_matrix = camera_perspective(camera); - camera_look_at_matrix = camera_look_at(camera); +void draw_camera(Vec3 position, float fov, Vec3 up, Vec3 direction) { + Camera const camera = { + .fov = fov, + .pos = position, + .target = direction, + .up = up, + }; + camera_projection_matrix = camera_perspective(&camera); + camera_look_at_matrix = camera_look_at(&camera); +} + + +/* TODO: https://stackoverflow.com/questions/62493770/how-to-add-roll-in-camera-class */ +DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position, float fov, float roll, float pitch, float yaw) { + (void)roll; + float yawc, yaws, pitchc, pitchs; + sincosf(yaw, &yaws, &yawc); + sincosf(pitch, &pitchs, &pitchc); + Camera const camera = { + .fov = fov, + .pos = position, + .target = m_vec_norm(((Vec3){ + yawc * pitchc, + pitchs, + yaws * pitchc, + })), + .up = (Vec3){0, 1, 0}, + }; + camera_projection_matrix = camera_perspective(&camera); + camera_look_at_matrix = camera_look_at(&camera); + + return (DrawCameraFromPrincipalAxesResult) { + .direction = camera.target, + .up = camera.up, + }; } diff --git a/src/twn_camera.c b/src/twn_camera.c index e658ec3..0aebf04 100644 --- a/src/twn_camera.c +++ b/src/twn_camera.c @@ -1,4 +1,4 @@ -#include "twn_camera.h" +#include "twn_camera_c.h" #include "twn_vec.h" #include "twn_engine_context_c.h" diff --git a/include/twn_camera.h b/src/twn_camera_c.h similarity index 66% rename from include/twn_camera.h rename to src/twn_camera_c.h index ff3031d..bd2377e 100644 --- a/include/twn_camera.h +++ b/src/twn_camera_c.h @@ -2,7 +2,6 @@ #define TWN_CAMERA_H #include "twn_types.h" -#include "twn_engine_api.h" /* TODO: make it cached? */ /* for example, perspective matrix only needs recaluclation on FOV change */ @@ -12,11 +11,11 @@ typedef struct Camera { Vec3 pos; /* eye position */ Vec3 target; /* normalized target vector */ Vec3 up; /* normalized up vector */ - float fov; /* field of view, in radians */ + float fov; /* field of view, in radians */ } Camera; -TWN_API Matrix4 camera_look_at(const Camera *camera); +Matrix4 camera_look_at(const Camera *camera); -TWN_API Matrix4 camera_perspective(const Camera *const camera); +Matrix4 camera_perspective(const Camera *const camera); #endif diff --git a/src/twn_textures_c.h b/src/twn_textures_c.h index 62ae179..8faa607 100644 --- a/src/twn_textures_c.h +++ b/src/twn_textures_c.h @@ -17,8 +17,8 @@ typedef struct Texture { - Rect srcrect; /* position in atlas */ - SDL_Surface *data; /* original image data */ + Rect srcrect; /* position in atlas */ + SDL_Surface *data; /* original image data */ int atlas_index; GPUTexture loner_texture; /* stored directly for loners, == 0 means atlas_index should be used */ GPUTexture repeating_texture; /* separately allocated Texture, for loners == loner_texture */