-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimizations #106
Optimizations #106
Changes from all commits
a39f4fd
1f1b608
02ce2b4
42b46f0
c5c5335
f940fe9
25e7bf7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -266,7 +266,7 @@ Collider::Collider(const VecDH<Box>& leafBB, | |
*/ | ||
template <typename T> | ||
SparseIndices Collider::Collisions(const VecDH<T>& querriesIn) const { | ||
int maxOverlaps = 1 << 20; | ||
int maxOverlaps = querriesIn.size() * 4; | ||
SparseIndices querryTri(maxOverlaps); | ||
int nOverlaps = 0; | ||
while (1) { | ||
|
@@ -282,7 +282,11 @@ SparseIndices Collider::Collisions(const VecDH<T>& querriesIn) const { | |
break; | ||
else { // if not enough memory was allocated, guess how much will be needed | ||
int lastQuery = querryTri.Get(0).H().back(); | ||
maxOverlaps *= 2 * static_cast<float>(querriesIn.size()) / lastQuery; | ||
pca006132 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
float ratio = static_cast<float>(querriesIn.size()) / lastQuery; | ||
if (ratio > 1000) // do not trust the ratio if it is too large | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
maxOverlaps *= 2; | ||
else | ||
maxOverlaps *= 2 * ratio; | ||
querryTri.Resize(maxOverlaps); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,9 @@ void Manifold::Impl::Face2Tri(const VecDH<int>& faceEdge, | |
const VecH<Halfedge>& halfedge = halfedge_.H(); | ||
const VecH<glm::vec3>& faceNormal = faceNormal_.H(); | ||
meshRelation_.triBary.resize(0); | ||
triVerts.reserve(faceEdge.size()); | ||
triNormal.reserve(faceEdge.size()); | ||
meshRelation_.triBary.H().reserve(faceEdge.size()*3); | ||
|
||
for (int face = 0; face < faceEdgeH.size() - 1; ++face) { | ||
const int firstEdge = faceEdgeH[face]; | ||
|
@@ -50,12 +53,17 @@ void Manifold::Impl::Face2Tri(const VecDH<int>& faceEdge, | |
ALWAYS_ASSERT(numEdge >= 3, topologyErr, "face has less than three edges."); | ||
const glm::vec3 normal = faceNormal[face]; | ||
|
||
std::map<int, int> vertBary; | ||
for (int j = firstEdge; j < lastEdge; ++j) | ||
vertBary[halfedge[j].startVert] = halfedgeBary.H()[j]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call, I bet this could be a big part of why the triangulation step has been scaling worse than it should. |
||
const int startTri = triVerts.size(); | ||
auto linearSearch = [](const int* mapping, int value) { | ||
int i = 0; | ||
while (mapping[i] != value) | ||
++i; | ||
return i; | ||
}; | ||
|
||
if (numEdge == 3) { // Single triangle | ||
int mapping[3] = {halfedge[firstEdge].startVert, | ||
halfedge[firstEdge + 1].startVert, | ||
halfedge[firstEdge + 2].startVert}; | ||
glm::ivec3 tri(halfedge[firstEdge].startVert, | ||
halfedge[firstEdge + 1].startVert, | ||
halfedge[firstEdge + 2].startVert); | ||
|
@@ -71,7 +79,16 @@ void Manifold::Impl::Face2Tri(const VecDH<int>& faceEdge, | |
|
||
triVerts.push_back(tri); | ||
triNormal.push_back(normal); | ||
meshRelation_.triBary.H().push_back(faceRef.H()[face]); | ||
for (int k : {0, 1, 2}) { | ||
int index = linearSearch(mapping, tri[k]); | ||
meshRelation_.triBary.H().back().vertBary[k] = halfedgeBary.H()[firstEdge + index]; | ||
} | ||
} else if (numEdge == 4) { // Pair of triangles | ||
int mapping[4] = {halfedge[firstEdge].startVert, | ||
halfedge[firstEdge + 1].startVert, | ||
halfedge[firstEdge + 2].startVert, | ||
halfedge[firstEdge + 3].startVert}; | ||
const glm::mat3x2 projection = GetAxisAlignedProjection(normal); | ||
auto triCCW = [&projection, &vertPos, this](const glm::ivec3 tri) { | ||
return CCW(projection * vertPos[tri[0]], projection * vertPos[tri[1]], | ||
|
@@ -111,13 +128,22 @@ void Manifold::Impl::Face2Tri(const VecDH<int>& faceEdge, | |
} | ||
} | ||
|
||
triVerts.push_back(tri0); | ||
triNormal.push_back(normal); | ||
triVerts.push_back(tri1); | ||
triNormal.push_back(normal); | ||
for (auto tri : { tri0, tri1 }) { | ||
triVerts.push_back(tri); | ||
triNormal.push_back(normal); | ||
meshRelation_.triBary.H().push_back(faceRef.H()[face]); | ||
for (int k : {0, 1, 2}) { | ||
int index = linearSearch(mapping, tri[k]); | ||
meshRelation_.triBary.H().back().vertBary[k] = halfedgeBary.H()[firstEdge + index]; | ||
} | ||
} | ||
} else { // General triangulation | ||
const glm::mat3x2 projection = GetAxisAlignedProjection(normal); | ||
|
||
std::map<int, int> vertBary; | ||
for (int j = firstEdge; j < lastEdge; ++j) | ||
vertBary[halfedge[j].startVert] = halfedgeBary.H()[j]; | ||
|
||
Polygons polys; | ||
try { | ||
polys = Face2Polygons(face, projection, faceEdgeH); | ||
|
@@ -134,18 +160,15 @@ void Manifold::Impl::Face2Tri(const VecDH<int>& faceEdge, | |
for (auto tri : newTris) { | ||
triVerts.push_back(tri); | ||
triNormal.push_back(normal); | ||
} | ||
} | ||
|
||
for (int tri = startTri; tri < triVerts.size(); ++tri) { | ||
meshRelation_.triBary.H().push_back(faceRef.H()[face]); | ||
for (int k : {0, 1, 2}) { | ||
meshRelation_.triBary.H().back().vertBary[k] = | ||
vertBary[triVerts[tri][k]]; | ||
meshRelation_.triBary.H().push_back(faceRef.H()[face]); | ||
for (int k : {0, 1, 2}) { | ||
meshRelation_.triBary.H().back().vertBary[k] = | ||
vertBary[tri[k]]; | ||
} | ||
} | ||
} | ||
} | ||
faceNormal_ = triNormalOut; | ||
faceNormal_ = std::move(triNormalOut); | ||
CreateAndFixHalfedges(triVertsOut); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -507,17 +507,19 @@ void Manifold::Impl::CreateHalfedges(const VecDH<glm::ivec3>& triVerts) { | |
*/ | ||
void Manifold::Impl::CreateAndFixHalfedges(const VecDH<glm::ivec3>& triVerts) { | ||
const int numTri = triVerts.size(); | ||
// drop the old value first to avoid copy | ||
halfedge_.resize(0); | ||
halfedge_.resize(3 * numTri); | ||
VecDH<TmpEdge> edge(3 * numTri); | ||
thrust::for_each_n(zip(countAt(0), triVerts.begin()), numTri, | ||
Tri2Halfedges({halfedge_.ptrH(), edge.ptrH()})); | ||
thrust::for_each_n(zip(countAt(0), triVerts.beginD()), numTri, | ||
Tri2Halfedges({halfedge_.ptrD(), edge.ptrD()})); | ||
// Stable sort is required here so that halfedges from the same face are | ||
// paired together (the triangles were created in face order). In some | ||
// degenerate situations the triangulator can add the same internal edge in | ||
// two different faces, causing this edge to not be 2-manifold. We detect this | ||
// and fix it by swapping one of the identical edges, so it is important that | ||
// we have the edges paired according to their face. | ||
std::stable_sort(edge.begin(), edge.end()); | ||
thrust::stable_sort(edge.beginD(), edge.endD()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this new? I vaguely recall using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From git blame of https://github.com/NVIDIA/thrust/blame/fa54f2c6f1217237953f27ddf67f901b6b34fbdd/testing/stable_sort.cu, it seems that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cool, I must have remembered wrong. |
||
thrust::for_each_n(thrust::host, countAt(0), halfedge_.size() / 2, | ||
LinkHalfedges({halfedge_.ptrH(), edge.cptrH()})); | ||
thrust::for_each(thrust::host, countAt(1), countAt(halfedge_.size() / 2), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