Browse Source

More bounding boxes

Godzil 4 years ago
parent
commit
307c125eba

+ 1 - 1
source/include/cone.h

@@ -30,7 +30,7 @@ public:
     double maxCap;
 
     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)); };
 
     void dumpMe(FILE *fp);

+ 1 - 1
source/include/cylinder.h

@@ -31,7 +31,7 @@ public:
 
     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)); };
 
     void dumpMe(FILE *fp);

+ 1 - 0
source/include/group.h

@@ -38,6 +38,7 @@ public:
     Shape *operator[](const int p) { return this->objectList[p]; }
 
     Intersect intersect(Ray r);
+    BoundingBox getLocalBounds();
     BoundingBox getBounds();
 
     void updateBoundingBox();

+ 1 - 1
source/include/plane.h

@@ -19,7 +19,7 @@ private:
 
 public:
     Plane() : Shape(SHAPE_PLANE) { stats.addPlane(); };
-    BoundingBox getBounds();
+    BoundingBox getLocalBounds();
     bool haveFiniteBounds() { return false; };
 };
 

+ 1 - 0
source/include/shape.h

@@ -59,6 +59,7 @@ public:
     Tuple normalAt(Tuple point);
 
     /* Bounding box points are always world value */
+    virtual BoundingBox getLocalBounds();
     virtual BoundingBox getBounds();
     virtual bool haveFiniteBounds() { return true; };
 

+ 1 - 1
source/include/triangle.h

@@ -24,7 +24,7 @@ public:
 
 public:
     Triangle(Point p1, Point p2, Point p3);
-    BoundingBox getBounds();
+    BoundingBox getLocalBounds();
 
     void dumpMe(FILE *fp);
 

+ 3 - 6
source/shapes/cone.cpp

@@ -122,7 +122,7 @@ Tuple Cone::localNormalAt(Tuple point)
     return Vector(point.x, y, point.z);
 }
 
-BoundingBox Cone::getBounds()
+BoundingBox Cone::getLocalBounds()
 {
     BoundingBox ret;
 
@@ -130,11 +130,8 @@ BoundingBox Cone::getBounds()
     double b = fabs(this->maxCap);
     double limit = (a > b)?a:b;
 
-    ret.min = this->objectToWorld(Point(-limit, this->minCap, -limit));
-    ret.max = this->objectToWorld(Point(limit, this->maxCap, limit));
-
-    ret.min.fixPoint();
-    ret.max.fixPoint();
+    ret | Point(-limit, this->minCap, -limit);
+    ret | Point(limit, this->maxCap, limit);
 
     return ret;
 }

+ 3 - 6
source/shapes/cylinder.cpp

@@ -108,15 +108,12 @@ Tuple Cylinder::localNormalAt(Tuple point)
     return Vector(point.x, 0, point.z);
 }
 
-BoundingBox Cylinder::getBounds()
+BoundingBox Cylinder::getLocalBounds()
 {
     BoundingBox ret;
 
-    ret.min = this->objectToWorld(Point(-1, this->minCap, -1));
-    ret.max = this->objectToWorld(Point(1, this->maxCap, 1));
-
-    ret.min.fixPoint();
-    ret.max.fixPoint();
+    ret | Point(-1, this->minCap, -1);
+    ret | Point(1, this->maxCap, 1);
 
     return ret;
 }

+ 5 - 0
source/shapes/group.cpp

@@ -116,6 +116,11 @@ bool Group::isEmpty()
     return (this->objectCount == 0) && (this->unboxableObjectCount == 0);
 }
 
+BoundingBox Group::getLocalBounds()
+{
+    return this->bounds;
+}
+
 BoundingBox Group::getBounds()
 {
     if (this->bounds.isEmpty()) { this->updateBoundingBox(); }

+ 3 - 6
source/shapes/plane.cpp

@@ -35,15 +35,12 @@ Tuple Plane::localNormalAt(Tuple point)
     return Vector(0, 1, 0);
 }
 
-BoundingBox Plane::getBounds()
+BoundingBox Plane::getLocalBounds()
 {
     BoundingBox ret;
 
-    ret.min = this->objectToWorld(Point(-INFINITY, 0-getEpsilon(), -INFINITY));
-    ret.max = this->objectToWorld(Point(INFINITY, 0+getEpsilon(), INFINITY));
-
-    ret.min.fixPoint();
-    ret.max.fixPoint();
+    ret | Point(-INFINITY, 0-getEpsilon(), -INFINITY);
+    ret | Point(INFINITY, 0+getEpsilon(), INFINITY);
 
     return ret;
 }

+ 15 - 2
source/shapes/shape.cpp

@@ -66,12 +66,25 @@ void Shape::setTransform(Matrix transform)
     this->updateTransform();
 }
 
