Revised Level::VTags for semi-sharpness and added corner tag:

- added new tag for sharp corner, now used in isolation
    - split single semi-sharp tag in two for vertex and edge sharpness
    - updated tag propagation and all tests of previous semi-sharp tag
    - added clear() methods for all tags and simplified initialization
This commit is contained in:
barfowl 2015-02-25 20:02:10 -08:00
parent 3c88851cf6
commit 4ced1b1461
6 changed files with 135 additions and 105 deletions

View File

@ -523,7 +523,7 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
// support regular patches with one corner or one boundary, i.e. with one or more
// smooth interior vertices.
selectFace = true;
} else if (compFaceVTag._semiSharp) {
} else if (compFaceVTag._semiSharp || compFaceVTag._semiSharpEdges) {
// Any semi-sharp feature at or around the vertex warrants isolation -- unless we
// optimize for the single-crease patch, i.e. only edge sharpness of a constant value
// along the entire regular patch boundary (quickly exclude the Corner case first):
@ -552,17 +552,25 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
// boundary patch, so don't isolate.
selectFace = false;
} else {
// This is the last case with at least one Corner (infinitely-sharp) vertex and one
// Smooth (interior) vertex. Distinguish the regular corner case from others -- this
// is where the _corner tag on the vertex would help but we still need ensure that no
// vertex other than the corner is sharp, and so inspection of each is unavoidable...
unsigned int boundaryCount = level._vertTags[faceVerts[0]]._boundary,
infSharpCount = level._vertTags[faceVerts[0]]._infSharp;
for (int i = 1; i < faceVerts.size(); ++i) {
boundaryCount += level._vertTags[faceVerts[i]]._boundary;
infSharpCount += level._vertTags[faceVerts[i]]._infSharp;
// The last case with at least one Corner vertex and one Smooth (interior) vertex --
// distinguish the regular corner case from others:
if (not compFaceVTag._corner) {
// We may consider interior sharp corners as regular in future, but for now we
// only accept a topological corner for the regular corner case:
selectFace = true;
} else if (level.getDepth() > 0) {
// A true corner at a subdivided level -- adjacent verts must be Crease and the
// opposite Smooth so we must have a regular corner:
selectFace = false;
} else {
// Make sure the adjacent boundary vertices were not sharpened, or equivalently,
// that only one corner is sharp:
unsigned int infSharpCount = level._vertTags[faceVerts[0]]._infSharp;
for (int i = 1; i < faceVerts.size(); ++i) {
infSharpCount += level._vertTags[faceVerts[i]]._infSharp;
}
selectFace = (infSharpCount != 1);
}
selectFace = (boundaryCount != 3) || (infSharpCount != 1);
}
//

View File

@ -175,8 +175,9 @@ TopologyRefinerFactoryBase::prepareComponentTagsAndSharpness(TopologyRefiner& re
// Sharpen the vertex before using it in conjunction with incident edge
// properties to determine the semi-sharp tag and rule:
//
bool isCorner = (vFaces.size() == 1) && (vEdges.size() == 2);
if (isCorner && sharpenCornerVerts) {
bool isTopologicalCorner = (vFaces.size() == 1) && (vEdges.size() == 2);
bool isSharpenedCorner = isTopologicalCorner && sharpenCornerVerts;
if (isSharpenedCorner) {
vSharpness = Sdc::Crease::SHARPNESS_INFINITE;
} else if (vTag._nonManifold && sharpenNonManFeatures) {
// Don't sharpen the vertex if a non-manifold crease:
@ -185,9 +186,9 @@ TopologyRefinerFactoryBase::prepareComponentTagsAndSharpness(TopologyRefiner& re
}
}
vTag._infSharp = Sdc::Crease::IsInfinite(vSharpness);
vTag._semiSharp = Sdc::Crease::IsSemiSharp(vSharpness) || (semiSharpEdgeCount > 0);
vTag._infSharp = Sdc::Crease::IsInfinite(vSharpness);
vTag._semiSharp = Sdc::Crease::IsSemiSharp(vSharpness);
vTag._semiSharpEdges = (semiSharpEdgeCount > 0);
vTag._rule = (Vtr::Level::VTag::VTagSize)creasing.DetermineVertexVertexRule(vSharpness, sharpEdgeCount);
@ -196,8 +197,9 @@ TopologyRefinerFactoryBase::prepareComponentTagsAndSharpness(TopologyRefiner& re
// tag is still being considered, but regardless, it depends on the Sdc::Scheme...
//
vTag._boundary = (vFaces.size() < vEdges.size());
if (isCorner) {
vTag._xordinary = !sharpenCornerVerts;
vTag._corner = isSharpenedCorner;
if (vTag._corner) {
vTag._xordinary = false;
} else if (vTag._boundary) {
vTag._xordinary = (vFaces.size() != schemeRegularBoundaryValence);
} else {

View File

@ -554,16 +554,20 @@ FVarRefinement::reclassifySemisharpValues() {
if (_refinement._childVertexTag[cVert]._incomplete) continue;
// If the parent vertex wasn't semi-sharp, the child vertex and values can't be:
Index pVert = _refinement.getChildVertexParentIndex(cVert);
if (!_parentLevel._vertTags[pVert]._semiSharp) continue;
Index pVert = _refinement.getChildVertexParentIndex(cVert);
Level::VTag pVertTags = _parentLevel._vertTags[pVert];
if (!pVertTags._semiSharp && !pVertTags._semiSharpEdges) continue;
// If the child vertex is still sharp, all values remain unaffected:
if (!Sdc::Crease::IsSmooth(_childLevel._vertSharpness[cVert])) continue;
Level::VTag cVertTags = _childLevel._vertTags[cVert];
if (cVertTags._semiSharp || cVertTags._infSharp) continue;
// If the child is no longer semi-sharp, we can just clear those values marked
// (i.e. make them creases, others may remain corners) and continue:
//
if (!_childLevel._vertTags[cVert]._semiSharp) {
if (!cVertTags._semiSharp && !cVertTags._semiSharpEdges) {
for (int j = 0; j < cValueTags.size(); ++j) {
if (cValueTags[j]._semiSharp) {
FVarLevel::ValueTag cValueTagOld = cValueTags[j];
@ -626,11 +630,6 @@ float
FVarRefinement::getFractionalWeight(Index pVert, LocalIndex pSibling,
Index cVert, LocalIndex /* cSibling */) const {
// Should only be called when the parent was semi-sharp but this child vertex
// value (not necessarily the child vertex as a whole) is no longer semi-sharp:
assert(_parentLevel._vertTags[pVert]._semiSharp);
assert(!_childLevel._vertTags[cVert]._incomplete);
//
// Need to identify sharpness values for edges within the spans for both the
// parent and child...

View File

@ -517,9 +517,11 @@ Level::print(const Refinement* pRefinement) const {
printf(" vert %4d:", i);
printf(" rule = %s", ruleString((Sdc::Crease::Rule)vTag._rule));
printf(", boundary = %d", (int)vTag._boundary);
printf(", corner = %d", (int)vTag._corner);
printf(", xordinary = %d", (int)vTag._xordinary);
printf(", semiSharp = %d", (int)vTag._semiSharp);
printf(", infSharp = %d", (int)vTag._infSharp);
printf(", semiSharp = %d", (int)vTag._semiSharp);
printf(", semiSharpEdges = %d", (int)vTag._semiSharpEdges);
printf("\n");
}
fflush(stdout);

View File

@ -135,17 +135,24 @@ public:
// level.
//
struct VTag {
typedef unsigned short VTagSize;
VTag() { }
VTagSize _nonManifold : 1; // fixed
VTagSize _xordinary : 1; // fixed
VTagSize _boundary : 1; // fixed
VTagSize _infSharp : 1; // fixed
VTagSize _semiSharp : 1; // variable
VTagSize _rule : 4; // variable when _semiSharp
VTagSize _incomplete : 1; // variable for sparse refinement
// When cleared, the VTag ALMOST represents a smooth, regular, interior
// vertex -- the Type enum requires a bit be explicitly set for Smooth,
// so that must be done explicitly if desired on initialization.
void clear() { std::memset(this, 0, sizeof(VTag)); }
typedef unsigned short VTagSize;
VTagSize _nonManifold : 1; // fixed
VTagSize _xordinary : 1; // fixed
VTagSize _boundary : 1; // fixed
VTagSize _corner : 1; // fixed
VTagSize _infSharp : 1; // fixed
VTagSize _semiSharp : 1; // variable
VTagSize _semiSharpEdges : 1; // variable
VTagSize _rule : 4; // variable when _semiSharp
VTagSize _incomplete : 1; // variable for sparse refinement
// On deck -- coming soon...
//VTagSize _constSharp : 1; // variable when _semiSharp
@ -153,20 +160,25 @@ public:
//VTagSize _editsApplied : 1; // variable
};
struct ETag {
typedef unsigned char ETagSize;
ETag() { }
// When cleared, the ETag represents a smooth, manifold, interior edge
void clear() { std::memset(this, 0, sizeof(ETag)); }
typedef unsigned char ETagSize;
ETagSize _nonManifold : 1; // fixed
ETagSize _boundary : 1; // fixed
ETagSize _infSharp : 1; // fixed
ETagSize _semiSharp : 1; // variable
};
struct FTag {
typedef unsigned char FTagSize;
FTag() { }
void clear() { std::memset(this, 0, sizeof(FTag)); }
typedef unsigned char FTagSize;
FTagSize _hole : 1; // fixed
// On deck -- coming soon...

View File

@ -665,10 +665,7 @@ Refinement::populateEdgeTagsFromParentFaces() {
// Tags for edges originating from faces are all constant:
//
Level::ETag eTag;
eTag._nonManifold = 0;
eTag._boundary = 0;
eTag._infSharp = 0;
eTag._semiSharp = 0;
eTag.clear();
Index cEdge = getFirstChildEdgeFromFaces();
Index cEdgeEnd = cEdge + getNumChildEdgesFromFaces();
@ -717,13 +714,8 @@ Refinement::populateVertexTagsFromParentFaces() {
if (getNumChildVerticesFromFaces() == 0) return;
Level::VTag vTag;
vTag._nonManifold = 0;
vTag._xordinary = 0;
vTag._boundary = 0;
vTag._infSharp = 0;
vTag._semiSharp = 0;
vTag._rule = Sdc::Crease::RULE_SMOOTH;
vTag._incomplete = 0;
vTag.clear();
vTag._rule = Sdc::Crease::RULE_SMOOTH;
Index cVert = getFirstChildVertexFromFaces();
Index cVertEnd = cVert + getNumChildVerticesFromFaces();
@ -749,22 +741,25 @@ Refinement::populateVertexTagsFromParentEdges() {
// Tags for vertices originating from edges are initialized according to the tags
// of the parent edge:
//
Level::VTag vTag;
vTag.clear();
for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
Index cVert = _edgeChildVertIndex[pEdge];
if (!IndexIsValid(cVert)) continue;
// From the cleared local VTag, we just need to assign properties dependent
// on the parent edge:
Level::ETag const& pEdgeTag = _parent->_edgeTags[pEdge];
Level::VTag& cVertTag = _child->_vertTags[cVert];
cVertTag._nonManifold = pEdgeTag._nonManifold;
cVertTag._xordinary = false;
cVertTag._boundary = pEdgeTag._boundary;
cVertTag._infSharp = false;
vTag._nonManifold = pEdgeTag._nonManifold;
vTag._boundary = pEdgeTag._boundary;
vTag._semiSharpEdges = pEdgeTag._semiSharp;
cVertTag._semiSharp = pEdgeTag._semiSharp;
cVertTag._rule = (Level::VTag::VTagSize)((pEdgeTag._semiSharp || pEdgeTag._infSharp)
vTag._rule = (Level::VTag::VTagSize)((pEdgeTag._semiSharp || pEdgeTag._infSharp)
? Sdc::Crease::RULE_CREASE : Sdc::Crease::RULE_SMOOTH);
cVertTag._incomplete = 0;
_child->_vertTags[cVert] = vTag;
}
}
void
@ -851,9 +846,13 @@ Refinement::subdivideSharpnessValues() {
// process. So for now we apply a post-process to explicitly handle all
// semi-sharp vertices.
//
// These methods will update sharpness tags local to the edges and vertices:
subdivideEdgeSharpness();
subdivideVertexSharpness();
// This method uses local sharpness tags (set above) to update vertex tags that
// reflect the neighborhood of the vertex (e.g. its rule):
reclassifySemisharpVertices();
}
@ -910,7 +909,9 @@ Refinement::subdivideEdgeSharpness() {
cSharpness = creasing.SubdivideEdgeSharpnessAtVertex(pSharpness, pVertEdges.size(),
pVertEdgeSharpness);
}
cEdgeTag._semiSharp = Sdc::Crease::IsSharp(cSharpness);
if (not Sdc::Crease::IsSharp(cSharpness)) {
cEdgeTag._semiSharp = false;
}
}
}
}
@ -942,11 +943,8 @@ Refinement::subdivideVertexSharpness() {
float pSharpness = _parent->_vertSharpness[pVert];
cSharpness = creasing.SubdivideVertexSharpness(pSharpness);
if (!Sdc::Crease::IsSharp(cSharpness)) {
// Need to visit edge neighborhood to determine if still semisharp...
// cVertTag._infSharp = ...?
// See the "reclassify" method below...
if (not Sdc::Crease::IsSharp(cSharpness)) {
cVertTag._semiSharp = false;
}
}
}
@ -969,7 +967,7 @@ Refinement::reclassifySemisharpVertices() {
for (Index cVert = vertFromEdgeBegin; cVert < vertFromEdgeEnd; ++cVert) {
Level::VTag& cVertTag = _child->_vertTags[cVert];
if (!cVertTag._semiSharp) continue;
if (!cVertTag._semiSharpEdges) continue;
Index pEdge = _childVertexParentIndex[cVert];
@ -977,21 +975,21 @@ Refinement::reclassifySemisharpVertices() {
if (_childVertexTag[cVert]._incomplete) {
// One child edge likely missing -- assume Crease if remaining edge semi-sharp:
cVertTag._semiSharp = (IndexIsValid(cEdges[0]) && _child->_edgeTags[cEdges[0]]._semiSharp) ||
(IndexIsValid(cEdges[1]) && _child->_edgeTags[cEdges[1]]._semiSharp);
cVertTag._rule = (VTagSize)(cVertTag._semiSharp ? Sdc::Crease::RULE_CREASE : Sdc::Crease::RULE_SMOOTH);
cVertTag._semiSharpEdges = (IndexIsValid(cEdges[0]) && _child->_edgeTags[cEdges[0]]._semiSharp) ||
(IndexIsValid(cEdges[1]) && _child->_edgeTags[cEdges[1]]._semiSharp);
cVertTag._rule = (VTagSize)(cVertTag._semiSharpEdges ? Sdc::Crease::RULE_CREASE : Sdc::Crease::RULE_SMOOTH);
} else {
int sharpEdgeCount = _child->_edgeTags[cEdges[0]]._semiSharp + _child->_edgeTags[cEdges[1]]._semiSharp;
cVertTag._semiSharp = (sharpEdgeCount > 0);
cVertTag._rule = (VTagSize)(creasing.DetermineVertexVertexRule(0.0, sharpEdgeCount));
cVertTag._semiSharpEdges = (sharpEdgeCount > 0);
cVertTag._rule = (VTagSize)(creasing.DetermineVertexVertexRule(0.0, sharpEdgeCount));
}
}
//
// Inspect all vertices derived from vertices -- for those whose parent vertices were
// semisharp, reset the semisharp tag and the associated Rule based on the neighborhood
// of child edges around the child vertex.
// semisharp (inherited in the child vert's tag), inspect and reset the semisharp tag
// and the associated Rule (based on neighboring child edges around the child vertex).
//
// We should never find such a vertex "incomplete" in a sparse refinement as a parent
// vertex is either selected or not, but never neighboring. So the only complication
@ -1006,47 +1004,56 @@ Refinement::reclassifySemisharpVertices() {
Index vertFromVertEnd = vertFromVertBegin + getNumChildVerticesFromVertices();
for (Index cVert = vertFromVertBegin; cVert < vertFromVertEnd; ++cVert) {
Index pVert = _childVertexParentIndex[cVert];
Level::VTag const& pVertTag = _parent->_vertTags[pVert];
// Skip if parent not semi-sharp:
if (!pVertTag._semiSharp && !pVertTag._semiSharpEdges) continue;
//
// We need to inspect the child neighborhood's sharpness when either semi-sharp
// edges were present around the parent vertex, or the parent vertex sharpness
// decayed:
//
Level::VTag& cVertTag = _child->_vertTags[cVert];
if (!cVertTag._semiSharp) continue;
// If the vertex is still sharp, it remains the semisharp Corner its parent was...
if (_child->_vertSharpness[cVert] > 0.0) continue;
bool sharpVertexDecayed = pVertTag._semiSharp && !cVertTag._semiSharp;
//
// See if we can use the vert-edges of the child vertex:
//
int sharpEdgeCount = 0;
int semiSharpEdgeCount = 0;
if (pVertTag._semiSharpEdges || sharpVertexDecayed) {
int infSharpEdgeCount = 0;
int semiSharpEdgeCount = 0;
bool cVertEdgesPresent = (_child->getNumVertexEdgesTotal() > 0);
if (cVertEdgesPresent) {
IndexArray const cEdges = _child->getVertexEdges(cVert);
bool cVertEdgesPresent = (_child->getNumVertexEdgesTotal() > 0);
if (cVertEdgesPresent) {
IndexArray const cEdges = _child->getVertexEdges(cVert);
for (int i = 0; i < cEdges.size(); ++i) {
Level::ETag cEdgeTag = _child->_edgeTags[cEdges[i]];
for (int i = 0; i < cEdges.size(); ++i) {
Level::ETag cEdgeTag = _child->_edgeTags[cEdges[i]];
sharpEdgeCount += cEdgeTag._semiSharp || cEdgeTag._infSharp;
semiSharpEdgeCount += cEdgeTag._semiSharp;
infSharpEdgeCount += cEdgeTag._infSharp;
semiSharpEdgeCount += cEdgeTag._semiSharp;
}
} else {
ConstIndexArray pEdges = _parent->getVertexEdges(pVert);
ConstLocalIndexArray pVertInEdge = _parent->getVertexEdgeLocalIndices(pVert);
for (int i = 0; i < pEdges.size(); ++i) {
ConstIndexArray cEdgePair = getEdgeChildEdges(pEdges[i]);
Index cEdge = cEdgePair[pVertInEdge[i]];
Level::ETag cEdgeTag = _child->_edgeTags[cEdge];
infSharpEdgeCount += cEdgeTag._infSharp;
semiSharpEdgeCount += cEdgeTag._semiSharp;
}
}
} else {
Index pVert = _childVertexParentIndex[cVert];
cVertTag._semiSharpEdges = (semiSharpEdgeCount > 0);
ConstIndexArray pEdges = _parent->getVertexEdges(pVert);
ConstLocalIndexArray pVertInEdge = _parent->getVertexEdgeLocalIndices(pVert);
for (int i = 0; i < pEdges.size(); ++i) {
ConstIndexArray cEdgePair = getEdgeChildEdges(pEdges[i]);
Index cEdge = cEdgePair[pVertInEdge[i]];
Level::ETag cEdgeTag = _child->_edgeTags[cEdge];
sharpEdgeCount += cEdgeTag._semiSharp || cEdgeTag._infSharp;
semiSharpEdgeCount += cEdgeTag._semiSharp;
if (!cVertTag._semiSharp && !cVertTag._infSharp) {
cVertTag._rule = (VTagSize)(creasing.DetermineVertexVertexRule(0.0,
infSharpEdgeCount + semiSharpEdgeCount));
}
}
cVertTag._semiSharp = (semiSharpEdgeCount > 0);
cVertTag._rule = (VTagSize)(creasing.DetermineVertexVertexRule(0.0, sharpEdgeCount));
}
}