Browse Source

Added planes!

Godzil 4 years ago
parent
commit
9d0db6a635
8 changed files with 212 additions and 3 deletions
  1. 5 1
      README.md
  2. BIN
      output/ch9_test.png
  3. 22 0
      source/include/plane.h
  4. 1 0
      source/include/shape.h
  5. 36 0
      source/shapes/plane.cpp
  6. 8 2
      tests/CMakeLists.txt
  7. 69 0
      tests/ch9_test.cpp
  8. 71 0
      tests/plane_test.cpp

+ 5 - 1
README.md

@@ -28,4 +28,8 @@ From Chapter 07:
 
 From Chapter 08:
 
-![Chapter 8 rendering test](output/ch8_test.png)
+![Chapter 8 rendering test](output/ch8_test.png)
+
+From Chapter 09:
+
+![Chapter 9 rendering test](output/ch9_test.png)

BIN
output/ch9_test.png


+ 22 - 0
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

+ 1 - 0
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 */

+ 36 - 0
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 <tuple.h>
+#include <ray.h>
+#include <shape.h>
+#include <plane.h>
+#include <math_helper.h>
+
+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);
+}

+ 8 - 2
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 $<TARGET_FILE:ch5_test>)
 add_test(NAME Chapter06_Test COMMAND $<TARGET_FILE:ch6_test>)
-add_test(NAME Chapter07_Test COMMAND $<TARGET_FILE:ch7_test>)
+add_test(NAME Chapter07_Test COMMAND $<TARGET_FILE:ch7_test>)
+add_test(NAME Chapter09_Test COMMAND $<TARGET_FILE:ch9_test>)

+ 69 - 0
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 <world.h>
+#include <light.h>
+#include <sphere.h>
+#include <plane.h>
+#include <material.h>
+#include <colour.h>
+#include <canvas.h>
+#include <camera.h>
+#include <transformation.h>
+
+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;
+}

+ 71 - 0
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 <ray.h>
+#include <shape.h>
+#include <plane.h>
+#include <material.h>
+#include <transformation.h>
+#include <gtest/gtest.h>
+
+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);
+}