Skip to content

Commit c60df1b

Browse files
Use forVert (#789)
* updated a bunch of do loops to ForVert * more cleanup * Hull failure case * test cleanup * test helper cleanup * fixed edge_op --------- Co-authored-by: John Collins <[email protected]>
1 parent 8d67ba3 commit c60df1b

15 files changed

+118
-129
lines changed

.vscode/launch.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
{
88
"name": "manifold test",
99
"type": "cppdbg",
10+
"MIMode": "lldb",
1011
"request": "launch",
1112
"program": "${workspaceFolder}/build/test/manifold_test",
1213
"args": [
1314
"--gtest_break_on_failure",
14-
"--gtest_filter=Manifold.GetMesh"
15+
"--gtest_filter=Manifold.HullFail"
1516
],
1617
"stopAtEntry": false,
1718
"cwd": "${workspaceFolder}/build/test",
@@ -20,7 +21,8 @@
2021
"name": "MALLOC_CHECK_",
2122
"value": "2"
2223
}
23-
]
24+
],
25+
"externalConsole": false
2426
}
2527
]
2628
}

src/manifold/src/edge_op.cpp

+16-27
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ struct FlagEdge {
7373
current = NextHalfedge(halfedge[current].pairedHalfedge);
7474
int tri = current / 3;
7575
const TriRef ref = triRef[tri];
76-
if ((ref.meshID != ref0.meshID || ref.tri != ref0.tri) &&
77-
(ref.meshID != ref1.meshID || ref.tri != ref1.tri))
78-
return false;
76+
if (!ref.SameFace(ref0) && !ref.SameFace(ref1)) return false;
7977
}
8078
return true;
8179
}
@@ -325,12 +323,10 @@ void Manifold::Impl::DedupeEdge(const int edge) {
325323
vertPos_.push_back(vertPos_[endVert]);
326324
if (vertNormal_.size() > 0) vertNormal_.push_back(vertNormal_[endVert]);
327325

328-
do {
329-
halfedge_[current].endVert = newVert;
330-
current = NextHalfedge(current);
331-
halfedge_[current].startVert = newVert;
332-
current = halfedge_[current].pairedHalfedge;
333-
} while (current != edge);
326+
ForVert(NextHalfedge(current), [this, newVert](int e) {
327+
halfedge_[e].startVert = newVert;
328+
halfedge_[halfedge_[e].pairedHalfedge].endVert = newVert;
329+
});
334330
}
335331

336332
// Orbit startVert
@@ -350,12 +346,10 @@ void Manifold::Impl::DedupeEdge(const int edge) {
350346
vertPos_.push_back(vertPos_[endVert]);
351347
if (vertNormal_.size() > 0) vertNormal_.push_back(vertNormal_[endVert]);
352348

353-
do {
354-
halfedge_[current].endVert = newVert;
355-
current = NextHalfedge(current);
356-
halfedge_[current].startVert = newVert;
357-
current = halfedge_[current].pairedHalfedge;
358-
} while (current != pair);
349+
ForVert(NextHalfedge(current), [this, newVert](int e) {
350+
halfedge_[e].startVert = newVert;
351+
halfedge_[halfedge_[e].pairedHalfedge].endVert = newVert;
352+
});
359353
}
360354
}
361355

