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 bool
Box::point_is_on_surface(const Vector3& p) Box::point_is_on_surface(const Vector3& p)
const 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 inline bool
Box::IntersectSlab(const Double& slabLow, Box::IntersectSlab(const Double& slabLow,
const Double& slabHigh, const Double& slabHigh,
@ -153,6 +141,20 @@ Box::IntersectSlab(const Double& slabLow,
{ {
Double t0, t1; 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)) { if (NearZero(rayDirectionComponent)) {
/* The ray is parallel to the X axis. */ /* The ray is parallel to the X axis. */
if (rayOriginComponent < slabLow || rayOriginComponent > slabHigh) { if (rayOriginComponent < slabLow || rayOriginComponent > slabHigh) {
@ -170,12 +172,13 @@ Box::IntersectSlab(const Double& slabLow,
tNear = t1; tNear = t1;
tFar = t0; tFar = t0;
} }
#endif #else
if (t0 > t1) { if (t0 > t1) {
Double tmp = t0; Double tmp = t0;
t0 = t1; t0 = t1;
t1 = tmp; t1 = tmp;
} }
#endif
if (t0 > tNear) { if (t0 > tNear) {
tNear = t0; tNear = t0;
} }

View file

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