From eb3b27849c74e111e16cc831bfade32553c563aa Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 12 May 2017 17:07:47 -0700 Subject: [PATCH] only keep one copy of Triangles --- libraries/render-utils/src/Model.cpp | 2 - libraries/shared/src/TriangleSet.cpp | 153 ++++++++++++++++----------- libraries/shared/src/TriangleSet.h | 61 +++++++---- 3 files changed, 132 insertions(+), 84 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 2c338674eb..9af1c6802e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -462,8 +462,6 @@ bool Model::convexHullContains(glm::vec3 point) { void Model::calculateTriangleSets() { PROFILE_RANGE(render, __FUNCTION__); - qDebug() << __FUNCTION__ << "url:" << _url; - const FBXGeometry& geometry = getFBXGeometry(); int numberOfMeshes = geometry.meshes.size(); diff --git a/libraries/shared/src/TriangleSet.cpp b/libraries/shared/src/TriangleSet.cpp index e13d8b126f..ef8f3ab91e 100644 --- a/libraries/shared/src/TriangleSet.cpp +++ b/libraries/shared/src/TriangleSet.cpp @@ -13,6 +13,22 @@ #include "TriangleSet.h" +void TriangleSet::insert(const Triangle& t) { + _isBalanced = false; + + _triangles.push_back(t); + _bounds += t.v0; + _bounds += t.v1; + _bounds += t.v2; +} + +void TriangleSet::clear() { + _triangles.clear(); + _bounds.clear(); + _isBalanced = false; + + // delete the octree? +} bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision) { @@ -27,53 +43,7 @@ bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& return result; } -void InternalTriangleSet::insert(const Triangle& t) { - _triangles.push_back(t); - - _bounds += t.v0; - _bounds += t.v1; - _bounds += t.v2; -} - -void InternalTriangleSet::clear() { - _triangles.clear(); - _bounds.clear(); -} - -// Determine of 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. -bool InternalTriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision, int& trianglesTouched) { - - bool intersectedSomething = false; - float boxDistance = std::numeric_limits::max(); - float bestDistance = std::numeric_limits::max(); - - if (_bounds.findRayIntersection(origin, direction, boxDistance, face, surfaceNormal)) { - if (precision) { - for (const auto& triangle : _triangles) { - float thisTriangleDistance; - trianglesTouched++; - if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) { - if (thisTriangleDistance < bestDistance) { - bestDistance = thisTriangleDistance; - intersectedSomething = true; - surfaceNormal = triangle.getNormal(); - distance = bestDistance; - } - } - } - } else { - intersectedSomething = true; - distance = boxDistance; - } - } - - return intersectedSomething; -} - - -bool InternalTriangleSet::convexHullContains(const glm::vec3& point) const { +bool TriangleSet::convexHullContains(const glm::vec3& point) const { if (!_bounds.contains(point)) { return false; } @@ -100,16 +70,76 @@ void TriangleSet::debugDump() { void TriangleSet::balanceOctree() { _triangleOctree.reset(_bounds, 0); - for (const auto& triangle : _triangles) { - _triangleOctree.insert(triangle); + + // insert all the triangles + + for (int i = 0; i < _triangles.size(); i++) { + _triangleOctree.insert(i); } + + // prune the empty cells + _triangleOctree.prune(); + _isBalanced = true; } + + +void InternalTriangleSet::insert(int triangleIndex) { + auto& triangle = _allTriangles[triangleIndex]; + + _triangleIndices.push_back(triangleIndex); + + _bounds += triangle.v0; + _bounds += triangle.v1; + _bounds += triangle.v2; +} + +void InternalTriangleSet::clear() { + _triangleIndices.clear(); + _bounds.clear(); +} + +// Determine of 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. +bool InternalTriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision, int& trianglesTouched) { + + bool intersectedSomething = false; + float boxDistance = std::numeric_limits::max(); + float bestDistance = std::numeric_limits::max(); + + if (_bounds.findRayIntersection(origin, direction, boxDistance, face, surfaceNormal)) { + if (precision) { + for (const auto& triangleIndex : _triangleIndices) { + const auto& triangle = _allTriangles[triangleIndex]; + float thisTriangleDistance; + trianglesTouched++; + if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) { + if (thisTriangleDistance < bestDistance) { + bestDistance = thisTriangleDistance; + intersectedSomething = true; + surfaceNormal = triangle.getNormal(); + distance = bestDistance; + } + } + } + } else { + intersectedSomething = true; + distance = boxDistance; + } + } + + return intersectedSomething; +} + static const int MAX_DEPTH = 3; // for now static const int MAX_CHILDREN = 8; -TriangleOctreeCell::TriangleOctreeCell(const AABox& bounds, int depth) { +TriangleOctreeCell::TriangleOctreeCell(std::vector& allTriangles, const AABox& bounds, int depth) : + _allTriangles(allTriangles), + _triangleSet(allTriangles) +{ reset(bounds, depth); } @@ -118,8 +148,11 @@ void TriangleOctreeCell::clear() { _population = 0; } +void TriangleOctreeCell::prune() { + // do nothing yet... +} + void TriangleOctreeCell::reset(const AABox& bounds, int depth) { - //qDebug() << __FUNCTION__ << "bounds:" << bounds << "depth:" << depth; clear(); _triangleSet._bounds = bounds; _depth = depth; @@ -128,12 +161,7 @@ void TriangleOctreeCell::reset(const AABox& bounds, int depth) { _children.clear(); for (int child = 0; child < MAX_CHILDREN; child++) { AABox childBounds = getBounds().getOctreeChild((AABox::OctreeChild)child); - /* - qDebug() << __FUNCTION__ << "bounds:" << bounds << "depth:" << depth - << "child:" << child << "childBounds:" << childBounds << "childDepth:" << childDepth; - */ - - _children.push_back(TriangleOctreeCell(childBounds, childDepth)); + _children.push_back(TriangleOctreeCell(_allTriangles, childBounds, childDepth)); } } } @@ -142,7 +170,7 @@ void TriangleOctreeCell::debugDump() { qDebug() << __FUNCTION__; qDebug() << "bounds:" << getBounds(); qDebug() << "depth:" << _depth; - qDebug() << "triangleSet:" << _triangleSet.size() << "at this level"; + //qDebug() << "triangleSet:" << _triangleSet.size() << "at this level"; qDebug() << "population:" << _population << "this level or below"; if (_depth < MAX_DEPTH) { int childNum = 0; @@ -154,20 +182,21 @@ void TriangleOctreeCell::debugDump() { } } -void TriangleOctreeCell::insert(const Triangle& t) { +void TriangleOctreeCell::insert(int triangleIndex) { + const Triangle& triangle = _allTriangles[triangleIndex]; _population++; // if we're not yet at the max depth, then check which child the triangle fits in if (_depth < MAX_DEPTH) { for (auto& child : _children) { - if (child.getBounds().contains(t)) { - child.insert(t); + if (child.getBounds().contains(triangle)) { + child.insert(triangleIndex); return; } } } // 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 - _triangleSet.insert(t); + _triangleSet.insert(triangleIndex); } bool TriangleOctreeCell::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/libraries/shared/src/TriangleSet.h b/libraries/shared/src/TriangleSet.h index c8703c6445..d98ba86cb5 100644 --- a/libraries/shared/src/TriangleSet.h +++ b/libraries/shared/src/TriangleSet.h @@ -14,14 +14,15 @@ #include "AABox.h" #include "GeometryUtil.h" + + class InternalTriangleSet { public: - InternalTriangleSet() { } + InternalTriangleSet(std::vector& allTriangles) : + _allTriangles(allTriangles) + { } - void reserve(size_t size) { _triangles.reserve(size); } // reserve space in the datastructure for size number of triangles - size_t size() const { return _triangles.size(); } - - virtual void insert(const Triangle& t); + virtual void insert(int triangleIndex); void clear(); // Determine if the given ray (origin/direction) in model space intersects with any triangles in the set. If an @@ -30,14 +31,11 @@ public: bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision, int& trianglesTouched); - // Determine if a point is "inside" all the triangles of a convex hull. It is the responsibility of the caller to - // determine that the triangle set is indeed a convex hull. If the triangles added to this set are not in fact a - // convex hull, the result of this method is meaningless and undetermined. - bool convexHullContains(const glm::vec3& point) const; const AABox& getBounds() const { return _bounds; } protected: - std::vector _triangles; + std::vector& _allTriangles; + std::vector _triangleIndices; AABox _bounds; friend class TriangleOctreeCell; @@ -45,11 +43,16 @@ protected: class TriangleOctreeCell { public: - TriangleOctreeCell() { } + TriangleOctreeCell(std::vector& allTriangles) : + _allTriangles(allTriangles), + _triangleSet(allTriangles) + { } - void insert(const Triangle& t); + + void insert(int triangleIndex); void reset(const AABox& bounds, int depth = 0); void clear(); + void prune(); // 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. @@ -61,8 +64,9 @@ public: void debugDump(); protected: - TriangleOctreeCell(const AABox& bounds, int depth); + TriangleOctreeCell(std::vector& allTriangles, const AABox& bounds, int depth); + std::vector& _allTriangles; InternalTriangleSet _triangleSet; std::vector _children; int _depth { 0 }; @@ -71,25 +75,42 @@ protected: friend class TriangleSet; }; -class TriangleSet : public InternalTriangleSet { +class TriangleSet { // pass through public implementation all the features of InternalTriangleSet public: - TriangleSet() { } + TriangleSet() : + _triangleOctree(_triangles) + {} void debugDump(); - virtual void insert(const Triangle& t) { - _isBalanced = false; - InternalTriangleSet::insert(t); - } + void insert(const Triangle& t); bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision); void balanceOctree(); + void reserve(size_t size) { _triangles.reserve(size); } // reserve space in the datastructure for size number of triangles + size_t size() const { return _triangles.size(); } + void clear(); + + // 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. + // note: this might side-effect internal structures + bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision, int& trianglesTouched); + + // Determine if a point is "inside" all the triangles of a convex hull. It is the responsibility of the caller to + // determine that the triangle set is indeed a convex hull. If the triangles added to this set are not in fact a + // convex hull, the result of this method is meaningless and undetermined. + bool convexHullContains(const glm::vec3& point) const; + const AABox& getBounds() const { return _bounds; } + protected: - bool _isBalanced { false }; + bool _isBalanced{ false }; TriangleOctreeCell _triangleOctree; + std::vector _triangles; + AABox _bounds; };