+ t = ndotv / ndotr;
+ if(t < EPSILON) {
+ return 0;
+ }
+
+ hit = alloc_hits(1);
+ hit->o = hit->end[0].o = hit->end[1].o = o;
+ hit->end[0].t = t;
+ hit->end[0].x = ray->x + ray->dx * t;
+ hit->end[0].y = ray->y + ray->dy * t;
+ hit->end[0].z = ray->z + ray->dz * t;
+
+ hit->end[0].nx = hit->end[1].nx = o->plane.nx;
+ hit->end[0].ny = hit->end[1].ny = o->plane.ny;
+ hit->end[0].nz = hit->end[1].nz = o->plane.nz;
+
+ hit->end[1].t = FLT_MAX;
+ hit->end[1].x = ray->x + ray->dx * 10000.0f;
+ hit->end[1].y = ray->y + ray->dy * 10000.0f;
+ hit->end[1].z = ray->z + ray->dz * 10000.0f;
+ return hit;
+}
+
+#define BEXT(x) ((x) * 0.49999)
+
+struct hinterv *ray_box(struct ray *ray, csg_object *o)
+{
+ int i, sign[3];
+ float param[2][3];
+ float inv_dir[3];
+ float tmin, tmax, tymin, tymax, tzmin, tzmax;
+ struct hinterv *hit;
+ struct ray locray = *ray;
+ float dirmat[16];
+
+ xform_ray(&locray, o->ob.inv_xform);
+
+ for(i=0; i<3; i++) {
+ float sz = *(&o->box.xsz + i);
+ param[0][i] = -0.5 * sz;
+ param[1][i] = 0.5 * sz;
+
+ inv_dir[i] = 1.0f / *(&locray.dx + i);
+ sign[i] = inv_dir[i] < 0;
+ }
+
+ tmin = (param[sign[0]][0] - locray.x) * inv_dir[0];
+ tmax = (param[1 - sign[0]][0] - locray.x) * inv_dir[0];
+ tymin = (param[sign[1]][1] - locray.y) * inv_dir[1];
+ tymax = (param[1 - sign[1]][1] - locray.y) * inv_dir[1];
+
+ if(tmin > tymax || tymin > tmax) {
+ return 0;
+ }
+ if(tymin > tmin) {
+ tmin = tymin;
+ }
+ if(tymax < tmax) {
+ tmax = tymax;
+ }
+
+ tzmin = (param[sign[2]][2] - locray.z) * inv_dir[2];
+ tzmax = (param[1 - sign[2]][2] - locray.z) * inv_dir[2];
+
+ if(tmin > tzmax || tzmin > tmax) {
+ return 0;
+ }
+ if(tzmin > tmin) {
+ tmin = tzmin;
+ }
+ if(tzmax < tmax) {
+ tmax = tzmax;
+ }
+
+ mat4_copy(dirmat, o->ob.xform);
+ mat4_upper3x3(dirmat);
+
+ hit = alloc_hits(1);
+ hit->o = o;
+ for(i=0; i<2; i++) {
+ float n[3] = {0};
+ float t = i == 0 ? tmin : tmax;
+
+ float x = (locray.x + locray.dx * t) / o->box.xsz;
+ float y = (locray.y + locray.dy * t) / o->box.ysz;
+ float z = (locray.z + locray.dz * t) / o->box.zsz;
+
+ if(fabs(x) > fabs(y) && fabs(x) > fabs(z)) {
+ n[0] = x > 0.0f ? 1.0f : -1.0f;
+ } else if(fabs(y) > fabs(z)) {
+ n[1] = y > 0.0f ? 1.0f : -1.0f;
+ } else {
+ n[2] = z > 0.0f ? 1.0f : -1.0f;
+ }
+
+ hit->end[i].o = o;
+ hit->end[i].t = t;
+ hit->end[i].x = ray->x + ray->dx * t;
+ hit->end[i].y = ray->y + ray->dy * t;
+ hit->end[i].z = ray->z + ray->dz * t;
+ mat4_xform3(&hit->end[i].nx, dirmat, n);