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