Box objects, parallel to the coordinate axes

This change implements Kay-Kajiya intersection (with slabs) too!
This commit is contained in:
Eryn Wells 2014-07-22 20:46:47 -07:00
parent d69d708b31
commit 15db0c42d4
3 changed files with 184 additions and 0 deletions

View file

@ -22,6 +22,7 @@ files = [
'light.cc',
'material.cc',
'object.cc',
'objectBox.cc',
'object_sphere.cc',
#'object_plane.cc',
'reader_yaml.cc',

152
src/objectBox.cc Normal file
View file

@ -0,0 +1,152 @@
/* objectBox.cc
* vim: set tw=80:
* Eryn Wells <eryn@erynwells.me>
*/
#include <limits>
#include "objectBox.hh"
namespace charles {
Box::Box()
/* A unit box centered on the origin. */
: Box(Vector3(-0.5, -0.5, -0.5), Vector3(0.5, 0.5, 0.5))
{ }
Box::Box(const Vector3& near, const Vector3& far)
: Object(),
mNear(near),
mFar(far)
{ }
bool
Box::DoesIntersect(const Ray& ray,
TVector& t)
const
{
/*
* 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).
*/
/* Unrolling the loop, so we start with the X planes... */
if (ray.direction.x == 0.0) {
/* The ray is parallel to the X axis. */
if (ray.origin.x < mNear.x || ray.origin.x > mFar.x) {
/* The ray's origin is not between the slabs, so no intersection. */
return false;
}
} else {
Double invX = 1.0 / ray.direction.x;
t0 = (mNear.x - ray.origin.x) * invX;
t1 = (mFar.x - ray.origin.x) * invX;
if (t0 > t1) {
tNear = t1;
tFar = t0;
} else {
tNear = t0;
tFar = t1;
}
if (tNear > tFar) {
/* Box is missed. */
return false;
}
if (tFar < 0.0) {
/* Box is behind the ray. */
return false;
}
}
/* Now the Y planes. */
if (ray.direction.y == 0.0) {
/* The ray is parallel to the Y axis. */
if (ray.origin.y < mNear.y || ray.origin.y > mFar.y) {
/* The ray's origin is not between the slabs, so no intersection. */
return false;
}
} else {
/* The ray isn't parallel, so calculate the intersection points. */
Double invY = 1.0 / ray.direction.y;
t0 = (mNear.y - ray.origin.y) * invY;
t1 = (mFar.y - ray.origin.y) * invY;
if (t0 > t1) {
tNear = t1;
tFar = t0;
} else {
tNear = t0;
tFar = t1;
}
if (tNear > tFar) {
/* Box is missed. */
return false;
}
if (tFar < 0.0) {
/* Box is behind the ray. */
return false;
}
}
/* Finally, the Z planes. */
if (ray.direction.z == 0.0) {
/* The ray is parallel to the Z axis. */
if (ray.origin.z < mNear.z || ray.origin.z > mFar.z) {
/* The ray's origin is not between the slabs, so no intersection. */
return false;
}
} else {
Double invZ = 1.0 / ray.direction.z;
t0 = (mNear.z - ray.origin.z) * invZ;
t1 = (mFar.z - ray.origin.z) * invZ;
if (t0 > t1) {
tNear = t1;
tFar = t0;
} else {
tNear = t0;
tFar = t1;
}
if (tNear > tFar) {
/* Box is missed. */
return false;
}
if (tFar < 0.0) {
/* Box is behind the ray. */
return false;
}
}
/* We have an intersection! */
t.push_back(t0);
t.push_back(t1);
return true;
}
} /* namespace charles */

31
src/objectBox.hh Normal file
View file

@ -0,0 +1,31 @@
/* objectBox.hh
* vim: set tw=80:
* Eryn Wells <eryn@erynwells.me>
*/
#include "basics.h"
#include "object.h"
#include "types.hh"
namespace charles {
struct Box
: public Object
{
Box();
Box(const Vector3& near, const Vector3& far);
bool DoesIntersect(const Ray& ray, TVector& t) const;
bool point_is_on_surface(const Vector3 &p) const;
Vector3 compute_normal(const Vector3 &p) const;
private:
/** The near, lower left corner. */
Vector3 mNear;
/** The far, upper right corner. */
Vector3 mFar;
};
} /* namespace charles */