From a85c25262e717be7247d1969c515940b17955d8b Mon Sep 17 00:00:00 2001 From: Lukas Jiriste Date: Sat, 23 Nov 2024 11:49:27 +0100 Subject: [PATCH] Implement cylinder-ray intersection detection This commit makes the project compilable. --- inc/miniRT.h | 6 ++++ src/scene.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/inc/miniRT.h b/inc/miniRT.h index b836d35..f40ed49 100644 --- a/inc/miniRT.h +++ b/inc/miniRT.h @@ -14,6 +14,12 @@ typedef struct s_color_sRGB unsigned char b; } t_color_sRGB; +typedef struct s_pair +{ + double first; + double second; +} t_pair; + typedef struct s_sphere { t_color color; diff --git a/src/scene.c b/src/scene.c index e7aa5cc..196ef43 100644 --- a/src/scene.c +++ b/src/scene.c @@ -86,6 +86,83 @@ double get_intersection_arg_nonbounded(const t_ray *ray, const t_object *object) return (NAN); } +t_vec3 ray_point(const t_ray *ray, double arg) +{ + return (vec_add(ray->start, vec_real_mul(ray->direction, arg))); +} + +double get_intersection_arg_cylinder_base + (const t_ray *ray, const t_cylinder *cylinder) +{ + double res; + t_plane base; + + base.point = vec_add(cylinder->center, vec_real_mul(cylinder->rot_axis, cylinder->height / 2)); + base.normal = cylinder->rot_axis; + res = get_intersection_arg_plane(ray, &base); + if (vec_norm(vec_diff(base.point, ray_point(ray, res))) <= cylinder->radius + && vec_scalar_mul(ray->direction, vec_diff(cylinder->center, base.point)) > 0) + return (res); + base.point = vec_diff(cylinder->center, vec_real_mul(cylinder->rot_axis, cylinder->height / 2)); + res = get_intersection_arg_plane(ray, &base); + if (vec_norm(vec_diff(base.point, ray_point(ray, res))) <= cylinder->radius + && vec_scalar_mul(ray->direction, vec_diff(cylinder->center, base.point)) > 0) + return (res); + return (NAN); +} + +t_pair solve_quadratic(double a, double b, double c) +{ + t_pair res; + double det; + + det = b * b - 4 * a * c; + if (det < 0) + { + res.first = NAN; + res.second = NAN; + return (res); + } + det = sqrt(det); + res.first = (-b - det) / (2 * a); + res.second = (-b + det) / (2 * a); + return (res); +} + +double get_intersection_arg_cylinder_around + (const t_ray *ray, const t_cylinder *cylinder) +{ + t_pair args; + t_vec3 v; + t_vec3 u; + t_vec3 intersect; + + v = vec_vec_mul(cylinder->rot_axis, ray->direction); + u = vec_vec_mul(cylinder->rot_axis, vec_diff(ray->start, cylinder->center)); + args = solve_quadratic(vec_scalar_mul(v, v), 2 * vec_scalar_mul(v, u), + vec_scalar_mul(u, u) - cylinder->radius * cylinder->radius); + intersect = ray_point(ray, args.first); + if (fabs(vec_scalar_mul(cylinder->rot_axis, intersect)) < cylinder->height / 2 + && vec_scalar_mul(ray->direction, vec_diff(cylinder->center, intersect)) > 0) + return (args.first); + intersect = ray_point(ray, args.second); + if (fabs(vec_scalar_mul(cylinder->rot_axis, intersect)) < cylinder->height / 2 + && vec_scalar_mul(ray->direction, vec_diff(cylinder->center, intersect)) > 0) + return (args.second); + return (NAN); +} + +double get_intersection_arg_cylinder + (const t_ray *ray, const t_cylinder *cylinder) +{ + double res; + + res = get_intersection_arg_cylinder_base(ray, cylinder); + if (res == NAN) + res = get_intersection_arg_cylinder_around(ray, cylinder); + return (res); +} + double get_intersection_arg_sphere(const t_ray *ray, const t_sphere *sphere) { t_vec3 start; -- 2.30.2