If you intersect many boxes with the same ray, it's faster to use the inverse ray directions to turn divisions into multiplications.
To find which face has been hit, you need to see which dimension wins on MinElem and MaxElem tests in below code.
void Ray::SetFinite (const qVec3& start, const qVec3& end)
{
origin = start;
direction = end - start;
length = direction.Length();
direction /= length;
invDirection = qVec3 (1.0 / direction[0], 1.0 / direction[1], 1.0 / direction[2]);
}
void Ray::SetInfinite (const qVec3& origin, const qVec3& direction)
{
this->origin = origin;
this->direction = direction;
//debugAssert(direction.isUnit());
invDirection = qVec3 (1.0 / direction[0], 1.0 / direction[1], 1.0 / direction[2]);
length = FLT_MAX;
}
// ray - box
void DistanceRayAABoxFrontAndBackface (qScalar &ffd, qScalar& bfd, const Ray& ray, const AABox& box)
{
qVec3 t0 = qVec3(box.minmax[0] - ray.origin).MulPerElem (ray.invDirection);
qVec3 t1 = qVec3(box.minmax[1] - ray.origin).MulPerElem (ray.invDirection);
qVec3 tMin = t0.MinPerElem (t1);
qVec3 tMax = t0.MaxPerElem (t1);
ffd = tMin.MaxElem(); // front face distance (behind origin if inside box)
bfd = tMax.MinElem(); // back face distance
}
bool TestRayAABox (const Ray& ray, const AABox& box)
{
// returns false if ray is parallel with box face
qVec3 t0 = qVec3(box.minmax[0] - ray.origin).MulPerElem (ray.invDirection);
qVec3 t1 = qVec3(box.minmax[1] - ray.origin).MulPerElem (ray.invDirection);
qVec3 tMin = t0.MinPerElem (t1);
qVec3 tMax = t0.MaxPerElem (t1);
qScalar ffd = tMin.MaxElem(); // front face distance (behind origin if inside box)
qScalar bfd = tMax.MinElem(); // back face distance
return (ffd <= bfd) & (bfd >= 0.0f) & (ffd <= ray.length);
}
bool IntersectRayAABox (const Ray& ray, const AABox& box, float& t)
{
qScalar ffd, bfd;
DistanceRayAABoxFrontAndBackface (ffd, bfd, ray, box);
//RenderPoint (3, qVec3(ray.origin + ray.direction * ffd), 1,0,0);
//RenderPoint (3, qVec3(ray.origin + ray.direction * bfd), 0,1,0);
t = (ffd > 0) ? ffd : bfd; // returns always the first intersection with a face
return (ffd <= bfd) & (bfd >= 0.0f) & (ffd <= ray.length);
}