Move Box intersection code to DoIntersect

This commit is contained in:
Eryn Wells 2014-08-09 10:08:21 -07:00
parent d0d667d6d2
commit 3846a1aa3a
2 changed files with 57 additions and 51 deletions

View file

@ -51,56 +51,6 @@ Box::SetFar(const Vector3& far)
}
bool
Box::DoesIntersect(const Ray& ray,
TVector& t,
Stats& stats)
const
{
stats.boxIntersectionTests++;
/*
* XXX: For now, I'm assuming that all boxes are parallel to the coordinate
* axes. This is the Kay-Kajiya box intersection algorithm.
*/
//Double t0, t1;
Double tNear = -std::numeric_limits<Double>::infinity();
Double tFar = std::numeric_limits<Double>::infinity();
/*
* From the Ray Tracing book:
*
* For a more efficient algorithm, unwrap the loop, expand the swap of t0
* and t1 into two branches, and change the calculations to multiply by
* the inverse of the ray's direction to avoid divisions. Unwrapping the
* loop allows elimination of comparing t0 adn t1 to tNear and tFar [for
* the X planes], as tNear will always be set to the smaller and tFar the
* larger of t0 and t1.
*
* Initially there was a for loop iterating over each parallel pair of
* planes (X, Y, and Z planes).
*/
if (!IntersectSlab(mNear.x, mFar.x, ray.origin.x, ray.direction.x, tNear, tFar)) {
return false;
}
if (!IntersectSlab(mNear.y, mFar.y, ray.origin.y, ray.direction.y, tNear, tFar)) {
return false;
}
if (!IntersectSlab(mNear.z, mFar.z, ray.origin.z, ray.direction.z, tNear, tFar)) {
return false;
}
/* We have an intersection! */
stats.boxIntersections++;
t.push_back(tNear);
t.push_back(tFar);
return true;
}
bool
Box::point_is_on_surface(const Vector3& p)
const
@ -142,6 +92,44 @@ Box::compute_normal(const Vector3& p)
}
/*
* charles::Box::DoIntersect --
*/
bool
Box::DoIntersect(const basics::Ray& ray,
TVector& t,
Stats& stats)
const
{
stats.boxIntersectionTests++;
/* This is the Kay-Kajiya box intersection algorithm. */
Double tNear = -std::numeric_limits<Double>::infinity();
Double tFar = std::numeric_limits<Double>::infinity();
if (!IntersectSlab(mNear.x, mFar.x, ray.origin.x, ray.direction.x, tNear, tFar)) {
return false;
}
if (!IntersectSlab(mNear.y, mFar.y, ray.origin.y, ray.direction.y, tNear, tFar)) {
return false;
}
if (!IntersectSlab(mNear.z, mFar.z, ray.origin.z, ray.direction.z, tNear, tFar)) {
return false;
}
/* We have an intersection! */
stats.boxIntersections++;
t.push_back(tNear);
t.push_back(tFar);
return true;
}
/*
* charles::Box::IntersectSlab --
*/
inline bool
Box::IntersectSlab(const Double& slabLow,
const Double& slabHigh,
@ -153,6 +141,20 @@ Box::IntersectSlab(const Double& slabLow,
{
Double t0, t1;
/*
* From the Ray Tracing book:
*
* For a more efficient algorithm, unwrap the loop, expand the swap of t0
* and t1 into two branches, and change the calculations to multiply by
* the inverse of the ray's direction to avoid divisions. Unwrapping the
* loop allows elimination of comparing t0 adn t1 to tNear and tFar [for
* the X planes], as tNear will always be set to the smaller and tFar the
* larger of t0 and t1.
*
* Initially there was a for loop iterating over each parallel pair of
* planes (X, Y, and Z planes).
*/
if (NearZero(rayDirectionComponent)) {
/* The ray is parallel to the X axis. */
if (rayOriginComponent < slabLow || rayOriginComponent > slabHigh) {
@ -170,12 +172,13 @@ Box::IntersectSlab(const Double& slabLow,
tNear = t1;
tFar = t0;
}
#endif
#else
if (t0 > t1) {
Double tmp = t0;
t0 = t1;
t1 = tmp;
}
#endif
if (t0 > tNear) {
tNear = t0;
}

View file

@ -28,6 +28,9 @@ struct Box
/** @see charles::Object::Write */
void Write(std::ostream& ost) const;
protected:
bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const;
private:
/**
* Perform the intersection test on a slab, defined by `slabHigh` and