Fix infinitely sharp edges isolation

- change topology refiner to check for edge sharpnesses when selecting faces for isolation
- add face-aggregator for edge tags to Vtr::Level
- fix logic in Far::PatchTablesFactory to correctly tag single-crease patches along infinitely sharp edges

note : this fix is a bit of a cludge - barfowl confirms that the vertex crease tags (VTags) are intended to
carry neighborhood information, which they currently do not. we will revisit this shortly and fix the tags,
which will allow us to simplify the traversal logic when isolating topology features.

fixes #369
This commit is contained in:
manuelk 2014-12-19 18:18:13 -08:00
parent 5faa961bf6
commit 15b4135cfb
6 changed files with 158 additions and 22 deletions

View File

@ -48,6 +48,7 @@ static std::vector<ShapeDesc> g_defaultShapes;
#include <shapes/catmark_cube_corner4.h>
#include <shapes/catmark_cube_creases0.h>
#include <shapes/catmark_cube_creases1.h>
#include <shapes/catmark_cube_creases2.h>
#include <shapes/catmark_cube.h>
#include <shapes/catmark_dart_edgecorner.h>
#include <shapes/catmark_dart_edgeonly.h>
@ -110,6 +111,7 @@ static void initShapes() {
g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_cube", catmark_cube, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark ) );
g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark ) );

View File

