From 6eb4da9e067175c7025ee1bf1c20074d457cb2bc Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 23 Sep 2025 15:35:26 +0100 Subject: [PATCH] Add front/back face detection --- demo.c | 3 ++- include/obj.h | 11 +++++++++-- src/obj.c | 24 +++++++++++++++--------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/demo.c b/demo.c index 88d104e..74e45a5 100644 --- a/demo.c +++ b/demo.c @@ -4,6 +4,7 @@ #include "ray.h" #include "vec3.h" +#include #include #include #include @@ -34,7 +35,7 @@ static vec3_t raycol(ray_t ray) { hit_t hit; for (unsigned i = 0; i < NELEMS(scene); ++i) { - if (scene[i].intersect(scene[i].params, ray, &hit)) + if (scene[i].intersect(scene[i].params, ray, &hit, 0.0, DBL_MAX)) return vec3_scale(vec3_add(hit.normal, white), 0.5); } diff --git a/include/obj.h b/include/obj.h index 5835d7d..f766634 100644 --- a/include/obj.h +++ b/include/obj.h @@ -14,6 +14,7 @@ typedef struct { vec3_t point, normal; double t; + bool front; } hit_t; typedef struct { @@ -25,11 +26,17 @@ typedef union { sphere_params_t sphere; } obj_params_t; +typedef bool intersect_fn_t( + obj_params_t params, ray_t ray, hit_t *hit_out, double t_min, + double t_max); + typedef struct { - bool (*intersect)(obj_params_t params, ray_t ray, hit_t *hit_out); + intersect_fn_t *intersect; obj_params_t params; } obj_t; -bool intersect_sphere(obj_params_t params, ray_t ray, hit_t *hit_out); +bool intersect_sphere( + obj_params_t params, ray_t ray, hit_t *hit_out, double t_min, + double t_max); #endif diff --git a/src/obj.c b/src/obj.c index 520c58d..0b5bdec 100644 --- a/src/obj.c +++ b/src/obj.c @@ -2,28 +2,34 @@ #include -bool intersect_sphere(obj_params_t params, ray_t ray, hit_t *hit_out) +bool intersect_sphere( + obj_params_t params, ray_t ray, hit_t *hit_out, double t_min, + double t_max) { const vec3_t centre = params.sphere.centre; const double r = params.sphere.radius; const vec3_t disp = vec3_sub(centre, ray.orig); const double a = vec3_dot(ray.dir, ray.dir); - const double b = -2.0 * vec3_dot(ray.dir, disp); + const double h = vec3_dot(ray.dir, disp); const double c = vec3_dot(disp, disp) - r * r; - const double discriminant = b * b - 4 * a * c; + const double discriminant = h * h - a * c; if (discriminant < 0) return false; - const double t = (-b - sqrt(discriminant)) / (2.0 * a); + const double sqrtd = sqrt(discriminant); + const double low = (h - sqrtd) / a; + const double t = low > t_min ? low : (h + sqrtd) / a; + if (t < t_min || t_max < t) + return false; + const vec3_t point = vec3_add(ray.orig, vec3_scale(ray.dir, t)); const vec3_t normal = vec3_unit(vec3_sub(point, centre)); - if (hit_out != nullptr) { - hit_out->point = point; - hit_out->normal = normal; - hit_out->t = t; - } + hit_out->point = point; + hit_out->normal = normal; + hit_out->t = t; + hit_out->front = vec3_dot(ray.dir, normal) < 0.0; return true; }