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 }