diff --git a/include/nori/octree.h b/include/nori/octree.h index f0cab93..c8111c6 100644 --- a/include/nori/octree.h +++ b/include/nori/octree.h @@ -14,10 +14,11 @@ public: std::vector triangles; // Methods - explicit Octree(BoundingBox3f *bbox, Mesh *mesh, std::vector triangles) : bbox(bbox), mesh(mesh), triangles(triangles) { + explicit Octree(BoundingBox3f *bbox, Mesh *mesh) : bbox(bbox), mesh(mesh) { children = std::vector(8, nullptr); } - static Octree *build(BoundingBox3f *bbox, Mesh *mesh, std::vector *triangles, int recursionDepth = 0); + void setTriangles(std::vector triangles) { this->triangles = triangles; } + 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 7c0e738..1392088 100644 --- a/src/accel.cpp +++ b/src/accel.cpp @@ -30,9 +30,9 @@ void Accel::addMesh(Mesh *mesh) { } void Accel::build() { - auto triangles = new std::vector(m_mesh->getTriangleCount()); + auto triangles = 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; diff --git a/src/octree.cpp b/src/octree.cpp index bf69d2c..e535942 100644 --- a/src/octree.cpp +++ b/src/octree.cpp @@ -5,20 +5,22 @@ NORI_NAMESPACE_BEGIN -Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector *triangles, int recursionDepth) { - if (triangles->size() <= 10 || recursionDepth > 10) { - return new Octree(bbox, mesh, *triangles); +Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector &triangles, int recursionDepth) { + auto node = new Octree(bbox, mesh); + + if (triangles.size() <= 20 || recursionDepth > 6) { + node->setTriangles(triangles); + return node; } auto m_F = mesh->getIndices(); auto m_V = mesh->getVertexPositions(); - - Octree *node = new Octree(bbox, mesh, std::vector()); auto bMin = bbox->min; auto w = bbox->max.x() - bMin.x(); auto h = bbox->max.y() - bMin.y(); auto d = bbox->max.z() - bMin.z(); auto w2 = w / 2.0f, h2 = h / 2.0f, d2 = d / 2.0f; + BoundingBox3f *newBboxes[8] = { new BoundingBox3f(bMin + Vector3f(0, 0, 0), bMin + Vector3f(w2, h2, d2)), new BoundingBox3f(bMin + Vector3f(w2, 0, 0), bMin + Vector3f(w, h2, d2)), @@ -30,44 +32,40 @@ Octree *Octree::build(BoundingBox3f *bbox, Mesh *mesh, std::vector *tr new BoundingBox3f(bMin + Vector3f(w2, h2, d2), bMin + Vector3f(w, h, d)) }; - std::vector *newTriangles[8]; + std::vector childTriangles[8]; BoundingBox3f triangleBbox; for(int i = 0; i < 8; i++) { - newTriangles[i] = new std::vector(); - newTriangles[i]->reserve(triangles->size() / 8); - for (uint32_t idx : *triangles) { + childTriangles[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); + childTriangles[i].push_back(idx); } } - newTriangles[i]->shrink_to_fit(); + childTriangles[i].shrink_to_fit(); } - if (recursionDepth < 2) { + 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()) { + if (childTriangles[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, childTriangles[i], recursionDepth + 1); } }); } else { for (int i = 0; i < 8; i++) { - if (newTriangles[i]->empty()) { + if (childTriangles[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, childTriangles[i], recursionDepth + 1); } } @@ -79,26 +77,43 @@ uint32_t Octree::getIntersectingTriangle(Ray3f &ray, Intersection &its, bool sha float u, v, t; uint32_t closestTriangle = -1; uint32_t triangle; + Octree *tmpChildren[8]; + double distances[8]; + float nearT, farT; + int n = 0; + int i, j, k; 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); - // }); - for (auto child : children) { - if (child == nullptr || !child->bbox->rayIntersect(ray)) { + for (i = 0; i < 8; i++) { + if (children[i] == nullptr) { continue; } - triangle = child->getIntersectingTriangle(ray, its, shadowRay); + if (!children[i]->bbox->rayIntersect(ray, nearT, farT)) { + continue; + } + for (j = 0; j < n; j++) { + if (farT >= distances[j]) { + continue; + } + + for (k = n; k > j; k--) { + distances[k] = distances[k - 1]; + tmpChildren[k] = tmpChildren[k - 1]; + } + break; + } + distances[j] = farT; + tmpChildren[j] = children[i]; + n++; + } + + for (i = 0; i < n; i++) { + triangle = tmpChildren[i]->getIntersectingTriangle(ray, its, shadowRay); if (triangle != (uint32_t) -1) { return triangle; } } + return -1; }