@@ -482,9 +476,9 @@ void Manifold::Impl::CollapseEdge(const int edge, std::vector<int>& edges) {
482476
const glm::mat3x2 projection = GetAxisAlignedProjection(faceNormal_[tri]);
483477
// Don't collapse if the edge is not redundant (this may have changed due
484478
// to the collapse of neighbors).
485-
if (ref.meshID != refCheck.meshID || ref.tri != refCheck.tri) {
479+
if (!ref.SameFace(refCheck)) {
486480
refCheck = triRef[edge / 3];
487-
if (ref.meshID != refCheck.meshID || ref.tri != refCheck.tri) {
481+
if (!ref.SameFace(refCheck)) {
488482
return;
489483
} else {
490484
// Don't collapse if the edges separating the faces are not colinear
@@ -522,11 +516,9 @@ void Manifold::Impl::CollapseEdge(const int edge, std::vector<int>& edges) {
522516
// Update the shifted triangles to the vertBary of endVert
523517
const int tri = current / 3;
524518
const int vIdx = current - 3 * tri;
525-
if (triRef[tri].meshID == triRef[tri0].meshID &&
526-
triRef[tri].tri == triRef[tri0].tri) {
519+
if (triRef[tri].SameFace(triRef[tri0])) {
527520
triProp[tri][vIdx] = triProp[tri0][triVert0];
528-
} else if (triRef[tri].meshID == triRef[tri1].meshID &&
529-
triRef[tri].tri == triRef[tri1].tri) {
521+
} else if (triRef[tri].SameFace(triRef[tri1])) {
530522
triProp[tri][vIdx] = triProp[tri1][triVert1];
531523
}
532524
}
@@ -676,14 +668,11 @@ void Manifold::Impl::SplitPinchedVerts() {
676668
} else {
677669
vertProcessed[vert] = true;
678670
}
679-
int current = i;
680-
do {
671+
ForVert(i, [this, &halfedgeProcessed, vert](int current) {
681672
halfedgeProcessed[current] = true;
682673
halfedge_[current].startVert = vert;
683-
current = halfedge_[current].pairedHalfedge;
684-
halfedge_[current].endVert = vert;
685-
current = NextHalfedge(current);
686-
} while (current != i);
674+
halfedge_[halfedge_[current].pairedHalfedge].endVert = vert;
675+
});
687676
}
688677
}
689678
} // namespace manifold

src/manifold/src/impl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ struct Manifold::Impl {
6969
inline void ForVert(int halfedge, std::function<void(int halfedge)> func) {
7070
int current = halfedge;
7171
do {
72-
func(current);
7372
current = NextHalfedge(halfedge_[current].pairedHalfedge);
73+
func(current);
7474
} while (current != halfedge);
7575
}
7676

src/manifold/src/smoothing.cpp

+56-60
Original file line numberDiff line numberDiff line change
@@ -663,36 +663,35 @@ void Manifold::Impl::SetNormals(int normalIdx, float minSharpAngle) {
663663
for (int tri = 0; tri < numTri; ++tri) {
664664
for (const int i : {0, 1, 2}) {
665665
if (meshRelation_.triProperties[tri][i] >= 0) continue;
666-
int current = 3 * tri + i;
667-
const int startEdge = current;
668-
const int vert = halfedge_[current].startVert;
666+
int startEdge = 3 * tri + i;
667+
const int vert = halfedge_[startEdge].startVert;
669668

670669
if (vertNumSharp[vert] < 2) {
671670
const glm::vec3 normal = vertFlatFace[vert] >= 0
672671
? faceNormal_[vertFlatFace[vert]]
673672
: vertNormal_[vert];
674673
int lastProp = -1;
675-
do {
676-
current = NextHalfedge(halfedge_[current].pairedHalfedge);
674+
ForVert(startEdge, [&](int current) {
677675
const int thisTri = current / 3;
678676
const int j = current - 3 * thisTri;
679677
const int prop = oldTriProp[thisTri][j];
680678
meshRelation_.triProperties[thisTri][j] = prop;
681-
if (prop == lastProp) continue;
679+
if (prop == lastProp) return;
682680
lastProp = prop;
683681
auto start = oldProperties.begin() + prop * oldNumProp;
684682
std::copy(start, start + oldNumProp,
685683
meshRelation_.properties.begin() + prop * numProp);
686684
for (const int i : {0, 1, 2})
687685
meshRelation_.properties[prop * numProp + normalIdx + i] =
688686
normal[i];
689-
} while (current != startEdge);
687+
});
690688
} else {
691689
const glm::vec3 centerPos = vertPos_[vert];
692690
// Length degree
693691
std::vector<int> group;
694692
// Length number of normals
695693
std::vector<glm::vec3> normals;
694+
int current = startEdge;
696695
int prevFace = halfedge_[current].face;
697696

698697
do {
@@ -713,34 +712,38 @@ void Manifold::Impl::SetNormals(int normalIdx, float minSharpAngle) {
713712
} while (current != startEdge);
714713

715714
const int endEdge = current;
716-
glm::vec3 prevEdgeVec =
717-
glm::normalize(vertPos_[halfedge_[current].endVert] - centerPos);
718-
719-
do {
720-
current = NextHalfedge(halfedge_[current].pairedHalfedge);
721-
const int face = halfedge_[current].face;
722-
723-
const float dihedral = glm::degrees(
724-
glm::acos(glm::dot(faceNormal_[face], faceNormal_[prevFace])));
725-
if (dihedral > minSharpAngle ||
726-
triIsFlatFace[face] != triIsFlatFace[prevFace] ||
727-
(triIsFlatFace[face] && triIsFlatFace[prevFace] &&
728-
!meshRelation_.triRef[face].SameFace(
729-
meshRelation_.triRef[prevFace]))) {
730-
normals.push_back(glm::vec3(0));
731-
}
732-
group.push_back(normals.size() - 1);
733-
734-
const glm::vec3 edgeVec =
735-
glm::normalize(vertPos_[halfedge_[current].endVert] - centerPos);
736-
float dot = glm::dot(prevEdgeVec, edgeVec);
737-
const float phi =
738-
dot >= 1 ? 0 : (dot <= -1 ? glm::pi<float>() : glm::acos(dot));
739-
normals.back() += faceNormal_[face] * phi;
740715

741-
prevFace = face;
742-
prevEdgeVec = edgeVec;
743-
} while (current != endEdge);
716+
struct FaceEdge {
717+
int face;
718+
glm::vec3 edgeVec;
719+
};
720+
721+
ForVert<FaceEdge>(
722+
endEdge,
723+
[this, centerPos](int current) {
724+
return FaceEdge(
725+
{halfedge_[current].face,
726+
glm::normalize(vertPos_[halfedge_[current].endVert] -
727+
centerPos)});
728+
},
729+
[this, &triIsFlatFace, &normals, &group, minSharpAngle](
730+
int current, const FaceEdge& here, const FaceEdge& next) {
731+
const float dihedral = glm::degrees(glm::acos(
732+
glm::dot(faceNormal_[here.face], faceNormal_[next.face])));
733+
if (dihedral > minSharpAngle ||
734+
triIsFlatFace[here.face] != triIsFlatFace[next.face] ||
735+
(triIsFlatFace[here.face] && triIsFlatFace[next.face] &&
736+
!meshRelation_.triRef[here.face].SameFace(
737+
meshRelation_.triRef[next.face]))) {
738+
normals.push_back(glm::vec3(0));
739+
}
740+
group.push_back(normals.size() - 1);
741+
float dot = glm::dot(here.edgeVec, next.edgeVec);
742+
const float phi =
743+
dot >= 1 ? 0
744+
: (dot <= -1 ? glm::pi<float>() : glm::acos(dot));
745+
normals.back() += faceNormal_[next.face] * phi;
746+
});
744747

745748
for (auto& normal : normals) {
746749
normal = glm::normalize(normal);
@@ -750,10 +753,9 @@ void Manifold::Impl::SetNormals(int normalIdx, float minSharpAngle) {
750753
int lastProp = -1;
751754
int newProp = -1;
752755
int idx = 0;
753-
do {
754-
current = NextHalfedge(halfedge_[current].pairedHalfedge);
755-
const int thisTri = current / 3;
756-
const int j = current - 3 * thisTri;
756+
ForVert(endEdge, [&](int current1) {
757+
const int thisTri = current1 / 3;
758+
const int j = current1 - 3 * thisTri;
757759
const int prop = oldTriProp[thisTri][j];
758760
auto start = oldProperties.begin() + prop * oldNumProp;
759761

@@ -780,7 +782,7 @@ void Manifold::Impl::SetNormals(int normalIdx, float minSharpAngle) {
780782

781783
meshRelation_.triProperties[thisTri][j] = newProp;
782784
++idx;
783-
} while (current != endEdge);
785+
});
784786
}
785787
}
786788
}
@@ -855,11 +857,9 @@ void Manifold::Impl::CreateTangents(int normalIdx) {
855857
}
856858
});
857859
} else { // Sharpen vertex uniformly
858-
int current = first;
859-
do {
860+
ForVert(first, [this](int current) {
860861
halfedgeTangent_[current] = glm::vec4(0);
861-
current = NextHalfedge(halfedge_[current].pairedHalfedge);
862-
} while (current != first);
862+
});
863863
}
864864
}
865865
}
@@ -947,18 +947,17 @@ void Manifold::Impl::CreateTangents(std::vector<Smoothness> sharpenedEdges) {
947947
tangent[second] = CircularTangent(
948948
-newTangent, vertPos_[halfedge_[second].endVert] - pos);
949949

950-
auto SmoothHalf = [&](int first, int last, float smoothness) {
951-
int current = NextHalfedge(halfedge_[first].pairedHalfedge);
952-
while (current != last) {
953-
tangent[current] = smoothness * tangent[current];
954-
current = NextHalfedge(halfedge_[current].pairedHalfedge);
955-
}
956-
};
957-
958-
SmoothHalf(first, second,
959-
(vert[0].second.smoothness + vert[1].first.smoothness) / 2);
960-
SmoothHalf(second, first,
961-
(vert[1].second.smoothness + vert[0].first.smoothness) / 2);
950+
float smoothness =
951+
(vert[0].second.smoothness + vert[1].first.smoothness) / 2;
952+
ForVert(
953+
first, [&tangent, &smoothness, &vert, first, second](int current) {
954+
if (current == second) {
955+
smoothness =
956+
(vert[1].second.smoothness + vert[0].first.smoothness) / 2;
957+
} else if (current != first) {
958+
tangent[current] = smoothness * tangent[current];
959+
}
960+
});
962961
} else { // Sharpen vertex uniformly
963962
float smoothness = 0;
964963
for (const Pair& pair : vert) {
@@ -967,12 +966,9 @@ void Manifold::Impl::CreateTangents(std::vector<Smoothness> sharpenedEdges) {
967966
}
968967
smoothness /= 2 * vert.size();
969968

970-
const int start = vert[0].first.halfedge;
971-
int current = start;
972-
do {
969+
ForVert(vert[0].first.halfedge, [&tangent, smoothness](int current) {
973970
tangent[current] = smoothness * tangent[current];
974-
current = NextHalfedge(halfedge_[current].pairedHalfedge);
975-
} while (current != start);
971+
});
976972
}
977973
}
978974
}

src/utilities/include/vec_view.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,16 @@ class VecView {
4646
operator VecView<const T>() const { return {ptr_, size_}; }
4747

4848
inline const T &operator[](size_t i) const {
49-
if (i >= size_) throw std::out_of_range("Vec out of range");
49+
if (i >= size_) {
50+
throw std::out_of_range("Vec out of range");
51+
}
5052
return ptr_[i];
5153
}
5254

5355
inline T &operator[](size_t i) {
54-
if (i >= size_) throw std::out_of_range("Vec out of range");
56+
if (i >= size_) {
57+
throw std::out_of_range("Vec out of range");
58+
}
5559
return ptr_[i];
5660
}
5761

@@ -93,7 +97,7 @@ class VecView {
9397
bool empty() const { return size_ == 0; }
9498

9599
#ifdef MANIFOLD_DEBUG
96-
void Dump() {
100+
void Dump() const {
97101
std::cout << "Vec = " << std::endl;
98102
for (size_t i = 0; i < size(); ++i) {
99103
std::cout << i << ", " << ptr_[i] << ", " << std::endl;

test/boolean_test.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
#include "polygon.h"
1717
#include "test.h"
1818

19-
#ifdef MANIFOLD_EXPORT
20-
#include "meshIO.h"
21-
#endif
22-
2319
using namespace manifold;
2420

2521
/**

test/cross_section_test.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@
2424
#include "public.h"
2525
#include "test.h"
2626

27-
#ifdef MANIFOLD_EXPORT
28-
#include "meshIO.h"
29-
#endif
30-
3127
using namespace manifold;
3228

3329
TEST(CrossSection, Square) {

test/manifold_test.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
#include "test.h"
2222
#include "tri_dist.h"
2323

24-
#ifdef MANIFOLD_EXPORT
25-
#include "meshIO.h"
26-
#endif
27-
2824
namespace {
2925

3026
using namespace manifold;
@@ -345,6 +341,15 @@ TEST(Manifold, Smooth) {
345341
#endif
346342
}
347343

344+
#ifdef MANIFOLD_EXPORT
345+
TEST(Manifold, HullFail) {
346+
Manifold body = ReadMesh("hull-body.glb");
347+
Manifold mask = ReadMesh("hull-mask.glb");
348+
Manifold ret = body - mask;
349+
MeshGL mesh = ret.GetMesh();
350+
}
351+
#endif
352+
348353
TEST(Manifold, SmoothFlat) {
349354
Manifold cone = Manifold::Cylinder(5, 10, 5).SmoothOut().CalculateNormals(0);
350355
Manifold smooth = cone.RefineToLength(0.1);

0 commit comments

Comments
 (0)