Implement cylinder-ray intersection detection
authorLukas Jiriste <ljiriste@student.42prague.com>
Sat, 23 Nov 2024 10:49:27 +0000 (11:49 +0100)
committerLukas Jiriste <ljiriste@student.42prague.com>
Sat, 23 Nov 2024 11:05:51 +0000 (12:05 +0100)
This commit makes the project compilable.

inc/miniRT.h
src/scene.c

index b836d35ecf6965ae8dad14e626236c7fd7101722..f40ed49dde31a7427bfcbb35729be3697f488621 100644 (file)
@@ -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;
index e7aa5cc6d045d3e4165d037953c679bb1017eda9..196ef43954455bed73b473c4cc3b2577f31795cf 100644 (file)
@@ -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;