diff --git a/README.md b/README.md index 1821b39..1f32ac8 100644 --- a/README.md +++ b/README.md @@ -54,4 +54,7 @@ From Chapter 13 - Cylinders: ![Chapter 13 rendering test](output/ch13_test.png) Bonus: -![Chapter 13 cone test](output/ch13_cone.png) \ No newline at end of file +![Chapter 13 cone test](output/ch13_cone.png) + +From Chapter 14 - Groups & Bounding boxes +![Chapter 14 rendering test](output/ch14_test.png) \ No newline at end of file diff --git a/output/ch14_test.png b/output/ch14_test.png new file mode 100644 index 0000000..968aadb Binary files /dev/null and b/output/ch14_test.png differ diff --git a/source/include/group.h b/source/include/group.h index f4bd471..c115c6b 100644 --- a/source/include/group.h +++ b/source/include/group.h @@ -37,10 +37,10 @@ public: Shape *operator[](const int p) { return this->objectList[p]; } Intersect intersect(Ray r); - BoundingBox getBounds(); void updateBoundingBox(); + void updateTransform(); Group(); }; diff --git a/source/include/shape.h b/source/include/shape.h index 190a145..6884fb3 100644 --- a/source/include/shape.h +++ b/source/include/shape.h @@ -61,7 +61,8 @@ public: virtual BoundingBox getBounds(); virtual bool haveFiniteBounds() { return true; }; - void updateTransform(); + virtual void updateTransform(); + Tuple worldToObject(Tuple point) { return this->inverseTransform * point; }; Tuple objectToWorld(Tuple point) { return this->transformMatrix * point; }; Tuple normalToWorld(Tuple normalVector); diff --git a/source/shapes/group.cpp b/source/shapes/group.cpp index 81c92f3..aa63e75 100644 --- a/source/shapes/group.cpp +++ b/source/shapes/group.cpp @@ -136,4 +136,32 @@ void Group::updateBoundingBox() } } } +} + +void Group::updateTransform() +{ + int i; + + Shape::updateTransform(); + if (this->objectCount > 0) + { + for (i = 0 ; i < this->objectCount ; i++) + { + this->objectList[i]->updateTransform(); + } + } + + /* We are force to do them all the time */ + if (this->unboxableObjectCount > 0) + { + for(i = 0; i < this->unboxableObjectCount; i++) + { + this->unboxableObjectList[i]->updateTransform(); + } + } + + /* Once the full stack being notified of the changes, let's update the + * bounding box + */ + this->updateBoundingBox(); } \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ffcb1a3..9b1deae 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -85,6 +85,11 @@ target_include_directories(ch13_cone PUBLIC ../source/include) target_sources(ch13_cone PRIVATE ch13_cone.cpp) target_link_libraries(ch13_cone rayonnement) +add_executable(ch14_test) +target_include_directories(ch14_test PUBLIC ../source/include) +target_sources(ch14_test PRIVATE ch14_test.cpp) +target_link_libraries(ch14_test rayonnement) + add_test(NAME Chapter05_Test COMMAND $) add_test(NAME Chapter06_Test COMMAND $) add_test(NAME Chapter07_Test COMMAND $) @@ -96,6 +101,7 @@ add_test(NAME Chapter11_Test COMMAND $) add_test(NAME Chapter12_Test COMMAND $) add_test(NAME Chapter13_Test COMMAND $) add_test(NAME Chapter13_ConeBonus COMMAND $) +add_test(NAME Chapter14_Test COMMAND $) add_test(NAME Test_Rendering COMMAND $) add_test(NAME Hw3Render COMMAND $ ${CMAKE_CURRENT_SOURCE_DIR}/test.hw3scene) add_test(NAME Hw3RenderAllCmds COMMAND $ ${CMAKE_CURRENT_SOURCE_DIR}/test_keys.hw3scene) \ No newline at end of file diff --git a/tests/ch14_test.cpp b/tests/ch14_test.cpp new file mode 100644 index 0000000..a5599ee --- /dev/null +++ b/tests/ch14_test.cpp @@ -0,0 +1,203 @@ +/* + * DoRayMe - a quick and dirty Raytracer + * Render test for reflection in chapter 13. + * + * Created by Manoƫl Trapier + * Copyright (c) 2020 986-Studio. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +Shape *leg() +{ + Group *ret = new Group(); + Sphere *s = new Sphere(); + s->setTransform(translation(0, 0, -1) * scaling(0.25, 0.25, 0.25)); + ret->addObject(s); + Cylinder *cyl = new Cylinder(); + cyl->minCap = 0; + cyl->maxCap = 1; + cyl->isClosed = false; + cyl->setTransform(translation(0, 0, -1) * rotationY(-0.5236) * rotationZ(-1.5708) * scaling(0.25, 1, 0.25)); + + ret->addObject(cyl); + + return ret; +} + +Shape *cap() +{ + Group *ret = new Group(); + + Cone *c = new Cone(); + c->minCap = -1; + c->maxCap = 0; + c->isClosed = false; + c->setTransform(rotationX(-0.7854) * scaling(0.24606, 1.37002, 0.24606)); + ret->addObject(c); + + c = new Cone(); + c->minCap = -1; + c->maxCap = 0; + c->isClosed = false; + c->setTransform(rotationY(1.0472) * rotationX(-0.7854) * scaling(0.24606, 1.37002, 0.24606)); + ret->addObject(c); + + c = new Cone(); + c->minCap = -1; + c->maxCap = 0; + c->isClosed = false; + c->setTransform(rotationY(2.0944) * rotationX(-0.7854) * scaling(0.24606, 1.37002, 0.24606)); + ret->addObject(c); + + c = new Cone(); + c->minCap = -1; + c->maxCap = 0; + c->isClosed = false; + c->setTransform(rotationY(3.1416) * rotationX(-0.7854) * scaling(0.24606, 1.37002, 0.24606)); + ret->addObject(c); + + c = new Cone(); + c->minCap = -1; + c->maxCap = 0; + c->isClosed = false; + c->setTransform(rotationY(4.1888) * rotationX(-0.7854) * scaling(0.24606, 1.37002, 0.24606)); + ret->addObject(c); + + c = new Cone(); + c->minCap = -1; + c->maxCap = 0; + c->isClosed = false; + c->setTransform(rotationY(5.236) * rotationX(-0.7854) * scaling(0.24606, 1.37002, 0.24606)); + ret->addObject(c); + + return ret; +} + +Shape *wacky() +{ + Group *ret = new Group(); + + Shape *s; + + s = leg(); + ret->addObject(s); + + s = leg(); + s->setTransform(rotationY(1.0472)); + ret->addObject(s); + + s = leg(); + s->setTransform(rotationY(2.0944)); + ret->addObject(s); + + s = leg(); + s->setTransform(rotationY(3.1416)); + ret->addObject(s); + + s = leg(); + s->setTransform(rotationY(4.1888)); + ret->addObject(s); + + s = leg(); + s->setTransform(rotationY(5.236)); + ret->addObject(s); + + s = cap(); + s->setTransform(translation(0, 1, 0)); + ret->addObject(s); + + s = cap(); + s->setTransform(rotationX(3.1416) * translation(0, 1, 0)); + ret->addObject(s); + + return ret; +} +int main() +{ + World w = World(); + + /* Add lights */ + Light light1 = Light(POINT_LIGHT, Point(10000, 10000, -10000), Colour(0.25, 0.25, 0.25)); + w.addLight(&light1); + Light light2 = Light(POINT_LIGHT, Point(-10000, 10000, -10000), Colour(0.25, 0.25, 0.25)); + w.addLight(&light2); + Light light3 = Light(POINT_LIGHT, Point(10000, -10000, -10000), Colour(0.25, 0.25, 0.25)); + w.addLight(&light3); + Light light4 = Light(POINT_LIGHT, Point(-10000, -10000, -10000), Colour(0.25, 0.25, 0.25)); + w.addLight(&light4); + + /* ----------------------------- */ + + /* White background */ + Plane p = Plane(); + p.setTransform(translation(0, 0, 100) * rotationX(1.5708)); + p.material.colour = Colour(1, 1, 1); + p.material.ambient = 1; + p.material.diffuse = 0; + p.material.specular = 0; + w.addObject(&p); + + Shape *wa; + + wa = wacky(); + wa->setTransform(translation(-2.8, 0, 0) * rotationX(0.4363) * rotationY(0.1745)); + wa->material.colour = Colour(0.9, 0.2, 0.4); + wa->material.ambient = 0.2; + wa->material.diffuse = 0.8; + wa->material.specular = 0.7; + wa->material.shininess = 20; + w.addObject(wa); + + wa = wacky(); + wa->setTransform(rotationY(0.1745)); + wa->material.colour = Colour(0.2, 0.9, 0.6); + wa->material.ambient = 0.2; + wa->material.diffuse = 0.8; + wa->material.specular = 0.7; + wa->material.shininess = 20; + w.addObject(wa); + + wa = wacky(); + wa->setTransform(translation(2.8, 0, 0) * rotationX(-0.4363) * rotationY(-0.1745)); + wa->material.colour = Colour(0.2, 0.3, 1.0); + wa->material.ambient = 0.2; + wa->material.diffuse = 0.8; + wa->material.specular = 0.7; + wa->material.shininess = 20; + w.addObject(wa); + + /* ----------------------------- */ + + /* Set the camera */ + Camera camera = Camera(1000, 334, 0.9); + camera.setTransform(viewTransform(Point(0, 0, -9), + Point(0, 0, 0), + Vector(0, 1, 0))); + + /* Now render it */ + Canvas image = camera.render(w, 5); + + image.SaveAsPNG("ch14_test.png"); + + return 0; +} \ No newline at end of file