Optimize octree generation and traversal

This commit is contained in:
Pavle Portic 2024-03-14 01:22:00 +01:00
parent eca59ad82d
commit 6f8ef6a7fe
Signed by: TheEdgeOfRage
GPG Key ID: 66AD4BA646FBC0D2
3 changed files with 34 additions and 26 deletions

View File

@ -17,7 +17,7 @@ public:
explicit Octree(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> triangles) : bbox(bbox), mesh(mesh), triangles(triangles) { explicit Octree(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> triangles) : bbox(bbox), mesh(mesh), triangles(triangles) {
children = std::vector<Octree*>(8, nullptr); children = std::vector<Octree*>(8, nullptr);
} }
static Octree *build(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> triangles, int recursionDepth = 0); static Octree *build(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> *triangles, int recursionDepth = 0);
uint32_t getIntersectingTriangle(Ray3f &ray, Intersection &its, bool shadowRay); uint32_t getIntersectingTriangle(Ray3f &ray, Intersection &its, bool shadowRay);
BoundingBox3f getBoundingBox() const { return *bbox; } BoundingBox3f getBoundingBox() const { return *bbox; }

View File

@ -30,9 +30,9 @@ void Accel::addMesh(Mesh *mesh) {
} }
void Accel::build() { void Accel::build() {
auto triangles = std::vector<uint32_t>(m_mesh->getTriangleCount()); auto triangles = new std::vector<uint32_t>(m_mesh->getTriangleCount());
for (uint32_t idx = 0; idx < m_mesh->getTriangleCount(); ++idx) { for (uint32_t idx = 0; idx < m_mesh->getTriangleCount(); ++idx) {
triangles[idx] = idx; (*triangles)[idx] = idx;
} }
cout << "Building octree" << endl; cout << "Building octree" << endl;
@ -40,7 +40,7 @@ void Accel::build() {
m_octree = Octree::build(&m_bbox, m_mesh, triangles); m_octree = Octree::build(&m_bbox, m_mesh, triangles);
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(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 { bool Accel::rayIntersect(const Ray3f &ray_, Intersection &its, bool shadowRay) const {

View File

@ -5,12 +5,9 @@
NORI_NAMESPACE_BEGIN NORI_NAMESPACE_BEGIN
Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> triangles, int recursionDepth) { Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> *triangles, int recursionDepth) {
if (triangles.empty()) { if (triangles->size() <= 10 || recursionDepth > 10) {
return nullptr; return new Octree(bbox, mesh, *triangles);
}
if (triangles.size() <= 20 || recursionDepth > 10 || bbox->getVolume() < 0.001f) {
return new Octree(bbox, mesh, triangles);
} }
auto m_F = mesh->getIndices(); auto m_F = mesh->getIndices();
@ -33,31 +30,43 @@ Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> tri
new BoundingBox3f(bMin + Vector3f(w2, h2, d2), bMin + Vector3f(w, h, d)) new BoundingBox3f(bMin + Vector3f(w2, h2, d2), bMin + Vector3f(w, h, d))
}; };
std::vector<uint32_t> newTriangles[8]; std::vector<uint32_t> *newTriangles[8];
BoundingBox3f triangleBbox; BoundingBox3f triangleBbox;
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
newTriangles[i].reserve(triangles.size() / 8); newTriangles[i] = new std::vector<uint32_t>();
for (uint32_t idx : triangles) { newTriangles[i]->reserve(triangles->size() / 8);
for (uint32_t idx : *triangles) {
auto a = m_V.col(m_F(0, idx)); auto a = m_V.col(m_F(0, idx));
auto b = m_V.col(m_F(1, idx)); auto b = m_V.col(m_F(1, idx));
auto c = m_V.col(m_F(2, idx)); auto c = m_V.col(m_F(2, idx));
triangleBbox.min = a.cwiseMin(b).cwiseMin(c); triangleBbox.min = a.cwiseMin(b).cwiseMin(c);
triangleBbox.max = a.cwiseMax(b).cwiseMax(c); triangleBbox.max = a.cwiseMax(b).cwiseMax(c);
if (newBboxes[i]->overlaps(triangleBbox)) { 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) { if (recursionDepth < 2) {
tbb::parallel_for(tbb::blocked_range<size_t>(0, 8), [&](const tbb::blocked_range<size_t> &range) { tbb::parallel_for(tbb::blocked_range<size_t>(0, 8), [&](const tbb::blocked_range<size_t> &range) {
for (size_t i = range.begin(); i != range.end(); ++i) { 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); node->children[i] = build(newBboxes[i], mesh, newTriangles[i], recursionDepth + 1);
} }
}); });
} else { } else {
for (int i = 0; i < 8; i++) { 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); 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; uint32_t triangle;
if (triangles.empty()) { if (triangles.empty()) {
std::sort(children.begin(), children.end(), [ray](Octree *a, Octree *b) { // std::sort(children.begin(), children.end(), [ray](Octree *a, Octree *b) {
if (a == nullptr) { // if (a == nullptr) {
return false; // return false;
} // }
if (b == nullptr) { // if (b == nullptr) {
return true; // return true;
} // }
return a->bbox->distanceTo(ray.o) < b->bbox->distanceTo(ray.o); // return a->bbox->distanceTo(ray.o) < b->bbox->distanceTo(ray.o);
}); // });
for (auto child : children) { for (auto child : children) {
if (child == nullptr || !child->bbox->rayIntersect(ray)) { if (child == nullptr || !child->bbox->rayIntersect(ray)) {
continue; continue;
@ -90,8 +99,7 @@ uint32_t Octree::getIntersectingTriangle(Ray3f &ray, Intersection &its, bool sha
return triangle; return triangle;
} }
} }
return -1;
return closestTriangle;
} }
for (auto triangle : triangles) { for (auto triangle : triangles) {