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:
barfowl 2014-10-13 12:17:25 -07:00
parent 5b7462286f
commit df23812759
3 changed files with 72 additions and 44 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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