mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-26 09:41:08 +00:00
Added proper fractional weighting for semi-sharp FVar boundaries:
- semi-sharp edges interior to FVar regions now properly recognized - added clear() method to FVar tags and reworked their initialization
This commit is contained in:
parent
5b7462286f
commit
df23812759
@ -74,8 +74,9 @@ FVarLevel::resizeComponents() {
|
||||
_faceVertValues.resize(_level.getNumFaceVerticesTotal());
|
||||
|
||||
// Per-edge members:
|
||||
_edgeTags.resize(_level.getNumEdges());
|
||||
std::memset(&_edgeTags[0], 0, _level.getNumEdges() * sizeof(ETag));
|
||||
ETag edgeTagMatch;
|
||||
edgeTagMatch.clear();
|
||||
_edgeTags.resize(_level.getNumEdges(), edgeTagMatch);
|
||||
|
||||
// Per-vertex members:
|
||||
_vertSiblingCounts.resize(_level.getNumVertices(), 0);
|
||||
@ -140,11 +141,14 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
// values in cases where there are more than 2 values at a vertex, its unclear what the intent of
|
||||
// "propagate corners" is if more than 2 are present.
|
||||
//
|
||||
bool sharpenAllIfMoreThan2 = (fvarOptions == Options::FVAR_LINEAR_CORNERS_PLUS1) ||
|
||||
(fvarOptions == Options::FVAR_LINEAR_CORNERS_PLUS2);
|
||||
bool sharpenAllIfAnyCorner = (fvarOptions == Options::FVAR_LINEAR_CORNERS_PLUS2);
|
||||
bool cornersPlus1 = (fvarOptions == Options::FVAR_LINEAR_CORNERS_PLUS1);
|
||||
bool cornersPlus2 = (fvarOptions == Options::FVAR_LINEAR_CORNERS_PLUS2);
|
||||
|
||||
bool sharpenDarts = sharpenAllIfAnyCorner || !_hasSmoothBoundaries;
|
||||
bool considerEntireVertex = cornersPlus1 || cornersPlus2;
|
||||
|
||||
bool sharpenAllIfMoreThan2 = considerEntireVertex;
|
||||
bool sharpenAllIfAnyCorner = cornersPlus2;
|
||||
bool sharpenDarts = cornersPlus2 || !_hasSmoothBoundaries;
|
||||
|
||||
//
|
||||
// Its awkward and potentially inefficient to try and accomplish everything in one
|
||||
@ -172,13 +176,11 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
//
|
||||
// Still looking or opportunities to economize effort between the two passes...
|
||||
//
|
||||
ValueTag valueTagMatch(false);
|
||||
valueTagMatch._crease = false;
|
||||
valueTagMatch._semiSharp = false;
|
||||
ValueTag valueTagMatch;
|
||||
valueTagMatch.clear();
|
||||
|
||||
ValueTag valueTagMismatch(true);
|
||||
valueTagMismatch._crease = false;
|
||||
valueTagMismatch._semiSharp = false;
|
||||
ValueTag valueTagMismatch = valueTagMatch;
|
||||
valueTagMismatch._mismatch = true;
|
||||
|
||||
_vertValueTags.resize(_level.getNumVertices(), valueTagMatch);
|
||||
_vertFaceSiblings.resize(_level.getNumVertexFacesTotal(), 0);
|
||||
@ -223,7 +225,7 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
} else {
|
||||
// Tag the corresponding edge as discts:
|
||||
Index eIndex = vEdges[i];
|
||||
ETag& eTag = _edgeTags[eIndex];
|
||||
ETag& eTag = _edgeTags[eIndex];
|
||||
|
||||
if (vInEdge[i] == 0) {
|
||||
eTag._disctsV0 = true;
|
||||
@ -317,11 +319,9 @@ FVarLevel::completeTopologyFromFaceValues() {
|
||||
// vertex and to inspect local face-varying topology in more detail when necessary:
|
||||
//
|
||||
ValueTag valueTagCrease = valueTagMismatch;
|
||||
valueTagCrease._crease = true;
|
||||
valueTagCrease._semiSharp = false;
|
||||
valueTagCrease._crease = true;
|
||||
|
||||
ValueTag valueTagSemiSharp = valueTagMismatch;
|
||||
valueTagSemiSharp._crease = false;
|
||||
valueTagSemiSharp._semiSharp = true;
|
||||
|
||||
for (int vIndex = 0; vIndex < _level.getNumVertices(); ++vIndex) {
|
||||
|
@ -91,7 +91,8 @@ public:
|
||||
//
|
||||
struct ETag {
|
||||
ETag() { }
|
||||
ETag(bool mismatch) : _mismatch(mismatch) { }
|
||||
|
||||
void clear() { std::memset(this, 0, sizeof(ETag)); }
|
||||
|
||||
typedef unsigned char ETagSize;
|
||||
|
||||
@ -109,7 +110,8 @@ public:
|
||||
//
|
||||
struct ValueTag {
|
||||
ValueTag() { }
|
||||
ValueTag(bool mismatch) : _mismatch(mismatch) { }
|
||||
|
||||
void clear() { std::memset(this, 0, sizeof(ValueTag)); }
|
||||
|
||||
typedef unsigned char ValueTagSize;
|
||||
|
||||
|
@ -320,7 +320,9 @@ FVarRefinement::propagateEdgeTags() {
|
||||
// - child edge for the matching end inherits tag
|
||||
// - child edge at the other end is doubly discts
|
||||
//
|
||||
FVarLevel::ETag eTagMatch(false);
|
||||
FVarLevel::ETag eTagMatch;
|
||||
eTagMatch.clear();
|
||||
eTagMatch._mismatch = false;
|
||||
|
||||
for (int eIndex = 0; eIndex < _refinement._childEdgeFromFaceCount; ++eIndex) {
|
||||
_child->_edgeTags[eIndex] = eTagMatch;
|
||||
@ -350,7 +352,8 @@ FVarRefinement::propagateValueTags() {
|
||||
//
|
||||
// Values from face-vertices -- all match:
|
||||
//
|
||||
FVarLevel::ValueTag valTagMatch(false);
|
||||
FVarLevel::ValueTag valTagMatch;
|
||||
valTagMatch.clear();
|
||||
|
||||
Index cVert = 0;
|
||||
for (cVert = 0; cVert < _refinement._childVertFromFaceCount; ++cVert) {
|
||||
@ -361,13 +364,11 @@ FVarRefinement::propagateValueTags() {
|
||||
// Values from edge-vertices -- for edges that are split, tag as mismatched and tag
|
||||
// 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 valTagMismatch = valTagMatch;
|
||||
valTagMismatch._mismatch = true;
|
||||
|
||||
FVarLevel::ValueTag valTagCrease(true);
|
||||
valTagCrease._crease = true;
|
||||
valTagCrease._semiSharp = false;
|
||||
FVarLevel::ValueTag valTagCrease = valTagMismatch;
|
||||
valTagCrease._crease = true;
|
||||
|
||||
FVarLevel::ValueTag& valTagSplitEdge = _parent->_hasSmoothBoundaries ? valTagCrease : valTagMismatch;
|
||||
|
||||
@ -494,12 +495,14 @@ FVarRefinement::reclassifySemisharpValues() {
|
||||
// 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 valTagCrease;
|
||||
valTagCrease.clear();
|
||||
valTagCrease._mismatch = true;
|
||||
valTagCrease._crease = true;
|
||||
|
||||
FVarLevel::ValueTag valTagSemiSharp(true);
|
||||
valTagSemiSharp._crease = false;
|
||||
FVarLevel::ValueTag valTagSemiSharp;
|
||||
valTagSemiSharp.clear();
|
||||
valTagSemiSharp._mismatch = true;
|
||||
valTagSemiSharp._semiSharp = true;
|
||||
|
||||
Index cVert = _refinement._childVertFromFaceCount + _refinement._childVertFromEdgeCount;
|
||||
@ -559,31 +562,54 @@ FVarRefinement::reclassifySemisharpValues() {
|
||||
}
|
||||
|
||||
float
|
||||
FVarRefinement::getFractionalWeight(Index pVert, Sibling /* pSibling */,
|
||||
FVarRefinement::getFractionalWeight(Index pVert, Sibling pSibling,
|
||||
Index cVert, Sibling /* cSibling */) const
|
||||
{
|
||||
FVarLevel const& parentFVar = *_parent;
|
||||
Level const& parent = *_refinement._parent;
|
||||
Level const& child = *_refinement._child;
|
||||
|
||||
// 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];
|
||||
assert(parent._vertTags[pVert]._semiSharp);
|
||||
assert(!child._vertTags[cVert]._incomplete);
|
||||
|
||||
//
|
||||
// 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;
|
||||
// Consider gathering the complete parent and child sharpness vectors outside
|
||||
// this method and re-using them for each sibling, i.e. passing them to this
|
||||
// method somehow. We may also need them there for mask-related purposes...
|
||||
//
|
||||
IndexArray const pVertEdges = parent.getVertexEdges(pVert);
|
||||
IndexArray const cVertEdges = child.getVertexEdges(cVert);
|
||||
|
||||
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;
|
||||
float * pEdgeSharpness = (float*) alloca(2 * pVertEdges.size() * sizeof(float));
|
||||
float * cEdgeSharpness = pEdgeSharpness + pVertEdges.size();
|
||||
|
||||
int pValueIndex = parentFVar.getVertexValueIndex(pVert, pSibling);
|
||||
LocalIndex const * pSiblingEnds = &parentFVar._vertValueCreaseEnds[2 * pValueIndex];
|
||||
|
||||
int interiorEdgeCount = 0;
|
||||
if (pSiblingEnds[1] > pSiblingEnds[0]) {
|
||||
for (int i = pSiblingEnds[0] + 1; i <= pSiblingEnds[1]; ++i, ++interiorEdgeCount) {
|
||||
pEdgeSharpness[interiorEdgeCount] = parent._edgeSharpness[pVertEdges[i]];
|
||||
cEdgeSharpness[interiorEdgeCount] = child._edgeSharpness[cVertEdges[i]];
|
||||
}
|
||||
} else if (pSiblingEnds[0] > pSiblingEnds[1]) {
|
||||
for (int i = pSiblingEnds[0] + 1; i < pVertEdges.size(); ++i, ++interiorEdgeCount) {
|
||||
pEdgeSharpness[interiorEdgeCount] = parent._edgeSharpness[pVertEdges[i]];
|
||||
cEdgeSharpness[interiorEdgeCount] = child._edgeSharpness[cVertEdges[i]];
|
||||
}
|
||||
for (int i = 0; i <= pSiblingEnds[1]; ++i, ++interiorEdgeCount) {
|
||||
pEdgeSharpness[interiorEdgeCount] = parent._edgeSharpness[pVertEdges[i]];
|
||||
cEdgeSharpness[interiorEdgeCount] = child._edgeSharpness[cVertEdges[i]];
|
||||
}
|
||||
}
|
||||
return Sdc::Crease(_refinement._schemeOptions).ComputeFractionalWeightAtVertex(
|
||||
pVertSharpness, cVertSharpness, numValueEdges, pEdgeSharpness, cEdgeSharpness);
|
||||
parent._vertSharpness[pVert], child._vertSharpness[cVert],
|
||||
interiorEdgeCount, pEdgeSharpness, cEdgeSharpness);
|
||||
}
|
||||
|
||||
} // end namespace Vtr
|
||||
|
Loading…
Reference in New Issue
Block a user