mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-26 09:41:08 +00:00
Added support for semi-sharp features along face-varying boundaries:
- added semi-sharp tag to FVar ValueTags and applied in base FVarLevel - re-assess status of tagged semi-sharp values in each FVarRefinement - detect and apply fractional weighting in InterpolateFaceVarying()
This commit is contained in:
parent
639788abbe
commit
f706062ab1
@ -1148,6 +1148,9 @@ TopologyRefiner::faceVaryingInterpolateChildVertsFromVerts(
|
||||
//
|
||||
// Each FVar value associated with a vertex will be either a corner or a crease,
|
||||
// or potentially in transition from corner to crease:
|
||||
// - if the CHILD is a corner, we have no transition but a corner
|
||||
// - otherwise if the PARENT is a crease too, we have no transition but a creas
|
||||
// - otherwise the parent must be a corner and the child a crease.
|
||||
//
|
||||
for (int cSibling = 0; cSibling < childFVar.getNumVertexValues(cVert); ++cSibling) {
|
||||
int pSibling = refineFVar.getChildValueParentSource(cVert, cSibling);
|
||||
@ -1159,15 +1162,29 @@ TopologyRefiner::faceVaryingInterpolateChildVertsFromVerts(
|
||||
U & vdst = dst[cVertValue];
|
||||
|
||||
vdst.Clear();
|
||||
if (parentFVar.isValueCorner(parentFVar.getVertexValueIndex(vert, pSibling))) {
|
||||
if (childFVar.isValueCorner(childFVar.getVertexValueIndex(cVert, cSibling))) {
|
||||
vdst.AddWithWeight(src[pVertValue], 1.0f);
|
||||
} else {
|
||||
//
|
||||
// We have either a crease or a transition from corner to crease -- in
|
||||
// either case, we need the end values for the crease:
|
||||
//
|
||||
Index pEndValues[2];
|
||||
parentFVar.getVertexCreaseEndValues(vert, pSibling, pEndValues);
|
||||
|
||||
vdst.AddWithWeight(src[pEndValues[0]], 0.125f);
|
||||
vdst.AddWithWeight(src[pEndValues[1]], 0.125f);
|
||||
vdst.AddWithWeight(src[pVertValue], 0.75f);
|
||||
float vWeight = 0.75f;
|
||||
float eWeight = 0.125f;
|
||||
|
||||
if (parentFVar.isValueSemiSharp(parentFVar.getVertexValueIndex(vert, pSibling))) {
|
||||
float wCorner = refineFVar.getFractionalWeight(vert, pSibling, cVert, cSibling);
|
||||
float wCrease = 1.0f - wCorner;
|
||||
|
||||
vWeight = wCrease * 0.75f + wCorner;
|
||||
eWeight = wCrease * 0.125f;
|
||||
}
|
||||
vdst.AddWithWeight(src[pEndValues[0]], eWeight);
|
||||
vdst.AddWithWeight(src[pEndValues[1]], eWeight);
|
||||
vdst.AddWithWeight(src[pVertValue], vWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,7 +311,12 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
// vertex and to inspect local face-varying topology in more detail when necessary:
|
||||
//
|
||||
ValueTag valueTagCrease = valueTagMismatch;
|
||||
valueTagCrease._crease = true;
|
||||
valueTagCrease._crease = true;
|
||||
valueTagCrease._semiSharp = false;
|
||||
|
||||
ValueTag valueTagSemiSharp = valueTagMismatch;
|
||||
valueTagSemiSharp._crease = false;
|
||||
valueTagSemiSharp._semiSharp = true;
|
||||
|
||||
for (int vIndex = 0; vIndex < _level.getNumVertices(); ++vIndex) {
|
||||
IndexArray const vFaces = _level.getVertexFaces(vIndex);
|
||||
@ -350,9 +355,16 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
// further inspection there may be other cases where all are determined to be
|
||||
// sharp, but use what information we can now to avoid that inspection:
|
||||
//
|
||||
bool vIsBoundary = _level._vertTags[vIndex]._boundary;
|
||||
// Regarding sharpness of the vertex itself, its vertex tags reflect the inf-
|
||||
// or semi-sharp nature of the vertex and edges around it, so be careful not
|
||||
// to assume too much from say, the presence of an incident inf-sharp edge.
|
||||
// We can make clear decisions based on the sharpness of the vertex itself.
|
||||
//
|
||||
bool vIsBoundary = _level._vertTags[vIndex]._boundary;
|
||||
float vSharpness = _level._vertSharpness[vIndex];
|
||||
|
||||
bool allCornersAreSharp = !_hasSmoothBoundaries ||
|
||||
Sdc::Crease::IsInfinite(vSharpness) ||
|
||||
(sharpenAllIfMoreThan2 && (vValueCount > 2)) ||
|
||||
(sharpenDarts && (vValueCount == 1) && !vIsBoundary) ||
|
||||
_level._vertTags[vIndex]._nonManifold;
|
||||
@ -363,69 +375,15 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
//
|
||||
// Values may be a mix of sharp corners and smooth boundaries...
|
||||
//
|
||||
// Gather information about the "span" of faces for each value. The "size" (number
|
||||
// of faces in which each value occurs), is most immediately useful in determining
|
||||
// whether a value is a corner or smooth boundary, while other properties such as
|
||||
// the first face and whether or not the span is interrupted by a discts edge (and
|
||||
// so made "disjoint") are useful to fully qualify smooth boundaries.
|
||||
// Gather information about the "span" of faces for each value. Use the results
|
||||
// in one last chance for all values to be made sharp via interpolation options...
|
||||
//
|
||||
struct ValueSpan {
|
||||
LocalIndex _size;
|
||||
LocalIndex _start;
|
||||
LocalIndex _disjoint;
|
||||
};
|
||||
assert(sizeof(ValueSpan) < sizeof(int));
|
||||
assert(sizeof(ValueSpan) <= sizeof(int));
|
||||
ValueSpan * vValueSpans = (ValueSpan *) indexBuffer;
|
||||
memset(vValueSpans, 0, vValueCount * sizeof(ValueSpan));
|
||||
|
||||
IndexArray const vEdges = _level.getVertexEdges(vIndex);
|
||||
LocalIndexArray const vInEdge = _level.getVertexEdgeLocalIndices(vIndex);
|
||||
gatherValueSpans(vIndex, vValueSpans);
|
||||
|
||||
if (vValueCount == 1) {
|
||||
// Mark an interior dart disjoint if more than one discts edge:
|
||||
for (int i = 0; i < vEdges.size(); ++i) {
|
||||
if (_edgeTags[vEdges[i]]._mismatch) {
|
||||
if (vValueSpans[0]._size) {
|
||||
vValueSpans[0]._disjoint = true;
|
||||
break;
|
||||
} else {
|
||||
vValueSpans[0]._size = (LocalIndex) vFaces.size();
|
||||
vValueSpans[0]._start = (LocalIndex) i;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Walk around the vertex and accumulate span info for each value -- be
|
||||
// careful about the span for the first value "wrapping" around:
|
||||
vValueSpans[0]._size = 1;
|
||||
vValueSpans[0]._start = 0;
|
||||
if (_edgeTags[vEdges[0]]._mismatch && !vIsBoundary) {
|
||||
vValueSpans[0]._disjoint = (vFaceSiblings[vFaces.size() - 1] == 0);
|
||||
}
|
||||
for (int i = 1; i < vFaces.size(); ++i) {
|
||||
if (_edgeTags[vEdges[i]]._mismatch) {
|
||||
if (vFaceSiblings[i] == vFaceSiblings[i-1]) {
|
||||
++ vValueSpans[vFaceSiblings[i]]._disjoint;
|
||||
} else {
|
||||
// If we have already set the span for this value, mark disjoint
|
||||
if (vValueSpans[vFaceSiblings[i]]._size > 0) {
|
||||
++ vValueSpans[vFaceSiblings[i]]._disjoint;
|
||||
}
|
||||
vValueSpans[vFaceSiblings[i]]._start = (LocalIndex) i;
|
||||
}
|
||||
}
|
||||
++ vValueSpans[vFaceSiblings[i]]._size;
|
||||
}
|
||||
// If the span for value 0 has wrapped around, decrement the disjoint added
|
||||
// at the interior edge where it started the closing part of the span:
|
||||
if ((vFaceSiblings[vFaces.size() - 1] == 0) && !vIsBoundary) {
|
||||
-- vValueSpans[0]._disjoint;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Last chance for all values to be made sharp via interpolation options...
|
||||
//
|
||||
bool testForSmoothBoundaries = true;
|
||||
if (sharpenAllIfAnyCorner) {
|
||||
for (int i = 0; i < vValueCount; ++i) {
|
||||
@ -435,18 +393,25 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Test each vertex value to determine if it is a smooth boundary (crease) -- if not
|
||||
// disjoint and not a sharp corner, tag as a smooth boundary and identify its ends.
|
||||
// Note if semi-sharp, and do not tag it as a crease now -- the refinement will tag
|
||||
// it once all sharpness has decayed to zero:
|
||||
//
|
||||
if (testForSmoothBoundaries) {
|
||||
//
|
||||
// Inspect each vertex value -- if not disjoint and not a sharp corner, tag as a
|
||||
// smooth boundary and identify its ends:
|
||||
//
|
||||
for (int i = 0; i < vValueCount; ++i) {
|
||||
ValueSpan& vSpan = vValueSpans[i];
|
||||
|
||||
if (!vSpan._disjoint && ((vSpan._size > 1) || !fvarCornersAreSharp)) {
|
||||
Index valueIndex = (i == 0) ? vIndex : (vSiblingOffset + i - 1);
|
||||
|
||||
_vertValueTags[valueIndex] = valueTagCrease;
|
||||
if ((vSpan._semiSharp > 0) || (vSharpness > 0)) {
|
||||
_vertValueTags[valueIndex] = valueTagSemiSharp;
|
||||
} else {
|
||||
_vertValueTags[valueIndex] = valueTagCrease;
|
||||
}
|
||||
|
||||
LocalIndex * endFaces = &_vertValueCreaseEnds[2 * valueIndex];
|
||||
|
||||
@ -642,6 +607,10 @@ FVarLevel::print() const {
|
||||
for (int j = 0; j < sCount; ++j) {
|
||||
printf("%4d", _vertValueTags[sOffset + j]._crease);
|
||||
}
|
||||
printf(", semi-sharp =%2d", (int)_vertValueTags[i]._semiSharp);
|
||||
for (int j = 0; j < sCount; ++j) {
|
||||
printf("%2d", _vertValueTags[sOffset + j]._semiSharp);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@ -868,6 +837,87 @@ printf(" edge[] tag mismatch = %d\n", _edgeTags[eIndex]._mismatch);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Gather information about the "span" of faces for each value:
|
||||
//
|
||||
// This method is only invoked when the spans for values may be smooth boundaries and
|
||||
// other criteria that make all sharp (e.g. a non-manifold vertex) have been considered.
|
||||
//
|
||||
// The "size" (number of faces in which each value occurs), is most immediately useful
|
||||
// in determining whether a value is a corner or smooth boundary, while other properties
|
||||
// such as the first face and whether or not the span is interrupted by a discts edge
|
||||
// (and so made "disjoint") or semi-sharp or infinite edges, are useful to fully qualify
|
||||
// smooth boundaries by the caller.
|
||||
//
|
||||
void
|
||||
FVarLevel::gatherValueSpans(Index vIndex, ValueSpan * vValueSpans) const {
|
||||
|
||||
IndexArray const vEdges = _level.getVertexEdges(vIndex);
|
||||
IndexArray const vFaces = _level.getVertexFaces(vIndex);
|
||||
|
||||
SiblingArray const vFaceSiblings = getVertexFaceSiblings(vIndex);
|
||||
|
||||
bool vHasSingleValue = (_vertSiblingCounts[vIndex] == 0);
|
||||
bool vIsBoundary = vEdges.size() > vFaces.size();
|
||||
|
||||
if (vHasSingleValue) {
|
||||
// Mark an interior dart disjoint if more than one discts edge:
|
||||
for (int i = 0; i < vEdges.size(); ++i) {
|
||||
if (_edgeTags[vEdges[i]]._mismatch) {
|
||||
if (vValueSpans[0]._size) {
|
||||
vValueSpans[0]._disjoint = true;
|
||||
break;
|
||||
} else {
|
||||
vValueSpans[0]._size = (LocalIndex) vFaces.size();
|
||||
vValueSpans[0]._start = (LocalIndex) i;
|
||||
}
|
||||
} else if (_level._edgeTags[vEdges[i]]._infSharp) {
|
||||
vValueSpans[0]._disjoint = true;
|
||||
break;
|
||||
} else if (_level._edgeTags[vEdges[i]]._semiSharp) {
|
||||
++ vValueSpans[0]._semiSharp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Walk around the vertex and accumulate span info for each value -- be
|
||||
// careful about the span for the first value "wrapping" around:
|
||||
vValueSpans[0]._size = 1;
|
||||
vValueSpans[0]._start = 0;
|
||||
if (!vIsBoundary && (vFaceSiblings[vFaces.size() - 1] == 0)) {
|
||||
if (_edgeTags[vEdges[0]]._mismatch) {
|
||||
vValueSpans[0]._disjoint = true;
|
||||
} else if (_level._edgeTags[vEdges[0]]._infSharp) {
|
||||
vValueSpans[0]._disjoint = true;
|
||||
} else if (_level._edgeTags[vEdges[0]]._semiSharp) {
|
||||
++ vValueSpans[0]._semiSharp;
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < vFaces.size(); ++i) {
|
||||
if (vFaceSiblings[i] == vFaceSiblings[i-1]) {
|
||||
if (_edgeTags[vEdges[i]]._mismatch) {
|
||||
++ vValueSpans[vFaceSiblings[i]]._disjoint;
|
||||
} else if (_level._edgeTags[vEdges[i]]._infSharp) {
|
||||
vValueSpans[vFaceSiblings[i]]._disjoint = true;
|
||||
} else if (_level._edgeTags[vEdges[i]]._semiSharp) {
|
||||
++ vValueSpans[vFaceSiblings[i]]._semiSharp;
|
||||
}
|
||||
} else {
|
||||
// If we have already set the span for this value, mark disjoint
|
||||
if (vValueSpans[vFaceSiblings[i]]._size > 0) {
|
||||
++ vValueSpans[vFaceSiblings[i]]._disjoint;
|
||||
}
|
||||
vValueSpans[vFaceSiblings[i]]._start = (LocalIndex) i;
|
||||
}
|
||||
++ vValueSpans[vFaceSiblings[i]]._size;
|
||||
}
|
||||
// If the span for value 0 has wrapped around, decrement the disjoint added
|
||||
// at the interior edge where it started the closing part of the span:
|
||||
if ((vFaceSiblings[vFaces.size() - 1] == 0) && !vIsBoundary) {
|
||||
-- vValueSpans[0]._disjoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace Vtr
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -115,8 +115,9 @@ public:
|
||||
|
||||
typedef unsigned char ValueTagSize;
|
||||
|
||||
ValueTagSize _mismatch : 1; // local FVar topology does not match
|
||||
ValueTagSize _crease : 1; // value is a crease, otherwise a corner
|
||||
ValueTagSize _mismatch : 1; // local FVar topology does not match
|
||||
ValueTagSize _crease : 1; // value is a crease, otherwise a corner
|
||||
ValueTagSize _semiSharp : 1; // value is a corner decaying to crease
|
||||
};
|
||||
|
||||
public:
|
||||
@ -149,8 +150,12 @@ public:
|
||||
SiblingArray const getVertexFaceSiblings(Index faceIndex) const;
|
||||
|
||||
// Queries specific to values:
|
||||
bool isValueCrease(Index valueIndex) const { return _vertValueTags[valueIndex]._crease; }
|
||||
bool isValueCorner(Index valueIndex) const { return !_vertValueTags[valueIndex]._crease; }
|
||||
bool isValueCrease(Index valueIndex) const { return _vertValueTags[valueIndex]._crease; }
|
||||
bool isValueCorner(Index valueIndex) const { return !_vertValueTags[valueIndex]._crease; }
|
||||
bool isValueSemiSharp(Index valueIndex) const { return _vertValueTags[valueIndex]._semiSharp; }
|
||||
bool isValueInfSharp(Index valueIndex) const { return !_vertValueTags[valueIndex]._semiSharp &&
|
||||
!_vertValueTags[valueIndex]._crease; }
|
||||
|
||||
|
||||
// Higher-level topological queries, i.e. values in a neighborhood:
|
||||
void getEdgeFaceValues(Index eIndex, int fIncToEdge, Index valuesPerVert[2]) const;
|
||||
@ -176,6 +181,15 @@ public:
|
||||
void initializeFaceValuesFromVertexFaceSiblings(int firstVertex = 0);
|
||||
void buildFaceVertexSiblingsFromVertexFaceSiblings(std::vector<Sibling>& fvSiblings) const;
|
||||
|
||||
// Information about the "span" for a value:
|
||||
struct ValueSpan {
|
||||
LocalIndex _size;
|
||||
LocalIndex _start;
|
||||
LocalIndex _disjoint;
|
||||
LocalIndex _semiSharp;
|
||||
};
|
||||
void gatherValueSpans(Index vIndex, ValueSpan * vValueSpans) const;
|
||||
|
||||
bool validate() const;
|
||||
void print() const;
|
||||
|
||||
|
@ -94,6 +94,7 @@ FVarRefinement::applyRefinement() {
|
||||
propagateValueTags();
|
||||
if (_child->_hasSmoothBoundaries) {
|
||||
propagateValueCreases();
|
||||
reclassifySemisharpValues();
|
||||
}
|
||||
|
||||
//
|
||||
@ -361,8 +362,12 @@ FVarRefinement::propagateValueTags() {
|
||||
// as corner or crease depending on the presence of creases in the parent:
|
||||
//
|
||||
FVarLevel::ValueTag valTagMismatch(true);
|
||||
valTagMismatch._crease = false;
|
||||
valTagMismatch._semiSharp = false;
|
||||
|
||||
FVarLevel::ValueTag valTagCrease(true);
|
||||
valTagCrease._crease = true;
|
||||
valTagCrease._crease = true;
|
||||
valTagCrease._semiSharp = false;
|
||||
|
||||
FVarLevel::ValueTag& valTagSplitEdge = _parent->_hasSmoothBoundaries ? valTagCrease : valTagMismatch;
|
||||
|
||||
@ -421,7 +426,7 @@ FVarRefinement::propagateValueCreases() {
|
||||
if (!_child->_vertValueTags[cVert]._mismatch) continue;
|
||||
if (_refinement._childVertexTag[cVert]._incomplete) continue;
|
||||
|
||||
if (_child->_vertValueTags[cVert]._crease) {
|
||||
if (!_child->isValueInfSharp(cVert)) {
|
||||
LocalIndex * sibling0Ends = &_child->_vertValueCreaseEnds[2 * cVert];
|
||||
sibling0Ends[0] = 0;
|
||||
sibling0Ends[1] = 1;
|
||||
@ -429,7 +434,7 @@ FVarRefinement::propagateValueCreases() {
|
||||
int vSiblingCount = _child->_vertSiblingCounts[cVert];
|
||||
if (vSiblingCount) {
|
||||
int cOffset = _child->_vertSiblingOffsets[cVert];
|
||||
if (_child->_vertValueTags[cOffset]._crease) {
|
||||
if (!_child->isValueInfSharp(cOffset)) {
|
||||
LocalIndex * sibling1Ends = &_child->_vertValueCreaseEnds[2 * cOffset];
|
||||
sibling1Ends[0] = 2;
|
||||
sibling1Ends[1] = 3;
|
||||
@ -439,7 +444,8 @@ FVarRefinement::propagateValueCreases() {
|
||||
|
||||
//
|
||||
// For each child vertex from a vertex that has FVar values and is complete, initialize
|
||||
// the crease-ends for those values tagged as smooth boundaries:
|
||||
// the crease-ends for those values tagged as smooth or semi-sharp (to become smooth
|
||||
// eventually):
|
||||
//
|
||||
for (int i = 0; i < _refinement._childVertFromVertCount; ++i, ++cVert) {
|
||||
if (!_child->_vertValueTags[cVert]._mismatch) continue;
|
||||
@ -447,7 +453,7 @@ FVarRefinement::propagateValueCreases() {
|
||||
|
||||
Index pVert = _refinement.getChildVertexParentIndex(cVert);
|
||||
|
||||
if (_child->_vertValueTags[cVert]._crease) {
|
||||
if (!_child->isValueInfSharp(cVert)) {
|
||||
LocalIndex * pSiblingEnds = &_parent->_vertValueCreaseEnds[2 * pVert];
|
||||
LocalIndex * cSiblingEnds = &_child->_vertValueCreaseEnds[2 * cVert];
|
||||
|
||||
@ -463,7 +469,7 @@ FVarRefinement::propagateValueCreases() {
|
||||
LocalIndex * cSiblingEnds = &_child->_vertValueCreaseEnds[2 * cSiblingOffset];
|
||||
|
||||
for (int j = 0; j < vSiblingCount; ++j, cSiblingEnds += 2, pSiblingEnds += 2) {
|
||||
if (_child->_vertValueTags[cSiblingOffset + j]._crease) {
|
||||
if (!_child->isValueInfSharp(cSiblingOffset + j)) {
|
||||
cSiblingEnds[0] = pSiblingEnds[0];
|
||||
cSiblingEnds[1] = pSiblingEnds[1];
|
||||
}
|
||||
@ -472,6 +478,114 @@ FVarRefinement::propagateValueCreases() {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FVarRefinement::reclassifySemisharpValues() {
|
||||
|
||||
//
|
||||
// Reclassify the tags of semi-sharp vertex values to smooth creases according to
|
||||
// changes in sharpness:
|
||||
//
|
||||
// Vertex values introduced on edge-verts can never be semi-sharp as they will be
|
||||
// introduced on discts edges, which are implicitly infinitely sharp, so we can
|
||||
// skip them entirely.
|
||||
//
|
||||
// So we just need to deal with those values descended from parent vertices that
|
||||
// were semi-sharp. The child values will have inherited the semi-sharp tag from
|
||||
// their parent values -- we will be able to clear it in many simple cases but
|
||||
// ultimately will need to inspect each value:
|
||||
//
|
||||
FVarLevel::ValueTag valTagCrease(true);
|
||||
valTagCrease._crease = true;
|
||||
valTagCrease._semiSharp = false;
|
||||
|
||||
FVarLevel::ValueTag valTagSemiSharp(true);
|
||||
valTagSemiSharp._crease = false;
|
||||
valTagSemiSharp._semiSharp = true;
|
||||
|
||||
Index cVert = _refinement._childVertFromFaceCount + _refinement._childVertFromEdgeCount;
|
||||
|
||||
for (int i = 0; i < _refinement._childVertFromVertCount; ++i, ++cVert) {
|
||||
if (!_child->_vertValueTags[cVert]._mismatch) continue;
|
||||
if (_refinement._childVertexTag[cVert]._incomplete) continue;
|
||||
|
||||
// Remember the child vertex may no longer be semisharp when the parent was:
|
||||
Index pVert = _refinement.getChildVertexParentIndex(cVert);
|
||||
if (!_refinement._parent->_vertTags[pVert]._semiSharp) continue;
|
||||
|
||||
// If the child vertex sharpness is non-zero, all values remain unaffected:
|
||||
if (!Sdc::Crease::IsSmooth(_refinement._child->_vertSharpness[cVert])) continue;
|
||||
|
||||
//
|
||||
// We are left with some or no semi-sharp edges in the child vertex. If none
|
||||
// left the child-vertex will no longer be semi-sharp and we can just clear
|
||||
// those values marked as semi-sharp. Otherwise, its simplest to assume all
|
||||
// semi-sharp edges have decayed (so clearing them again) and using the
|
||||
// remaining semi-sharp edges to reset those values that still are.
|
||||
//
|
||||
// So convert all semi-sharp tags to creases and reset those that remain if
|
||||
// the child vertex is still tagged as semi-sharp:
|
||||
//
|
||||
int vSiblingOffset = _child->_vertSiblingOffsets[cVert];
|
||||
int vSiblingCount = _child->_vertSiblingCounts[cVert];
|
||||
int vValueCount = 1 + vSiblingCount;
|
||||
for (int j = 0; j < vValueCount; ++j) {
|
||||
int vValueIndex = (j == 0) ? cVert : (vSiblingOffset + j - 1);
|
||||
|
||||
if (_child->isValueSemiSharp(vValueIndex)) {
|
||||
_child->_vertValueTags[vValueIndex] = valTagCrease;
|
||||
}
|
||||
}
|
||||
if (!_refinement._child->_vertTags[cVert]._semiSharp) continue;
|
||||
|
||||
//
|
||||
// Identify the remaining semi-sharp edges and the corresponding values that
|
||||
// should be retained as semi-sharp:
|
||||
//
|
||||
SiblingArray const vFaceSiblings = _child->getVertexFaceSiblings(cVert);
|
||||
|
||||
IndexArray const cVertEdges = _refinement._child->getVertexEdges(cVert);
|
||||
for (int j = 0; j < cVertEdges.size(); ++j) {
|
||||
if (_refinement._child->_edgeTags[cVertEdges[j]]._semiSharp) {
|
||||
int jPrev = j ? (j - 1) : (vFaceSiblings.size() - 1);
|
||||
if (vFaceSiblings[jPrev] == vFaceSiblings[j]) {
|
||||
int vSibling = vFaceSiblings[j];
|
||||
int vValueIndex = (vSibling == 0) ? cVert : (vSiblingOffset + vSibling - 1);
|
||||
|
||||
_child->_vertValueTags[vValueIndex] = valTagSemiSharp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
FVarRefinement::getFractionalWeight(Index pVert, Sibling /* pSibling */,
|
||||
Index cVert, Sibling /* 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(_refinement._parent->_vertTags[pVert]._semiSharp);
|
||||
|
||||
float pVertSharpness = _refinement._parent->_vertSharpness[pVert];
|
||||
float cVertSharpness = _refinement._child->_vertSharpness[cVert];
|
||||
|
||||
//
|
||||
// Need to identify sharpness values for edges within the spans for both the
|
||||
// parent and child...
|
||||
//
|
||||
int numValueEdges = 0;
|
||||
float * pEdgeSharpness = 0;
|
||||
float * cEdgeSharpness = 0;
|
||||
|
||||
if (Sdc::Crease::IsSmooth(pVertSharpness)) {
|
||||
printf("Warning -- FVarRefinement::getFractionalWeight() currently ignores edge sharpness...\n");
|
||||
// Consider fully sharp until we gather and average the edge sharpness values...
|
||||
return 1.0;
|
||||
}
|
||||
return Sdc::Crease(_refinement._schemeOptions).ComputeFractionalWeightAtVertex(
|
||||
pVertSharpness, cVertSharpness, numValueEdges, pEdgeSharpness, cEdgeSharpness);
|
||||
}
|
||||
|
||||
} // end namespace Vtr
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
|
@ -56,6 +56,9 @@ namespace Vtr {
|
||||
//
|
||||
|
||||
class FVarRefinement {
|
||||
public:
|
||||
typedef FVarLevel::Sibling Sibling;
|
||||
typedef FVarLevel::SiblingArray SiblingArray;
|
||||
|
||||
public:
|
||||
FVarRefinement(Refinement const& refinement, FVarLevel& parent, FVarLevel& child);
|
||||
@ -80,6 +83,10 @@ public:
|
||||
void propagateEdgeTags();
|
||||
void propagateValueTags();
|
||||
void propagateValueCreases();
|
||||
void reclassifySemisharpValues();
|
||||
|
||||
float getFractionalWeight(Index pVert, Sibling pSibling,
|
||||
Index cVert, Sibling cSibling) const;
|
||||
|
||||
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user