From 6a87119c70155976bb95da1be26a796180b824a5 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Mon, 27 Jan 2025 03:25:14 +0300 Subject: [PATCH] add zoom option to camera to work around the orthographic camera --- include/twn_draw.h | 6 ++++-- share/twn_api.json | 6 ++++-- src/rendering/twn_draw.c | 13 +++++++++++-- src/twn_camera.c | 8 ++++---- src/twn_camera_c.h | 1 + 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/twn_draw.h b/include/twn_draw.h index 2b44756..3016507 100644 --- a/include/twn_draw.h +++ b/include/twn_draw.h @@ -83,7 +83,8 @@ TWN_API void draw_billboard(const char *texture, TWN_API void draw_camera(Vec3 position, Vec3 direction, /* optional, default: (0, 0, -1) */ Vec3 up, /* optional, default: (0, 1, 0) */ - float fov); /* optional, default: PI / 6 * 3 (90 degrees) */ + float fov, /* optional, default: PI / 6 * 3 (90 degrees) */ + float zoom); /* optional, default: 1 */ /* same as draw_camera(), but with first person controller in mind */ /* direction and up vectors are inferred from roll, pitch and yaw parameters (in radians) */ @@ -97,7 +98,8 @@ draw_camera_from_principal_axes(Vec3 position, float roll, /* optional, default: 0 */ float pitch, /* optional, default: 0 */ float yaw, /* optional, default: 0 */ - float fov); /* optional, default: PI / 6 * 3 (90 degrees) */ + float fov, /* optional, default: PI / 6 * 3 (90 degrees) */ + float zoom); /* optional, default: 1 */ /* expects '*' masks that will be expanded to 6 names: 'up', 'down', 'east', 'west', 'north' and 'south' */ TWN_API void draw_skybox(const char *textures); diff --git a/share/twn_api.json b/share/twn_api.json index 891529e..4712de3 100644 --- a/share/twn_api.json +++ b/share/twn_api.json @@ -181,7 +181,8 @@ { "name": "position", "type": "Vec3" }, { "name": "direction", "type": "Vec3", "default": { "x": 0, "y": 0, "z": -1 } }, { "name": "up", "type": "Vec3", "default": { "x": 0, "y": 1, "z": 0 } }, - { "name": "fov", "type": "float", "default": 1.57079632679 } + { "name": "fov", "type": "float", "default": 1.57079632679 }, + { "name": "zoom", "type": "float", "default": 1 } ] }, @@ -194,7 +195,8 @@ { "name": "roll", "type": "float", "default": 0 }, { "name": "pitch", "type": "float", "default": 0 }, { "name": "yaw", "type": "float", "default": 0 }, - { "name": "fov", "type": "float", "default": 1.57079632679 } + { "name": "fov", "type": "float", "default": 1.57079632679 }, + { "name": "zoom", "type": "float", "default": 1 } ], "return": { "fields": [ diff --git a/src/rendering/twn_draw.c b/src/rendering/twn_draw.c index 065ab2f..b8455dc 100644 --- a/src/rendering/twn_draw.c +++ b/src/rendering/twn_draw.c @@ -413,7 +413,7 @@ void render(void) { } -void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov) { +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 >= M_PIf) log_warn("Invalid fov given (%f)", (double)fov); @@ -423,6 +423,10 @@ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov) { .pos = position, .target = direction, .up = up, + .viewbox = { + (Vec2){ 1/-zoom, 1/zoom }, + (Vec2){ 1/zoom, 1/-zoom } + }, }; if (!orthographic) @@ -439,7 +443,8 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position, float roll, float pitch, float yaw, - float fov) + float fov, + float zoom) { bool const orthographic = fabsf(0.0f - fov) < 0.00001f; if (!orthographic && fov >= M_PIf) @@ -460,6 +465,10 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position, yaws * pitchc, })), .up = (Vec3){0, 1, 0}, + .viewbox = { + (Vec2){ 1/-zoom, 1/zoom }, + (Vec2){ 1/zoom, 1/-zoom } + }, }; if (!orthographic) diff --git a/src/twn_camera.c b/src/twn_camera.c index 87466c1..375fd2e 100644 --- a/src/twn_camera.c +++ b/src/twn_camera.c @@ -59,15 +59,15 @@ Matrix4 camera_orthographic(const Camera *const camera) { Matrix4 result = {0}; - const float rl = 1.0f / (float)1; - const float tb = 1.0f / (float)1; + const float rl = 1.0f / (camera->viewbox[0].y - camera->viewbox[0].x); + const float tb = 1.0f / (camera->viewbox[1].x - camera->viewbox[1].y); const float fn = -1.0f / (CAMERA_FAR_Z - CAMERA_NEAR_Z); result.row[0].x = 2.0f * rl; result.row[1].y = 2.0f * tb; result.row[2].z = 2.0f * fn; - result.row[3].x = -(float)1 * rl; - result.row[3].y = -(float)1 * tb; + result.row[3].x = -(camera->viewbox[0].y + camera->viewbox[0].x) * rl; + result.row[3].y = -(camera->viewbox[1].x + camera->viewbox[1].y) * tb; result.row[3].z = (CAMERA_FAR_Z + CAMERA_NEAR_Z) * fn; result.row[3].w = 1.0f; diff --git a/src/twn_camera_c.h b/src/twn_camera_c.h index e6e3ea5..602af79 100644 --- a/src/twn_camera_c.h +++ b/src/twn_camera_c.h @@ -13,6 +13,7 @@ typedef struct Camera { Vec3 target; /* normalized target vector */ Vec3 up; /* normalized up vector */ float fov; /* field of view, in radians */ + Vec2 viewbox[2]; /* othrographic aabb, ((left, right), (top, bottom)) */ } Camera; Matrix4 camera_look_at(const Camera *camera);