hit.c
 1  /* ************************************************************************** */
 2  /*                                                                            */
 3  /*                                                        :::      ::::::::   */
 4  /*   hit.c                                              :+:      :+:    :+:   */
 5  /*                                                    +:+ +:+         +:+     */
 6  /*   By: gychoi <gychoi@student.42seoul.kr>         +#+  +:+       +#+        */
 7  /*                                                +#+#+#+#+#+   +#+           */
 8  /*   Created: 2023/05/25 20:03:37 by gychoi            #+#    #+#             */
 9  /*   Updated: 2023/05/28 20:16:05 by gychoi           ###   ########.fr       */
10  /*                                                                            */
11  /* ************************************************************************** */
12  
13  #include "hit.h"
14  
15  t_bool	hit(t_object *world, t_ray ray, t_hit_record *rec)
16  {
17  	t_bool			hit_anything;
18  	t_hit_record	temp_rec;
19  
20  	temp_rec = *rec;
21  	hit_anything = FALSE;
22  	while (world)
23  	{
24  		if (hit_obj(world, ray, &temp_rec))
25  		{
26  			hit_anything = TRUE;
27  			temp_rec.tmax = temp_rec.t;
28  			*rec = temp_rec;
29  		}
30  		world = world->next;
31  	}
32  	return (hit_anything);
33  }
34  
35  t_bool	hit_obj(t_object *world, t_ray ray, t_hit_record *rec)
36  {
37  	t_bool	hit_result;
38  
39  	hit_result = FALSE;
40  	if (world->type == SP)
41  		hit_result = hit_sphere(world->element, world->albedo, ray, rec);
42  	return (hit_result);
43  }
44  
45  void	set_face_normal(t_ray r, t_hit_record *rec)
46  {
47  	rec->front_face = vdot(r.dir, rec->normal) < 0;
48  	if (!rec->front_face)
49  		rec->normal = vmults(rec->normal, -1);
50  }
51  
52  t_bool	hit_sphere(t_sphere *sp, t_color3 albedo, t_ray ray, t_hit_record *rec)
53  {
54  	t_vec3	cp;
55  	double	a;
56  	double	half_b;
57  	double	c;
58  	double	disc;
59  	double	sqrtd;
60  	double	root;
61  
62  	cp = vsub(ray.origin, sp->center);
63  	a = vlen_pow(ray.dir);
64  	half_b = vdot(cp, ray.dir);
65  	c = vlen_pow(cp) - (sp->radius * sp->radius);
66  	disc = half_b * half_b - a * c;
67  	if (disc < 0)
68  		return (FALSE);
69  	sqrtd = sqrt(disc);
70  	root = (-half_b - sqrtd) / a;
71  	if (root < rec->tmin || rec->tmax < root)
72  	{
73  		root = (-half_b + sqrtd) / a;
74  		if (root < rec->tmin || rec->tmax < root)
75  			return (FALSE);
76  	}
77  	rec->t = root;
78  	rec->p = ray_at(ray, root);
79  	rec->normal = vdivs(vsub(rec->p, sp->center), sp->radius);
80  	rec->albedo = albedo;
81  	set_face_normal(ray, rec);
82  	return (TRUE);
83  }