diff --git a/source/include/boundingbox.h b/source/include/boundingbox.h new file mode 100644 index 0000000..12d5061 --- /dev/null +++ b/source/include/boundingbox.h @@ -0,0 +1,21 @@ +/* + * DoRayMe - a quick and dirty Raytracer + * Bounding box header + * + * Created by Manoƫl Trapier + * Copyright (c) 2020 986-Studio. + * + */ +#ifndef DORAYME_BOUNDINGBOX_H +#define DORAYME_BOUNDINGBOX_H + +struct BoundingBox +{ + Tuple min; + Tuple max; + + BoundingBox() : min(-0, -0, -0), max(0, 0, 0) { }; + BoundingBox(Tuple min, Tuple max) : min(min), max(max) { }; +}; + +#endif //DORAYME_BOUNDINGBOX_H diff --git a/source/include/cone.h b/source/include/cone.h index 891ce48..b26397c 100644 --- a/source/include/cone.h +++ b/source/include/cone.h @@ -28,6 +28,7 @@ public: double maxCap; Cone() : minCap(-INFINITY), maxCap(INFINITY), isClosed(false), Shape(SHAPE_CONE) {}; + BoundingBox getBounds(); }; #endif /* DORAYME_CONE_H */ diff --git a/source/include/cylinder.h b/source/include/cylinder.h index 7950c13..46c1825 100644 --- a/source/include/cylinder.h +++ b/source/include/cylinder.h @@ -28,6 +28,8 @@ public: double maxCap; Cylinder() : minCap(-INFINITY), maxCap(INFINITY), isClosed(false), Shape(SHAPE_CYLINDER) {}; + + BoundingBox getBounds(); }; #endif //DORAYME_CYLINDER_H diff --git a/source/include/group.h b/source/include/group.h index 30bbeb7..b905773 100644 --- a/source/include/group.h +++ b/source/include/group.h @@ -32,6 +32,8 @@ public: Intersect intersect(Ray r); + BoundingBox getBounds(); + Group(); }; diff --git a/source/include/plane.h b/source/include/plane.h index 9fe3cc2..6ef85ba 100644 --- a/source/include/plane.h +++ b/source/include/plane.h @@ -17,6 +17,7 @@ private: public: Plane() : Shape(SHAPE_PLANE) { }; + BoundingBox getBounds(); }; #endif //DORAYME_PLANE_H diff --git a/source/include/shape.h b/source/include/shape.h index 65b1ee2..616c909 100644 --- a/source/include/shape.h +++ b/source/include/shape.h @@ -16,6 +16,7 @@ class Shape; #include #include #include +#include enum ShapeType { @@ -51,13 +52,15 @@ public: public: Shape(ShapeType = SHAPE_NONE); - Intersect intersect(Ray r); + virtual Intersect intersect(Ray r); Tuple normalAt(Tuple point); - //virtual Bounds getBounds(); + /* Bouding box points are always world value */ + virtual BoundingBox getBounds(); void updateTransform(); Tuple worldToObject(Tuple point) { return this->inverseTransform * point; }; + Tuple objectToWorld(Tuple point) { return this->transformMatrix * point; }; Tuple normalToWorld(Tuple normalVector); void setTransform(Matrix transform); diff --git a/source/include/tuple.h b/source/include/tuple.h index 5b1f337..2b0cbce 100644 --- a/source/include/tuple.h +++ b/source/include/tuple.h @@ -17,6 +17,7 @@ public: double x, y, z, w; public: + Tuple() : x(0), y(0), z(0), w(0.0) {}; Tuple(double x, double y, double z) : x(x), y(y), z(z), w(0.0) {}; Tuple(double x, double y, double z, double w) : x(x), y(y), z(z), w(w) {}; bool isPoint() { return (this->w == 1.0); }; @@ -39,6 +40,7 @@ public: Tuple operator/(const double &b) const { return Tuple(this->x / b, this->y / b, this->z / b, this->w / b); }; + void set(double nX, double nY, double nZ) { this->x = nX; this->y = nY; this->z = nZ; }; double magnitude(); Tuple normalise(); double dot(const Tuple &b); @@ -49,12 +51,14 @@ public: class Point: public Tuple { public: + Point() : Tuple(0, 0, 0, 1.0) {}; Point(double x, double y, double z) : Tuple(x, y, z, 1.0) {}; }; class Vector: public Tuple { public: + Vector() : Tuple(0, 0, 0, 0.0) {}; Vector(double x, double y, double z) : Tuple(x, y, z, 0.0) {}; }; diff --git a/source/shapes/cone.cpp b/source/shapes/cone.cpp index de41cca..1e694f2 100644 --- a/source/shapes/cone.cpp +++ b/source/shapes/cone.cpp @@ -122,3 +122,13 @@ Tuple Cone::localNormalAt(Tuple point) } return Vector(point.x, y, point.z); } + +BoundingBox Cone::getBounds() +{ + BoundingBox ret; + + ret.min = this->objectToWorld(Point(-1, this->minCap, -1)); + ret.max = this->objectToWorld(Point(1, this->maxCap, 1)); + + return ret; +} \ No newline at end of file diff --git a/source/shapes/cylinder.cpp b/source/shapes/cylinder.cpp index f10ddd3..bb70463 100644 --- a/source/shapes/cylinder.cpp +++ b/source/shapes/cylinder.cpp @@ -107,3 +107,13 @@ Tuple Cylinder::localNormalAt(Tuple point) return Vector(point.x, 0, point.z); } + +BoundingBox Cylinder::getBounds() +{ + BoundingBox ret; + + ret.min = this->objectToWorld(Point(-1, this->minCap, -1)); + ret.max = this->objectToWorld(Point(1, this->maxCap, 1)); + + return ret; +} \ No newline at end of file diff --git a/source/shapes/group.cpp b/source/shapes/group.cpp index 7aeff43..11b377f 100644 --- a/source/shapes/group.cpp +++ b/source/shapes/group.cpp @@ -70,4 +70,31 @@ void Group::addObject(Shape *s) bool Group::isEmpty() { return (this->objectCount == 0); +} + +BoundingBox Group::getBounds() +{ + BoundingBox ret; + + if (this->objectCount > 0) + { + ret.min = Point(INFINITY, INFINITY, INFINITY); + ret.max = Point(-INFINITY, -INFINITY, -INFINITY); + + int i; + for(i = 0; i < this->objectCount; i++) + { + BoundingBox obj = this->objectList[i]->getBounds(); + + if (ret.min.x > obj.min.x) { ret.min.x = obj.min.x; } + if (ret.min.y > obj.min.y) { ret.min.y = obj.min.y; } + if (ret.min.z > obj.min.z) { ret.min.z = obj.min.z; } + + if (ret.max.x < obj.max.x) { ret.max.x = obj.max.x; } + if (ret.max.y < obj.max.y) { ret.max.y = obj.max.y; } + if (ret.max.z < obj.max.z) { ret.max.z = obj.max.z; } + } + } + + return ret; } \ No newline at end of file diff --git a/source/shapes/plane.cpp b/source/shapes/plane.cpp index f6399b7..7a47044 100644 --- a/source/shapes/plane.cpp +++ b/source/shapes/plane.cpp @@ -33,4 +33,14 @@ Intersect Plane::localIntersect(Ray r) Tuple Plane::localNormalAt(Tuple point) { return Vector(0, 1, 0); +} + +BoundingBox Plane::getBounds() +{ + BoundingBox ret; + + ret.min = this->objectToWorld(Point(-INFINITY, 0-getEpsilon(), -INFINITY)); + ret.max = this->objectToWorld(Point(INFINITY, 0+getEpsilon(), INFINITY)); + + return ret; } \ No newline at end of file diff --git a/source/shapes/shape.cpp b/source/shapes/shape.cpp index dcf73a0..0732c74 100644 --- a/source/shapes/shape.cpp +++ b/source/shapes/shape.cpp @@ -65,3 +65,12 @@ void Shape::setTransform(Matrix transform) this->localTransformMatrix = transform; this->updateTransform(); } + +BoundingBox Shape::getBounds() +{ + BoundingBox ret; + + ret.min = this->objectToWorld(Point(-1, -1, -1)); + ret.max = this->objectToWorld(Point(1, 1, 1)); + return ret; +} \ No newline at end of file diff --git a/tests/shape_test.cpp b/tests/shape_test.cpp index 29d2011..c306073 100644 --- a/tests/shape_test.cpp +++ b/tests/shape_test.cpp @@ -163,4 +163,15 @@ TEST(TestShape, Finding_the_normal_on_a_child_object) ASSERT_EQ(p, Vector(0.2857, 0.4286, -0.8571)); set_equal_precision(FLT_EPSILON); -} \ No newline at end of file +} + +TEST(TestShape, Test_the_bouding_box_of_the_test_shape) +{ + TestShape t = TestShape(); + BoundingBox b = BoundingBox(Point(-1, -1, -1), Point(1, 1, 1)); + + BoundingBox res = t.getBounds(); + + ASSERT_EQ(res.min, b.min); + ASSERT_EQ(res.max, b.max); +}