Skip to content

Commit

Permalink
Merge pull request elalish#106 from pca006132/optimizations
Browse files Browse the repository at this point in the history
Optimizations
  • Loading branch information
elalish authored May 11, 2022
2 parents 66ee815 + 5580c41 commit 14c10f0
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 25 deletions.
8 changes: 6 additions & 2 deletions collider/src/collider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
float ratio = static_cast<float>(querriesIn.size()) / lastQuery;
if (ratio > 1000) // do not trust the ratio if it is too large
maxOverlaps *= 2;
else
maxOverlaps *= 2 * ratio;
querryTri.Resize(maxOverlaps);
}
}
Expand Down
57 changes: 40 additions & 17 deletions manifold/src/face_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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];
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);
Expand All @@ -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]],
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}

Expand Down
8 changes: 5 additions & 3 deletions manifold/src/impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
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),
Expand Down
2 changes: 1 addition & 1 deletion manifold/src/smoothing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ Manifold::Impl::MeshRelationD Manifold::Impl::Subdivide(int n) {
MeshRelationD relation;
relation.barycentric.resize(numTri * VertsPerTri(n + 1));
relation.triBary.resize(n * n * numTri);
MeshRelationD oldMeshRelation = meshRelation_;
MeshRelationD oldMeshRelation = std::move(meshRelation_);
meshRelation_.barycentric.resize(relation.barycentric.size());
meshRelation_.triBary.resize(relation.triBary.size());

Expand Down
4 changes: 2 additions & 2 deletions manifold/src/sort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,8 @@ void Manifold::Impl::GatherFaces(const VecDH<int>& faceNew2Old) {

if (faceNormal_.size() == NumTri()) Permute(faceNormal_, faceNew2Old);

VecDH<Halfedge> oldHalfedge(halfedge_);
VecDH<glm::vec4> oldHalfedgeTangent(halfedgeTangent_);
VecDH<Halfedge> oldHalfedge(std::move(halfedge_));
VecDH<glm::vec4> oldHalfedgeTangent(std::move(halfedgeTangent_));
VecDH<int> faceOld2New(oldHalfedge.size() / 3);
thrust::scatter(countAt(0), countAt(numTri), faceNew2Old.beginD(),
faceOld2New.beginD());
Expand Down

0 comments on commit 14c10f0

Please sign in to comment.