diff --git a/opensubdiv/far/topologyRefiner.cpp b/opensubdiv/far/topologyRefiner.cpp index 4a3d125d..c150212c 100644 --- a/opensubdiv/far/topologyRefiner.cpp +++ b/opensubdiv/far/topologyRefiner.cpp @@ -501,33 +501,23 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::internal::SparseSelector& // if (! selectFace && considerFVarChannels) { for (int channel = 0; ! selectFace && (channel < numFVarChannels); ++channel) { - Vtr::internal::FVarLevel const & fvarLevel = level.getFVarLevel(channel); - - // - // Retrieve the counterpart to the face-vertices composite tag for the face-values - // for this channel. We can make some quick accept/reject tests but eventually we - // will need to combine the face-vertex and face-varying topology to determine the - // regularity of faces along face-varying boundaries. - // - Vtr::ConstIndexArray faceValues = fvarLevel.getFaceValues(face); - - Vtr::internal::FVarLevel::ValueTag compFVarFaceTag = - fvarLevel.getFaceCompositeValueTag(faceValues, faceVerts); // No mismatch in topology -> no need to further isolate... - if (! compFVarFaceTag._mismatch) continue; + if (level.doesFaceFVarTopologyMatch(face, channel)) continue; - if (compFVarFaceTag._xordinary) { + // + // Get the corner tags for the FVar topology, combine, then make similar inferences + // from the combined tags as done above for the vertex topology: + // + Vtr::internal::Level::VTag fvarVTags[4]; + level.getFaceVTags(face, fvarVTags, channel); + + Vtr::internal::Level::VTag compFVarVTag = Vtr::internal::Level::VTag::BitwiseOr(fvarVTags); + + if (compFVarVTag._xordinary) { // An xordinary boundary value always requires isolation: selectFace = true; } else { - // Combine the FVar topology tags (ValueTags) at corners with the vertex topology - // tags (VTags), then make similar inferences from the combined tags as was done - // for the face. - Vtr::internal::Level::VTag fvarVTags[4]; - Vtr::internal::Level::VTag compFVarVTag = - fvarLevel.getFaceCompositeValueAndVTag(faceValues, faceVerts, fvarVTags); - if (! (compFVarVTag._rule & Sdc::Crease::RULE_SMOOTH)) { // No Smooth corners so too many boundaries/corners -- need to isolate: selectFace = true; diff --git a/opensubdiv/far/topologyRefinerFactory.cpp b/opensubdiv/far/topologyRefinerFactory.cpp index 0fc72855..e506c28c 100644 --- a/opensubdiv/far/topologyRefinerFactory.cpp +++ b/opensubdiv/far/topologyRefinerFactory.cpp @@ -273,11 +273,12 @@ TopologyRefinerFactoryBase::prepareComponentTagsAndSharpness(TopologyRefiner& re // vTag._infSharpEdges = (infSharpEdgeCount > 0); vTag._infSharpCrease = false; - vTag._infSharpCorners = false; vTag._infIrregular = vTag._infSharp || vTag._infSharpEdges; if (vTag._infSharpEdges) { - Sdc::Crease::Rule infRule = creasing.DetermineVertexVertexRule(vSharpness, infSharpEdgeCount); + // Ignore semi-sharp vertex sharpness when computing the inf-sharp Rule: + Sdc::Crease::Rule infRule = creasing.DetermineVertexVertexRule( + (vTag._infSharp ? vSharpness : 0.0f), infSharpEdgeCount); if (infRule == Sdc::Crease::RULE_CREASE) { vTag._infSharpCrease = true; @@ -305,8 +306,6 @@ TopologyRefinerFactoryBase::prepareComponentTagsAndSharpness(TopologyRefiner& re } } } else if (infRule == Sdc::Crease::RULE_CORNER) { - vTag._infSharpCorners = true; - // A regular set of inf-corners occurs when all edges are sharp and not // a smooth corner: // diff --git a/opensubdiv/vtr/fvarLevel.cpp b/opensubdiv/vtr/fvarLevel.cpp index 65ee0af3..0e5f070a 100644 --- a/opensubdiv/vtr/fvarLevel.cpp +++ b/opensubdiv/vtr/fvarLevel.cpp @@ -508,12 +508,17 @@ FVarLevel::completeTopologyFromFaceValues(int regularBoundaryValence) { bool isInfSharp = allCornersAreSharp || vSpan._infSharp || ((vSpan._size == 1) && fvarCornersAreSharp); + if (vSpan._size == 1) { valueTag._xordinary = !isInfSharp; } else { valueTag._xordinary = (vSpan._size != regularBoundaryValence); } + valueTag._infSharpEdges = (vSpan._infSharp > 0); + valueTag._infIrregular = vSpan._infSharp ? ((vSpan._size - vSpan._infSharp) > 1) + : valueTag._xordinary; + if (!isInfSharp) { if (vSpan._semiSharp || vTag._semiSharp) { valueTag._semiSharp = true; @@ -533,7 +538,6 @@ FVarLevel::completeTopologyFromFaceValues(int regularBoundaryValence) { } else { valueCrease._endFace = (LocalIndex) (vSpan._start + vSpan._size - 1); } - valueTag._creaseEnds = true; } } } @@ -1007,13 +1011,6 @@ FVarLevel::getFaceCompositeValueTag(Index faceIndex) const { ConstIndexArray faceValues = getFaceValues(faceIndex); ConstIndexArray faceVerts = _level.getFaceVertices(faceIndex); - return getFaceCompositeValueTag(faceValues, faceVerts); -} - -FVarLevel::ValueTag -FVarLevel::getFaceCompositeValueTag(ConstIndexArray & faceValues, - ConstIndexArray & faceVerts) const { - typedef ValueTag::ValueTagSize ValueTagSize; ValueTag compTag; @@ -1032,71 +1029,6 @@ FVarLevel::getFaceCompositeValueTag(ConstIndexArray & faceValues, return compTag; } -Level::VTag -FVarLevel::getFaceCompositeValueAndVTag(ConstIndexArray & faceValues, - ConstIndexArray & faceVerts, - Level::VTag * fvarVTags) const { - - typedef Level::VTag VertTag; - typedef Level::VTag::VTagSize VertTagSize; - - // - // Create a composite VTag for the face that augments the vertex corners' VTag's with - // topological information about the FVar values at each corner. Only when there is - // a mismatch does the FVar value need to be inspected further: - // - VertTag compVTag; - VertTagSize & compInt = *(reinterpret_cast(&compVTag)); - - compInt = 0; - for (int i = 0; i < faceVerts.size(); ++i) { - VertTag & srcVTag = fvarVTags[i]; - VertTagSize & srcInt = *(reinterpret_cast(&srcVTag)); - - srcVTag = _level.getVertexTag(faceVerts[i]); - - Index srcValueIndex = findVertexValueIndex(faceVerts[i], faceValues[i]); - assert(_vertValueIndices[srcValueIndex] == faceValues[i]); - - ValueTag const & srcValueTag = _vertValueTags[srcValueIndex]; - srcVTag = srcValueTag.combineWithLevelVTag(srcVTag); - - compInt |= srcInt; - } - return compVTag; -} - -Level::ETag -FVarLevel::getFaceCompositeCombinedEdgeTag(ConstIndexArray & faceEdges, - Level::ETag * fvarETags) const { - - typedef Level::ETag FaceETag; - typedef Level::ETag::ETagSize FaceETagSize; - - // - // Create a composite ETag for the face that augments the edges ETag's with - // topological information about the FVar values at each corner. Only when there is - // a mismatch does the FVar value need to be inspected further: - // - FaceETag compETag; - FaceETagSize & compInt = *(reinterpret_cast(&compETag)); - - compInt = 0; - for (int i = 0; i < faceEdges.size(); ++i) { - FaceETag & srcETag = fvarETags[i]; - FaceETagSize & srcInt = *(reinterpret_cast(&srcETag)); - - srcETag = _level.getEdgeTag(faceEdges[i]); - - FVarLevel::ETag const & fvarETag = _edgeTags[faceEdges[i]]; - if (fvarETag._mismatch) { - srcETag._boundary = true; - } - compInt |= srcInt; - } - return compETag; -} - } // end namespace internal } // end namespace Vtr diff --git a/opensubdiv/vtr/fvarLevel.h b/opensubdiv/vtr/fvarLevel.h index 15927154..27d4ab6f 100644 --- a/opensubdiv/vtr/fvarLevel.h +++ b/opensubdiv/vtr/fvarLevel.h @@ -103,7 +103,7 @@ public: // Tag per Value: // - informs both refinement and interpolation // - every value spawns a child value in refinement - // - given ordering of values (1-per-vertex first) serves as a vertex tag + // - includes a subset of Level::VTag to be later combined with a VTag // struct ValueTag { ValueTag() { } @@ -116,7 +116,10 @@ public: bool isSemiSharp() const { return _semiSharp; } bool isInfSharp() const { return !_semiSharp && !_crease; } bool isDepSharp() const { return _depSharp; } - bool hasCreaseEnds() const { return _creaseEnds; } + bool hasCreaseEnds() const { return _crease || _semiSharp; } + + bool hasInfSharpEdges() const { return _infSharpEdges; } + bool hasInfIrregularity() const { return _infIrregular; } typedef unsigned char ValueTagSize; @@ -125,10 +128,12 @@ public: ValueTagSize _xordinary : 1; // local FVar topology is extra-ordinary ValueTagSize _nonManifold : 1; // local FVar topology is non-manifold ValueTagSize _crease : 1; // value is a crease, otherwise a corner - ValueTagSize _creaseEnds : 1; // set when a crease-end-pair is assigned ValueTagSize _semiSharp : 1; // value is a corner decaying to crease ValueTagSize _depSharp : 1; // value is a corner by dependency on another + ValueTagSize _infSharpEdges : 1; // value is a corner by inf-sharp features + ValueTagSize _infIrregular : 1; // value span includes inf-sharp irregularity + Level::VTag combineWithLevelVTag(Level::VTag) const; }; @@ -209,15 +214,6 @@ public: void getFaceValueTags(Index faceIndex, ValueTag valueTags[]) const; ValueTag getFaceCompositeValueTag(Index faceIndex) const; - ValueTag getFaceCompositeValueTag(ConstIndexArray & faceValues, - ConstIndexArray & faceVerts) const; - - Level::VTag getFaceCompositeValueAndVTag(ConstIndexArray & faceValues, - ConstIndexArray & faceVerts, - Level::VTag * fvarVTags) const; - - Level::ETag getFaceCompositeCombinedEdgeTag(ConstIndexArray & faceEdges, - Level::ETag * fvarETags) const; // Higher-level topological queries, i.e. values in a neighborhood: void getEdgeFaceValues(Index eIndex, int fIncToEdge, Index valuesPerVert[2]) const; @@ -401,10 +397,15 @@ FVarLevel::ValueTag::combineWithLevelVTag(Level::VTag levelTag) const if (this->isCorner()) { levelTag._rule = (Level::VTag::VTagSize) Sdc::Crease::RULE_CORNER; levelTag._infSharp = true; + levelTag._infSharpCrease = false; } else { levelTag._rule = (Level::VTag::VTagSize) Sdc::Crease::RULE_CREASE; levelTag._infSharp = false; + levelTag._infSharpCrease = true; } + levelTag._infSharpEdges = true; + levelTag._infIrregular = this->_infIrregular; + levelTag._boundary = true; levelTag._xordinary = this->_xordinary; levelTag._nonManifold = this->_nonManifold; diff --git a/opensubdiv/vtr/level.cpp b/opensubdiv/vtr/level.cpp index f7ab066d..fc8616c7 100644 --- a/opensubdiv/vtr/level.cpp +++ b/opensubdiv/vtr/level.cpp @@ -539,7 +539,6 @@ Level::print(const Refinement* pRefinement) const { printf(", infSharp = %d", (int)vTag._infSharp); printf(", infSharpEdges = %d", (int)vTag._infSharpEdges); printf(", infSharpCrease = %d", (int)vTag._infSharpCrease); - printf(", infSharpCorners = %d",(int)vTag._infSharpCorners); printf(", infIrregular = %d", (int)vTag._infIrregular); printf(", semiSharp = %d", (int)vTag._semiSharp); printf(", semiSharpEdges = %d", (int)vTag._semiSharpEdges); diff --git a/opensubdiv/vtr/level.h b/opensubdiv/vtr/level.h index 68e17a6c..71534740 100644 --- a/opensubdiv/vtr/level.h +++ b/opensubdiv/vtr/level.h @@ -114,17 +114,11 @@ public: VTagSize _rule : 4; // variable when _semiSharp VTagSize _incomplete : 1; // variable for sparse refinement - // Inf-sharp tags -- in development, some may not persist... + // Tags indicating incident infinitely-sharp (permanent) features VTagSize _infSharpEdges : 1; // fixed VTagSize _infSharpCrease : 1; // fixed - VTagSize _infSharpCorners : 1; // fixed VTagSize _infIrregular : 1; // fixed - // On deck -- coming soon... - //VTagSize _constSharp : 1; // variable when _semiSharp - //VTagSize _hasEdits : 1; // variable - //VTagSize _editsApplied : 1; // variable - static VTag BitwiseOr(VTag const vTags[], int size = 4); }; struct ETag {