+BoundingBox Shape::getLocalBounds()
+{
+    return BoundingBox(Point(-1, -1, -1), Point(1,1,1));
+}
+
 BoundingBox Shape::getBounds()
 {
     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;
 }
 

+ 4 - 7
source/shapes/triangle.cpp

@@ -59,16 +59,13 @@ Tuple Triangle::localNormalAt(Tuple point)
     return this->normal;
 }
 
-BoundingBox Triangle::getBounds()
+BoundingBox Triangle::getLocalBounds()
 {
     BoundingBox ret;
 
-    ret | p1;
-    ret | p2;
-    ret | p3;
-
-    ret.min = this->objectToWorld(ret.min);
-    ret.max = this->objectToWorld(ret.max);
+    ret | this->objectToWorld(p1);
+    ret | this->objectToWorld(p2);
+    ret | this->objectToWorld(p3);
 
     return ret;
 }

+ 2 - 2
source/tuple.cpp

@@ -56,7 +56,6 @@ void Tuple::fixPoint()
 
 void Tuple::fixVector()
 {
-
     if (isnan(this->x) || isnan(this->y) || isnan(this->z))
     {
         /* w is probably broken, so fix it */
@@ -66,5 +65,6 @@ void Tuple::fixVector()
 
 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 - 10
tests/boundingbox_test.cpp

@@ -22,7 +22,7 @@
 #include <boundingbox.h>
 #include <gtest/gtest.h>
 
-TEST(BoundingBox, Default_boundingbox_is_not_set)
+TEST(BoundingBoxTest, Creating_an_empty_bounding_box)
 {
     BoundingBox bb;
 
@@ -31,16 +31,16 @@ TEST(BoundingBox, Default_boundingbox_is_not_set)
     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_EQ(bb.min, Point(-1, -1, -1));
-    ASSERT_EQ(bb.max, Point(1, 1, 1));
+    ASSERT_EQ(bb.min, Point(-1, -2, -3));
+    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;
 
@@ -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));
 }
 
-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));
 
@@ -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));
 }
 
-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));
 
@@ -71,7 +83,7 @@ TEST(BoundingBox, A_smaller_bb_should_fit_in_a_bigger)
     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));
 

+ 5 - 2
tests/cone_test.cpp

@@ -163,8 +163,11 @@ TEST(ConeTest, An_uncut_cone_have_infinite_bounds)
 TEST(ConeTest, A_cut_cone_have_finite_bounds)
 {
     Cone t = Cone();
-    t.minCap = -1;
-    t.maxCap = 1;
+    t.minCap = -5;
+    t.maxCap = 3;
+    BoundingBox res = t.getBounds();
 
     ASSERT_TRUE(t.haveFiniteBounds());
+    ASSERT_EQ(res.min, Point(-5, -5, -5));
+    ASSERT_EQ(res.max, Point(5, 3, 5));
 }

+ 4 - 3
tests/cube_test.cpp

@@ -119,12 +119,13 @@ TEST(CubeTest, The_normal_on_the_surface_of_a_cube)
 TEST(CubeTest, The_bounding_box_of_a_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();
 
-    ASSERT_EQ(res.min, b.min);
-    ASSERT_EQ(res.max, b.max);
+    ASSERT_EQ(res.min, boxMin);
+    ASSERT_EQ(res.max, boxMax);
 }
 
 TEST(CubeTest, A_cube_have_finite_bounds)

+ 5 - 3
tests/cylinder_test.cpp

@@ -254,8 +254,10 @@ TEST(CylinderTest, An_uncut_cylinder_have_infinite_bounds)
 TEST(CylinderTest, A_cut_cylinder_have_finite_bounds)
 {
     Cylinder t = Cylinder();
-    t.minCap = -1;
-    t.maxCap = 1;
-
+    t.minCap = -5;
+    t.maxCap = 3;
+    BoundingBox res = t.getBounds();
     ASSERT_TRUE(t.haveFiniteBounds());
+    ASSERT_EQ(res.min, Point(-1, -5, -1));
+    ASSERT_EQ(res.max, Point(1, 3, 1));
 }

+ 4 - 3
tests/sphere_test.cpp

@@ -212,12 +212,13 @@ TEST(SphereTest, A_helper_for_producing_a_sphere_with_a_glassy_material)
 TEST(SphereTest, The_bounding_box_of_a_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();
 
-    ASSERT_EQ(res.min, b.min);
-    ASSERT_EQ(res.max, b.max);
+    ASSERT_EQ(res.min, sphereMin);
+    ASSERT_EQ(res.max, sphereMax);
 }
 
 TEST(SphereTest, A_sphere_have_finite_bounds)

+ 11 - 1
tests/triangle_test.cpp

@@ -88,4 +88,14 @@ TEST(TriangleTest, A_ray_strikes_a_triangle)
 
     ASSERT_EQ(xs.count(), 1);
     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));
+}