/ miniRT / practice / miniRT_practice / cylinder_surface.c
cylinder_surface.c
 1  /* ************************************************************************** */
 2  /*                                                                            */
 3  /*                                                        :::      ::::::::   */
 4  /*   cylinder_surface.c                                 :+:      :+:    :+:   */
 5  /*                                                    +:+ +:+         +:+     */
 6  /*   By: salee2 <salee2@student.42seoul.kr>         +#+  +:+       +#+        */
 7  /*                                                +#+#+#+#+#+   +#+           */
 8  /*   Created: 2023/05/24 20:21:56 by salee2            #+#    #+#             */
 9  /*   Updated: 2023/05/24 20:21:57 by salee2           ###   ########.fr       */
10  /*                                                                            */
11  /* ************************************************************************** */
12  
13  #include "include/minirt.h"
14  
15  static t_coefficient	get_coefficient(const t_cylinder *cylinder, t_ray *ray)
16  {
17  	t_coefficient	coef;
18  	const t_vec3	w = sub(ray->origin, cylinder->base_center);
19  	const double	v_dot_h = dot(ray->dir, cylinder->normal);
20  	const double	w_dot_h = dot(w, cylinder->normal);
21  
22  	coef.a = mag_sq(ray->dir) - v_dot_h * v_dot_h;
23  	coef.b = dot(ray->dir, w) - v_dot_h * w_dot_h;
24  	coef.c = mag_sq(w) - w_dot_h * w_dot_h - cylinder->radius_sq;
25  	return (coef);
26  }
27  
28  static double	ray_surface_intersection(const t_cylinder *cylinder, \
29  t_ray *ray, t_hit *hit)
30  {
31  	const t_coefficient	coef = get_coefficient(cylinder, ray);
32  	const double		d = coef.b * coef.b - coef.a * coef.c;
33  	double				root;
34  	double				height;
35  	t_vec3				cp;
36  
37  	if (d < 0.0)
38  		return (INVALID_ROOT);
39  	root = (-coef.b - sqrt(d)) / coef.a;
40  	if (root < hit->t_min || hit->t_max < root)
41  	{
42  		root = (-coef.b + sqrt(d)) / coef.a;
43  		if (root < hit->t_min || hit->t_max < root)
44  			return (INVALID_ROOT);
45  	}
46  	cp = sub(ray_at(root, ray), cylinder->base_center);
47  	height = dot(cp, cylinder->normal);
48  	if (height < 0 || cylinder->height < height)
49  		return (INVALID_ROOT);
50  	return (root);
51  }
52  
53  t_bool	intersect_cylinder_surface(t_object *object, t_ray *ray, t_hit *hit)
54  {
55  	const t_cylinder	*cylinder = object->element;
56  	const double		root = ray_surface_intersection(cylinder, ray, hit);
57  	t_vec3				cp;
58  
59  	if (root == INVALID_ROOT)
60  		return (FALSE);
61  	hit->t = root;
62  	hit->t_max = hit->t;
63  	hit->point = ray_at(hit->t, ray);
64  	cp = sub(hit->point, cylinder->base_center);
65  	hit->normal = norm(sub(cp, scl_mul(dot(cp, cylinder->normal), \
66  	cylinder->normal)));
67  	if (dot(ray->dir, hit->normal) > 0.0)
68  		hit->normal = scl_mul(-1, hit->normal);
69  	hit->albedo = object->albedo;
70  	return (TRUE);
71  }