@ -1000,7 +1000,7 @@ PatchTablesFactory::identifyAdaptivePatches( TopologyRefiner const & refiner,
assert(!compFaceVertTag._nonManifold);
patchTag._hasPatch = true;
patchTag._isRegular = !compFaceVertTag._xordinary;
patchTag._isRegular = not compFaceVertTag._xordinary;
int boundaryEdgeMask = 0;
@ -1008,17 +1008,22 @@ PatchTablesFactory::identifyAdaptivePatches( TopologyRefiner const & refiner,
// single crease patch optimization
if (options.useSingleCreasePatch and
!compFaceVertTag._xordinary and compFaceVertTag._semiSharp and not hasBoundaryVertex) {
not compFaceVertTag._xordinary and not hasBoundaryVertex) {
float sharpness = 0;
int rotation = 0;
if (level->isSingleCreasePatch(faceIndex, &sharpness, &rotation)) {
Vtr::ConstIndexArray fEdges = level->getFaceEdges(faceIndex);
Vtr::Level::ETag compFaceETag = level->getFaceCompositeETag(fEdges);
// cap sharpness to the max isolation level
float cappedSharpness = std::min(sharpness, (float)(options.maxIsolationLevel-i));
if (cappedSharpness > 0) {
patchTag._isSingleCrease = true;
patchTag._boundaryIndex = (rotation + 2) % 4;
if (compFaceETag._semiSharp or compFaceETag._infSharp) {
float sharpness = 0;
int rotation = 0;
if (level->isSingleCreasePatch(faceIndex, &sharpness, &rotation)) {
// cap sharpness to the max isolation level
float cappedSharpness = std::min(sharpness, (float)(options.maxIsolationLevel-i));
if (cappedSharpness > 0) {
patchTag._isSingleCrease = true;
patchTag._boundaryIndex = (rotation + 2) % 4;
}
}
}
}

View File

@ -433,7 +433,7 @@ TopologyRefiner::RefineAdaptive(int subdivLevel, bool fullTopology, bool useSing
// This was originally written specific to the quad-centric Catmark scheme and was since
// generalized to support Loop given the enhanced tagging of components based on the scheme.
// Any further enhancements here, e.g. new approaches for dealing with infinitely sharp
// creases, should be aware of the intended generality. Ultimately it may not be worth
// creases, should be aware of the intended generality. Ultimately it may not be worth
// trying to keep this general and we will be better off specializing it for each scheme.
// The fact that this method is intimately tied to patch generation also begs for it to
// become part of a class that encompasses both the feature adaptive tagging and the
@ -448,11 +448,11 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
bool considerSingleCreasePatch = _useSingleCreasePatch && (regularFaceSize == 4);
for (Vtr::Index face = 0; face < level.getNumFaces(); ++face) {
if (level.isHole(face)) {
continue;
}
Vtr::ConstIndexArray faceVerts = level.getFaceVertices(face);
//
@ -482,32 +482,32 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
// be necessary in some cases, particularly when we start trying to be clever about
// minimizing refinement for inf-sharp creases, etc.):
//
Vtr::Level::VTag compFaceTag = level.getFaceCompositeVTag(faceVerts);
if (compFaceTag._incomplete) {
Vtr::Level::VTag compFaceVTag = level.getFaceCompositeVTag(faceVerts);
if (compFaceVTag._incomplete) {
continue;
}
bool selectFace = false;
if (compFaceTag._xordinary) {
if (compFaceVTag._xordinary) {
selectFace = true;
} else if (compFaceTag._rule & Sdc::Crease::RULE_DART) {
} else if (compFaceVTag._rule & Sdc::Crease::RULE_DART) {
// Get this case out of the way before testing hard features
selectFace = true;
} else if (compFaceTag._nonManifold) {
} else if (compFaceVTag._nonManifold) {
// Warrants further inspection -- isolate for now
// - will want to defer inf-sharp treatment to below
selectFace = true;
} else if (!(compFaceTag._rule & Sdc::Crease::RULE_SMOOTH)) {
} else if (!(compFaceVTag._rule & Sdc::Crease::RULE_SMOOTH)) {
// None of the vertices is Smooth, so we have all vertices either Crease or Corner,
// though some may be regular patches, this currently warrants isolation as we only
// support regular patches with one corner or one boundary.
selectFace = true;
} else if (compFaceTag._semiSharp) {
} else if (compFaceVTag._semiSharp) {
// if this is regular and the adjacent edges have same sharpness
// and no vertex corner sharpness,
// we can stop refinning and use single-crease patch.
if (considerSingleCreasePatch) {
selectFace = ! level.isSingleCreasePatch(face);
selectFace = not level.isSingleCreasePatch(face);
} else {
selectFace = true;
}
@ -518,8 +518,26 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
// that do warrant isolation -- needing further inspection.
//
// For now go with the boundary cases and don't isolate...
selectFace = false;
//selectFace = false;
}
if (not selectFace) {
// Infinitely sharp edges do not influence vertex flags, but they need to
// isolated unless they can be treated as 'single-crease' cases.
// XXXX manuelk this will probably have to be revisited once infinitely
// sharp creases are handled correctly.
Vtr::ConstIndexArray faceEdges = level.getFaceEdges(face);
Vtr::Level::ETag compFaceETag = level.getFaceCompositeETag(faceEdges);
if (compFaceETag._infSharp and not compFaceETag._boundary) {
// XXXX manuelk we are testing an 'and' aggregate of flags for all
// edges : this should be safe, because if the sharp edge is not
// the edge on the boundary, this face would have been selected
// with one of the previous tests
selectFace = considerSingleCreasePatch ?
not level.isSingleCreasePatch(face) : true;
}
}
if (selectFace) {
selector.selectFace(face);
}

View File

@ -553,7 +553,22 @@ Level::getFaceCompositeVTag(ConstIndexArray & faceVerts) const {
}
return compTag;
}
Level::ETag
Level::getFaceCompositeETag(ConstIndexArray & faceEdges) const {
ETag compTag = _edgeTags[faceEdges[0]];
for (int i = 1; i < faceEdges.size(); ++i) {
ETag const& edgeTag = _edgeTags[faceEdges[i]];
if (sizeof(ETag) == sizeof(unsigned char)) {
combineTags<ETag, unsigned char>(compTag, edgeTag);
} else {
assert("ETag size is uint_8 -- need to adjust composite tag code..." == 0);
}
}
return compTag;
}
//
// High-level topology gathering functions -- used mainly in patch construction. These

View File

@ -175,6 +175,8 @@ public:
VTag getFaceCompositeVTag(ConstIndexArray & faceVerts) const;
ETag getFaceCompositeETag(ConstIndexArray & faceEdges) const;
public:
Level();
~Level();

View File

@ -0,0 +1,94 @@
//
// Copyright 2013 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
static const std::string catmark_cube_creases2 =
"# This file uses centimeters as units for non-parametric coordinates.\n"
"\n"
"v 0.000000 -1.414214 1.000000\n"
"v 1.414214 0.000000 1.000000\n"
"v -1.414214 0.000000 1.000000\n"
"v 0.000000 1.414214 1.000000\n"
"v -1.414214 0.000000 -1.000000\n"
"v 0.000000 1.414214 -1.000000\n"
"v 0.000000 -1.414214 -1.000000\n"
"v 1.414214 0.000000 -1.000000\n"
"vt 0.375000 0.000000\n"
"vt 0.625000 0.000000\n"
"vt 0.375000 0.250000\n"
"vt 0.625000 0.250000\n"
"vt 0.375000 0.500000\n"
"vt 0.625000 0.500000\n"
"vt 0.375000 0.750000\n"
"vt 0.625000 0.750000\n"
"vt 0.375000 1.000000\n"
"vt 0.625000 1.000000\n"
"vt 0.875000 0.000000\n"
"vt 0.875000 0.250000\n"
"vt 0.125000 0.000000\n"
"vt 0.125000 0.250000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn 0.000000 0.000000 1.000000\n"
"vn -0.707107 0.707107 0.000000\n"
"vn -0.707107 0.707107 0.000000\n"
"vn -0.707107 0.707107 0.000000\n"
"vn -0.707107 0.707107 0.000000\n"
"vn 0.000000 0.000000 -1.000000\n"
"vn 0.000000 0.000000 -1.000000\n"
"vn 0.000000 0.000000 -1.000000\n"
"vn 0.000000 0.000000 -1.000000\n"
"vn 0.707107 -0.707107 0.000000\n"
"vn 0.707107 -0.707107 0.000000\n"
"vn 0.707107 -0.707107 0.000000\n"
"vn 0.707107 -0.707107 0.000000\n"
"vn 0.707107 0.707107 0.000000\n"
"vn 0.707107 0.707107 0.000000\n"
"vn 0.707107 0.707107 0.000000\n"
"vn 0.707107 0.707107 0.000000\n"
"vn -0.707107 -0.707107 0.000000\n"
"vn -0.707107 -0.707107 0.000000\n"
"vn -0.707107 -0.707107 0.000000\n"
"vn -0.707107 -0.707107 0.000000\n"
"s off\n"
"f 1/1/1 2/2/2 4/4/3 3/3/4\n"
"f 3/3/5 4/4/6 6/6/7 5/5/8\n"
"f 5/5/9 6/6/10 8/8/11 7/7/12\n"
"f 7/7/13 8/8/14 2/10/15 1/9/16\n"
"f 2/2/17 8/11/18 6/12/19 4/4/20\n"
"f 7/13/21 1/1/22 3/3/23 5/14/24\n"
"t crease 2/1/0 0 1 10.0\n"
"t crease 2/1/0 1 3 10.0\n"
"t crease 2/1/0 3 2 10.0\n"
"t crease 2/1/0 2 0 10.0\n"
"t crease 2/1/0 4 5 10.0\n"
"t crease 2/1/0 5 7 10.0\n"
"t crease 2/1/0 7 6 10.0\n"
"t crease 2/1/0 6 4 10.0\n"
"t crease 2/1/0 0 6 10.0\n"
"t crease 2/1/0 1 7 10.0\n"
"t crease 2/1/0 2 4 10.0\n"
"t crease 2/1/0 3 5 0.1\n"
"t interpolateboundary 1/0/0 2\n"
;