Box objects, parallel to the coordinate axes
This change implements Kay-Kajiya intersection (with slabs) too!
This commit is contained in:
parent
d69d708b31
commit
15db0c42d4
3 changed files with 184 additions and 0 deletions
|
@ -22,6 +22,7 @@ files = [
|
||||||
'light.cc',
|
'light.cc',
|
||||||
'material.cc',
|
'material.cc',
|
||||||
'object.cc',
|
'object.cc',
|
||||||
|
'objectBox.cc',
|
||||||
'object_sphere.cc',
|
'object_sphere.cc',
|
||||||
#'object_plane.cc',
|
#'object_plane.cc',
|
||||||
'reader_yaml.cc',
|
'reader_yaml.cc',
|
||||||
|
|
152
src/objectBox.cc
Normal file
152
src/objectBox.cc
Normal 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
31
src/objectBox.hh
Normal 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 */
|
Loading…
Add table
Add a link
Reference in a new issue