From 791ab628ca6ba803cce46848c83d93cb31fb9f8a Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Mon, 27 Jan 2025 02:42:36 +0300 Subject: [PATCH] orthographic projection for fov=0, rework of order and defaults for 3d camera api --- include/twn_draw.h | 17 +++++++++++------ share/twn_api.json | 14 +++++++------- src/rendering/twn_draw.c | 31 +++++++++++++++++++++++-------- src/twn_camera.c | 21 +++++++++++++++++++++ src/twn_camera_c.h | 2 +- 5 files changed, 63 insertions(+), 22 deletions(-) diff --git a/include/twn_draw.h b/include/twn_draw.h index 7cb3419..2b44756 100644 --- a/include/twn_draw.h +++ b/include/twn_draw.h @@ -79,7 +79,11 @@ TWN_API void draw_billboard(const char *texture, bool cylindrical); /* optional, default: false */ /* 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); +/* fov = 0 corresponds to orthographic projection */ +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) */ /* 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) */ @@ -88,11 +92,12 @@ typedef struct DrawCameraFromPrincipalAxesResult { Vec3 direction; Vec3 up; } DrawCameraFromPrincipalAxesResult; -TWN_API DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position, - float fov, - float roll, - float pitch, - float yaw); +TWN_API DrawCameraFromPrincipalAxesResult +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) */ /* 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 efe8af0..891529e 100644 --- a/share/twn_api.json +++ b/share/twn_api.json @@ -179,9 +179,9 @@ "header": "twn_draw.h", "params": [ { "name": "position", "type": "Vec3" }, - { "name": "fov", "type": "float" }, - { "name": "up", "type": "Vec3" }, - { "name": "direction", "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 } ] }, @@ -191,10 +191,10 @@ "header": "twn_draw.h", "params": [ { "name": "position", "type": "Vec3" }, - { "name": "fov", "type": "float" }, - { "name": "roll", "type": "float" }, - { "name": "pitch", "type": "float" }, - { "name": "yaw", "type": "float" } + { "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 } ], "return": { "fields": [ diff --git a/src/rendering/twn_draw.c b/src/rendering/twn_draw.c index 853d931..065ab2f 100644 --- a/src/rendering/twn_draw.c +++ b/src/rendering/twn_draw.c @@ -413,8 +413,9 @@ void render(void) { } -void draw_camera(Vec3 position, float fov, Vec3 up, Vec3 direction) { - if (fabsf(0.0f - fov) < 0.00001f || fov >= M_PIf) +void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov) { + bool const orthographic = fabsf(0.0f - fov) < 0.00001f; + if (!orthographic && fov >= M_PIf) log_warn("Invalid fov given (%f)", (double)fov); Camera const camera = { @@ -424,14 +425,24 @@ void draw_camera(Vec3 position, float fov, Vec3 up, Vec3 direction) { .up = up, }; - camera_projection_matrix = camera_perspective(&camera); - camera_look_at_matrix = camera_look_at(&camera); + if (!orthographic) + camera_projection_matrix = camera_perspective(&camera); + else + camera_projection_matrix = camera_orthographic(&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) { - if (fabsf(0.0f - fov) < 0.00001f || fov >= M_PIf) +DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position, + float roll, + float pitch, + float yaw, + float fov) +{ + bool const orthographic = fabsf(0.0f - fov) < 0.00001f; + if (!orthographic && fov >= M_PIf) log_warn("Invalid fov given (%f)", (double)fov); (void)roll; @@ -451,8 +462,12 @@ DrawCameraFromPrincipalAxesResult draw_camera_from_principal_axes(Vec3 position, .up = (Vec3){0, 1, 0}, }; - camera_projection_matrix = camera_perspective(&camera); - camera_look_at_matrix = camera_look_at(&camera); + if (!orthographic) + camera_projection_matrix = camera_perspective(&camera); + else + camera_projection_matrix = camera_orthographic(&camera); + + camera_look_at_matrix = camera_look_at(&camera); return (DrawCameraFromPrincipalAxesResult) { .direction = camera.target, diff --git a/src/twn_camera.c b/src/twn_camera.c index 8d7c3b5..87466c1 100644 --- a/src/twn_camera.c +++ b/src/twn_camera.c @@ -52,3 +52,24 @@ Matrix4 camera_perspective(const Camera *const camera) { return result; } + +Matrix4 camera_orthographic(const Camera *const camera) { + /* from cglm */ + (void)camera; + + Matrix4 result = {0}; + + const float rl = 1.0f / (float)1; + const float tb = 1.0f / (float)1; + 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].z = (CAMERA_FAR_Z + CAMERA_NEAR_Z) * fn; + result.row[3].w = 1.0f; + + return result; +} diff --git a/src/twn_camera_c.h b/src/twn_camera_c.h index 96d6ad0..e6e3ea5 100644 --- a/src/twn_camera_c.h +++ b/src/twn_camera_c.h @@ -16,7 +16,7 @@ typedef struct Camera { } Camera; Matrix4 camera_look_at(const Camera *camera); - Matrix4 camera_perspective(const Camera *const camera); +Matrix4 camera_orthographic(const Camera *const camera); #endif