Optimize octree traversal
This commit is contained in:
parent
6f8ef6a7fe
commit
f5ec79e841
|
@ -14,10 +14,11 @@ public:
|
||||||
std::vector<uint32_t> triangles;
|
std::vector<uint32_t> triangles;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
explicit Octree(BoundingBox3f *bbox, Mesh *mesh, std::vector<uint32_t> triangles) : bbox(bbox), mesh(mesh), triangles(triangles) {
|
explicit Octree(BoundingBox3f *bbox, Mesh *mesh) : bbox(bbox), mesh(mesh) {
|
||||||
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);
|
void setTriangles(std::vector<uint32_t> triangles) { this->triangles = triangles; }
|
||||||
|
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; }
|
||||||
|
|
|
@ -30,9 +30,9 @@ void Accel::addMesh(Mesh *mesh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Accel::build() {
|
void Accel::build() {
|
||||||
auto triangles = new std::vector<uint32_t>(m_mesh->getTriangleCount());
|
auto triangles = 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;
|
||||||
|
|
|
@ -5,20 +5,22 @@
|
||||||
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->size() <= 10 || recursionDepth > 10) {
|
auto node = new Octree(bbox, mesh);
|
||||||
return new Octree(bbox, mesh, *triangles);
|
|
||||||
|
if (triangles.size() <= 20 || recursionDepth > 6) {
|
||||||
|
node->setTriangles(triangles);
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto m_F = mesh->getIndices();
|
auto m_F = mesh->getIndices();
|
||||||
auto m_V = mesh->getVertexPositions();
|
auto m_V = mesh->getVertexPositions();
|
||||||
|
|
||||||
Octree *node = new Octree(bbox, mesh, std::vector<uint32_t>());
|
|
||||||
auto bMin = bbox->min;
|
auto bMin = bbox->min;
|
||||||
auto w = bbox->max.x() - bMin.x();
|
auto w = bbox->max.x() - bMin.x();
|
||||||
auto h = bbox->max.y() - bMin.y();
|
auto h = bbox->max.y() - bMin.y();
|
||||||
auto d = bbox->max.z() - bMin.z();
|
auto d = bbox->max.z() - bMin.z();
|
||||||
auto w2 = w / 2.0f, h2 = h / 2.0f, d2 = d / 2.0f;
|
auto w2 = w / 2.0f, h2 = h / 2.0f, d2 = d / 2.0f;
|
||||||
|
|
||||||
BoundingBox3f *newBboxes[8] = {
|
BoundingBox3f *newBboxes[8] = {
|
||||||
new BoundingBox3f(bMin + Vector3f(0, 0, 0), bMin + Vector3f(w2, h2, d2)),
|
new BoundingBox3f(bMin + Vector3f(0, 0, 0), bMin + Vector3f(w2, h2, d2)),
|
||||||
new BoundingBox3f(bMin + Vector3f(w2, 0, 0), bMin + Vector3f(w, 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<uint32_t> *tr
|
||||||
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> childTriangles[8];
|
||||||
BoundingBox3f triangleBbox;
|
BoundingBox3f triangleBbox;
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
newTriangles[i] = new std::vector<uint32_t>();
|
childTriangles[i].reserve(triangles.size() / 8);
|
||||||
newTriangles[i]->reserve(triangles->size() / 8);
|
for (uint32_t idx : triangles) {
|
||||||
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);
|
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<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()) {
|
if (childTriangles[i].empty()) {
|
||||||
node->children[i] = nullptr;
|
node->children[i] = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
node->children[i] = build(newBboxes[i], mesh, newTriangles[i], recursionDepth + 1);
|
node->children[i] = build(newBboxes[i], mesh, childTriangles[i], recursionDepth + 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
if (newTriangles[i]->empty()) {
|
if (childTriangles[i].empty()) {
|
||||||
node->children[i] = nullptr;
|
node->children[i] = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (newTriangles[i]->size() > 10) {
|
node->children[i] = build(newBboxes[i], mesh, childTriangles[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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,26 +77,43 @@ uint32_t Octree::getIntersectingTriangle(Ray3f &ray, Intersection &its, bool sha
|
||||||
float u, v, t;
|
float u, v, t;
|
||||||
uint32_t closestTriangle = -1;
|
uint32_t closestTriangle = -1;
|
||||||
uint32_t triangle;
|
uint32_t triangle;
|
||||||
|
Octree *tmpChildren[8];
|
||||||
|
double distances[8];
|
||||||
|
float nearT, farT;
|
||||||
|
int n = 0;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
if (triangles.empty()) {
|
if (triangles.empty()) {
|
||||||
// std::sort(children.begin(), children.end(), [ray](Octree *a, Octree *b) {
|
for (i = 0; i < 8; i++) {
|
||||||
// if (a == nullptr) {
|
if (children[i] == 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;
|
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) {
|
if (triangle != (uint32_t) -1) {
|
||||||
return triangle;
|
return triangle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue