-
Notifications
You must be signed in to change notification settings - Fork 98
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
Separate coplanarity from faceID #991
Changes from all commits
5bf8f2b
604104a
69926bf
dc3412e
5444b11
7fce56f
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 |
---|---|---|
|
@@ -93,14 +93,11 @@ struct UpdateMeshID { | |
|
||
struct CoplanarEdge { | ||
VecView<std::pair<int, int>> face2face; | ||
VecView<std::pair<int, int>> vert2vert; | ||
VecView<double> triArea; | ||
VecView<const Halfedge> halfedge; | ||
VecView<const vec3> vertPos; | ||
VecView<const TriRef> triRef; | ||
VecView<const ivec3> triProp; | ||
VecView<const double> prop; | ||
VecView<const double> propTol; | ||
const int numProp; | ||
const double precision; | ||
|
||
|
@@ -118,19 +115,9 @@ struct CoplanarEdge { | |
const int jointNum = edge.pairedHalfedge - 3 * pairFace; | ||
|
||
if (numProp > 0) { | ||
const int prop0 = triProp[edgeFace][baseNum]; | ||
const int prop1 = triProp[pairFace][jointNum == 2 ? 0 : jointNum + 1]; | ||
bool propEqual = true; | ||
for (int p = 0; p < numProp; ++p) { | ||
if (std::abs(prop[numProp * prop0 + p] - prop[numProp * prop1 + p]) > | ||
propTol[p]) { | ||
propEqual = false; | ||
break; | ||
} | ||
} | ||
if (propEqual) { | ||
vert2vert[edgeIdx] = std::make_pair(prop0, prop1); | ||
} | ||
if (triProp[edgeFace][baseNum] != triProp[pairFace][Next3(jointNum)] || | ||
triProp[edgeFace][Next3(baseNum)] != triProp[pairFace][jointNum]) | ||
return; | ||
} | ||
|
||
if (!edge.IsForward()) return; | ||
|
@@ -158,32 +145,6 @@ struct CoplanarEdge { | |
// Only operate on coplanar triangles | ||
if (volume > std::max(area, areaPair) * precision) return; | ||
|
||
// Check property linearity | ||
if (area > 0) { | ||
normal /= area; | ||
for (int i = 0; i < numProp; ++i) { | ||
const double scale = precision / propTol[i]; | ||
|
||
const double baseProp = prop[numProp * triProp[edgeFace][baseNum] + i]; | ||
const double jointProp = | ||
prop[numProp * triProp[pairFace][jointNum] + i]; | ||
const double edgeProp = prop[numProp * triProp[edgeFace][edgeNum] + i]; | ||
const double pairProp = prop[numProp * triProp[pairFace][pairNum] + i]; | ||
|
||
const vec3 iJointVec = | ||
jointVec + normal * scale * (jointProp - baseProp); | ||
const vec3 iEdgeVec = edgeVec + normal * scale * (edgeProp - baseProp); | ||
const vec3 iPairVec = pairVec + normal * scale * (pairProp - baseProp); | ||
|
||
vec3 cross = la::cross(iJointVec, iEdgeVec); | ||
const double areaP = std::max( | ||
la::length(cross), la::length(la::cross(iPairVec, iJointVec))); | ||
const double volumeP = std::abs(la::dot(cross, iPairVec)); | ||
// Only operate on consistent triangles | ||
if (volumeP > areaP * precision) return; | ||
} | ||
} | ||
|
||
face2face[edgeIdx] = std::make_pair(edgeFace, pairFace); | ||
} | ||
}; | ||
|
@@ -339,40 +300,67 @@ void Manifold::Impl::RemoveUnreferencedVerts() { | |
}); | ||
} | ||
|
||
void Manifold::Impl::InitializeOriginal() { | ||
void Manifold::Impl::InitializeOriginal(bool keepFaceID) { | ||
const int meshID = ReserveIDs(1); | ||
meshRelation_.originalID = meshID; | ||
auto& triRef = meshRelation_.triRef; | ||
triRef.resize(NumTri()); | ||
for_each_n(autoPolicy(NumTri(), 1e5), countAt(0), NumTri(), | ||
[meshID, &triRef](const int tri) { | ||
triRef[tri] = {meshID, meshID, tri}; | ||
[meshID, keepFaceID, &triRef](const int tri) { | ||
triRef[tri] = {meshID, meshID, tri, | ||
keepFaceID ? triRef[tri].faceID : tri}; | ||
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. What will happen if we always keep face ID? 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. I think that would be weird - for a regular initialization, that would mean every faceID was zero, which would imply the whole object was a single face. It would probably confuse something at some point. |
||
}); | ||
meshRelation_.meshIDtransform.clear(); | ||
meshRelation_.meshIDtransform[meshID] = {meshID}; | ||
} | ||
|
||
void Manifold::Impl::CreateFaces(const std::vector<double>& propertyTolerance) { | ||
void Manifold::Impl::CreateFaces() { | ||
ZoneScoped; | ||
constexpr double kDefaultPropTolerance = 1e-5; | ||
Vec<double> propertyToleranceD = | ||
propertyTolerance.empty() | ||
? Vec<double>(meshRelation_.numProp, kDefaultPropTolerance) | ||
: propertyTolerance; | ||
|
||
Vec<std::pair<int, int>> face2face(halfedge_.size(), {-1, -1}); | ||
Vec<std::pair<int, int>> vert2vert(halfedge_.size(), {-1, -1}); | ||
Vec<double> triArea(NumTri()); | ||
for_each_n(autoPolicy(halfedge_.size(), 1e4), countAt(0), halfedge_.size(), | ||
CoplanarEdge({face2face, vert2vert, triArea, halfedge_, vertPos_, | ||
meshRelation_.triRef, meshRelation_.triProperties, | ||
meshRelation_.properties, propertyToleranceD, | ||
meshRelation_.numProp, precision_})); | ||
|
||
if (meshRelation_.triProperties.size() > 0) { | ||
const size_t numProp = NumProp(); | ||
if (numProp > 0) { | ||
for_each_n( | ||
autoPolicy(halfedge_.size(), 1e4), countAt(0), halfedge_.size(), | ||
[&vert2vert, numProp, this](const int edgeIdx) { | ||
const Halfedge edge = halfedge_[edgeIdx]; | ||
const Halfedge pair = halfedge_[edge.pairedHalfedge]; | ||
const int edgeFace = edgeIdx / 3; | ||
const int pairFace = edge.pairedHalfedge / 3; | ||
|
||
if (meshRelation_.triRef[edgeFace].meshID != | ||
meshRelation_.triRef[pairFace].meshID) | ||
return; | ||
|
||
const int baseNum = edgeIdx - 3 * edgeFace; | ||
const int jointNum = edge.pairedHalfedge - 3 * pairFace; | ||
|
||
const int prop0 = meshRelation_.triProperties[edgeFace][baseNum]; | ||
const int prop1 = | ||
meshRelation_ | ||
.triProperties[pairFace][jointNum == 2 ? 0 : jointNum + 1]; | ||
bool propEqual = true; | ||
for (size_t p = 0; p < numProp; ++p) { | ||
if (meshRelation_.properties[numProp * prop0 + p] != | ||
meshRelation_.properties[numProp * prop1 + p]) { | ||
propEqual = false; | ||
break; | ||
} | ||
} | ||
if (propEqual) { | ||
vert2vert[edgeIdx] = std::make_pair(prop0, prop1); | ||
} | ||
}); | ||
DedupePropVerts(meshRelation_.triProperties, vert2vert); | ||
} | ||
|
||
for_each_n(autoPolicy(halfedge_.size(), 1e4), countAt(0), halfedge_.size(), | ||
CoplanarEdge({face2face, triArea, halfedge_, vertPos_, | ||
meshRelation_.triRef, meshRelation_.triProperties, | ||
meshRelation_.numProp, precision_})); | ||
|
||
std::vector<int> components; | ||
const int numComponent = GetLabels(components, face2face, NumTri()); | ||
|
||
|
@@ -394,7 +382,7 @@ void Manifold::Impl::CreateFaces(const std::vector<double>& propertyTolerance) { | |
for (size_t tri = 0; tri < NumTri(); ++tri) { | ||
const int referenceTri = comp2tri[components[tri]]; | ||
if (referenceTri >= 0) { | ||
triRef[tri].tri = referenceTri; | ||
triRef[tri].faceID = referenceTri; | ||
} | ||
} | ||
} | ||
|
@@ -511,8 +499,9 @@ void Manifold::Impl::WarpBatch(std::function<void(VecView<vec3>)> warpFunc) { | |
faceNormal_.resize(0); // force recalculation of triNormal | ||
CalculateNormals(); | ||
SetPrecision(); | ||
InitializeOriginal(); | ||
Finish(); | ||
CreateFaces(); | ||
meshRelation_.originalID = -1; | ||
} | ||
|
||
Manifold::Impl Manifold::Impl::Transform(const mat3x4& transform_) const { | ||
|
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.
One question: should we rename our public
faceID
, since it really has nothing to do with faces now? MaybetriID
ortriIndex
?The worst part is now in our internal
TriRef
struct we havefaceID
which really is a face ID andtri
which is the internal analogue to this publicfaceID
. That's pretty much bound to confuse someone eventually, probably me.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.
Yeah,
triID
sounds better fit here.We should add some documentation for the internalIt seems that it is already documented.faceID
to clarify things a bit as well.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.
Since that will be a big change across all of our binding surfaces and such, I'll leave that to its own PR.