From e8fab659be640584f7233aca23b69b86403234d8 Mon Sep 17 00:00:00 2001 From: Yoel <s73017@beuth-hochschule.de> Date: Fri, 22 Jan 2021 15:56:43 +0100 Subject: [PATCH] Optimized 2.0 --- RayTracer/shape/TriangleMesh.cpp | 93 ++++++++++++++++++++++++++------ RayTracer/shape/TriangleMesh.h | 2 + 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/RayTracer/shape/TriangleMesh.cpp b/RayTracer/shape/TriangleMesh.cpp index 227a7de..bfc19e7 100644 --- a/RayTracer/shape/TriangleMesh.cpp +++ b/RayTracer/shape/TriangleMesh.cpp @@ -3,6 +3,7 @@ #include "TriangleMesh.h" #include <cassert> +#include <limits> #include <sstream> #include <string> @@ -23,7 +24,57 @@ TriangleMesh::TriangleMesh(std::istream& in, hierarch(0, v); } std::optional<cam::Hit> TriangleMesh::intersect(const cam::Ray& r) const { - return std::nullopt; + return intersect(0, r); +} +std::optional<cam::Hit> TriangleMesh::intersect(size_t i, + const cam::Ray& r) const { + std::array<cam::Hit, 3> hits = { + cam::Hit(util::Vec3(0), util::Vec3(0), + std::numeric_limits<float>::infinity(), nullptr), + cam::Hit(util::Vec3(0), util::Vec3(0), + std::numeric_limits<float>::infinity(), nullptr), + cam::Hit(util::Vec3(0), util::Vec3(0), + std::numeric_limits<float>::infinity(), nullptr)}; + // Check left + size_t left_i = hierarchy[i].left; + std::optional<cam::Hit> left_hit = std::nullopt; + if (left_i != -1) left_hit = intersect(left_i, r); + hits[0] = left_hit.value_or(cam::Hit(util::Vec3(0), util::Vec3(0), + std::numeric_limits<float>::infinity(), + nullptr)); + // Check right + size_t right_i = hierarchy[i].right; + std::optional<cam::Hit> right_hit = std::nullopt; + if (right_i != -1) right_hit = intersect(right_i, r); + hits[1] = right_hit.value_or( + cam::Hit(util::Vec3(0), util::Vec3(0), + std::numeric_limits<float>::infinity(), nullptr)); + + std::optional<cam::Hit> temp = std::nullopt; + std::optional<cam::Hit> mid_hit = std::nullopt; + int_fast16_t bound = hierarchy[i].leaves_i + hierarchy[i].leaves_size - 1; + assert(!(hierarchy[i].leaves_i == -1 ^ hierarchy[i].leaves_size == -1)); + for (size_t tri_i = hierarchy[i].leaves_i; tri_i <= bound; tri_i++) { + auto tri = leaves[tri_i]; + std::optional<cam::Hit> temp = tri.intersect(r); + if (temp) { + if (r.in_range(temp->scalar())) { + if (!mid_hit) { + mid_hit = temp; + } else if (mid_hit->scalar() > temp->scalar()) { + mid_hit = temp; + } + } + } + } + hits[2] = mid_hit.value_or(cam::Hit(util::Vec3(0), util::Vec3(0), + std::numeric_limits<float>::infinity(), + nullptr)); + std::sort(hits.begin(), hits.end(), + [](cam::Hit a, cam::Hit b) { return a.scalar() < b.scalar(); }); + if (hits[0].material == nullptr) return std::nullopt; + // for (auto hit : hits) std::cout << hit << std::endl; + return hits[0]; } util::AxisAlignedBoundingBox TriangleMesh::bounds() const { return hierarchy[0].bb; @@ -44,7 +95,6 @@ util::AxisAlignedBoundingBox TriangleMesh::initBB() { void TriangleMesh::hierarch(size_t i, std::vector<std::shared_ptr<Triangle>> v) { - if (v.empty()) return; auto bb_pair = util::splitAABB(hierarchy[i].bb); TriMeshNode left({bb_pair[0], -1, -1, -1, -1}); TriMeshNode right({bb_pair[1], -1, -1, -1, -1}); @@ -57,31 +107,42 @@ void TriangleMesh::hierarch(size_t i, } else if (right.bb.contains(tri_ptr->bounds())) { right_non_leaves.push_back(tri_ptr); } else { + if (!left.bb.partiallyContains(tri_ptr->bounds())) { + std::cout << "Node " << hierarchy[i].bb << std::endl; + std::cout << left.bb << "//////" << tri_ptr->bounds() + << std::endl; + } assert(left.bb.partiallyContains(tri_ptr->bounds())); assert(right.bb.partiallyContains(tri_ptr->bounds())); middle.push_back(tri_ptr); } } - // std::cout << depth << " Left: " << left.shapeList.size() << std::endl; - // std::cout << depth << " Right: " << right.shapeList.size() << std::endl; - // std::cout << depth << " Middle: " << group.shapeList.size() << std::endl; + // std::cout << depth << " Left: " << left.shapeList.size() << + // std::endl; std::cout << depth << " Right: " << right.shapeList.size() + // << std::endl; std::cout << depth << " Middle: " << + // group.shapeList.size() << std::endl; // Handle middle leaves - hierarchy[i].leaves_i = leaves.size(); - hierarchy[i].leaves_size = middle.size(); - for (auto tri_ptr : middle) leaves.push_back(*tri_ptr); - + if (!middle.empty()) { + hierarchy[i].leaves_i = leaves.size(); + hierarchy[i].leaves_size = middle.size(); + for (auto tri_ptr : middle) leaves.push_back(*tri_ptr); + } // Handle left box - hierarchy.push_back(left); - std::cout << i << std::endl; - hierarchy[i].left = hierarchy.size(); + if (!left_non_leaves.empty()) { + hierarchy[i].left = hierarchy.size(); + hierarchy.push_back(left); + } // Handle right box - hierarchy.push_back(right); - hierarchy[i].right = hierarchy.size(); + if (!right_non_leaves.empty()) { + hierarchy[i].right = hierarchy.size(); + hierarchy.push_back(right); + } // Handle recursion - hierarch(hierarchy.size() - 2, left_non_leaves); - hierarch(hierarchy.size() - 1, right_non_leaves); + if (!left_non_leaves.empty()) hierarch(hierarchy[i].left, left_non_leaves); + if (!right_non_leaves.empty()) + hierarch(hierarchy[i].right, right_non_leaves); /*size_t hierarch_min_cluster_size = 1; if (left.shapeList.size() >= hierarch_min_cluster_size) { diff --git a/RayTracer/shape/TriangleMesh.h b/RayTracer/shape/TriangleMesh.h index 9f570d0..355da23 100644 --- a/RayTracer/shape/TriangleMesh.h +++ b/RayTracer/shape/TriangleMesh.h @@ -37,6 +37,8 @@ class TriangleMesh : public Light, public Shape { private: util::AxisAlignedBoundingBox initBB(); + std::optional<cam::Hit> TriangleMesh::intersect(size_t i, + const cam::Ray& r) const; void hierarch(size_t i, const std::vector<std::shared_ptr<Triangle>> v); }; } // namespace shapes -- GitLab