From ef79acef7364151456f8ebbd94f2600d62e8081b Mon Sep 17 00:00:00 2001 From: Maximilian Giller Date: Thu, 10 Nov 2022 17:31:50 +0100 Subject: [PATCH] Fixes, Changes and Crumbles --- ex1.cpp | 66 ++++++++++++++++++++++-------------------- primitive/sphere.cpp | 27 ++++++++++++----- primitive/triangle.cpp | 52 ++++++++++++++++++++------------- 3 files changed, 86 insertions(+), 59 deletions(-) diff --git a/ex1.cpp b/ex1.cpp index f560890..a85f07b 100644 --- a/ex1.cpp +++ b/ex1.cpp @@ -10,43 +10,45 @@ #include "shader/flatshader.h" -int main() { - // Let's create a simple cornell box scene... - SimpleScene scene; +int main() +{ + // Let's create a simple cornell box scene... + SimpleScene scene; - // Add shaders for the walls - auto red = std::make_shared(Color(1.0f, 0.3f, 0.2f)); - auto white = std::make_shared(Color(1.0f, 1.0f, 1.0f)); - auto blue = std::make_shared(Color(0.2f, 0.3f, 1.0f)); + // Add shaders for the walls + auto red = std::make_shared(Color(1.0f, 0.3f, 0.2f)); + auto white = std::make_shared(Color(1.0f, 1.0f, 1.0f)); + auto blue = std::make_shared(Color(0.2f, 0.3f, 1.0f)); + auto black = std::make_shared(Color(0, 0, 0)); - // Add shaders for the objects - auto green = std::make_shared(Color(0.0f, 1.0f, 0.0f)); - auto purple = std::make_shared(Color(0.5f, 0.2f, 1.0f)); - auto orange = std::make_shared(Color(1.0f, 0.5f, 0.0f)); + // Add shaders for the objects + auto green = std::make_shared(Color(0.0f, 1.0f, 0.0f)); + auto purple = std::make_shared(Color(0.5f, 0.2f, 1.0f)); + auto orange = std::make_shared(Color(1.0f, 0.5f, 0.0f)); - // Set up the cornell box walls - scene.add(std::make_shared(Vector3d(0.0f, 0.0f, +5.0f), Vector3d(0.0f, 0.0f, -1.0f), purple)); - scene.add(std::make_shared(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), purple)); - scene.add(std::make_shared(Vector3d(0.0f, +5.0f, 0.0f), Vector3d(0.0f, -1.0f, 0.0f), white)); - scene.add(std::make_shared(Vector3d(0.0f, -5.0f, 0.0f), Vector3d(0.0f, +1.0f, 0.0f), white)); - scene.add(std::make_shared(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), blue)); - scene.add(std::make_shared(Vector3d(-5.0f, 0.0f, 0.0f), Vector3d(+1.0f, 0.0f, 0.0f), red)); + // Set up the cornell box walls + scene.add(std::make_shared(Vector3d(0.0f, 0.0f, +5.0f), Vector3d(0.0f, 0.0f, -1.0f), black)); + scene.add(std::make_shared(Vector3d(0.0f, 0.0f, -5.0f), Vector3d(0.0f, 0.0f, +1.0f), purple)); + scene.add(std::make_shared(Vector3d(0.0f, +5.0f, 0.0f), Vector3d(0.0f, -1.0f, 0.0f), white)); + scene.add(std::make_shared(Vector3d(0.0f, -5.0f, 0.0f), Vector3d(0.0f, +1.0f, 0.0f), white)); + scene.add(std::make_shared(Vector3d(+5.0f, 0.0f, 0.0f), Vector3d(-1.0f, 0.0f, 0.0f), blue)); + scene.add(std::make_shared(Vector3d(-5.0f, 0.0f, 0.0f), Vector3d(+1.0f, 0.0f, 0.0f), red)); - // Add a sphere - scene.add(std::make_shared(Vector3d(-3.0f, 0.0f, 0.0f), 1.5f, green)); - scene.add(std::make_shared(Vector3d(0.0f, -5.0f, -4.0f), Vector3d(0.0f, -3.0f, 0.0f), - Vector3d(5.0f, -2.0f, -3.0f), orange)); + // Add a sphere + scene.add(std::make_shared(Vector3d(0.0f, 0.0f, 0.0f), 0.5f, green)); + scene.add(std::make_shared(Vector3d(0.5f, 0.0f, 0.0f), Vector3d(-0.5f, 0.0f, 0.0f), + Vector3d(0.0f, 0.0f, 0.5f), orange)); - // Set up the camera - PerspectiveCamera camera; - camera.setFovAngle(70); - camera.setPosition(Vector3d(-2.5f, 2.5f, -12.0f)); - camera.setForwardDirection(Vector3d(0.0f, -0.33f, 1.0f)); - camera.setUpDirection(Vector3d(0.2f, 1.0f, 0.0f)); + // Set up the camera + PerspectiveCamera camera; + camera.setFovAngle(70); + camera.setPosition(Vector3d(0.0f, 4.0f, 0.0f)); + camera.setForwardDirection(Vector3d(0.0f, -1.0f, 0.0f)); + camera.setUpDirection(Vector3d(0.0f, 0.0f, 1.0f)); - // Render the scene - SimpleRenderer renderer; - renderer.renderImage(scene, camera, 512, 512).save("result.png"); + // Render the scene + SimpleRenderer renderer; + renderer.renderImage(scene, camera, 512, 512).save("result.png"); - return 0; + return 0; } diff --git a/primitive/sphere.cpp b/primitive/sphere.cpp index f988c2a..fb952b3 100644 --- a/primitive/sphere.cpp +++ b/primitive/sphere.cpp @@ -12,18 +12,20 @@ Sphere::Sphere(Vector3d const ¢er, float radius, std::shared_ptr con // Primitive functions ///////////////////////////////////////////////////////// bool Sphere::intersect(Ray &ray) const { + auto origin = ray.origin - this->center; + // Determine whether the ray intersects the sphere float A = pow(ray.direction[Vector3d::Dimension::X], 2) + pow(ray.direction[Vector3d::Dimension::Y], 2) + pow(ray.direction[Vector3d::Dimension::Z], 2); float B = 2 * ( - ray.direction[Vector3d::Dimension::X] * ray.origin[Vector3d::Dimension::X] + - ray.direction[Vector3d::Dimension::Y] * ray.origin[Vector3d::Dimension::Y] + - ray.direction[Vector3d::Dimension::Z] * ray.origin[Vector3d::Dimension::Z] + ray.direction[Vector3d::Dimension::X] * origin[Vector3d::Dimension::X] + + ray.direction[Vector3d::Dimension::Y] * origin[Vector3d::Dimension::Y] + + ray.direction[Vector3d::Dimension::Z] * origin[Vector3d::Dimension::Z] ); - float C = pow(ray.origin[Vector3d::Dimension::X], 2) + - pow(ray.origin[Vector3d::Dimension::Y], 2) + - pow(ray.origin[Vector3d::Dimension::Z], 2) - + float C = pow(origin[Vector3d::Dimension::X], 2) + + pow(origin[Vector3d::Dimension::Y], 2) + + pow(origin[Vector3d::Dimension::Z], 2) - pow(this->radius, 2); float t = INFINITY; @@ -43,7 +45,18 @@ bool Sphere::intersect(Ray &ray) const { }())}; float t0 = q / A; float t1 = C / q; - t = std::min(t0, t1); + + if (t0 < 0 && t1 < 0) { + return false; + } + + if (t0 < 0) { + t = t1; + } else if (t1 < 0) { + t = t0; + } else { + t = std::min(t0, t1); + } } // Test whether this is the foremost primitive in front of the camera diff --git a/primitive/triangle.cpp b/primitive/triangle.cpp index 6a39e0f..99838e9 100644 --- a/primitive/triangle.cpp +++ b/primitive/triangle.cpp @@ -3,43 +3,49 @@ // Constructor ///////////////////////////////////////////////////////////////// -Triangle::Triangle(std::shared_ptr const &shader) : Primitive(shader) {} +Triangle::Triangle(std::shared_ptr const &shader) : Primitive(shader) +{} Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, std::shared_ptr const &shader) - : Primitive(shader), vertex{a, b, c} {} + : Primitive(shader), vertex{a, b, c} +{} Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, std::shared_ptr const &shader) - : Primitive(shader), vertex{a, b, c}, normal{na, nb, nc} {} + : Primitive(shader), vertex{a, b, c}, normal{na, nb, nc} +{} Triangle::Triangle(Vector3d const &a, Vector3d const &b, Vector3d const &c, Vector3d const &na, Vector3d const &nb, Vector3d const &nc, Vector2d const &ta, Vector2d const &tb, Vector2d const &tc, std::shared_ptr const &shader) - : Primitive(shader), vertex{a, b, c}, normal{na, nb, nc}, surface{ta, tb, tc} {} + : Primitive(shader), vertex{a, b, c}, normal{na, nb, nc}, surface{ta, tb, tc} +{} // Primitive functions ///////////////////////////////////////////////////////// -bool Triangle::intersect(Ray &ray) const { +bool Triangle::intersect(Ray &ray) const +{ Vector3d edge1 = this->vertex[0] - this->vertex[2]; Vector3d edge2 = this->vertex[1] - this->vertex[2]; - Vector3d normalVector = crossProduct(edge1, edge2); + Vector3d normalVector = normalized(crossProduct(edge1, edge2)); float d = dotProduct(this->vertex[0], normalVector) / length(normalVector); - // catch divided by 0 + // catch divided by 0, in case the triangle plane is not hit float dotDirectionNormalVector = dotProduct(ray.direction, normalVector); - if (dotDirectionNormalVector == 0) { + if (dotDirectionNormalVector == 0) + { return false; } - float t = (d - dotProduct(ray.origin, ray.direction)) / dotDirectionNormalVector; + float t = (d - dotProduct(ray.origin, normalVector)) / dotDirectionNormalVector; Vector3d p = ray.origin + t * ray.direction; // Barycentric Coordinates a,b to determine if intersect with Triangle - float triangleArea = length(normalVector) / 2; + float triangleArea = length(crossProduct(this->vertex[2] - this->vertex[0], this->vertex[1] - this->vertex[0])) / 2; - Vector3d rightSide = crossProduct(this->vertex[2] - this->vertex[1], p - this->vertex[1]); - Vector3d leftSide = crossProduct(this->vertex[0] - this->vertex[2], p - this->vertex[2]); + Vector3d rightSide = crossProduct(p - this->vertex[1], this->vertex[2] - this->vertex[1]); + Vector3d leftSide = crossProduct(p - this->vertex[2], this->vertex[0] - this->vertex[2]); float triangleAreaRightSide = length(rightSide) / 2; float triangleAreaLeftSide = length(leftSide) / 2; @@ -51,20 +57,24 @@ bool Triangle::intersect(Ray &ray) const { // Determine whether the ray intersects the triangle - if(1.0f - a - b >= 1.0f || 0.0f >= a || 0.0f >= b){ + if (a < 0 || a > 1 || b < 0 || a+b > 1) + { return false; } - if(dotProduct(normalVector, leftSide) < 0){ + if (dotProduct(normalVector, leftSide) > 0) + { return false; } - if(dotProduct(normalVector, rightSide) < 0){ + if (dotProduct(normalVector, rightSide) > 0) + { return false; } // Test whether this is the foremost primitive in front of the camera - if (t >= ray.length) { + if (t >= ray.length) + { //it is bigger so further away return false; } @@ -82,10 +92,12 @@ bool Triangle::intersect(Ray &ray) const { // Bounding box //////////////////////////////////////////////////////////////// -float Triangle::minimumBounds(int dimension) const { - return std::min(this->vertex[0][dimension], std::min(this->vertex[1][dimension], this->vertex[2][dimension])); +float Triangle::minimumBounds(int dimension) const +{ + return std::min(this->vertex[0][dimension], std::min(this->vertex[1][dimension], this->vertex[2][dimension])); } -float Triangle::maximumBounds(int dimension) const { - return std::max(this->vertex[0][dimension], std::max(this->vertex[1][dimension], this->vertex[2][dimension])); +float Triangle::maximumBounds(int dimension) const +{ + return std::max(this->vertex[0][dimension], std::max(this->vertex[1][dimension], this->vertex[2][dimension])); }