only keep one copy of Triangles

This commit is contained in:
ZappoMan 2017-05-12 17:07:47 -07:00
parent 6d7e98274b
commit eb3b27849c
3 changed files with 132 additions and 84 deletions

View file

@ -462,8 +462,6 @@ bool Model::convexHullContains(glm::vec3 point) {
void Model::calculateTriangleSets() { void Model::calculateTriangleSets() {
PROFILE_RANGE(render, __FUNCTION__); PROFILE_RANGE(render, __FUNCTION__);
qDebug() << __FUNCTION__ << "url:" << _url;
const FBXGeometry& geometry = getFBXGeometry(); const FBXGeometry& geometry = getFBXGeometry();
int numberOfMeshes = geometry.meshes.size(); int numberOfMeshes = geometry.meshes.size();

View file

@ -13,6 +13,22 @@
#include "TriangleSet.h" #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, 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) {
@ -27,53 +43,7 @@ bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3&
return result; return result;
} }
void InternalTriangleSet::insert(const Triangle& t) { bool TriangleSet::convexHullContains(const glm::vec3& point) const {
_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<float>::max();
float bestDistance = std::numeric_limits<float>::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 {
if (!_bounds.contains(point)) { if (!_bounds.contains(point)) {
return false; return false;
} }
@ -100,16 +70,76 @@ void TriangleSet::debugDump() {
void TriangleSet::balanceOctree() { void TriangleSet::balanceOctree() {
_triangleOctree.reset(_bounds, 0); _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; _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<float>::max();
float bestDistance = std::numeric_limits<float>::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_DEPTH = 3; // for now
static const int MAX_CHILDREN = 8; static const int MAX_CHILDREN = 8;
TriangleOctreeCell::TriangleOctreeCell(const AABox& bounds, int depth) { TriangleOctreeCell::TriangleOctreeCell(std::vector<Triangle>& allTriangles, const AABox& bounds, int depth) :
_allTriangles(allTriangles),
_triangleSet(allTriangles)
{
reset(bounds, depth); reset(bounds, depth);
} }
@ -118,8 +148,11 @@ 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) {
//qDebug() << __FUNCTION__ << "bounds:" << bounds << "depth:" << depth;
clear(); clear();
_triangleSet._bounds = bounds; _triangleSet._bounds = bounds;
_depth = depth; _depth = depth;
@ -128,12 +161,7 @@ void TriangleOctreeCell::reset(const AABox& bounds, int depth) {
_children.clear(); _children.clear();
for (int child = 0; child < MAX_CHILDREN; child++) { for (int child = 0; child < MAX_CHILDREN; child++) {
AABox childBounds = getBounds().getOctreeChild((AABox::OctreeChild)child); AABox childBounds = getBounds().getOctreeChild((AABox::OctreeChild)child);
/* _children.push_back(TriangleOctreeCell(_allTriangles, childBounds, childDepth));
qDebug() << __FUNCTION__ << "bounds:" << bounds << "depth:" << depth
<< "child:" << child << "childBounds:" << childBounds << "childDepth:" << childDepth;
*/
_children.push_back(TriangleOctreeCell(childBounds, childDepth));
} }
} }
} }
@ -142,7 +170,7 @@ 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() << "triangleSet:" << _triangleSet.size() << "at this level";
qDebug() << "population:" << _population << "this level or below"; qDebug() << "population:" << _population << "this level or below";
if (_depth < MAX_DEPTH) { if (_depth < MAX_DEPTH) {
int childNum = 0; 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++; _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) {
for (auto& child : _children) { for (auto& child : _children) {
if (child.getBounds().contains(t)) { if (child.getBounds().contains(triangle)) {
child.insert(t); child.insert(triangleIndex);
return; 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
_triangleSet.insert(t); _triangleSet.insert(triangleIndex);
} }
bool TriangleOctreeCell::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool TriangleOctreeCell::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,

View file

@ -14,14 +14,15 @@
#include "AABox.h" #include "AABox.h"
#include "GeometryUtil.h" #include "GeometryUtil.h"
class InternalTriangleSet { class InternalTriangleSet {
public: public:
InternalTriangleSet() { } InternalTriangleSet(std::vector<Triangle>& allTriangles) :
_allTriangles(allTriangles)
{ }
void reserve(size_t size) { _triangles.reserve(size); } // reserve space in the datastructure for size number of triangles virtual void insert(int triangleIndex);
size_t size() const { return _triangles.size(); }
virtual void insert(const Triangle& t);
void clear(); void clear();
// 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
@ -30,14 +31,11 @@ public:
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precision, int& trianglesTouched); 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; } const AABox& getBounds() const { return _bounds; }
protected: protected:
std::vector<Triangle> _triangles; std::vector<Triangle>& _allTriangles;
std::vector<int> _triangleIndices;
AABox _bounds; AABox _bounds;
friend class TriangleOctreeCell; friend class TriangleOctreeCell;
@ -45,11 +43,16 @@ protected:
class TriangleOctreeCell { class TriangleOctreeCell {
public: public:
TriangleOctreeCell() { } TriangleOctreeCell(std::vector<Triangle>& allTriangles) :
_allTriangles(allTriangles),
_triangleSet(allTriangles)
{ }
void insert(const Triangle& t);
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.
@ -61,8 +64,9 @@ public:
void debugDump(); void debugDump();
protected: protected:
TriangleOctreeCell(const AABox& bounds, int depth); TriangleOctreeCell(std::vector<Triangle>& allTriangles, const AABox& bounds, int depth);
std::vector<Triangle>& _allTriangles;
InternalTriangleSet _triangleSet; InternalTriangleSet _triangleSet;
std::vector<TriangleOctreeCell> _children; std::vector<TriangleOctreeCell> _children;
int _depth { 0 }; int _depth { 0 };
@ -71,25 +75,42 @@ protected:
friend class TriangleSet; friend class TriangleSet;
}; };
class TriangleSet : public InternalTriangleSet { class TriangleSet {
// pass through public implementation all the features of InternalTriangleSet // pass through public implementation all the features of InternalTriangleSet
public: public:
TriangleSet() { } TriangleSet() :
_triangleOctree(_triangles)
{}
void debugDump(); void debugDump();
virtual void insert(const Triangle& t) { void insert(const Triangle& t);
_isBalanced = false;
InternalTriangleSet::insert(t);
}
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool 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);
void balanceOctree(); 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: protected:
bool _isBalanced { false }; bool _isBalanced{ false };
TriangleOctreeCell _triangleOctree; TriangleOctreeCell _triangleOctree;
std::vector<Triangle> _triangles;
AABox _bounds;
}; };