From 6f8ef6a7fe2d394bb22bcafcd8c063fa580e7268 Mon Sep 17 00:00:00 2001 From: TheEdgeOfRage Date: Thu, 14 Mar 2024 01:22:00 +0100 Subject: [PATCH] Optimize octree generation and traversal --- include/nori/octree.h | 2 +- src/accel.cpp | 6 ++--- src/octree.cpp | 52 +++++++++++++++++++++++++------------------ 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/include/nori/octree.h b/include/nori/octree.h index 67ed5fb..f0cab93 100644 --- a/include/nori/octree.h +++ b/include/nori/octree.h @@ -17,7 +17,7 @@ public: explicit Octree(BoundingBox3f *bbox, Mesh *mesh, std::vector triangles) : bbox(bbox), mesh(mesh), triangles(triangles) { children = std::vector(8, nullptr); } - static Octree *build(BoundingBox3f *bbox, Mesh *mesh, std::vector triangles, int recursionDepth = 0); + static Octree *build(BoundingBox3f *bbox, Mesh *mesh, std::vector *triangles, int recursionDepth = 0); uint32_t getIntersectingTriangle(Ray3f &ray, Intersection &its, bool shadowRay); BoundingBox3f getBoundingBox() const { return *bbox; } diff --git a/src/accel.cpp b/src/accel.cpp index d20ca80..7c0e738 100644 --- a/src/accel.cpp +++ b/src/accel.cpp @@ -30,9 +30,9 @@ void Accel::addMesh(Mesh *mesh) { } void Accel::build() { - auto triangles = std::vector(m_mesh->getTriangleCount()); + auto triangles = new std::vector(m_mesh->getTriangleCount()); for (uint32_t idx = 0; idx < m_mesh->getTriangleCount(); ++idx) { - triangles[idx] = idx; + (*triangles)[idx] = idx; } cout << "Building octree" << endl; @@ -40,7 +40,7 @@ void Accel::build() { m_octree = Octree::build(&m_bbox, m_mesh, triangles); auto duration = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start); - std::cout << "Octree build took " << duration.count()/1000.0f << " s" << std::endl; + std::cout << "Octree build took " << duration.count() << "ms" << std::endl; } bool Accel::rayIntersect(const Ray3f &ray_, Intersection &its, bool shadowRay) const { diff --git a/src/octree.cpp b/src/octree.cpp index 11e2177..bf69d2c 100644 --- a/src/octree.cpp +++ b/src/octree.cpp @@ -5,12 +5,9 @@ NORI_NAMESPACE_BEGIN -Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector triangles, int recursionDepth) { - if (triangles.empty()) { - return nullptr; - } - if (triangles.size() <= 20 || recursionDepth > 10 || bbox->getVolume() < 0.001f) { - return new Octree(bbox, mesh, triangles); +Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector *triangles, int recursionDepth) { + if (triangles->size() <= 10 || recursionDepth > 10) { + return new Octree(bbox, mesh, *triangles); } auto m_F = mesh->getIndices(); @@ -33,31 +30,43 @@ Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector tri new BoundingBox3f(bMin + Vector3f(w2, h2, d2), bMin + Vector3f(w, h, d)) }; - std::vector newTriangles[8]; + std::vector *newTriangles[8]; BoundingBox3f triangleBbox; for(int i = 0; i < 8; i++) { - newTriangles[i].reserve(triangles.size() / 8); - for (uint32_t idx : triangles) { + newTriangles[i] = new std::vector(); + newTriangles[i]->reserve(triangles->size() / 8); + for (uint32_t idx : *triangles) { auto a = m_V.col(m_F(0, idx)); auto b = m_V.col(m_F(1, idx)); auto c = m_V.col(m_F(2, idx)); triangleBbox.min = a.cwiseMin(b).cwiseMin(c); triangleBbox.max = a.cwiseMax(b).cwiseMax(c); if (newBboxes[i]->overlaps(triangleBbox)) { - newTriangles[i].push_back(idx); + newTriangles[i]->push_back(idx); } } - newTriangles[i].shrink_to_fit(); + newTriangles[i]->shrink_to_fit(); } if (recursionDepth < 2) { tbb::parallel_for(tbb::blocked_range(0, 8), [&](const tbb::blocked_range &range) { for (size_t i = range.begin(); i != range.end(); ++i) { + if (newTriangles[i]->empty()) { + node->children[i] = nullptr; + continue; + } node->children[i] = build(newBboxes[i], mesh, newTriangles[i], recursionDepth + 1); } }); } else { for (int i = 0; i < 8; i++) { + if (newTriangles[i]->empty()) { + node->children[i] = nullptr; + continue; + } + if (newTriangles[i]->size() > 10) { + node->children[i] = build(newBboxes[i], mesh, newTriangles[i], recursionDepth + 1); + } node->children[i] = build(newBboxes[i], mesh, newTriangles[i], recursionDepth + 1); } } @@ -72,15 +81,15 @@ uint32_t Octree::getIntersectingTriangle(Ray3f &ray, Intersection &its, bool sha uint32_t triangle; if (triangles.empty()) { - std::sort(children.begin(), children.end(), [ray](Octree *a, Octree *b) { - if (a == nullptr) { - return false; - } - if (b == nullptr) { - return true; - } - return a->bbox->distanceTo(ray.o) < b->bbox->distanceTo(ray.o); - }); + // std::sort(children.begin(), children.end(), [ray](Octree *a, Octree *b) { + // if (a == nullptr) { + // return false; + // } + // if (b == nullptr) { + // return true; + // } + // return a->bbox->distanceTo(ray.o) < b->bbox->distanceTo(ray.o); + // }); for (auto child : children) { if (child == nullptr || !child->bbox->rayIntersect(ray)) { continue; @@ -90,8 +99,7 @@ uint32_t Octree::getIntersectingTriangle(Ray3f &ray, Intersection &its, bool sha return triangle; } } - - return closestTriangle; + return -1; } for (auto triangle : triangles) {