Browse Source

Triangles!!!

Godzil 4 years ago
parent
commit
aded6bb943

+ 1 - 1
source/include/cube.h

@@ -15,7 +15,7 @@
 
 class Cube : public Shape {
 private:
-    void checkAxis(double axeOrigine, double axeDirection, double *axeMin, double *axeMax);
+    void checkAxis(double axeOrigin, double axeDirection, double *axeMin, double *axeMax);
 
     Intersect localIntersect(Ray r);
 

+ 1 - 0
source/include/shape.h

@@ -27,6 +27,7 @@ enum ShapeType
     SHAPE_CYLINDER,
     SHAPE_CONE,
     SHAPE_GROUP,
+    SHAPE_TRIANGLE,
 
 };
 

+ 28 - 0
source/include/triangle.h

@@ -0,0 +1,28 @@
+/*
+ *  DoRayMe - a quick and dirty Raytracer
+ *  Triangle header
+ *
+ *  Created by Manoël Trapier
+ *  Copyright (c) 2020 986-Studio.
+ *
+ */
+#ifndef DORAYME_TRIANGLE_H
+#define DORAYME_TRIANGLE_H
+
+#include <shape.h>
+
+class Triangle : public Shape
+{
+    Intersect localIntersect(Ray r);
+    Tuple localNormalAt(Tuple point);
+
+public:
+    Tuple p1, p2, p3;
+    Tuple e1, e2;
+    Tuple normal;
+
+public:
+    Triangle(Point p1, Point p2, Point p3);
+};
+
+#endif /* DORAYME_TRIANGLE_H */

+ 57 - 0
source/shapes/triangle.cpp

@@ -0,0 +1,57 @@
+/*
+ *  DoRayMe - a quick and dirty Raytracer
+ *  Cone implementation
+ *
+ *  Created by Manoël Trapier
+ *  Copyright (c) 2020 986-Studio.
+ *
+ */
+#include <ray.h>
+#include <shape.h>
+#include <triangle.h>
+#include <math_helper.h>
+
+Triangle::Triangle(Point p1, Point p2, Point p3) : Shape(SHAPE_TRIANGLE), p1(p1), p2(p2), p3(p3)
+{
+    this->e1 = p2 - p1;
+    this->e2 = p3 - p1;
+    this->normal = e2.cross(e1).normalise();
+}
+
+Intersect Triangle::localIntersect(Ray r)
+{
+    Intersect ret;
+
+    Tuple dirCrossE2 = r.direction.cross(this->e2);
+    double determinant = this->e1.dot(dirCrossE2);
+    if (fabs(determinant) < getEpsilon())
+    {
+        return ret;
+    }
+
+    double f = 1.0 / determinant;
+    Tuple p1ToOrigin = r.origin - this->p1;
+    Tuple originCrossE1 = p1ToOrigin.cross(this->e1);
+    double u = f * p1ToOrigin.dot(dirCrossE2);
+    double v = f * r.direction.dot(originCrossE1);
+
+    if ((u < 0) || (u > 1))
+    {
+        return ret;
+    }
+
+    if ((v < 0) || ((u + v) > 1))
+    {
+        return ret;
+    }
+
+    double t = f * this->e2.dot(originCrossE1);
+    ret.add(Intersection(t, this));
+
+    return ret;
+}
+
+Tuple Triangle::localNormalAt(Tuple point)
+{
+    return this->normal;
+}

+ 1 - 1
tests/CMakeLists.txt

@@ -6,7 +6,7 @@ find_package(Threads REQUIRED)
 set(TESTS_SRC math_test.cpp 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 plane_test.cpp pattern_test.cpp cube_test.cpp cylinder_test.cpp cone_test.cpp group_test.cpp
-        boundingbox_test.cpp)
+        boundingbox_test.cpp triangle_test.cpp)
 
 add_executable(testMyRays)
 target_include_directories(testMyRays PUBLIC ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})

