9 /* TODO custom hit allocator */
10 struct hit *alloc_hit(void)
12 struct hit *hit = calloc(sizeof *hit, 1);
14 perror("failed to allocate ray hit node");
20 struct hit *alloc_hits(int n)
26 struct hit *hit = alloc_hit();
34 void free_hit(struct hit *hit)
39 void free_hit_list(struct hit *hit)
42 struct hit *tmp = hit;
48 struct hit *ray_intersect(struct ray *ray, csg_object *o)
52 return ray_sphere(ray, o);
54 return ray_cylinder(ray, o);
56 return ray_plane(ray, o);
58 return ray_csg_un(ray, o);
60 return ray_csg_isect(ray, o);
62 return ray_csg_sub(ray, o);
69 struct hit *ray_sphere(struct ray *ray, csg_object *o)
72 float a, b, c, d, sqrt_d, t[2], sq_rad, tmp;
73 struct hit *hit, *hitlist;
74 struct ray locray = *ray;
76 if(o->sph.rad == 0.0f) {
79 sq_rad = o->sph.rad * o->sph.rad;
81 xform_ray(&locray, o->ob.inv_xform);
83 a = locray.dx * locray.dx + locray.dy * locray.dy + locray.dz * locray.dz;
84 b = 2.0f * (locray.dx * locray.x + locray.dy * locray.y + locray.dz * locray.z);
85 c = (locray.x * locray.x + locray.y * locray.y + locray.z * locray.z) - sq_rad;
87 d = b * b - 4.0f * a * c;
88 if(d < EPSILON) return 0;
91 t[0] = (-b + sqrt_d) / (2.0f * a);
92 t[1] = (-b - sqrt_d) / (2.0f * a);
94 if(t[0] < EPSILON && t[1] < EPSILON) {
104 hitlist = hit = alloc_hits(2);
106 float c[3] = {0, 0, 0};
107 mat4_xform3(c, o->ob.xform, c);
110 hit->x = ray->x + ray->dx * t[i];
111 hit->y = ray->y + ray->dy * t[i];
112 hit->z = ray->z + ray->dz * t[i];
113 hit->nx = (hit->x - c[0]) / o->sph.rad;
114 hit->ny = (hit->y - c[1]) / o->sph.rad;
115 hit->nz = (hit->z - c[2]) / o->sph.rad;
123 struct hit *ray_cylinder(struct ray *ray, csg_object *o)
125 struct ray locray = *ray;
127 xform_ray(&locray, o->ob.inv_xform);
131 struct hit *ray_plane(struct ray *ray, csg_object *o)
133 float vx, vy, vz, ndotv, ndotr, t;
135 struct ray locray = *ray;
137 xform_ray(&locray, o->ob.inv_xform);
139 ndotr = o->plane.nx * locray.dx + o->plane.ny * locray.dy + o->plane.nz * locray.dz;
140 if(fabs(ndotr) < EPSILON) return 0;
142 vx = o->plane.nx * o->plane.d - locray.x;
143 vy = o->plane.ny * o->plane.d - locray.y;
144 vz = o->plane.nz * o->plane.d - locray.z;
146 ndotv = o->plane.nx * vx + o->plane.ny * vy + o->plane.nz * vz;
153 hit->x = ray->x + ray->dx * t;
154 hit->y = ray->y + ray->dy * t;
155 hit->z = ray->z + ray->dz * t;
156 hit->nx = o->plane.nx;
157 hit->ny = o->plane.ny;
158 hit->nz = o->plane.nz;
164 struct hit *ray_csg_un(struct ray *ray, csg_object *o)
166 struct hit *hita, *hitb;
168 hita = ray_intersect(ray, o->un.a);
169 hitb = ray_intersect(ray, o->un.b);
171 if(!hita) return hitb;
172 if(!hitb) return hita;
174 if(hita->t < hitb->t) {
182 struct hit *ray_csg_isect(struct ray *ray, csg_object *o)
187 static struct hit *first(struct hit *hlist)
192 static struct hit *last(struct hit *hlist)
200 struct hit *ray_csg_sub(struct ray *ray, csg_object *o)
202 struct hit *hita, *hitb, *lasthit, tmp;
204 hita = ray_intersect(ray, o->sub.a);
205 hitb = ray_intersect(ray, o->sub.b);
208 if(!hitb) return hita;
210 if(first(hita)->t < first(hitb)->t) {
214 if(first(hita)->t < (lasthit = last(hitb))->t) {
219 free_hit_list(tmp.next);
221 hitb->nx = -hitb->nx;
222 hitb->ny = -hitb->ny;
223 hitb->nz = -hitb->nz;
234 void xform_ray(struct ray *ray, float *mat)
238 mat4_copy(m3x3, mat);
241 mat4_xform3(&ray->x, mat, &ray->x);
242 mat4_xform3(&ray->dx, m3x3, &ray->dx);