diff --git a/README.md b/README.md index 21bd921..bac884f 100644 --- a/README.md +++ b/README.md @@ -28,4 +28,8 @@ From Chapter 07: From Chapter 08: -![Chapter 8 rendering test](output/ch8_test.png) \ No newline at end of file +![Chapter 8 rendering test](output/ch8_test.png) + +From Chapter 09: + +![Chapter 9 rendering test](output/ch9_test.png) \ No newline at end of file diff --git a/output/ch9_test.png b/output/ch9_test.png new file mode 100644 index 0000000..2ffb372 Binary files /dev/null and b/output/ch9_test.png differ diff --git a/source/include/plane.h b/source/include/plane.h new file mode 100644 index 0000000..9fe3cc2 --- /dev/null +++ b/source/include/plane.h @@ -0,0 +1,22 @@ +/* + * DoRayMe - a quick and dirty Raytracer + * Plane header + * + * Created by Manoël Trapier + * Copyright (c) 2020 986-Studio. + * + */ +#ifndef DORAYME_PLANE_H +#define DORAYME_PLANE_H + +class Plane : public Shape +{ +private: + Intersect localIntersect(Ray r); + Tuple localNormalAt(Tuple point); + +public: + Plane() : Shape(SHAPE_PLANE) { }; +}; + +#endif //DORAYME_PLANE_H diff --git a/source/include/shape.h b/source/include/shape.h index 9750dde..11f1f08 100644 --- a/source/include/shape.h +++ b/source/include/shape.h @@ -21,6 +21,7 @@ enum ShapeType { SHAPE_NONE, SHAPE_SPHERE, + SHAPE_PLANE, }; /* Base class for all object that can be presented in the world */ diff --git a/source/shapes/plane.cpp b/source/shapes/plane.cpp new file mode 100644 index 0000000..f6399b7 --- /dev/null +++ b/source/shapes/plane.cpp @@ -0,0 +1,36 @@ +/* + * DoRayMe - a quick and dirty Raytracer + * Plane implementation + * + * Created by Manoël Trapier + * Copyright (c) 2020 986-Studio. + * + */ +#include +#include +#include +#include +#include + +Intersect Plane::localIntersect(Ray r) +{ + double t; + Intersect ret = Intersect(); + + if (fabs(r.direction.y) < getEpsilon()) + { + /* With a direction == 0, the ray can't intersect the plane */ + return ret; + } + + t = -r.origin.y / r.direction.y; + + ret.add(Intersection(t, this)); + + return ret; +} + +Tuple Plane::localNormalAt(Tuple point) +{ + return Vector(0, 1, 0); +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 22a4ad5..d4b55d8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,7 +5,7 @@ find_package(Threads REQUIRED) set(TESTS_SRC tuple_test.cpp colour_test.cpp canvas_test.cpp matrix_test.cpp transformation_test.cpp ray_test.cpp intersect_test.cpp sphere_test.cpp light_test.cpp material_test.cpp world_test.cpp camera_test.cpp - shape_test.cpp) + shape_test.cpp plane_test.cpp) add_executable(testMyRays) target_include_directories(testMyRays PUBLIC ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) @@ -34,6 +34,12 @@ target_include_directories(ch6_test PUBLIC ../source/include) target_sources(ch7_test PRIVATE ch7_test.cpp) target_link_libraries(ch7_test rayonnement) +add_executable(ch9_test) +target_include_directories(ch6_test PUBLIC ../source/include) +target_sources(ch9_test PRIVATE ch9_test.cpp) +target_link_libraries(ch9_test rayonnement) + add_test(NAME Chapter05_Test COMMAND $) add_test(NAME Chapter06_Test COMMAND $) -add_test(NAME Chapter07_Test COMMAND $) \ No newline at end of file +add_test(NAME Chapter07_Test COMMAND $) +add_test(NAME Chapter09_Test COMMAND $) \ No newline at end of file diff --git a/tests/ch9_test.cpp b/tests/ch9_test.cpp new file mode 100644 index 0000000..a1eaa80 --- /dev/null +++ b/tests/ch9_test.cpp @@ -0,0 +1,69 @@ +/* + * DoRayMe - a quick and dirty Raytracer + * Render test for chapter 5 "Put it together". + * + * Created by Manoël Trapier + * Copyright (c) 2020 986-Studio. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + /* First we need to construct the world */ + Plane floor = Plane(); + floor.material.colour = Colour(1, 0.9, 0.9); + floor.material.specular = 0; + + Sphere middle = Sphere(); + middle.setTransform(translation(-0.5, 1, 0.5)); + middle.material.colour = Colour(0.1, 1, 0.5); + middle.material.diffuse = 0.7; + middle.material.specular = 0.3; + + Sphere right = Sphere(); + right.setTransform(translation(1.5, 0.5, -0.5) * scaling(0.5, 0.5, 0.5)); + right.material.colour = Colour(0.5, 1, 0.1); + right.material.diffuse = 0.7; + right.material.specular = 0.3; + + Sphere left = Sphere(); + left.setTransform(translation(-1.5, 0.33, -0.75) * scaling(0.33, 0.33, 0.33)); + left.material.colour = Colour(1, 0.8, 0.1); + left.material.diffuse = 0.7; + left.material.specular = 0.3; + + World w = World(); + + w.addObject(&floor); + w.addObject(&middle); + w.addObject(&left); + w.addObject(&right); + + /* Add light */ + Light light = Light(POINT_LIGHT, Point(-10, 10, -10), Colour(1, 1, 1)); + + w.addLight(&light); + + /* Set the camera */ + Camera camera = Camera(1000, 500, M_PI / 3); + camera.setTransform(viewTransform(Point(0, 1.5, -5), + Point(0, 1, 0), + Vector(0, 1, 0))); + + /* Now render it */ + Canvas image = camera.render(w); + + image.SaveAsPNG("ch9_test.png"); + + + return 0; +} \ No newline at end of file diff --git a/tests/plane_test.cpp b/tests/plane_test.cpp new file mode 100644 index 0000000..be06593 --- /dev/null +++ b/tests/plane_test.cpp @@ -0,0 +1,71 @@ +/* + * DoRayMe - a quick and dirty Raytracer + * Plane unit tests + * + * Created by Manoël Trapier + * Copyright (c) 2020 986-Studio. + * + */ + +#include +#include +#include +#include +#include +#include + +TEST(PlaneTest, The_normal_of_a_plane_is_constant_everywhere) +{ + Plane p = Plane(); + Tuple n1 = p.normalAt(Point(0, 0, 0)); + Tuple n2 = p.normalAt(Point(10, 0, -10)); + Tuple n3 = p.normalAt(Point(-5, 0, 0150)); + + ASSERT_EQ(n1, Vector(0, 1, 0)); + ASSERT_EQ(n2, Vector(0, 1, 0)); + ASSERT_EQ(n3, Vector(0, 1, 0)); +} + +TEST(PlaneTest, Intersect_with_a_ray_parallel_to_the_plane) +{ + Plane p = Plane(); + Ray r = Ray(Point(0, 10, 0), Vector(0, 0, 1)); + + Intersect xs = p.intersect(r); + + ASSERT_EQ(xs.count(), 0); +} + +TEST(PlaneTest, Intersect_with_a_coplanar_ray) +{ + Plane p = Plane(); + Ray r = Ray(Point(0, 0, 0), Vector(0, 0, 1)); + + Intersect xs = p.intersect(r); + + ASSERT_EQ(xs.count(), 0); +} + +TEST(PlaneTest, A_ray_intersecting_a_plane_from_above) +{ + Plane p = Plane(); + Ray r = Ray(Point(0, 1, 0), Vector(0, -1, 0)); + + Intersect xs = p.intersect(r); + + ASSERT_EQ(xs.count(), 1); + ASSERT_EQ(xs[0].t, 1); + ASSERT_EQ(xs[0].object, &p); +} + +TEST(PlaneTest, A_ray_intersecting_a_plane_from_below) +{ + Plane p = Plane(); + Ray r = Ray(Point(0, -1, 0), Vector(0, 1, 0)); + + Intersect xs = p.intersect(r); + + ASSERT_EQ(xs.count(), 1); + ASSERT_EQ(xs[0].t, 1); + ASSERT_EQ(xs[0].object, &p); +} \ No newline at end of file