diff --git a/README.md b/README.md index 1f32ac8..00296d3 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,9 @@ Bonus: ![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 +![Chapter 14 rendering test](output/ch14_test.png) + + +Bonus (from the forum): +![Christmas ball](output/christmasball.png) +(about 7min render time using OpenMP on a 2.6Ghz Core i7 3720QM) \ No newline at end of file diff --git a/output/christmasball.png b/output/christmasball.png new file mode 100644 index 0000000..e551692 Binary files /dev/null and b/output/christmasball.png differ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9b1deae..72afea4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -90,6 +90,11 @@ target_include_directories(ch14_test PUBLIC ../source/include) target_sources(ch14_test PRIVATE ch14_test.cpp) target_link_libraries(ch14_test rayonnement) +add_executable(christmasball_render) +target_include_directories(christmasball_render PUBLIC ../source/include) +target_sources(christmasball_render PRIVATE christmasball_render.cpp) +target_link_libraries(christmasball_render rayonnement) + add_test(NAME Chapter05_Test COMMAND $) add_test(NAME Chapter06_Test COMMAND $) add_test(NAME Chapter07_Test COMMAND $) @@ -103,5 +108,6 @@ 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 ChristmasBall_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/christmasball_render.cpp b/tests/christmasball_render.cpp new file mode 100644 index 0000000..2c355c2 --- /dev/null +++ b/tests/christmasball_render.cpp @@ -0,0 +1,244 @@ +/* + * 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 +#include +#include + +double frand(void) +{ + return rand() / ((double) RAND_MAX); +} + +Shape *fir_branch() +{ + Group *ret = new Group(); + double length = 2; + double radius = 0.025; + int segments = 20; + int perSegment = 24; + + Cylinder *branch = new Cylinder(); + branch->minCap = 0; + branch->maxCap = length; + branch->isClosed = true; + branch->setTransform(scaling(radius, 1, radius)); + branch->material.colour = Colour(0.5, 0.35, 0.26); + branch->material.ambient = 0.2; + branch->material.specular = 0; + branch->material.diffuse = 0.6; + ret->addObject(branch); + + double seq_size = length / (segments - 1); + double theta = 2.1 * M_PI / perSegment; + double maxLenght = 20 * radius; + + int y, i; + Triangle *needle; + for(y = 0; y < segments; y++) + { + Group *subGroup = new Group(); + + for(i = 0; i < perSegment; i++) + { + /* Each needle is a triangle */ + /* yBase is the y coordinate of the base of the triangle */ + double yBase = seq_size * y + frand() * seq_size; + /* yTipe is the y coordinate of the tip of the triangle */ + double yTip = yBase - frand() * seq_size; + /* yAndle is the angle (in radians) that the need shold be rotated + * around the branch */ + double yAngle = i * theta + frand() * theta; + /* How long is the needle? */ + double needleLenght = maxLenght / 2 * (1 + frand()); + /* How much is the needle offset fomr the center of the branch? */ + double ofs = radius / 2; + Point p1 = Point(ofs, yBase, ofs); + Point p2 = Point(-ofs, yBase, ofs); + Point p3 = Point(0, yTip, needleLenght); + needle = new Triangle(p1, p2, p3); + needle->setTransform(rotationY(yAngle)); + needle->material.colour = Colour(0.26, 0.36, 0.16); + needle->material.specular = 0.1; + subGroup->addObject(needle); + } + ret->addObject(subGroup); + } + + + return ret; +} + +int main() +{ + World w = World(); + + printf("Preparing scene...\n"); + + /* Add lights */ + Light light1 = Light(POINT_LIGHT, Point(-10, 10, -10), Colour(0.6, 0.6, 0.6)); + w.addLight(&light1); + Sphere light1Sphere = Sphere(); + light1Sphere.dropShadow = false; + light1Sphere.setTransform(translation(-10, 10, -10) * scaling(1.5, 1.5, 1.5)); + light1Sphere.material.colour = Colour(1, 1, 1); + light1Sphere.material.ambient = 0.6; + light1Sphere.material.diffuse = 0; + light1Sphere.material.specular = 0; + w.addObject(&light1Sphere); + + Light light2 = Light(POINT_LIGHT, Point(10, 10, -10), Colour(0.6, 0.6, 0.6)); + w.addLight(&light2); + Sphere light2Sphere = Sphere(); + light2Sphere.dropShadow = false; + light2Sphere.setTransform(translation(10, 10, -10) * scaling(1.5, 1.5, 1.5)); + light2Sphere.material.colour = Colour(1, 1, 1); + light2Sphere.material.ambient = 0.6; + light2Sphere.material.diffuse = 0; + light2Sphere.material.specular = 0; + w.addObject(&light2Sphere); + + Light light3 = Light(POINT_LIGHT, Point(-2, 1, -6), Colour(0.2, 0.1, 0.1)); + w.addLight(&light3); + Sphere light3Sphere = Sphere(); + light3Sphere.dropShadow = false; + light3Sphere.setTransform(translation(-2, 1, -6) * scaling(.4, .4, .4)); + light3Sphere.material.colour = Colour(1, 0.5, 0.5); + light3Sphere.material.ambient = 0.6; + light3Sphere.material.diffuse = 0; + light3Sphere.material.specular = 0; + w.addObject(&light3Sphere); + + Light light4 = Light(POINT_LIGHT, Point(-1, -2, -6), Colour(0.1, 0.2, 0.1)); + w.addLight(&light4); + Sphere light4Sphere = Sphere(); + light4Sphere.dropShadow = false; + light4Sphere.setTransform(translation(-1, -2, -16) * scaling(.4, .4, .4)); + light4Sphere.material.colour = Colour(0.5, 1, 0.5); + light4Sphere.material.ambient = 0.6; + light4Sphere.material.diffuse = 0; + light4Sphere.material.specular = 0; + w.addObject(&light4Sphere); + + Light light5 = Light(POINT_LIGHT, Point(3, -1, -6), Colour(0.2, 0.2, 0.2)); + w.addLight(&light5); + Sphere light5Sphere = Sphere(); + light5Sphere.dropShadow = false; + light5Sphere.setTransform(translation(3, -1, -6) * scaling(0.5, 0.5, 0.5)); + light5Sphere.material.colour = Colour(1, 1, 1); + light5Sphere.material.ambient = 0.6; + light5Sphere.material.diffuse = 0; + light5Sphere.material.specular = 0; + w.addObject(&light5Sphere); + + /* ----------------------------- */ + + Sphere theBall = Sphere(); + theBall.material.colour = Colour(1, 0.25, 0.25); + theBall.material.ambient = 0; + theBall.material.specular = 0; + theBall.material.diffuse = 0.5; + theBall.material.reflective = 0.5; + w.addObject(&theBall); + + Cylinder crown = Cylinder(); + crown.minCap = 0; + crown.maxCap = 1; + crown.setTransform(rotationZ(-0.1) * translation(0, 0.9, 0) * scaling(0.2, 0.3, 0.2)); + crown.material.pattern = new CheckersPattern(Colour(1, 1, 1), Colour(0.94, 0.94, 0.94)); + crown.material.pattern->setTransform(scaling(0.2, 0.2, 0.2)); + crown.material.ambient = 0.02; + crown.material.diffuse = 0.7; + crown.material.specular = 0.8; + crown.material.shininess = 20; + crown.material.reflective = 0.05; + w.addObject(&crown); + + /* ----------------------------- */ + + Shape *s; + s = fir_branch(); + s->setTransform(translation(-1, -1, 0) * rotationY(0.349) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(-1, 1, 0) * rotationY(0.349) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(1, -1, 0) * rotationY(-0.349) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(1, 1, 0) * rotationY(-0.349) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(0.2, -1.25, 0) * rotationY(-0.349) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(-0.2, -1.25, 0) * rotationY(0.349) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(-1.2, 0.1, 0) * rotationY(0.5236) * rotationX(0.087) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(-1.2, -0.35, 0.5) * rotationY(0.5236) * rotationX(-0.1745) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(-0.2, 1.5, 0.25) * rotationY(-0.5236) * rotationX(0.087) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(1.3, 0.4, 0) * rotationY(-0.5236) * rotationX(-0.087) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + s = fir_branch(); + s->setTransform(translation(1.5, -0.5, 0) * rotationY(-0.1754) * rotationX(0.087) * rotationX(-1.5708) * translation(0, -0.5, 0)); + w.addObject(s); + + + /* ----------------------------- */ + + /* Set the camera */ + Camera camera = Camera(40, 30, 1.047); + camera.setTransform(viewTransform(Point(0, 0, -4), + Point(0, 0, 0), + Vector(0, 1, 0))); + + printf("And render!\n"); + /* Now render it */ + Canvas image = camera.render(w, 20); + + image.SaveAsPNG("christmasball.png"); + + return 0; +} \ No newline at end of file