Minor additions and revisions to TopologyRefiner interface:

- new Options for Refine() methods for base face and vertex ordering
    - removed ignored/unused "full topology" choice from AdaptiveOptions
    - added base face and vertex ordering logic to Refinement
    - addition of TopologyRefiner members for component counts and max valence
    - refactoring of Level additions to update all new member totals
    - addition of GetMaxValence() to TopologyRefiner
    - updated PatchTablesFactory to user new GetMaxValence() method
    - renaming of "Hole" methods for TopologyRefiner and Vtr::Level
This commit is contained in:
barfowl 2015-04-01 20:44:33 -07:00
parent 9222c9e169
commit 898d68ae79
9 changed files with 269 additions and 151 deletions

View File

@ -1065,7 +1065,7 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
options.triangulateQuads &= (refiner.GetSchemeType()==Sdc::SCHEME_BILINEAR or options.triangulateQuads &= (refiner.GetSchemeType()==Sdc::SCHEME_BILINEAR or
refiner.GetSchemeType()==Sdc::SCHEME_CATMARK); refiner.GetSchemeType()==Sdc::SCHEME_CATMARK);
int maxvalence = refiner.getLevel(0).getMaxValence(), int maxvalence = refiner.GetMaxValence(),
maxlevel = refiner.GetMaxLevel(), maxlevel = refiner.GetMaxLevel(),
firstlevel = options.generateAllLevels ? 0 : maxlevel, firstlevel = options.generateAllLevels ? 0 : maxlevel,
nlevels = maxlevel-firstlevel+1; nlevels = maxlevel-firstlevel+1;
@ -1150,7 +1150,7 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
if (level>=firstlevel) { if (level>=firstlevel) {
for (int face=0; face<nfaces; ++face) { for (int face=0; face<nfaces; ++face) {
if (refiner.HasHoles() and refiner.IsHole(level, face)) { if (refiner.HasHoles() and refiner.IsFaceHole(level, face)) {
continue; continue;
} }
@ -1222,7 +1222,7 @@ PatchTablesFactory::createAdaptive(TopologyRefiner const & refiner, Options opti
// Create the instance of the tables and allocate and initialize its members based on // Create the instance of the tables and allocate and initialize its members based on
// the inventory of patches determined above: // the inventory of patches determined above:
// //
int maxValence = refiner.getLevel(0).getMaxValence(); int maxValence = refiner.GetMaxValence();
context.tables = new PatchTables(maxValence); context.tables = new PatchTables(maxValence);
@ -1323,7 +1323,7 @@ PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) {
patchTag.clear(); patchTag.clear();
patchTag._hasPatch = false; patchTag._hasPatch = false;
if (level->isHole(faceIndex)) { if (level->isFaceHole(faceIndex)) {
continue; continue;
} }
@ -1613,7 +1613,7 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
assert(not context.RequiresLegacyGregoryPatches()); assert(not context.RequiresLegacyGregoryPatches());
int maxvalence = refiner.getLevel(0).getMaxValence(), int maxvalence = refiner.GetMaxValence(),
npatches = context.patchInventory.GP; npatches = context.patchInventory.GP;
gregoryStencilsFactory = gregoryStencilsFactory =
@ -1646,7 +1646,7 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
for (int faceIndex = 0; faceIndex < level->getNumFaces(); ++faceIndex) { for (int faceIndex = 0; faceIndex < level->getNumFaces(); ++faceIndex) {
if (level->isHole(faceIndex)) { if (level->isFaceHole(faceIndex)) {
continue; continue;
} }

View File

@ -44,8 +44,14 @@ TopologyRefiner::TopologyRefiner(Sdc::SchemeType schemeType, Sdc::Options scheme
_subdivOptions(schemeOptions), _subdivOptions(schemeOptions),
_isUniform(true), _isUniform(true),
_hasHoles(false), _hasHoles(false),
_useSingleCreasePatch(false), _maxLevel(0),
_maxLevel(0) { _uniformOptions(0),
_adaptiveOptions(0),
_totalVertices(0),
_totalEdges(0),
_totalFaces(0),
_totalFaceVertices(0),
_maxValence(0) {
// Need to revisit allocation scheme here -- want to use smart-ptrs for these // Need to revisit allocation scheme here -- want to use smart-ptrs for these
// but will probably have to settle for explicit new/delete... // but will probably have to settle for explicit new/delete...
@ -72,6 +78,7 @@ TopologyRefiner::Unrefine() {
delete _levels[i]; delete _levels[i];
} }
_levels.resize(1); _levels.resize(1);
initializeInventory();
} }
for (int i=0; i<(int)_refinements.size(); ++i) { for (int i=0; i<(int)_refinements.size(); ++i) {
delete _refinements[i]; delete _refinements[i];
@ -80,42 +87,73 @@ TopologyRefiner::Unrefine() {
} }
//
// Intializing and updating the component inventory:
//
void
TopologyRefiner::initializeInventory() {
if (_levels.size()) {
assert(_levels.size() == 1);
Vtr::Level const & baseLevel = *_levels[0];
_totalVertices = baseLevel.getNumVertices();
_totalEdges = baseLevel.getNumEdges();
_totalFaces = baseLevel.getNumFaces();
_totalFaceVertices = baseLevel.getNumFaceVerticesTotal();
_maxValence = baseLevel.getMaxValence();
} else {
_totalVertices = 0;
_totalEdges = 0;
_totalFaces = 0;
_totalFaceVertices = 0;
_maxValence = 0;
}
}
void
TopologyRefiner::updateInventory(Vtr::Level const & newLevel) {
_totalVertices += newLevel.getNumVertices();
_totalEdges += newLevel.getNumEdges();
_totalFaces += newLevel.getNumFaces();
_totalFaceVertices += newLevel.getNumFaceVerticesTotal();
_maxValence = std::max(_maxValence, newLevel.getMaxValence());
}
void
TopologyRefiner::appendLevel(Vtr::Level & newLevel) {
_levels.push_back(&newLevel);
updateInventory(newLevel);
}
void
TopologyRefiner::appendRefinement(Vtr::Refinement & newRefinement) {
//
// There may be properties to transfer between refinements that cannot be passed on
// when refining between the parent and child since they exist "above" the parent:
//
bool applyBaseFace = (_isUniform && _uniformOptions.applyBaseFacePerFace) ||
(!_isUniform && _adaptiveOptions.applyBaseFacePerFace);
if (applyBaseFace) {
newRefinement.propagateBaseFace(_refinements.size() ? _refinements.back() : 0);
}
_refinements.push_back(&newRefinement);
}
// //
// Accessors to the topology information: // Accessors to the topology information:
// //
int int
TopologyRefiner::GetNumVerticesTotal() const {
int sum = 0;
for (int i = 0; i < (int)_levels.size(); ++i) {
sum += _levels[i]->getNumVertices();
}
return sum;
}
int
TopologyRefiner::GetNumEdgesTotal() const {
int sum = 0;
for (int i = 0; i < (int)_levels.size(); ++i) {
sum += _levels[i]->getNumEdges();
}
return sum;
}
int
TopologyRefiner::GetNumFacesTotal() const {
int sum = 0;
for (int i = 0; i < (int)_levels.size(); ++i) {
sum += _levels[i]->getNumFaces();
}
return sum;
}
int
TopologyRefiner::GetNumFaceVerticesTotal() const {
int sum = 0;
for (int i = 0; i < (int)_levels.size(); ++i) {
sum += _levels[i]->getNumFaceVerticesTotal();
}
return sum;
}
int
TopologyRefiner::GetNumFVarValuesTotal(int channel) const { TopologyRefiner::GetNumFVarValuesTotal(int channel) const {
int sum = 0; int sum = 0;
for (int i = 0; i < (int)_levels.size(); ++i) { for (int i = 0; i < (int)_levels.size(); ++i) {
@ -129,7 +167,7 @@ TopologyRefiner::GetNumHoles(int level) const {
int sum = 0; int sum = 0;
Vtr::Level const & lvl = getLevel(level); Vtr::Level const & lvl = getLevel(level);
for (Index face = 0; face < lvl.getNumFaces(); ++face) { for (Index face = 0; face < lvl.getNumFaces(); ++face) {
if (lvl.isHole(face)) { if (lvl.isFaceHole(face)) {
++sum; ++sum;
} }
} }
@ -309,6 +347,8 @@ TopologyRefiner::RefineUniform(UniformOptions options) {
// //
// Allocate the stack of levels and the refinements between them: // Allocate the stack of levels and the refinements between them:
// //
_uniformOptions = options;
_isUniform = true; _isUniform = true;
_maxLevel = options.refinementLevel; _maxLevel = options.refinementLevel;
@ -318,10 +358,11 @@ TopologyRefiner::RefineUniform(UniformOptions options) {
// Initialize refinement options for Vtr -- adjusting full-topology for the last level: // Initialize refinement options for Vtr -- adjusting full-topology for the last level:
// //
Vtr::Refinement::Options refineOptions; Vtr::Refinement::Options refineOptions;
refineOptions._sparse = false; refineOptions._sparse = false;
refineOptions._orderFaceVertsFirst = options.orderVerticesFromFacesFirst;
for (int i = 1; i <= (int)options.refinementLevel; ++i) { for (int i = 1; i <= (int)options.refinementLevel; ++i) {
refineOptions._faceTopologyOnly = refineOptions._minimalTopology =
options.fullTopologyInLastLevel ? false : (i == options.refinementLevel); options.fullTopologyInLastLevel ? false : (i == options.refinementLevel);
Vtr::Level& parentLevel = getLevel(i-1); Vtr::Level& parentLevel = getLevel(i-1);
@ -335,8 +376,8 @@ TopologyRefiner::RefineUniform(UniformOptions options) {
} }
refinement->refine(refineOptions); refinement->refine(refineOptions);
_levels.push_back(&childLevel); appendLevel(childLevel);
_refinements.push_back(refinement); appendRefinement(*refinement);
} }
} }
@ -349,24 +390,24 @@ TopologyRefiner::RefineAdaptive(AdaptiveOptions options) {
// //
// Allocate the stack of levels and the refinements between them: // Allocate the stack of levels and the refinements between them:
// //
_adaptiveOptions = options;
_isUniform = false; _isUniform = false;
_maxLevel = options.isolationLevel; _maxLevel = options.isolationLevel;
_useSingleCreasePatch = options.useSingleCreasePatch;
// //
// Initialize refinement options for Vtr: // Initialize refinement options for Vtr -- full topology is always generated in
// the last level as expected usage is for patch retrieval:
// //
Vtr::Refinement::Options refineOptions; Vtr::Refinement::Options refineOptions;
refineOptions._sparse = true; refineOptions._sparse = true;
refineOptions._faceTopologyOnly = not options.fullTopologyInLastLevel; refineOptions._minimalTopology = false;
refineOptions._orderFaceVertsFirst = options.orderVerticesFromFacesFirst;
Sdc::Split splitType = (_subdivType == Sdc::SCHEME_LOOP) ? Sdc::SPLIT_TO_TRIS : Sdc::SPLIT_TO_QUADS; Sdc::Split splitType = (_subdivType == Sdc::SCHEME_LOOP) ? Sdc::SPLIT_TO_TRIS : Sdc::SPLIT_TO_QUADS;
for (int i = 1; i <= (int)options.isolationLevel; ++i) { for (int i = 1; i <= (int)options.isolationLevel; ++i) {
// Keeping full topology on for debugging -- may need to go back a level and "prune"
// its topology if we don't use the full depth
refineOptions._faceTopologyOnly = false;
Vtr::Level& parentLevel = getLevel(i-1); Vtr::Level& parentLevel = getLevel(i-1);
Vtr::Level& childLevel = *(new Vtr::Level); Vtr::Level& childLevel = *(new Vtr::Level);
@ -384,9 +425,6 @@ TopologyRefiner::RefineAdaptive(AdaptiveOptions options) {
// maximum level and stop refinining any further. Otherwise, refine and append // maximum level and stop refinining any further. Otherwise, refine and append
// the new refinement and child. // the new refinement and child.
// //
// Note that if we support the "full topology at last level" option properly,
// we should prune the previous level generated, as it is now the last...
//
Vtr::SparseSelector selector(*refinement); Vtr::SparseSelector selector(*refinement);
selectFeatureAdaptiveComponents(selector); selectFeatureAdaptiveComponents(selector);
@ -400,11 +438,8 @@ TopologyRefiner::RefineAdaptive(AdaptiveOptions options) {
refinement->refine(refineOptions); refinement->refine(refineOptions);
_levels.push_back(&childLevel); appendLevel(childLevel);
_refinements.push_back(refinement); appendRefinement(*refinement);
//childLevel.print(refinement);
//assert(childLevel.validateTopology());
} }
} }
@ -430,8 +465,8 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
Vtr::Level const& level = selector.getRefinement().parent(); Vtr::Level const& level = selector.getRefinement().parent();
int regularFaceSize = selector.getRefinement()._regFaceSize; int regularFaceSize = selector.getRefinement()._regFaceSize;
bool considerSingleCreasePatch = _useSingleCreasePatch && (regularFaceSize == 4); bool considerSingleCreasePatch = _adaptiveOptions.useSingleCreasePatch && (regularFaceSize == 4);
// //
// Face-varying consideration when isolating features: // Face-varying consideration when isolating features:
@ -464,7 +499,7 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
// //
for (Vtr::Index face = 0; face < level.getNumFaces(); ++face) { for (Vtr::Index face = 0; face < level.getNumFaces(); ++face) {
if (level.isHole(face)) { if (level.isFaceHole(face)) {
continue; continue;
} }

View File

@ -79,22 +79,23 @@ public:
/// \brief Returns the highest level of refinement /// \brief Returns the highest level of refinement
int GetMaxLevel() const { return _maxLevel; } int GetMaxLevel() const { return _maxLevel; }
/// \brief Returns the maximum vertex valence in all levels
int GetMaxValence() const { return _maxValence; }
/// \ brief Returns true if faces have been tagged as holes /// \ brief Returns true if faces have been tagged as holes
bool HasHoles() const { return _hasHoles; } bool HasHoles() const { return _hasHoles; }
// XXXX barfowl -- should cache these internally for trivial return)
/// \brief Returns the total number of vertices in all levels /// \brief Returns the total number of vertices in all levels
int GetNumVerticesTotal() const; int GetNumVerticesTotal() const { return _totalVertices; }
/// \brief Returns the total number of edges in all levels /// \brief Returns the total number of edges in all levels
int GetNumEdgesTotal() const; int GetNumEdgesTotal() const { return _totalEdges; }
/// \brief Returns the total number of edges in all levels /// \brief Returns the total number of edges in all levels
int GetNumFacesTotal() const; int GetNumFacesTotal() const { return _totalFaces; }
/// \brief Returns the total number of face vertices in all levels /// \brief Returns the total number of face vertices in all levels
int GetNumFaceVerticesTotal() const; int GetNumFaceVerticesTotal() const { return _totalFaceVertices; }
//@{ //@{
/// @name High-level refinement and related methods /// @name High-level refinement and related methods
@ -109,11 +110,18 @@ public:
UniformOptions(int level) : UniformOptions(int level) :
refinementLevel(level), refinementLevel(level),
applyBaseFacePerFace(false),
orderVerticesFromFacesFirst(false),
fullTopologyInLastLevel(false) { } fullTopologyInLastLevel(false) { }
unsigned int refinementLevel:4, ///< Number of refinement iterations unsigned int refinementLevel:4, ///< Number of refinement iterations
fullTopologyInLastLevel:1; ///< Skip secondary topological relationships applyBaseFacePerFace:1, ///< For each refined face, record the index
///< at the highest level of refinement. ///< of the base face from which it originates
orderVerticesFromFacesFirst:1, ///< Order child vertices from faces first
///< instead of child vertices of vertices
fullTopologyInLastLevel:1; ///< Skip topological relationships in the last
///< level of refinement that are not needed for
///< interpolation (keep false if using limit).
}; };
/// \brief Refine the topology uniformly /// \brief Refine the topology uniformly
@ -122,6 +130,9 @@ public:
/// ///
void RefineUniform(UniformOptions options); void RefineUniform(UniformOptions options);
/// \brief Returns the options specified on refinement
UniformOptions GetUniformOptions() const { return _uniformOptions; }
// //
// Adaptive refinement // Adaptive refinement
// //
@ -131,15 +142,18 @@ public:
AdaptiveOptions(int level) : AdaptiveOptions(int level) :
isolationLevel(level), isolationLevel(level),
fullTopologyInLastLevel(false), useSingleCreasePatch(false),
useSingleCreasePatch(false) { } applyBaseFacePerFace(false),
orderVerticesFromFacesFirst(false) { }
unsigned int isolationLevel:4, ///< Number of iterations applied to isolate unsigned int isolationLevel:4, ///< Number of iterations applied to isolate
///< extraordinary vertices and creases ///< extraordinary vertices and creases
fullTopologyInLastLevel:1, ///< Skip secondary topological relationships useSingleCreasePatch:1, ///< Use 'single-crease' patch and stop
///< at the highest level of refinement. ///< isolation where applicable
useSingleCreasePatch:1; ///< Use 'single-crease' patch and stop applyBaseFacePerFace:1, ///< For each refined face, record the index
///< isolation where applicable ///< of the base face from which it originates
orderVerticesFromFacesFirst:1; ///< Order child vertices from faces first
///< instead of child vertices of vertices
}; };
/// \brief Feature Adaptive topology refinement /// \brief Feature Adaptive topology refinement
@ -148,6 +162,9 @@ public:
/// ///
void RefineAdaptive(AdaptiveOptions options); void RefineAdaptive(AdaptiveOptions options);
/// \brief Returns the options specified on refinement
AdaptiveOptions GetAdaptiveOptions() const { return _adaptiveOptions; }
/// \brief Unrefine the topology (keep control cage) /// \brief Unrefine the topology (keep control cage)
void Unrefine(); void Unrefine();
@ -336,8 +353,8 @@ public:
} }
/// \brief Returns true if 'face' at 'level' is tagged as a hole /// \brief Returns true if 'face' at 'level' is tagged as a hole
bool IsHole(int level, Index face) const { bool IsFaceHole(int level, Index face) const {
return _levels[level]->isHole(face); return _levels[level]->isFaceHole(face);
} }
/// \brief Returns the vertices of an 'edge' at 'level' (2 of them) /// \brief Returns the vertices of an 'edge' at 'level' (2 of them)
@ -415,7 +432,7 @@ public:
//@{ //@{
/// @name Parent-to-child relationships, /// @name Parent-to-child relationships,
/// Telationships between components in one level /// Relationships between components in one level
/// and the next (entries may be invalid if sparse): /// and the next (entries may be invalid if sparse):
/// ///
@ -452,6 +469,23 @@ public:
//@} //@}
//@{
/// @name Child-to-parent or child-to-base relationships,
/// Relationships between components in one level and the
/// previous or base level (to be called with level > 0):
///
/// \brief Returns the parent face of face 'f' at 'level'
Index GetFaceParentFace(int level, Index f) const {
return _refinements[level-1]->getChildFaceParentFace(f);
}
/// \brief Returns the base face of face 'f' at 'level'
Index GetFaceBaseFace(int level, Index f) const {
return _refinements[level-1]->getChildFaceBaseFace(f);
}
//@}
//@{ //@{
/// Ptex /// Ptex
@ -535,7 +569,7 @@ protected:
void setBaseEdgeSharpness(Index e, float s) { _levels[0]->getEdgeSharpness(e) = s; } void setBaseEdgeSharpness(Index e, float s) { _levels[0]->getEdgeSharpness(e) = s; }
void setBaseVertexSharpness(Index v, float s) { _levels[0]->getVertexSharpness(v) = s; } void setBaseVertexSharpness(Index v, float s) { _levels[0]->getVertexSharpness(v) = s; }
void setBaseFaceHole(Index f, bool b) { _levels[0]->setHole(f, b); _hasHoles |= b; } void setBaseFaceHole(Index f, bool b) { _levels[0]->setFaceHole(f, b); _hasHoles |= b; }
// Optional methods for creating and assigning face-varying data channels: // Optional methods for creating and assigning face-varying data channels:
int createBaseFVarChannel(int numValues); int createBaseFVarChannel(int numValues);
@ -543,6 +577,9 @@ protected:
IndexArray setBaseFVarFaceValues(Index face, int channel = 0); IndexArray setBaseFVarFaceValues(Index face, int channel = 0);
void setBaseMaxValence(int valence) { _levels[0]->setMaxValence(valence); }
void initializeBaseInventory() { initializeInventory(); }
protected: protected:
// //
@ -579,6 +616,12 @@ private:
void initializePtexIndices() const; void initializePtexIndices() const;
void initializeInventory();
void updateInventory(Vtr::Level const & newLevel);
void appendLevel(Vtr::Level & newLevel);
void appendRefinement(Vtr::Refinement & newRefinement);
private: private:
Sdc::SchemeType _subdivType; Sdc::SchemeType _subdivType;
@ -586,9 +629,19 @@ private:
unsigned int _isUniform : 1, unsigned int _isUniform : 1,
_hasHoles : 1, _hasHoles : 1,
_useSingleCreasePatch : 1,
_maxLevel : 4; _maxLevel : 4;
// Options assigned on refinement:
UniformOptions _uniformOptions;
AdaptiveOptions _adaptiveOptions;
// Cumulative properties of all levels:
int _totalVertices;
int _totalEdges;
int _totalFaces;
int _totalFaceVertices;
int _maxValence;
std::vector<Vtr::Level *> _levels; std::vector<Vtr::Level *> _levels;
std::vector<Vtr::Refinement *> _refinements; std::vector<Vtr::Refinement *> _refinements;

View File

@ -115,6 +115,13 @@ TopologyRefinerFactoryBase::prepareComponentTopologyAssignment(TopologyRefiner&
Warning(msg); Warning(msg);
return false; return false;
} }
} else {
if (baseLevel.getMaxValence() == 0) {
char msg[1024];
snprintf(msg, 1024, "Invalid topology detected : maximum valence not assigned.");
Warning(msg);
return false;
}
} }
if (fullValidation) { if (fullValidation) {
@ -128,6 +135,9 @@ TopologyRefinerFactoryBase::prepareComponentTopologyAssignment(TopologyRefiner&
return false; return false;
} }
} }
// Now that we have a valid base level, initialize the Refiner's component inventory:
refiner.initializeBaseInventory();
return true; return true;
} }

View File

@ -275,29 +275,17 @@ FVarRefinement::populateChildValues() {
// //
// Be sure to match the same vertex ordering as Refinement, i.e. face-vertices // Be sure to match the same vertex ordering as Refinement, i.e. face-vertices
// first vs vertex-vertices first, etc. A few optimizations within the use of // first vs vertex-vertices first, etc. A few optimizations within the use of
// face-varying data take advantage of this assumption. // face-varying data take advantage of this assumption, and it just makes sense
// // to be consistent (e.g. if there is a 1-to-1 correspondence between vertices
// Right now there are only two orderings under consideration, and its unclear // and their FVar-values, their children will correspond).
// whether only one will be supported or both. Until that's determined, assert
// the conditions we expect for these two.
// //
_childFVar._valueCount = 0; _childFVar._valueCount = 0;
if (_refinement.getFirstChildVertexFromVertices() > 0) { if (_refinement._faceVertsFirst) {
assert((_refinement.getFirstChildVertexFromFaces() <=
_refinement.getFirstChildVertexFromEdges()) &&
(_refinement.getFirstChildVertexFromEdges() <
_refinement.getFirstChildVertexFromVertices()));
populateChildValuesFromFaceVertices(); populateChildValuesFromFaceVertices();
populateChildValuesFromEdgeVertices(); populateChildValuesFromEdgeVertices();
populateChildValuesFromVertexVertices(); populateChildValuesFromVertexVertices();
} else { } else {
assert((_refinement.getFirstChildVertexFromVertices() <
_refinement.getFirstChildVertexFromFaces()) &&
(_refinement.getFirstChildVertexFromFaces() <=
_refinement.getFirstChildVertexFromEdges()));
populateChildValuesFromVertexVertices(); populateChildValuesFromVertexVertices();
populateChildValuesFromFaceVertices(); populateChildValuesFromFaceVertices();
populateChildValuesFromEdgeVertices(); populateChildValuesFromEdgeVertices();

View File

@ -241,8 +241,8 @@ public:
Index findEdge(Index v0Index, Index v1Index) const; Index findEdge(Index v0Index, Index v1Index) const;
// Holes // Holes
void setHole(Index faceIndex, bool b); void setFaceHole(Index faceIndex, bool b);
bool isHole(Index faceIndex) const; bool isFaceHole(Index faceIndex) const;
// Face-varying // Face-varying
Sdc::Options getFVarOptions(int channel = 0) const; Sdc::Options getFVarOptions(int channel = 0) const;
@ -351,6 +351,8 @@ protected:
void resizeVertexFaces(int numVertexFacesTotal); void resizeVertexFaces(int numVertexFacesTotal);
void resizeVertexEdges(int numVertexEdgesTotal); void resizeVertexEdges(int numVertexEdgesTotal);
void setMaxValence(int maxValence);
// Modifiers to populate the relations for each component: // Modifiers to populate the relations for each component:
IndexArray getFaceVertices(Index faceIndex); IndexArray getFaceVertices(Index faceIndex);
IndexArray getFaceEdges(Index faceIndex); IndexArray getFaceEdges(Index faceIndex);
@ -447,11 +449,14 @@ protected:
int _edgeCount; int _edgeCount;
int _vertCount; int _vertCount;
// TBD - "depth" is clearly useful in both the topological splitting and the // The "depth" member is clearly useful in both the topological splitting and the
// stencil queries so could be valuable in both. As face-vert valence becomes // stencil queries, but arguably it ties the Level to a hierarchy which counters
// constant there is no need to store face-vert and face-edge counts so it has // the idea if it being independent.
// value in Level, though perhaps specified as something other than "depth"
int _depth; int _depth;
// Maxima to help clients manage sizing of data buffers. Given "max valence",
// the "max edge faces" is strictly redundant as it will always be less, but
// since it will typically be so much less (i.e. 2) it is kept for now.
int _maxEdgeFaces; int _maxEdgeFaces;
int _maxValence; int _maxValence;
@ -619,6 +624,11 @@ Level::trimVertexEdges(Index vertIndex, int count) {
_vertEdgeCountsAndOffsets[vertIndex*2] = count; _vertEdgeCountsAndOffsets[vertIndex*2] = count;
} }
inline void
Level::setMaxValence(int valence) {
_maxValence = valence;
}
// //
// Access/modify the vertices indicent a given edge: // Access/modify the vertices indicent a given edge:
// //
@ -700,11 +710,11 @@ Level::getVertexRule(Index vertIndex) const {
// Access/modify hole tag: // Access/modify hole tag:
// //
inline void inline void
Level::setHole(Index faceIndex, bool b) { Level::setFaceHole(Index faceIndex, bool b) {
_faceTags[faceIndex]._hole = b; _faceTags[faceIndex]._hole = b;
} }
inline bool inline bool
Level::isHole(Index faceIndex) const { Level::isFaceHole(Index faceIndex) const {
return _faceTags[faceIndex]._hole; return _faceTags[faceIndex]._hole;
} }

View File

@ -966,10 +966,9 @@ QuadRefinement::markSparseFaceChildren() {
int marked = false; int marked = false;
for (int i = 0; i < fVerts.size(); ++i) { for (int i = 0; i < fVerts.size(); ++i) {
// NOTE - the mod 4 here will not work for N-gons (and want to avoid % anyway)
int iPrev = (i+3) % 4;
if (_parentVertexTag[fVerts[i]]._selected) { if (_parentVertexTag[fVerts[i]]._selected) {
int iPrev = i ? (i - 1) : (fVerts.size() - 1);
markSparseIndexNeighbor(fChildFaces[i]); markSparseIndexNeighbor(fChildFaces[i]);
markSparseIndexNeighbor(fChildEdges[i]); markSparseIndexNeighbor(fChildEdges[i]);

View File

@ -49,6 +49,8 @@ Refinement::Refinement(Level const & parent, Level & child, Sdc::Options const&
_child(&child), _child(&child),
_options(options), _options(options),
_regFaceSize(-1), _regFaceSize(-1),
_uniform(false),
_faceVertsFirst(false),
_childFaceFromFaceCount(0), _childFaceFromFaceCount(0),
_childEdgeFromFaceCount(0), _childEdgeFromFaceCount(0),
_childEdgeFromEdgeCount(0), _childEdgeFromEdgeCount(0),
@ -116,7 +118,8 @@ Refinement::refine(Options refineOptions) {
// This will become redundant when/if assigned on construction: // This will become redundant when/if assigned on construction:
assert(_parent && _child); assert(_parent && _child);
_uniform = !refineOptions._sparse; _uniform = !refineOptions._sparse;
_faceVertsFirst = refineOptions._faceVertsFirst;
// We may soon have an option here to suppress refinement of FVar channels... // We may soon have an option here to suppress refinement of FVar channels...
bool refineOptions_ignoreFVarChannels = false; bool refineOptions_ignoreFVarChannels = false;
@ -140,7 +143,7 @@ Refinement::refine(Options refineOptions) {
// (though we do require the vertex-face relation for refining FVar channels): // (though we do require the vertex-face relation for refining FVar channels):
// //
Relations relationsToPopulate; Relations relationsToPopulate;
if (refineOptions._faceTopologyOnly) { if (refineOptions._minimalTopology) {
relationsToPopulate.setAll(false); relationsToPopulate.setAll(false);
relationsToPopulate._faceVertices = true; relationsToPopulate._faceVertices = true;
} else { } else {
@ -222,18 +225,12 @@ void
Refinement::populateParentChildIndices() { Refinement::populateParentChildIndices() {
// //
// Two vertex orderings are under consideration -- the original mode orders // Two vertex orderings are currently supported -- ordering vertices refined
// vertices originating from faces first (historically these were relied upon // from vertices first, or those refined from faces first. Its possible this
// to compute the rest of the vertices) while ordering vertices from vertices // may be extended to more possibilities. Once the ordering is defined here,
// first is being considered (advantageous as it preserves the index of a parent // other than analogous initialization in FVarRefinement, the treatment of
// vertex at all subsequent levels). // vertices in blocks based on origin should make the rest of the code
// // invariant to ordering changes.
// Other than defining the same ordering for refinement face-varying channels
// (which can be inferred from settings here) the rest of the code should be
// invariant to vertex ordering.
//
bool faceVertsFirst = false;
// //
// These two blocks now differ only in the utility function that assigns the // These two blocks now differ only in the utility function that assigns the
// sequential values to the index vectors -- so parameterization/simplification // sequential values to the index vectors -- so parameterization/simplification
@ -252,7 +249,7 @@ Refinement::populateParentChildIndices() {
_childEdgeFromEdgeCount = sequenceFullIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge); _childEdgeFromEdgeCount = sequenceFullIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge);
// child vertices: // child vertices:
if (faceVertsFirst) { if (_faceVertsFirst) {
_firstChildVertFromFace = 0; _firstChildVertFromFace = 0;
_childVertFromFaceCount = sequenceFullIndexVector(_faceChildVertIndex, _firstChildVertFromFace); _childVertFromFaceCount = sequenceFullIndexVector(_faceChildVertIndex, _firstChildVertFromFace);
@ -284,7 +281,7 @@ Refinement::populateParentChildIndices() {
_childEdgeFromEdgeCount = sequenceSparseIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge); _childEdgeFromEdgeCount = sequenceSparseIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge);
// child vertices: // child vertices:
if (faceVertsFirst) { if (_faceVertsFirst) {
_firstChildVertFromFace = 0; _firstChildVertFromFace = 0;
_childVertFromFaceCount = sequenceSparseIndexVector(_faceChildVertIndex, _firstChildVertFromFace); _childVertFromFaceCount = sequenceSparseIndexVector(_faceChildVertIndex, _firstChildVertFromFace);
@ -1081,6 +1078,25 @@ Refinement::subdivideFVarChannels() {
} }
} }
//
// Methods to inherit properties between refinements in a hierarchy:
//
void
Refinement::propagateBaseFace(Refinement const * grandParent) {
_childFaceBaseFaceIndex.resize(_child->_faceCount);
if (grandParent == 0) {
_childFaceBaseFaceIndex = _childFaceParentIndex;
} else {
IndexVector & childBaseFace = _childFaceBaseFaceIndex;
IndexVector const & parentBaseFace = grandParent->_childFaceBaseFaceIndex;
for (Index cFace = 0; cFace < _child->_faceCount; ++cFace) {
childBaseFace[cFace] = parentBaseFace[_childFaceParentIndex[cFace]];
}
}
}
// //
// Marking of sparse child components -- including those selected and those neighboring... // Marking of sparse child components -- including those selected and those neighboring...

View File

@ -82,40 +82,36 @@ public:
Level& child() { return *_child; } Level& child() { return *_child; }
// //
// Options associated with the actual refinement operation, which are going to get // Options associated with the actual refinement operation, which may end up
// quite involved to ensure that the refinement of data that is not of interest can // quite involved if we want to allow for the refinement of data that is not
// be suppressed. For now we have: // of interest to be suppressed. For now we have:
// //
// "sparse": the alternative to uniform refinement, which requires that // "sparse": the alternative to uniform refinement, which requires that
// components be previously selected/marked to be included. // components be previously selected/marked to be included.
// //
// "face topology only": this is one that may get broken down into a finer // "minimal topology": this is one that may get broken down into a finer
// set of options. It suppresses "full topology" in the child level // set of options. It suppresses "full topology" in the child level
// and only generates what is necessary to define the list of faces. // and only generates what is minimally necessary for interpolation --
// This is only one of the six possible topological relations that // which requires at least the face-vertices for faces, but also the
// can be generated -- we may eventually want a flag for each. // vertex-faces for any face-varying channels present. So it will
// generate one or two of the six possible topological relations.
// //
// "compute masks": this is intended to be temporary, along with the data // These are strictly controlled right now, e.g. for sparse refinement, we
// members associated with it -- it will trigger the computation and // currently enforce full topology at the finest level to allow for subsequent
// storage of mask weights for all child vertices. This is naively // patch construction.
// stored at this point and exists only for reference.
//
// Its still up for debate as to how finely these should be controlled, e.g.
// for sparse refinement, we likely want full topology at the finest level to
// allow for subsequent patch construction...
// //
struct Options { struct Options {
Options() : _sparse(0), Options() : _sparse(false),
_faceTopologyOnly(0) _faceVertsFirst(false),
_minimalTopology(false)
{ } { }
unsigned int _sparse : 1; unsigned int _sparse : 1;
unsigned int _faceTopologyOnly : 1; unsigned int _faceVertsFirst : 1;
unsigned int _minimalTopology : 1;
// Currently under consideration: // Still under consideration:
//unsigned int _childToParentMap : 1; //unsigned int _childToParentMap : 1;
//unsigned int _ancestorFacePerFace : 1;
//unsigned int _computeMasks : 1;
}; };
void refine(Options options = Options()); void refine(Options options = Options());
@ -156,6 +152,9 @@ public:
Index getChildVertexParentIndex(Index v) const { return _childVertexParentIndex[v]; } Index getChildVertexParentIndex(Index v) const { return _childVertexParentIndex[v]; }
// Child-to-"ancestor" relationships:
Index getChildFaceBaseFace(Index f) const { return _childFaceBaseFaceIndex[f]; }
// //
// Non-public methods: // Non-public methods:
// //
@ -263,6 +262,8 @@ protected:
void populateVertexTagsFromParentEdges(); void populateVertexTagsFromParentEdges();
void populateVertexTagsFromParentVertices(); void populateVertexTagsFromParentVertices();
void propagateBaseFace(Refinement const * previousRefinement);
// //
// Methods (and types) involved in subdividing the topology -- though not // Methods (and types) involved in subdividing the topology -- though not
// fully exploited, any subset of the 6 relations can be generated: // fully exploited, any subset of the 6 relations can be generated:
@ -326,6 +327,7 @@ protected:
// Determined by the refinement options: // Determined by the refinement options:
bool _uniform; bool _uniform;
bool _faceVertsFirst;
// //
// Inventory and ordering of the types of child components: // Inventory and ordering of the types of child components:
@ -391,6 +393,11 @@ protected:
// Refinement data for face-varying channels present in the Levels being refined: // Refinement data for face-varying channels present in the Levels being refined:
// //
std::vector<FVarRefinement*> _fvarChannels; std::vector<FVarRefinement*> _fvarChannels;
//
// Child-to-base/ancestor mappings:
//
IndexVector _childFaceBaseFaceIndex;
}; };
inline ConstIndexArray inline ConstIndexArray