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