From 58e3a869bb5857b089f0980a51b2706eb9987292 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Tue, 23 Sep 2025 15:35:26 +0100 Subject: [PATCH] Implement simple intersection detection with sphere --- demo.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/demo.c b/demo.c index 7ab11e8..63e5597 100644 --- a/demo.c +++ b/demo.c @@ -18,8 +18,14 @@ typedef struct { vec3_t orig, dir; } ray_t; -static const vec3_t lightblue = { 0.5, 0.7, 1.0 }; +typedef struct { + vec3_t centre; + double rad; +} sphere_t; + +static const vec3_t lightblue = { 0.4, 0.6, 1.0 }; static const vec3_t white = { 1.0, 1.0, 1.0 }; +static const vec3_t red = { 1.0, 0.1, 0.2 }; static const vec3_t camera = { 0, 0, 0 }; static const vec3_t vp_disp = { 0, 0, FOCLEN }; @@ -28,12 +34,35 @@ static const vec3_t vp_v = { 0, -VP_H, 0 }; static const vec3_t pix_x_step = { VP_W / W, 0, 0 }; static const vec3_t pix_y_step = { 0, -VP_H / H, 0 }; +static const sphere_t obj = { + .centre = { 1.0, 0.0, -3.0 }, + .rad = 1.0, +}; + static pix_t pix[W * H]; +static double intersect(sphere_t sphere, ray_t ray) +{ + const vec3_t disp = vec3_sub(sphere.centre, ray.orig); + + const double a = vec3_dot(ray.dir, ray.dir); + const double b = -2.0 * vec3_dot(ray.dir, disp); + const double c = vec3_dot(disp, disp) - sphere.rad * sphere.rad; + + const double discriminant = b * b - 4 * a * c; + if (discriminant < 0) + return -1.0; + else + return (-b - sqrt(discriminant)) / (2.0 * a); +} + static vec3_t raycol(ray_t ray) { - const vec3_t u = vec3_unit(ray.dir); - const double a = (u.y + 1.0) / 2.0; + const double t = intersect(obj, ray); + if (t > 0.0) + return red; + + const double a = (ray.dir.y + 1.0) / 2.0; return vec3_add(vec3_scale(lightblue, a), vec3_scale(white, 1 - a)); } @@ -64,7 +93,7 @@ int main() for (unsigned x = 0; x < W; ++x) { const ray_t ray = { .orig = camera, - .dir = vec3_add(row, vec3_scale(pix_x_step, x)), + .dir = vec3_unit(vec3_add(row, vec3_scale(pix_x_step, x))), }; const vec3_t col = raycol(ray); setpix(col, pix + (W * y + x));