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 if(t[0] < EPSILON) t[0] = EPSILON;
105 if(t[1] < EPSILON) t[1] = EPSILON;
107 hitlist = hit = alloc_hits(2);
109 float c[3] = {0, 0, 0};
110 mat4_xform3(c, o->ob.xform, c);
113 hit->x = ray->x + ray->dx * t[i];
114 hit->y = ray->y + ray->dy * t[i];
115 hit->z = ray->z + ray->dz * t[i];
116 hit->nx = (hit->x - c[0]) / o->sph.rad;
117 hit->ny = (hit->y - c[1]) / o->sph.rad;
118 hit->nz = (hit->z - c[2]) / o->sph.rad;
126 struct hit *ray_cylinder(struct ray *ray, csg_object *o)
128 struct ray locray = *ray;
130 xform_ray(&locray, o->ob.inv_xform);
134 struct hit *ray_plane(struct ray *ray, csg_object *o)
136 float vx, vy, vz, ndotv, ndotr, t;
138 struct ray locray = *ray;
140 xform_ray(&locray, o->ob.inv_xform);
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;
147 if(fabs(ndotv) < EPSILON) return 0;
149 ndotr = o->plane.nx * locray.dx + o->plane.ny * locray.dy + o->plane.nz * locray.dz;
155 hit->x = ray->x + ray->dx * t;
156 hit->y = ray->y + ray->dy * t;
157 hit->z = ray->z + ray->dz * t;
158 hit->nx = o->plane.nx;
159 hit->ny = o->plane.ny;
160 hit->nz = o->plane.nz;
166 struct hit *ray_csg_un(struct ray *ray, csg_object *o)
168 struct hit *hita, *hitb;
170 hita = ray_intersect(ray, o->un.a);
171 hitb = ray_intersect(ray, o->un.b);
173 if(!hita) return hitb;
174 if(!hitb) return hita;
176 if(hita->t < hitb->t) {
184 struct hit *ray_csg_isect(struct ray *ray, csg_object *o)
189 struct hit *ray_csg_sub(struct ray *ray, csg_object *o)
195 void xform_ray(struct ray *ray, float *mat)
199 mat4_copy(m3x3, mat);
202 mat4_xform3(&ray->x, mat, &ray->x);
203 mat4_xform3(&ray->dx, m3x3, &ray->dx);