-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path4_find_intersection.c
136 lines (120 loc) · 4.46 KB
/
4_find_intersection.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 4_find_intersection.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: aschenk <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/12/09 11:59:09 by aschenk #+# #+# */
/* Updated: 2025/03/03 17:03:31 by aschenk ### ########.fr */
/* */
/* ************************************************************************** */
/*
Handles camera ray -> object intersection for planes, spheres, and cylinders
in the parsed object list. Determines the intersection data for the closest
object hit by the ray.
*/
#include "main.h"
// IN FILE:
void find_ix(t_vec3 ray_ori, t_vec3 ray_dir, t_rt *rt, t_ix *ix);
/**
Checks for intersection of a ray with a plane object.
Updates the intersection data in the provided `ixr` struct if an intersection
occurs that is closer than the current closest distance.
@param ray_ori The origin of the ray.
@param ray_dir The normalized direction vector of the ray.
@param obj Pointer to the object data.
@param ix Pointer to the 'intersection data' struct to update.
*/
static void plane_ix(t_vec3 ray_ori, t_vec3 ray_dir, t_obj *obj, t_ix *ix)
{
double t;
if (ray_hit_plane(ray_ori, ray_dir, obj, &t) && t < ix->t_hit)
{
ix->t_hit = t;
ix->hit_obj = obj;
}
}
/**
Checks for intersection of a ray with a sphere object.
Updates the intersection data in the provided `ixr` struct if an intersection
occurs that is closer than the current closest distance.
@param ray_ori The origin of the ray.
@param ray_dir The normalized direction vector of the ray.
@param obj Pointer to the object data.
@param ix Pointer to the 'intersection data' struct to update.
*/
static void sphere_ix(t_vec3 ray_ori, t_vec3 ray_dir, t_obj *obj, t_ix *ix)
{
double t;
if (ray_hit_sphere(ray_ori, ray_dir, obj, &t) && t < ix->t_hit)
{
ix->t_hit = t;
ix->hit_obj = obj;
}
}
/**
Checks for intersection of a ray with a cylinder object, including its caps.
Updates the intersection data in the provided `ixr` struct if an intersection
occurs that is closer than the current closest distance.
@param ray_ori The origin of the ray.
@param ray_dir The normalized direction vector of the ray.
@param obj Pointer to the object data.
@param ix Pointer to the 'intersection data' struct to update.
@note
The function avoids unnecessary checks by skipping the bottom cap test if the
top cap is already marked as hit, and vice versa.
This ensures that only one cap can be marked as hit per cylinder intersection
check, as only one cap can be visible at a time in the rendering.
*/
static void cyl_ix(t_vec3 ray_origin, t_vec3 ray_dir, t_obj *obj, t_ix *ix)
{
double t;
if (ray_hit_cyl(ray_origin, ray_dir, obj, &t) && t < ix->t_hit)
{
ix->t_hit = t;
ix->hit_obj = obj;
ix->cap_hit = NO_HIT;
}
if (ray_hit_cap_top(ray_origin, ray_dir, obj, &t) && t < ix->t_hit)
{
ix->t_hit = t;
ix->hit_obj = obj;
ix->cap_hit = TOP_CAP;
}
if (ray_hit_cap_bottom(ray_origin, ray_dir, obj, &t) && t < ix->t_hit)
{
ix->t_hit = t;
ix->hit_obj = obj;
ix->cap_hit = BOTTOM_CAP;
}
}
/**
Updates the intersection struct with the closest intersection data found in the
scene (object and distance) for a given camera ray.
@param ray_ori The origin of the ray.
@param ray_dir The normalized direction vector of the ray.
@param obj Pointer to the object data.
@param ix Pointer to the 'intersection data' struct to update.
*/
void find_ix(t_vec3 ray_ori, t_vec3 ray_dir, t_rt *rt, t_ix *ix)
{
t_list *current_obj;
t_obj *obj;
current_obj = rt->scene.objs;
ix->hit_obj = NULL;
ix->t_hit = INFINITY;
while (current_obj)
{
obj = (t_obj *)current_obj->content;
if (obj->object_type == PLANE)
plane_ix(ray_ori, ray_dir, obj, ix);
else if (obj->object_type == SPHERE)
sphere_ix(ray_ori, ray_dir, obj, ix);
else if (obj->object_type == CYLINDER)
cyl_ix(ray_ori, ray_dir, obj, ix);
current_obj = current_obj->next;
}
if (ix->hit_obj != NULL)
ix->hit_point = vec3_add(ray_ori, vec3_mult(ray_dir, ix->t_hit));
}