mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-29 23:01:05 +00:00
Merge pull request #850 from barfowl/fvar_tags
Minor updates to tags for face-varying and inf-sharp topology
This commit is contained in:
commit
831e2092dd
@ -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;
|
||||
|
@ -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:
|
||||
//
|
||||
|
@ -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<VertTagSize *>(&compVTag));
|
||||
|
||||
compInt = 0;
|
||||
for (int i = 0; i < faceVerts.size(); ++i) {
|
||||
VertTag & srcVTag = fvarVTags[i];
|
||||
VertTagSize & srcInt = *(reinterpret_cast<VertTagSize *>(&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<FaceETagSize *>(&compETag));
|
||||
|
||||
compInt = 0;
|
||||
for (int i = 0; i < faceEdges.size(); ++i) {
|
||||
FaceETag & srcETag = fvarETags[i];
|
||||
FaceETagSize & srcInt = *(reinterpret_cast<FaceETagSize *>(&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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user