From aded6bb9433e99790bb471a5bccdf4d8e2edaefd Mon Sep 17 00:00:00 2001 From: Godzil Date: Tue, 25 Feb 2020 18:42:45 +0000 Subject: [PATCH] Triangles!!! --- source/include/cube.h | 2 +- source/include/shape.h | 1 + source/include/triangle.h | 28 ++++++++++++ source/shapes/triangle.cpp | 57 ++++++++++++++++++++++++ tests/CMakeLists.txt | 2 +- tests/triangle_test.cpp | 91 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 source/include/triangle.h create mode 100644 source/shapes/triangle.cpp create mode 100644 tests/triangle_test.cpp diff --git a/source/include/cube.h b/source/include/cube.h index 03fcfb9..22aa96c 100644 --- a/source/include/cube.h +++ b/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); diff --git a/source/include/shape.h b/source/include/shape.h index cd5b0bb..190a145 100644 --- a/source/include/shape.h +++ b/source/include/shape.h @@ -27,6 +27,7 @@ enum ShapeType SHAPE_CYLINDER, SHAPE_CONE, SHAPE_GROUP, + SHAPE_TRIANGLE, }; diff --git a/source/include/triangle.h b/source/include/triangle.h new file mode 100644 index 0000000..52f0743 --- /dev/null +++ b/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 + +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 */ diff --git a/source/shapes/triangle.cpp b/source/shapes/triangle.cpp new file mode 100644 index 0000000..d8db8eb --- /dev/null +++ b/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 +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9298ad8..ffcb1a3 100644 --- a/tests/CMakeLists.txt +++ b/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}) diff --git a/tests/triangle_test.cpp b/tests/triangle_test.cpp new file mode 100644 index 0000000..37490ba --- /dev/null +++ b/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 +#include +#include + +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); +} \ No newline at end of file