+ 91 - 0
tests/triangle_test.cpp

@@ -0,0 +1,91 @@
+/*
+ *  DoRayMe - a quick and dirty Raytracer
+ *  Triangle unit tests
+ *
+ *  Created by Manoël Trapier
+ *  Copyright (c) 2020 986-Studio.
+ *
+ */
+#include <triangle.h>
+#include <math.h>
+#include <gtest/gtest.h>
+
+TEST(TriangleTest, Construcring_a_triangle)
+{
+    Point p1 = Point(0, 1, 0);
+    Point p2 = Point(-1, 0, 0);
+    Point p3 = Point(1, 0, 0);
+
+    Triangle t = Triangle(p1, p2, p3);
+
+    ASSERT_EQ(t.p1, p1);
+    ASSERT_EQ(t.p2, p2);
+    ASSERT_EQ(t.p3, p3);
+    ASSERT_EQ(t.e1, Vector(-1, -1, 0));
+    ASSERT_EQ(t.e2, Vector(1, -1, 0));
+    ASSERT_EQ(t.normal, Vector(0, 0, -1));
+}
+
+TEST(TriangleTest, Finding_the_normal_on_a_triangle)
+{
+    Triangle t = Triangle(Point(0, 1, 0), Point(-1, 0, 0), Point(1, 0, 0));
+
+    Tuple n1 = t.normalAt(Point(0, 0.5, 0));
+    Tuple n2 = t.normalAt(Point(-0.5, 0.75, 0));
+    Tuple n3 = t.normalAt(Point(0.5, 0.25, 0));
+
+    ASSERT_EQ(n1, t.normal);
+    ASSERT_EQ(n2, t.normal);
+    ASSERT_EQ(n3, t.normal);
+}
+
+TEST(TriangleTest, Intersecting_a_ray_parallel_to_the_triangle)
+{
+    Triangle t = Triangle(Point(0, 1, 0), Point(-1, 0, 0), Point(1, 0, 0));
+    Ray r = Ray(Point(0, -1, -2), Vector(0, 1, 0));
+
+    Intersect xs = t.intersect(r);
+
+    ASSERT_EQ(xs.count(), 0);
+}
+
+TEST(TriangleTest, A_ray_miss_the_p1_p3_edge)
+{
+    Triangle t = Triangle(Point(0, 1, 0), Point(-1, 0, 0), Point(1, 0, 0));
+    Ray r = Ray(Point(1, 1, -2), Vector(0, 0, 1));
+
+    Intersect xs = t.intersect(r);
+
+    ASSERT_EQ(xs.count(), 0);
+}
+
+TEST(TriangleTest, A_ray_miss_the_p1_p2_edge)
+{
+    Triangle t = Triangle(Point(0, 1, 0), Point(-1, 0, 0), Point(1, 0, 0));
+    Ray r = Ray(Point(-1, 1, -2), Vector(0, 0, 1));
+
+    Intersect xs = t.intersect(r);
+
+    ASSERT_EQ(xs.count(), 0);
+}
+
+TEST(TriangleTest, A_ray_miss_the_p2_p3_edge)
+{
+    Triangle t = Triangle(Point(0, 1, 0), Point(-1, 0, 0), Point(1, 0, 0));
+    Ray r = Ray(Point(0, -1, -2), Vector(0, 0, 1));
+
+    Intersect xs = t.intersect(r);
+
+    ASSERT_EQ(xs.count(), 0);
+}
+
+TEST(TriangleTest, A_ray_strikes_a_triangle)
+{
+    Triangle t = Triangle(Point(0, 1, 0), Point(-1, 0, 0), Point(1, 0, 0));
+    Ray r = Ray(Point(0, .5, -2), Vector(0, 0, 1));
+
+    Intersect xs = t.intersect(r);
+
+    ASSERT_EQ(xs.count(), 1);
+    EXPECT_EQ(xs[0].t, 2);
+}