mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-09 13:50:05 +00:00
Fixed bug detecting non-manifold crease in Bfr::SurfaceFactory:
- added method to Bfr::FaceVertex to inspect manifold subsets around vertex - updated topology inspection in Bfr::FaceVertex to use new method
This commit is contained in:
parent
8f2ebf3b3c
commit
ebd928f9b4
@ -24,6 +24,8 @@
|
||||
|
||||
#include "../bfr/faceVertex.h"
|
||||
#include "../sdc/crease.h"
|
||||
#include "../vtr/array.h"
|
||||
#include "../vtr/stackBuffer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
@ -628,7 +630,7 @@ FaceVertex::ConnectUnOrderedFaces(Index const fvIndices[]) {
|
||||
// properties of the corner:
|
||||
assignUnOrderedFaceNeighbors(edges, feEdges);
|
||||
|
||||
finalizeUnOrderedTags(edges, numEdges);
|
||||
finalizeUnOrderedTags(edges, numEdges, fvIndices);
|
||||
}
|
||||
|
||||
//
|
||||
@ -797,7 +799,8 @@ FaceVertex::assignUnOrderedFaceNeighbors(Edge const edges[],
|
||||
}
|
||||
|
||||
void
|
||||
FaceVertex::finalizeUnOrderedTags(Edge const edges[], int numEdges) {
|
||||
FaceVertex::finalizeUnOrderedTags(Edge const edges[], int numEdges,
|
||||
Index const fvIndices[]) {
|
||||
|
||||
//
|
||||
// Summarize properties of the corner given the number and nature of
|
||||
@ -850,9 +853,12 @@ FaceVertex::finalizeUnOrderedTags(Edge const edges[], int numEdges) {
|
||||
|
||||
if (!hasDegenerateEdges && !hasDuplicateEdges && !hasBoundaryEdges) {
|
||||
// Special crease case that avoids sharpening: two interior
|
||||
// non-manifold edges radiating more than two sets of faces:
|
||||
isNonManifoldCrease = (numNonManifoldEdges == 2) &&
|
||||
(GetNumFaces() > numEdges);
|
||||
// non-manifold edges radiating more than two sets of faces.
|
||||
// This requires closer inspection to confirm, so make use of
|
||||
// as many pre-conditions available here to avoid doing so:
|
||||
isNonManifoldCrease = !_isExpInfSharp &&
|
||||
(numNonManifoldEdges == 2) && (GetNumFaces() > numEdges) &&
|
||||
testNonManifoldCrease(edges, numEdges, fvIndices);
|
||||
}
|
||||
} else {
|
||||
// Mismatch between number of incident faces and edges:
|
||||
@ -897,6 +903,102 @@ FaceVertex::finalizeUnOrderedTags(Edge const edges[], int numEdges) {
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FaceVertex::testNonManifoldCrease(Edge const edges[], int numEdges,
|
||||
Index const fvIndices[]) const {
|
||||
//
|
||||
// Local struct that keeps track of face-corners remaining around
|
||||
// a vertex as those visited as part of connected manifold subsets
|
||||
// are removed during inspection:
|
||||
//
|
||||
struct FaceCornerArray {
|
||||
typedef Vtr::internal::StackBuffer<int,32,true> MemberArray;
|
||||
typedef Vtr::ConstArray<int> SearchArray;
|
||||
|
||||
MemberArray leading;
|
||||
MemberArray trailing;
|
||||
int size;
|
||||
|
||||
FaceCornerArray(int n) : leading(n), trailing(n), size(n) { }
|
||||
|
||||
int FindLeading(int vertex) const {
|
||||
return SearchArray(leading, size).FindIndex(vertex);
|
||||
}
|
||||
int FindTrailing(int vertex) const {
|
||||
return SearchArray(trailing, size).FindIndex(vertex);
|
||||
}
|
||||
void RemoveFace(int index) {
|
||||
std::swap(leading[index], leading[size - 1]);
|
||||
std::swap(trailing[index], trailing[size - 1]);
|
||||
-- size;
|
||||
}
|
||||
int RemoveManifoldSubset(int startVertex, int endVertex) {
|
||||
assert(startVertex != endVertex);
|
||||
|
||||
for (int nextVertex = startVertex; nextVertex != endVertex; ) {
|
||||
int faceIndex = FindLeading(nextVertex);
|
||||
if (faceIndex < 0) return (nextVertex == startVertex) ? 0 : -1;
|
||||
|
||||
nextVertex = trailing[faceIndex];
|
||||
if (nextVertex == startVertex) return -1;
|
||||
|
||||
RemoveFace(faceIndex);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Identify the vertices at the ends of the two non-manifold edges
|
||||
// of the potential crease:
|
||||
//
|
||||
int creaseEnd[2] = { -1, -1 };
|
||||
|
||||
for (int i = 0; i < numEdges; ++i) {
|
||||
if (edges[i].nonManifold) {
|
||||
creaseEnd[creaseEnd[0] >= 0] = edges[i].endVertex;
|
||||
}
|
||||
}
|
||||
assert((creaseEnd[0] >= 0) && (creaseEnd[1] >= 0));
|
||||
|
||||
//
|
||||
// Use the locally defined set of face-edge pairs to determine if
|
||||
// the collection of faces around the vertex forms a non-manifold
|
||||
// crease.
|
||||
//
|
||||
// First initialize the FaceCornerArray from the face vertices:
|
||||
//
|
||||
int numFaces = GetNumFaces();
|
||||
|
||||
FaceCornerArray faceCorners(numFaces);
|
||||
|
||||
for (int i = 0; i < numFaces; ++i) {
|
||||
faceCorners.leading[i] = GetFaceIndexLeading( i, fvIndices);
|
||||
faceCorners.trailing[i] = GetFaceIndexTrailing(i, fvIndices);
|
||||
}
|
||||
|
||||
// Remove faces for manifold subsets in one direction:
|
||||
int removed = 0;
|
||||
do {
|
||||
removed = faceCorners.RemoveManifoldSubset(creaseEnd[0], creaseEnd[1]);
|
||||
if (removed < 0) {
|
||||
return false;
|
||||
}
|
||||
} while (removed);
|
||||
|
||||
if (faceCorners.size == 0) return true;
|
||||
|
||||
// Remove faces for manifold subsets in the other direction:
|
||||
do {
|
||||
removed = faceCorners.RemoveManifoldSubset(creaseEnd[1], creaseEnd[0]);
|
||||
if (removed < 0) {
|
||||
return false;
|
||||
}
|
||||
} while (removed);
|
||||
|
||||
return (faceCorners.size == 0);
|
||||
}
|
||||
|
||||
} // end namespace Bfr
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -200,7 +200,11 @@ private:
|
||||
void assignUnOrderedFaceNeighbors(Edge const edges[],
|
||||
short const faceEdgeIndices[]);
|
||||
|
||||
void finalizeUnOrderedTags(Edge const edges[], int numEdges);
|
||||
bool testNonManifoldCrease(Edge const edges[], int numEdges,
|
||||
Index const faceVertIndices[]) const;
|
||||
|
||||
void finalizeUnOrderedTags(Edge const edges[], int numEdges,
|
||||
Index const faceVertIndices[]);
|
||||
|
||||
// Ordered counterpart to the above method for finalizing tags
|
||||
void finalizeOrderedTags();
|
||||
|
Loading…
Reference in New Issue
Block a user