mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 19:16:56 +02:00
only keep one copy of Triangles
This commit is contained in:
parent
6d7e98274b
commit
eb3b27849c
3 changed files with 132 additions and 84 deletions
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue