More bounding boxes
This commit is contained in:
@@ -30,7 +30,7 @@ public:
|
|||||||
double maxCap;
|
double maxCap;
|
||||||
|
|
||||||
Cone() : minCap(-INFINITY), maxCap(INFINITY), isClosed(false), Shape(SHAPE_CONE) { stats.addCone(); };
|
Cone() : minCap(-INFINITY), maxCap(INFINITY), isClosed(false), Shape(SHAPE_CONE) { stats.addCone(); };
|
||||||
BoundingBox getBounds();
|
BoundingBox getLocalBounds();
|
||||||
bool haveFiniteBounds() { return !(isinf(this->minCap) || isinf(this->maxCap)); };
|
bool haveFiniteBounds() { return !(isinf(this->minCap) || isinf(this->maxCap)); };
|
||||||
|
|
||||||
void dumpMe(FILE *fp);
|
void dumpMe(FILE *fp);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
|
|
||||||
Cylinder() : minCap(-INFINITY), maxCap(INFINITY), isClosed(false), Shape(SHAPE_CYLINDER) { stats.addCylinder(); };
|
Cylinder() : minCap(-INFINITY), maxCap(INFINITY), isClosed(false), Shape(SHAPE_CYLINDER) { stats.addCylinder(); };
|
||||||
|
|
||||||
BoundingBox getBounds();
|
BoundingBox getLocalBounds();
|
||||||
bool haveFiniteBounds() { return !(isinf(this->minCap) || isinf(this->maxCap)); };
|
bool haveFiniteBounds() { return !(isinf(this->minCap) || isinf(this->maxCap)); };
|
||||||
|
|
||||||
void dumpMe(FILE *fp);
|
void dumpMe(FILE *fp);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
Shape *operator[](const int p) { return this->objectList[p]; }
|
Shape *operator[](const int p) { return this->objectList[p]; }
|
||||||
|
|
||||||
Intersect intersect(Ray r);
|
Intersect intersect(Ray r);
|
||||||
|
BoundingBox getLocalBounds();
|
||||||
BoundingBox getBounds();
|
BoundingBox getBounds();
|
||||||
|
|
||||||
void updateBoundingBox();
|
void updateBoundingBox();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Plane() : Shape(SHAPE_PLANE) { stats.addPlane(); };
|
Plane() : Shape(SHAPE_PLANE) { stats.addPlane(); };
|
||||||
BoundingBox getBounds();
|
BoundingBox getLocalBounds();
|
||||||
bool haveFiniteBounds() { return false; };
|
bool haveFiniteBounds() { return false; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public:
|
|||||||
Tuple normalAt(Tuple point);
|
Tuple normalAt(Tuple point);
|
||||||
|
|
||||||
/* Bounding box points are always world value */
|
/* Bounding box points are always world value */
|
||||||
|
virtual BoundingBox getLocalBounds();
|
||||||
virtual BoundingBox getBounds();
|
virtual BoundingBox getBounds();
|
||||||
virtual bool haveFiniteBounds() { return true; };
|
virtual bool haveFiniteBounds() { return true; };
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Triangle(Point p1, Point p2, Point p3);
|
Triangle(Point p1, Point p2, Point p3);
|
||||||
BoundingBox getBounds();
|
BoundingBox getLocalBounds();
|
||||||
|
|
||||||
void dumpMe(FILE *fp);
|
void dumpMe(FILE *fp);
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ Tuple Cone::localNormalAt(Tuple point)
|
|||||||
return Vector(point.x, y, point.z);
|
return Vector(point.x, y, point.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox Cone::getBounds()
|
BoundingBox Cone::getLocalBounds()
|
||||||
{
|
{
|
||||||
BoundingBox ret;
|
BoundingBox ret;
|
||||||
|
|
||||||
@@ -130,11 +130,8 @@ BoundingBox Cone::getBounds()
|
|||||||
double b = fabs(this->maxCap);
|
double b = fabs(this->maxCap);
|
||||||
double limit = (a > b)?a:b;
|
double limit = (a > b)?a:b;
|
||||||
|
|
||||||
ret.min = this->objectToWorld(Point(-limit, this->minCap, -limit));
|
ret | Point(-limit, this->minCap, -limit);
|
||||||
ret.max = this->objectToWorld(Point(limit, this->maxCap, limit));
|
ret | Point(limit, this->maxCap, limit);
|
||||||
|
|
||||||
ret.min.fixPoint();
|
|
||||||
ret.max.fixPoint();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,15 +108,12 @@ Tuple Cylinder::localNormalAt(Tuple point)
|
|||||||
return Vector(point.x, 0, point.z);
|
return Vector(point.x, 0, point.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox Cylinder::getBounds()
|
BoundingBox Cylinder::getLocalBounds()
|
||||||
{
|
{
|
||||||
BoundingBox ret;
|
BoundingBox ret;
|
||||||
|
|
||||||
ret.min = this->objectToWorld(Point(-1, this->minCap, -1));
|
ret | Point(-1, this->minCap, -1);
|
||||||
ret.max = this->objectToWorld(Point(1, this->maxCap, 1));
|
ret | Point(1, this->maxCap, 1);
|
||||||
|
|
||||||
ret.min.fixPoint();
|
|
||||||
ret.max.fixPoint();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,11 @@ bool Group::isEmpty()
|
|||||||
return (this->objectCount == 0) && (this->unboxableObjectCount == 0);
|
return (this->objectCount == 0) && (this->unboxableObjectCount == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox Group::getLocalBounds()
|
||||||
|
{
|
||||||
|
return this->bounds;
|
||||||
|
}
|
||||||
|
|
||||||
BoundingBox Group::getBounds()
|
BoundingBox Group::getBounds()
|
||||||
{
|
{
|
||||||
if (this->bounds.isEmpty()) { this->updateBoundingBox(); }
|
if (this->bounds.isEmpty()) { this->updateBoundingBox(); }
|
||||||
|
|||||||
@@ -35,15 +35,12 @@ Tuple Plane::localNormalAt(Tuple point)
|
|||||||
return Vector(0, 1, 0);
|
return Vector(0, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox Plane::getBounds()
|
BoundingBox Plane::getLocalBounds()
|
||||||
{
|
{
|
||||||
BoundingBox ret;
|
BoundingBox ret;
|
||||||
|
|
||||||
ret.min = this->objectToWorld(Point(-INFINITY, 0-getEpsilon(), -INFINITY));
|
ret | Point(-INFINITY, 0-getEpsilon(), -INFINITY);
|
||||||
ret.max = this->objectToWorld(Point(INFINITY, 0+getEpsilon(), INFINITY));
|
ret | Point(INFINITY, 0+getEpsilon(), INFINITY);
|
||||||
|
|
||||||
ret.min.fixPoint();
|
|
||||||
ret.max.fixPoint();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -66,12 +66,25 @@ void Shape::setTransform(Matrix transform)
|
|||||||
this->updateTransform();
|
this->updateTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingBox Shape::getLocalBounds()
|
||||||
|
{
|
||||||
|
return BoundingBox(Point(-1, -1, -1), Point(1,1,1));
|
||||||
|
}
|
||||||
|
|
||||||
BoundingBox Shape::getBounds()
|
BoundingBox Shape::getBounds()
|
||||||
{
|
{
|
||||||
BoundingBox ret;
|
BoundingBox ret;
|
||||||
|
BoundingBox me = this->getLocalBounds();
|
||||||
|
|
||||||
|
ret | this->objectToWorld(Point(me.min.x, me.min.y, me.min.z));
|
||||||
|
ret | this->objectToWorld(Point(me.min.x, me.min.y, me.max.z));
|
||||||
|
ret | this->objectToWorld(Point(me.min.x, me.max.y, me.min.z));
|
||||||
|
ret | this->objectToWorld(Point(me.max.x, me.min.y, me.min.z));
|
||||||
|
ret | this->objectToWorld(Point(me.max.x, me.max.y, me.min.z));
|
||||||
|
ret | this->objectToWorld(Point(me.max.x, me.min.y, me.max.z));
|
||||||
|
ret | this->objectToWorld(Point(me.min.x, me.max.y, me.max.z));
|
||||||
|
ret | this->objectToWorld(Point(me.max.x, me.max.y, me.max.z));
|
||||||
|
|
||||||
ret.min = this->objectToWorld(Point(-1, -1, -1));
|
|
||||||
ret.max = this->objectToWorld(Point(1, 1, 1));
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,16 +59,13 @@ Tuple Triangle::localNormalAt(Tuple point)
|
|||||||
return this->normal;
|
return this->normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox Triangle::getBounds()
|
BoundingBox Triangle::getLocalBounds()
|
||||||
{
|
{
|
||||||
BoundingBox ret;
|
BoundingBox ret;
|
||||||
|
|
||||||
ret | p1;
|
ret | this->objectToWorld(p1);
|
||||||
ret | p2;
|
ret | this->objectToWorld(p2);
|
||||||
ret | p3;
|
ret | this->objectToWorld(p3);
|
||||||
|
|
||||||
ret.min = this->objectToWorld(ret.min);
|
|
||||||
ret.max = this->objectToWorld(ret.max);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ void Tuple::fixPoint()
|
|||||||
|
|
||||||
void Tuple::fixVector()
|
void Tuple::fixVector()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (isnan(this->x) || isnan(this->y) || isnan(this->z))
|
if (isnan(this->x) || isnan(this->y) || isnan(this->z))
|
||||||
{
|
{
|
||||||
/* w is probably broken, so fix it */
|
/* w is probably broken, so fix it */
|
||||||
@@ -66,5 +65,6 @@ void Tuple::fixVector()
|
|||||||
|
|
||||||
bool Tuple::isRepresentable()
|
bool Tuple::isRepresentable()
|
||||||
{
|
{
|
||||||
return !(isnan(this->x) || isnan(this->y) || isnan(this->z));
|
return !(isnan(this->x) || isnan(this->y) || isnan(this->z) ||
|
||||||
|
isinf(this->x) || isinf(this->y) || isinf(this->z));
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <boundingbox.h>
|
#include <boundingbox.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
TEST(BoundingBox, Default_boundingbox_is_not_set)
|
TEST(BoundingBoxTest, Creating_an_empty_bounding_box)
|
||||||
{
|
{
|
||||||
BoundingBox bb;
|
BoundingBox bb;
|
||||||
|
|
||||||
@@ -31,16 +31,16 @@ TEST(BoundingBox, Default_boundingbox_is_not_set)
|
|||||||
ASSERT_EQ(bb.max, Point(-INFINITY, -INFINITY, -INFINITY));
|
ASSERT_EQ(bb.max, Point(-INFINITY, -INFINITY, -INFINITY));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BoundingBox, Bounding_box_can_be_created_with_values)
|
TEST(BoundingBoxTest, Crteating_a_bounding_box_with_volume)
|
||||||
{
|
{
|
||||||
BoundingBox bb = BoundingBox(Point(-1, -1, -1), Point(1, 1, 1));
|
BoundingBox bb = BoundingBox(Point(-1, -2, -3), Point(3, 2, 1));
|
||||||
|
|
||||||
ASSERT_FALSE(bb.isEmpty());
|
ASSERT_FALSE(bb.isEmpty());
|
||||||
ASSERT_EQ(bb.min, Point(-1, -1, -1));
|
ASSERT_EQ(bb.min, Point(-1, -2, -3));
|
||||||
ASSERT_EQ(bb.max, Point(1, 1, 1));
|
ASSERT_EQ(bb.max, Point(3, 2, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BoundingBox, Cating_a_bb_to_an_empty_bb_reset_the_original_one)
|
TEST(BoundingBoxTest, Adding_on_bouding_to_an_empty_bounding_box)
|
||||||
{
|
{
|
||||||
BoundingBox bb;
|
BoundingBox bb;
|
||||||
|
|
||||||
@@ -51,9 +51,9 @@ TEST(BoundingBox, Cating_a_bb_to_an_empty_bb_reset_the_original_one)
|
|||||||
ASSERT_EQ(bb.max, Point(1, 1, 1));
|
ASSERT_EQ(bb.max, Point(1, 1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BoundingBox, Cating_a_bb_to_another_bb_expand_the_original_one_if_needed)
|
TEST(BoundingBoxTest, Adding_boudingbox_to_another)
|
||||||
{
|
{
|
||||||
BoundingBox bb(Point(-1, -1, -1), Point(1, 1, 1));
|
BoundingBox bb(Point(-1, -1, 0), Point(4, 0, 1));
|
||||||
|
|
||||||
bb | BoundingBox(Point(-2, 0, -5), Point(4, 5, 0.5));
|
bb | BoundingBox(Point(-2, 0, -5), Point(4, 5, 0.5));
|
||||||
|
|
||||||
@@ -62,7 +62,19 @@ TEST(BoundingBox, Cating_a_bb_to_another_bb_expand_the_original_one_if_needed)
|
|||||||
ASSERT_EQ(bb.max, Point(4, 5, 1));
|
ASSERT_EQ(bb.max, Point(4, 5, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BoundingBox, A_smaller_bb_should_fit_in_a_bigger)
|
TEST(BoundingBoxTest, Adding_points_to_an_empty_bounding_box)
|
||||||
|
{
|
||||||
|
BoundingBox bb;
|
||||||
|
|
||||||
|
bb | Point(-5, 2, 0);
|
||||||
|
bb | Point(7, 0, -3);
|
||||||
|
|
||||||
|
ASSERT_FALSE(bb.isEmpty());
|
||||||
|
ASSERT_EQ(bb.min, Point(-5, 0, -3));
|
||||||
|
ASSERT_EQ(bb.max, Point(7, 2, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BoundingBoxTest, A_smaller_bb_should_fit_in_a_bigger)
|
||||||
{
|
{
|
||||||
BoundingBox bigBb = BoundingBox(Point(-10, -10, -10), Point(10, 10, 10));
|
BoundingBox bigBb = BoundingBox(Point(-10, -10, -10), Point(10, 10, 10));
|
||||||
|
|
||||||
@@ -71,7 +83,7 @@ TEST(BoundingBox, A_smaller_bb_should_fit_in_a_bigger)
|
|||||||
ASSERT_TRUE(bigBb.fitsIn(smallBb));
|
ASSERT_TRUE(bigBb.fitsIn(smallBb));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BoundingBox, A_big_bb_should_not_fit_in_a_smaller)
|
TEST(BoundingBoxTest, A_big_bb_should_not_fit_in_a_smaller)
|
||||||
{
|
{
|
||||||
BoundingBox bigBb = BoundingBox(Point(-10, -10, -10), Point(10, 10, 10));
|
BoundingBox bigBb = BoundingBox(Point(-10, -10, -10), Point(10, 10, 10));
|
||||||
|
|
||||||
|
|||||||
@@ -163,8 +163,11 @@ TEST(ConeTest, An_uncut_cone_have_infinite_bounds)
|
|||||||
TEST(ConeTest, A_cut_cone_have_finite_bounds)
|
TEST(ConeTest, A_cut_cone_have_finite_bounds)
|
||||||
{
|
{
|
||||||
Cone t = Cone();
|
Cone t = Cone();
|
||||||
t.minCap = -1;
|
t.minCap = -5;
|
||||||
t.maxCap = 1;
|
t.maxCap = 3;
|
||||||
|
BoundingBox res = t.getBounds();
|
||||||
|
|
||||||
ASSERT_TRUE(t.haveFiniteBounds());
|
ASSERT_TRUE(t.haveFiniteBounds());
|
||||||
|
ASSERT_EQ(res.min, Point(-5, -5, -5));
|
||||||
|
ASSERT_EQ(res.max, Point(5, 3, 5));
|
||||||
}
|
}
|
||||||
@@ -119,12 +119,13 @@ TEST(CubeTest, The_normal_on_the_surface_of_a_cube)
|
|||||||
TEST(CubeTest, The_bounding_box_of_a_cube)
|
TEST(CubeTest, The_bounding_box_of_a_cube)
|
||||||
{
|
{
|
||||||
Cube t = Cube();
|
Cube t = Cube();
|
||||||
BoundingBox b = BoundingBox(Point(-1, -1, -1), Point(1, 1, 1));
|
Tuple boxMin = Point(-1, -1, -1);
|
||||||
|
Tuple boxMax = Point(1, 1, 1);
|
||||||
|
|
||||||
BoundingBox res = t.getBounds();
|
BoundingBox res = t.getBounds();
|
||||||
|
|
||||||
ASSERT_EQ(res.min, b.min);
|
ASSERT_EQ(res.min, boxMin);
|
||||||
ASSERT_EQ(res.max, b.max);
|
ASSERT_EQ(res.max, boxMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CubeTest, A_cube_have_finite_bounds)
|
TEST(CubeTest, A_cube_have_finite_bounds)
|
||||||
|
|||||||
@@ -254,8 +254,10 @@ TEST(CylinderTest, An_uncut_cylinder_have_infinite_bounds)
|
|||||||
TEST(CylinderTest, A_cut_cylinder_have_finite_bounds)
|
TEST(CylinderTest, A_cut_cylinder_have_finite_bounds)
|
||||||
{
|
{
|
||||||
Cylinder t = Cylinder();
|
Cylinder t = Cylinder();
|
||||||
t.minCap = -1;
|
t.minCap = -5;
|
||||||
t.maxCap = 1;
|
t.maxCap = 3;
|
||||||
|
BoundingBox res = t.getBounds();
|
||||||
ASSERT_TRUE(t.haveFiniteBounds());
|
ASSERT_TRUE(t.haveFiniteBounds());
|
||||||
|
ASSERT_EQ(res.min, Point(-1, -5, -1));
|
||||||
|
ASSERT_EQ(res.max, Point(1, 3, 1));
|
||||||
}
|
}
|
||||||
@@ -212,12 +212,13 @@ TEST(SphereTest, A_helper_for_producing_a_sphere_with_a_glassy_material)
|
|||||||
TEST(SphereTest, The_bounding_box_of_a_sphere)
|
TEST(SphereTest, The_bounding_box_of_a_sphere)
|
||||||
{
|
{
|
||||||
Sphere t = Sphere();
|
Sphere t = Sphere();
|
||||||
BoundingBox b = BoundingBox(Point(-1, -1, -1), Point(1, 1, 1));
|
Tuple sphereMin = Point(-1, -1, -1);
|
||||||
|
Tuple sphereMax = Point(1, 1, 1);
|
||||||
|
|
||||||
BoundingBox res = t.getBounds();
|
BoundingBox res = t.getBounds();
|
||||||
|
|
||||||
ASSERT_EQ(res.min, b.min);
|
ASSERT_EQ(res.min, sphereMin);
|
||||||
ASSERT_EQ(res.max, b.max);
|
ASSERT_EQ(res.max, sphereMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SphereTest, A_sphere_have_finite_bounds)
|
TEST(SphereTest, A_sphere_have_finite_bounds)
|
||||||
|
|||||||
@@ -88,4 +88,14 @@ TEST(TriangleTest, A_ray_strikes_a_triangle)
|
|||||||
|
|
||||||
ASSERT_EQ(xs.count(), 1);
|
ASSERT_EQ(xs.count(), 1);
|
||||||
EXPECT_EQ(xs[0].t, 2);
|
EXPECT_EQ(xs[0].t, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TriangleTest, A_triangle_has_a_bounding_box)
|
||||||
|
{
|
||||||
|
Triangle t = Triangle(Point(-3, 7, 2), Point(6, 2, -4), Point(2, -1, -1));
|
||||||
|
|
||||||
|
BoundingBox res = t.getBounds();
|
||||||
|
|
||||||
|
ASSERT_EQ(res.min, Point(-3, -1, -4));
|
||||||
|
ASSERT_EQ(res.max, Point(6, 7, 2));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user