make sure to exit early if box intersection is already larger than best triangle intersection

This commit is contained in:
ZappoMan 2017-05-12 17:56:45 -07:00
parent eb3b27849c
commit 89b6a79f68
2 changed files with 47 additions and 19 deletions

View file

@ -33,13 +33,16 @@ void TriangleSet::clear() {
bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision) { float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision) {
// reset our distance to be the max possible, lower level tests will store best distance here
distance = std::numeric_limits<float>::max();
if (!_isBalanced) { if (!_isBalanced) {
balanceOctree(); balanceOctree();
} }
int trianglesTouched = 0; int trianglesTouched = 0;
auto result = _triangleOctree.findRayIntersection(origin, direction, distance, face, surfaceNormal, precision, trianglesTouched); auto result = _triangleOctree.findRayIntersection(origin, direction, distance, face, surfaceNormal, precision, trianglesTouched);
qDebug() << "trianglesTouched :" << trianglesTouched << "out of:" << _triangleOctree._population; //qDebug() << "trianglesTouched :" << trianglesTouched << "out of:" << _triangleOctree._population;
return result; return result;
} }
@ -77,10 +80,9 @@ void TriangleSet::balanceOctree() {
_triangleOctree.insert(i); _triangleOctree.insert(i);
} }
// prune the empty cells
_triangleOctree.prune();
_isBalanced = true; _isBalanced = true;
//debugDump();
} }
@ -106,10 +108,17 @@ bool InternalTriangleSet::findRayIntersection(const glm::vec3& origin, const glm
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision, int& trianglesTouched) { float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision, int& trianglesTouched) {
bool intersectedSomething = false; bool intersectedSomething = false;
float boxDistance = std::numeric_limits<float>::max(); float boxDistance = distance; // std::numeric_limits<float>::max();
float bestDistance = std::numeric_limits<float>::max(); float bestDistance = distance; // std::numeric_limits<float>::max();
if (_bounds.findRayIntersection(origin, direction, boxDistance, face, surfaceNormal)) { if (_bounds.findRayIntersection(origin, direction, boxDistance, face, surfaceNormal)) {
// if our bounding box intersects at a distance greater than the current known
// best distance, than we can safely not check any of our triangles
if (boxDistance > bestDistance) {
return false;
}
if (precision) { if (precision) {
for (const auto& triangleIndex : _triangleIndices) { for (const auto& triangleIndex : _triangleIndices) {
const auto& triangle = _allTriangles[triangleIndex]; const auto& triangle = _allTriangles[triangleIndex];
@ -148,10 +157,6 @@ void TriangleOctreeCell::clear() {
_population = 0; _population = 0;
} }
void TriangleOctreeCell::prune() {
// do nothing yet...
}
void TriangleOctreeCell::reset(const AABox& bounds, int depth) { void TriangleOctreeCell::reset(const AABox& bounds, int depth) {
clear(); clear();
_triangleSet._bounds = bounds; _triangleSet._bounds = bounds;
@ -159,10 +164,6 @@ void TriangleOctreeCell::reset(const AABox& bounds, int depth) {
if (depth <= MAX_DEPTH) { if (depth <= MAX_DEPTH) {
int childDepth = depth + 1; int childDepth = depth + 1;
_children.clear(); _children.clear();
for (int child = 0; child < MAX_CHILDREN; child++) {
AABox childBounds = getBounds().getOctreeChild((AABox::OctreeChild)child);
_children.push_back(TriangleOctreeCell(_allTriangles, childBounds, childDepth));
}
} }
} }
@ -170,8 +171,9 @@ void TriangleOctreeCell::debugDump() {
qDebug() << __FUNCTION__; qDebug() << __FUNCTION__;
qDebug() << "bounds:" << getBounds(); qDebug() << "bounds:" << getBounds();
qDebug() << "depth:" << _depth; qDebug() << "depth:" << _depth;
//qDebug() << "triangleSet:" << _triangleSet.size() << "at this level";
qDebug() << "population:" << _population << "this level or below"; qDebug() << "population:" << _population << "this level or below";
qDebug() << "triangleSet:" << _triangleSet.size() << "in this cell";
qDebug() << "child cells:" << _children.size();
if (_depth < MAX_DEPTH) { if (_depth < MAX_DEPTH) {
int childNum = 0; int childNum = 0;
for (auto& child : _children) { for (auto& child : _children) {
@ -187,12 +189,30 @@ void TriangleOctreeCell::insert(int triangleIndex) {
_population++; _population++;
// if we're not yet at the max depth, then check which child the triangle fits in // if we're not yet at the max depth, then check which child the triangle fits in
if (_depth < MAX_DEPTH) { if (_depth < MAX_DEPTH) {
// check existing children to see if this triangle fits them...
for (auto& child : _children) { for (auto& child : _children) {
if (child.getBounds().contains(triangle)) { if (child.getBounds().contains(triangle)) {
child.insert(triangleIndex); child.insert(triangleIndex);
return; return;
} }
} }
// if it doesn't exist in an existing child, then check for new possible children
// note: this will actually re-check the bounds of all the existing children as well, hmmm
for (int child = 0; child < MAX_CHILDREN; child++) {
AABox childBounds = getBounds().getOctreeChild((AABox::OctreeChild)child);
if (childBounds.contains(triangle)) {
// create a child node
auto child = TriangleOctreeCell(_allTriangles, childBounds, _depth + 1);
_children.push_back(child);
// insert this triangle into it
child.insert(triangleIndex);
return;
}
}
} }
// either we're at max depth, or the triangle doesn't fit in one of our // either we're at max depth, or the triangle doesn't fit in one of our
// children and so we want to just record it here // children and so we want to just record it here
@ -206,16 +226,23 @@ bool TriangleOctreeCell::findRayIntersection(const glm::vec3& origin, const glm:
return false; // no triangles below here, so we can't intersect return false; // no triangles below here, so we can't intersect
} }
float bestLocalDistance = std::numeric_limits<float>::max(); float bestLocalDistance = distance; // std::numeric_limits<float>::max();
BoxFace bestLocalFace; BoxFace bestLocalFace;
glm::vec3 bestLocalNormal; glm::vec3 bestLocalNormal;
bool intersects = false; bool intersects = false;
// if the ray intersects our bounding box, then continue // if the ray intersects our bounding box, then continue
if (getBounds().findRayIntersection(origin, direction, bestLocalDistance, bestLocalFace, bestLocalNormal)) { if (getBounds().findRayIntersection(origin, direction, bestLocalDistance, bestLocalFace, bestLocalNormal)) {
bestLocalDistance = std::numeric_limits<float>::max();
float childDistance = std::numeric_limits<float>::max(); // if the intersection with our bounding box, is greater than the current best distance (the distance passed in)
// then we know that none of our triangles can represent a better intersection and we can return
if (bestLocalDistance > distance) {
return false;
}
bestLocalDistance = distance; // std::numeric_limits<float>::max();
float childDistance = distance; // std::numeric_limits<float>::max();
BoxFace childFace; BoxFace childFace;
glm::vec3 childNormal; glm::vec3 childNormal;

View file

@ -33,6 +33,8 @@ public:
const AABox& getBounds() const { return _bounds; } const AABox& getBounds() const { return _bounds; }
size_t size() const { return _triangleIndices.size(); }
protected: protected:
std::vector<Triangle>& _allTriangles; std::vector<Triangle>& _allTriangles;
std::vector<int> _triangleIndices; std::vector<int> _triangleIndices;
@ -52,7 +54,6 @@ public:
void insert(int triangleIndex); void insert(int triangleIndex);
void reset(const AABox& bounds, int depth = 0); void reset(const AABox& bounds, int depth = 0);
void clear(); void clear();
void prune();
// Determine if the given ray (origin/direction) in model space intersects with any triangles in the set. If an // Determine if the given ray (origin/direction) in model space intersects with any triangles in the set. If an
// intersection occurs, the distance and surface normal will be provided. // intersection occurs, the distance and surface normal will be provided.