From 46b2cac54b8599d23bcfc93b6a319934e0b0d2eb Mon Sep 17 00:00:00 2001 From: David G Yu Date: Mon, 27 Apr 2015 12:40:18 -0700 Subject: [PATCH] Fixed gathering of patches near non-manifold topo The previous change to the gathering of patch points went a bit too far. Near non-manifold features it is important to be careful when traversing the faces in a level to avoid assumptions that are valid only for manifold topology. Also, removed Vtr::Level::gatherQuadRegularPatchPoints(). This method was added in my previous change, but it is unsafe to use in the presence of non-manifold topology. --- opensubdiv/far/patchTablesFactory.cpp | 52 +++++++++---- opensubdiv/vtr/level.cpp | 105 -------------------------- opensubdiv/vtr/level.h | 3 - 3 files changed, 38 insertions(+), 122 deletions(-) diff --git a/opensubdiv/far/patchTablesFactory.cpp b/opensubdiv/far/patchTablesFactory.cpp index fed7d2eb..cfae13b0 100644 --- a/opensubdiv/far/patchTablesFactory.cpp +++ b/opensubdiv/far/patchTablesFactory.cpp @@ -194,20 +194,18 @@ offsetAndPermuteIndices(Far::Index const indices[], int count, if (permutation) { for (int i = 0; i < count; ++i) { - Far::Index index = indices[permutation[i]]; - if (index == Vtr::INDEX_INVALID) { - index = knownGoodIndex; + if (permutation[i] < 0) { + result[i] = offset + knownGoodIndex; + } else { + result[i] = offset + indices[permutation[i]]; } - result[i] = offset + index; + } + } else if (offset) { + for (int i = 0; i < count; ++i) { + result[i] = offset + indices[i]; } } else { - for (int i = 0; i < count; ++i) { - Far::Index index = indices[i]; - if (index == Vtr::INDEX_INVALID) { - index = knownGoodIndex; - } - result[i] = offset + index; - } + std::memcpy(result, indices, count * sizeof(Far::Index)); } } @@ -1341,9 +1339,35 @@ PatchTablesFactory::populateAdaptivePatches( int transitionMask = patchTag._transitionMask; if (!patchTag._isSingleCrease) { - int const permuteRegular[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 }; - level->gatherQuadRegularPatchPoints(faceIndex, patchVerts, boundaryMask); - offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permuteRegular, iptrs.R); + int const * permutation = 0; + + if (patchTag._boundaryCount == 0) { + static int const permuteRegular[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 }; + permutation = permuteRegular; + level->gatherQuadRegularInteriorPatchPoints(faceIndex, patchVerts, bIndex); + } else if (patchTag._boundaryCount == 1) { + // Expand boundary patch vertices and rotate to restore correct orientation. + static int const permuteBoundary[4][16] = { + { -1, -1, -1, -1, 11, 3, 0, 4, 10, 2, 1, 5, 9, 8, 7, 6 }, + { 9, 10, 11, -1, 8, 2, 3, -1, 7, 1, 0, -1, 6, 5, 4, -1 }, + { 6, 7, 8, 9, 5, 1, 2, 10, 4, 0, 3, 11, -1, -1, -1, -1 }, + { -1, 4, 5, 6, -1, 0, 1, 7, -1, 3, 2, 8, -1, 11, 10, 9 } }; + permutation = permuteBoundary[bIndex]; + level->gatherQuadRegularBoundaryPatchPoints(faceIndex, patchVerts, bIndex); + } else if (patchTag._boundaryCount == 2) { + // Expand corner patch vertices and rotate to restore correct orientation. + static int const permuteCorner[4][16] = { + { -1, -1, -1, -1, -1, 0, 1, 4, -1, 3, 2, 5, -1, 8, 7, 6 }, + { -1, -1, -1, -1, 8, 3, 0, -1, 7, 2, 1, -1, 6, 5, 4, -1 }, + { 6, 7, 8, -1, 5, 2, 3, -1, 4, 1, 0, -1, -1, -1, -1, -1 }, + { -1, 4, 5, 6, -1, 1, 2, 7, -1, 0, 3, 8, -1, -1, -1, -1 } }; + permutation = permuteCorner[bIndex]; + level->gatherQuadRegularCornerPatchPoints(faceIndex, patchVerts, bIndex); + } else { + assert(patchTag._boundaryCount >=0 && patchTag._boundaryCount <= 2); + } + + offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permutation, iptrs.R); iptrs.R += 16; pptrs.R = computePatchParam(refiner, ptexIndices, i, faceIndex, boundaryMask, transitionMask, pptrs.R); diff --git a/opensubdiv/vtr/level.cpp b/opensubdiv/vtr/level.cpp index 6c4fef27..4f038e25 100644 --- a/opensubdiv/vtr/level.cpp +++ b/opensubdiv/vtr/level.cpp @@ -672,111 +672,6 @@ Level::gatherQuadLinearPatchPoints( return 4; } -// -// Gathering the 16 vertices of a quad-regular patch: -// - the neighborhood of the face is assumed to be quad-regular -// except for the boundaries specified by boundaryMask -// -// Ordering of resulting vertices: -// A complete sequence of 16 vertices is returned including values for -// non-existent vertices along boundary and corner edges. The locations of -// boundary edges are determined by the specified boundaryMask. -// For boundary and corner edges, INDEX_INVALID will be returned for -// the corresponding undefined patch vertices. The four vertices of the -// face begin the patch. -// -// | | | | -// ---5-----4-----15----14--- -// | | | | -// | | | | -// ---6-----0-----3-----13--- -// | |x x| | -// | |x x| | -// ---7-----1-----2-----12--- -// | | | | -// | | | | -// ---8-----9-----10----11--- -// | | | | -// -int -Level::gatherQuadRegularPatchPoints( - Index thisFace, Index patchPoints[], int boundaryMask, int rotation, int fvarChannel) const { - - Level const& level = *this; - - assert((0 <= rotation) && (rotation < 4)); - static int const rotationSequence[7] = { 0, 1, 2, 3, 0, 1, 2 }; - int const * rotatedVerts = &rotationSequence[rotation]; - - ConstIndexArray thisFaceVerts = level.getFaceVertices(thisFace); - - ConstIndexArray facePoints = (fvarChannel < 0) ? thisFaceVerts : - level.getFVarFaceValues(thisFace, fvarChannel); - - patchPoints[0] = facePoints[rotatedVerts[0]]; - patchPoints[1] = facePoints[rotatedVerts[1]]; - patchPoints[2] = facePoints[rotatedVerts[2]]; - patchPoints[3] = facePoints[rotatedVerts[3]]; - - int undefinedPoint = INDEX_INVALID; - - // - // For each of the four corner vertices, there may be a face diagonally opposite - // the given/central face. Each of these faces contains three points of the - // entire ring of points around that given/central face. - // - int pointIndex = 4; - for (int i = 0; i < 4; ++i) { - Index v = thisFaceVerts[rotatedVerts[i]]; - - ConstIndexArray vFaces = level.getVertexFaces(v); - ConstLocalIndexArray vInFaces = level.getVertexFaceLocalIndices(v); - - if (vFaces.size() == 1) { - // corner - patchPoints[pointIndex++] = undefinedPoint; - patchPoints[pointIndex++] = undefinedPoint; - patchPoints[pointIndex++] = undefinedPoint; - } else if (vFaces.size() == 2) { - // boundary - int thisFaceInVFaces = vFaces.FindIndex(thisFace); - int otherFaceInVFaces = 1 - thisFaceInVFaces; - - Index otherFace = vFaces[otherFaceInVFaces]; - int vInOtherFace = vInFaces[otherFaceInVFaces]; - - facePoints = (fvarChannel < 0) ? level.getFaceVertices(otherFace) : - level.getFVarFaceValues(otherFace, fvarChannel); - - if (boundaryMask & (1<