From d9df3f9b04c4d9d3b74b7489f3a6399d2e89b661 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Wed, 5 Feb 2025 00:54:38 +0300 Subject: [PATCH] twn_draw.c: draw_camera_2d()! --- apps/demos/platformer/scenes/ingame.c | 5 ++++ include/twn_draw.h | 4 ++++ share/twn_api.json | 11 +++++++++ src/rendering/twn_draw.c | 33 +++++++++++++++++++++++++-- src/rendering/twn_draw_c.h | 4 ++++ src/rendering/twn_gl_15_rendering.c | 9 +++++++- 6 files changed, 63 insertions(+), 3 deletions(-) diff --git a/apps/demos/platformer/scenes/ingame.c b/apps/demos/platformer/scenes/ingame.c index d4086dc..21bde0b 100644 --- a/apps/demos/platformer/scenes/ingame.c +++ b/apps/demos/platformer/scenes/ingame.c @@ -18,6 +18,11 @@ static void ingame_tick(State *state) { input_action("player_jump", "SPACE"); input_action("player_run", "LSHIFT"); + draw_camera_2d((Vec2){ scn->player->rect.x + scn->player->rect.w / 2 - ctx.resolution.x / 2, + scn->player->rect.y + scn->player->rect.h / 2 - ctx.resolution.y / 2 }, + 0, 1 + ); + world_drawdef(scn->world); player_calc(scn->player); } diff --git a/include/twn_draw.h b/include/twn_draw.h index f237eed..4ed1d2a 100644 --- a/include/twn_draw.h +++ b/include/twn_draw.h @@ -81,6 +81,10 @@ TWN_API void draw_billboard(const char *texture, Color color, /* optional, default: all 255 */ bool cylindrical); /* optional, default: false */ +TWN_API void draw_camera_2d(Vec2 position, /* optional, default: (0, 0) */ + float rotation, /* optional, default: 0 */ + float zoom); /* optional, default: 1 */ + /* sets a perspective 3d camera to be used for all 3d commands */ /* fov = 0 corresponds to orthographic projection */ TWN_API void draw_camera(Vec3 position, diff --git a/share/twn_api.json b/share/twn_api.json index cfd96fe..447ebfb 100644 --- a/share/twn_api.json +++ b/share/twn_api.json @@ -185,6 +185,17 @@ ] }, + "draw_camera_2d": { + "module": "draw", + "symbol": "camera_2d", + "header": "twn_draw.h", + "params": [ + { "name": "position", "type": "Vec2", "default": { "x": 0, "y": 0 } }, + { "name": "rotation", "type": "float", "default": 0 }, + { "name": "zoom", "type": "float", "default": 1 } + ] + }, + "draw_camera": { "module": "draw", "symbol": "camera", diff --git a/src/rendering/twn_draw.c b/src/rendering/twn_draw.c index 652afc9..7a8b959 100644 --- a/src/rendering/twn_draw.c +++ b/src/rendering/twn_draw.c @@ -17,19 +17,30 @@ DeferredCommand *deferred_commands; -/* TODO: have a default initialized one */ /* TODO: with buffered render, don't we use camera of wrong frame right now ? */ Matrix4 camera_projection_matrix; Matrix4 camera_look_at_matrix; +float camera_2d_rotation; +Vec2 camera_2d_position; +float camera_2d_zoom; + double depth_range_low, depth_range_high; +static void reset_camera_2d(void) { + camera_2d_position = (Vec2){0}; + camera_2d_zoom = 1; + camera_2d_rotation = 0; +} + + void render_clear(void) { draw_camera((Vec3){0, 0, 0}, (Vec3){0, 0, 1}, (Vec3){0, 1, 0}, 1.57079632679f, 1); + reset_camera_2d(); text_cache_reset_arena(&ctx.text_cache); - + /* since i don't intend to free the queues, */ /* it's faster and simpler to just "start over" */ /* and start overwriting the existing data */ @@ -415,6 +426,22 @@ void render(void) { } +/* TODO: check for NaNs and alike */ +TWN_API void draw_camera_2d(Vec2 position, + float rotation, + float zoom) +{ + if (zoom <= 0) { + log_warn("Invalid zoom value given to draw_camera_2d()"); + zoom = 0.1f; + } + + camera_2d_position = position; + camera_2d_rotation = rotation; + camera_2d_zoom = zoom; +} + +/* TODO: check for NaNs and alike */ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom) { bool const orthographic = fabsf(0.0f - fov) < 0.00001f; if (!orthographic && fov >= (float)(M_PI)) @@ -441,6 +468,8 @@ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom) /* TODO: https://stackoverflow.com/questions/62493770/how-to-add-roll-in-camera-class */ +/* TODO: check for NaNs and alike */ +/* TODOL call draw_camera() instead, to reuse the code */ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position, float roll, float pitch, diff --git a/src/rendering/twn_draw_c.h b/src/rendering/twn_draw_c.h index e8ed484..4ef9995 100644 --- a/src/rendering/twn_draw_c.h +++ b/src/rendering/twn_draw_c.h @@ -17,6 +17,10 @@ extern Matrix4 camera_projection_matrix; extern Matrix4 camera_look_at_matrix; +extern float camera_2d_rotation; +extern Vec2 camera_2d_position; +extern float camera_2d_zoom; + extern double depth_range_low, depth_range_high; #define QUAD_ELEMENT_BUFFER_LENGTH (65536 / 6) diff --git a/src/rendering/twn_gl_15_rendering.c b/src/rendering/twn_gl_15_rendering.c index 5e6558b..2616628 100644 --- a/src/rendering/twn_gl_15_rendering.c +++ b/src/rendering/twn_gl_15_rendering.c @@ -161,8 +161,15 @@ static void finally_use_2d_pipeline(void) { glOrtho(0, (double)ctx.base_render_width, (double)ctx.base_render_height, 0, 0, 1); glMatrixMode(GL_MODELVIEW); - /* TODO: 2d camera */ glLoadIdentity(); + /* rotate against center of the viewport */ + Vec2 const center_offset = { ctx.game.resolution.x / 2, ctx.game.resolution.y / 2 }; + glTranslatef(center_offset.x, center_offset.y, 0); + glRotatef(camera_2d_rotation, 0, 0, 1); + glScalef(camera_2d_zoom, camera_2d_zoom, 1); + glTranslatef(-center_offset.x, -center_offset.y, 0); + /* apply the rest */ + glTranslatef(-camera_2d_position.x, -camera_2d_position.y, 0); texture_mode_last_used = -1; pipeline_last_used = PIPELINE_2D;