Vec3f diff_min = m_min - ray.origin(); // o-a
Vec3f diff_max = m_max - ray.origin();
- float cos_theta;
- float tx_near, tx_far;
+ float cos_theta, temp;
+ float tx_near = -Infinity, tx_far = Infinity,
+ ty_near = -Infinity, ty_far = Infinity,
+ tz_near = -Infinity, tz_far = Infinity;
// clip along x axis
- if(cos_theta = ray.direction().dot(Vec3f(1,0,0)) != 0) // if not parallel...
+ if((cos_theta = ray.direction().dot(Vec3f(1,0,0))) != 0) // if not parallel...
tx_near = diff_min.dot(Vec3f(1,0,0)) / cos_theta;
- if(cos_theta = ray.direction().dot(Vec3f(1,0,0)) != 0)
+ if((cos_theta = ray.direction().dot(Vec3f(1,0,0))) != 0)
tx_far = diff_max.dot(Vec3f(1,0,0)) / cos_theta;
- // clip along y axis
- if(cos_theta = ray.direction().dot(Vec3f(0,1,0)) != 0)
+ // we don't know which is nearer, m_min or m_max, so swap them if neccessary
+ if(tx_near > tx_far) {
+ temp = tx_near;
+ tx_near = tx_far;
+ tx_far = temp;
+ }
+
+ // do the same for y axis
+ if((cos_theta = ray.direction().dot(Vec3f(0,1,0))) != 0)
ty_near = diff_min.dot(Vec3f(0,1,0)) / cos_theta;
- if(cos_theta = ray.direction().dot(Vec3f(0,0,1)) != 0)
+ if((cos_theta = ray.direction().dot(Vec3f(0,1,0))) != 0)
ty_far = diff_max.dot(Vec3f(0,1,0)) / cos_theta;
-
- // ray intersects box iff it intersects projection on xy plane
- // in this case: tx_near <= ty_near <= tx_far <= ty_far
- // or: tx_far <= ty_near <= tx_near <= ty_far
- // or: tx_far <= ty_far <= tx_near <= ty_near
- // or: tx_near <= ty_far <= tx_far <= ty_near
- if(tx_near <= ty_near && tx_far <= ty_near &&
- tx_near <= ty_far && tx_far <= ty_far) {
-
- // clip along z axis
- if (cos_theta = ray.direction().dot(Vec3f(0, 1, 0)) != 0)
- tz_near = diff_min.dot(Vec3f(0, 1, 0)) / cos_theta;
- if (cos_theta = ray.direction().dot(Vec3f(0, 0, 1)) != 0)
- tz_far = diff_max.dot(Vec3f(0, 1, 0)) / cos_theta;
-
- } else {
-
+ if(ty_near > ty_far) {
+ temp = ty_near;
+ ty_near = ty_far;
+ ty_far = temp;
}
- //////////////////////////
+ // ...and for z axis
+ if((cos_theta = ray.direction().dot(Vec3f(0,0,1))) != 0)
+ tz_near = diff_min.dot(Vec3f(0,0,1)) / cos_theta;
+ if((cos_theta = ray.direction().dot(Vec3f(0,0,1))) != 0)
+ tz_far = diff_max.dot(Vec3f(0,0,1)) / cos_theta;
+ if(tz_near > tz_far) {
+ temp = tz_near;
+ tz_near = tz_far;
+ tz_far = temp;
+ }
+ // now the maximum of "near"s is the entry point of the ray, the minimum
+ // of "far"s is the ray's exit point. Visually speaking: the ray must cross
+ // all three "near" planes before it can be inside the box.
+ // Note: If t_near_max > t_far_min, the ray does not intersect the box
+ tnear = fmax(fmax(tx_near, ty_near), tz_near);
+ tfar = fmin(fmin(tx_far, ty_far), tz_far);
}
const Vec3f&