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

View File

@ -44,8 +44,14 @@ TopologyRefiner::TopologyRefiner(Sdc::SchemeType schemeType, Sdc::Options scheme
_subdivOptions(schemeOptions),
_isUniform(true),
_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
// but will probably have to settle for explicit new/delete...
@ -72,6 +78,7 @@ TopologyRefiner::Unrefine() {
delete _levels[i];
}
_levels.resize(1);
initializeInventory();
}
for (int i=0; i<(int)_refinements.size(); ++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:
//
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 {
int sum = 0;
for (int i = 0; i < (int)_levels.size(); ++i) {
@ -129,7 +167,7 @@ TopologyRefiner::GetNumHoles(int level) const {
int sum = 0;
Vtr::Level const & lvl = getLevel(level);
for (Index face = 0; face < lvl.getNumFaces(); ++face) {
if (lvl.isHole(face)) {
if (lvl.isFaceHole(face)) {
++sum;
}
}
@ -309,6 +347,8 @@ TopologyRefiner::RefineUniform(UniformOptions options) {
//
// Allocate the stack of levels and the refinements between them:
//
_uniformOptions = options;
_isUniform = true;
_maxLevel = options.refinementLevel;
@ -318,10 +358,11 @@ TopologyRefiner::RefineUniform(UniformOptions options) {
// Initialize refinement options for Vtr -- adjusting full-topology for the last level:
//
Vtr::Refinement::Options refineOptions;
refineOptions._sparse = false;
refineOptions._sparse = false;
refineOptions._orderFaceVertsFirst = options.orderVerticesFromFacesFirst;
for (int i = 1; i <= (int)options.refinementLevel; ++i) {
refineOptions._faceTopologyOnly =
refineOptions._minimalTopology =
options.fullTopologyInLastLevel ? false : (i == options.refinementLevel);
Vtr::Level& parentLevel = getLevel(i-1);
@ -335,8 +376,8 @@ TopologyRefiner::RefineUniform(UniformOptions options) {
}
refinement->refine(refineOptions);
_levels.push_back(&childLevel);
_refinements.push_back(refinement);
appendLevel(childLevel);
appendRefinement(*refinement);
}
}
@ -349,24 +390,24 @@ TopologyRefiner::RefineAdaptive(AdaptiveOptions options) {
//
// Allocate the stack of levels and the refinements between them:
//
_adaptiveOptions = options;
_isUniform = false;
_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;
refineOptions._sparse = true;
refineOptions._faceTopologyOnly = not options.fullTopologyInLastLevel;
refineOptions._sparse = true;
refineOptions._minimalTopology = false;
refineOptions._orderFaceVertsFirst = options.orderVerticesFromFacesFirst;
Sdc::Split splitType = (_subdivType == Sdc::SCHEME_LOOP) ? Sdc::SPLIT_TO_TRIS : Sdc::SPLIT_TO_QUADS;
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& childLevel = *(new Vtr::Level);
@ -384,9 +425,6 @@ TopologyRefiner::RefineAdaptive(AdaptiveOptions options) {
// maximum level and stop refinining any further. Otherwise, refine and append
// 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);
selectFeatureAdaptiveComponents(selector);
@ -400,11 +438,8 @@ TopologyRefiner::RefineAdaptive(AdaptiveOptions options) {
refinement->refine(refineOptions);
_levels.push_back(&childLevel);
_refinements.push_back(refinement);
//childLevel.print(refinement);
//assert(childLevel.validateTopology());
appendLevel(childLevel);
appendRefinement(*refinement);
}
}
@ -430,8 +465,8 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
Vtr::Level const& level = selector.getRefinement().parent();
int regularFaceSize = selector.getRefinement()._regFaceSize;
bool considerSingleCreasePatch = _useSingleCreasePatch && (regularFaceSize == 4);
int regularFaceSize = selector.getRefinement()._regFaceSize;
bool considerSingleCreasePatch = _adaptiveOptions.useSingleCreasePatch && (regularFaceSize == 4);
//
// Face-varying consideration when isolating features:
@ -464,7 +499,7 @@ TopologyRefiner::selectFeatureAdaptiveComponents(Vtr::SparseSelector& selector)
//
for (Vtr::Index face = 0; face < level.getNumFaces(); ++face) {
if (level.isHole(face)) {
if (level.isFaceHole(face)) {
continue;
}

View File

@ -79,22 +79,23 @@ public:
/// \brief Returns the highest level of refinement
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
bool HasHoles() const { return _hasHoles; }
// XXXX barfowl -- should cache these internally for trivial return)
/// \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
int GetNumEdgesTotal() const;
int GetNumEdgesTotal() const { return _totalEdges; }
/// \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
int GetNumFaceVerticesTotal() const;
int GetNumFaceVerticesTotal() const { return _totalFaceVertices; }
//@{
/// @name High-level refinement and related methods
@ -109,11 +110,18 @@ public:
UniformOptions(int level) :
refinementLevel(level),
applyBaseFacePerFace(false),
orderVerticesFromFacesFirst(false),
fullTopologyInLastLevel(false) { }
unsigned int refinementLevel:4, ///< Number of refinement iterations
fullTopologyInLastLevel:1; ///< Skip secondary topological relationships
///< at the highest level of refinement.
unsigned int refinementLevel:4, ///< Number of refinement iterations
applyBaseFacePerFace:1, ///< For each refined face, record the index
///< 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
@ -122,6 +130,9 @@ public:
///
void RefineUniform(UniformOptions options);
/// \brief Returns the options specified on refinement
UniformOptions GetUniformOptions() const { return _uniformOptions; }
//
// Adaptive refinement
//
@ -131,15 +142,18 @@ public:
AdaptiveOptions(int level) :
isolationLevel(level),
fullTopologyInLastLevel(false),
useSingleCreasePatch(false) { }
useSingleCreasePatch(false),
applyBaseFacePerFace(false),
orderVerticesFromFacesFirst(false) { }
unsigned int isolationLevel:4, ///< Number of iterations applied to isolate
///< extraordinary vertices and creases
fullTopologyInLastLevel:1, ///< Skip secondary topological relationships
///< at the highest level of refinement.
useSingleCreasePatch:1; ///< Use 'single-crease' patch and stop
///< isolation where applicable
unsigned int isolationLevel:4, ///< Number of iterations applied to isolate
///< extraordinary vertices and creases
useSingleCreasePatch:1, ///< Use 'single-crease' patch and stop
///< isolation where applicable
applyBaseFacePerFace:1, ///< For each refined face, record the index
///< 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
@ -148,6 +162,9 @@ public:
///
void RefineAdaptive(AdaptiveOptions options);
/// \brief Returns the options specified on refinement
AdaptiveOptions GetAdaptiveOptions() const { return _adaptiveOptions; }
/// \brief Unrefine the topology (keep control cage)
void Unrefine();
@ -336,8 +353,8 @@ public:
}
/// \brief Returns true if 'face' at 'level' is tagged as a hole
bool IsHole(int level, Index face) const {
return _levels[level]->isHole(face);
bool IsFaceHole(int level, Index face) const {
return _levels[level]->isFaceHole(face);
}
/// \brief Returns the vertices of an 'edge' at 'level' (2 of them)
@ -415,7 +432,7 @@ public:
//@{
/// @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):
///
@ -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
@ -535,7 +569,7 @@ protected:
void setBaseEdgeSharpness(Index e, float s) { _levels[0]->getEdgeSharpness(e) = 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:
int createBaseFVarChannel(int numValues);
@ -543,6 +577,9 @@ protected:
IndexArray setBaseFVarFaceValues(Index face, int channel = 0);
void setBaseMaxValence(int valence) { _levels[0]->setMaxValence(valence); }
void initializeBaseInventory() { initializeInventory(); }
protected:
//
@ -579,6 +616,12 @@ private:
void initializePtexIndices() const;
void initializeInventory();
void updateInventory(Vtr::Level const & newLevel);
void appendLevel(Vtr::Level & newLevel);
void appendRefinement(Vtr::Refinement & newRefinement);
private:
Sdc::SchemeType _subdivType;
@ -586,9 +629,19 @@ private:
unsigned int _isUniform : 1,
_hasHoles : 1,
_useSingleCreasePatch : 1,
_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::Refinement *> _refinements;

View File

@ -115,6 +115,13 @@ TopologyRefinerFactoryBase::prepareComponentTopologyAssignment(TopologyRefiner&
Warning(msg);
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) {
@ -128,6 +135,9 @@ TopologyRefinerFactoryBase::prepareComponentTopologyAssignment(TopologyRefiner&
return false;
}
}
// Now that we have a valid base level, initialize the Refiner's component inventory:
refiner.initializeBaseInventory();
return true;
}

View File

@ -275,29 +275,17 @@ FVarRefinement::populateChildValues() {
//
// 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
// face-varying data take advantage of this assumption.
//
// Right now there are only two orderings under consideration, and its unclear
// whether only one will be supported or both. Until that's determined, assert
// the conditions we expect for these two.
// 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
// and their FVar-values, their children will correspond).
//
_childFVar._valueCount = 0;
if (_refinement.getFirstChildVertexFromVertices() > 0) {
assert((_refinement.getFirstChildVertexFromFaces() <=
_refinement.getFirstChildVertexFromEdges()) &&
(_refinement.getFirstChildVertexFromEdges() <
_refinement.getFirstChildVertexFromVertices()));
if (_refinement._faceVertsFirst) {
populateChildValuesFromFaceVertices();
populateChildValuesFromEdgeVertices();
populateChildValuesFromVertexVertices();
} else {
assert((_refinement.getFirstChildVertexFromVertices() <
_refinement.getFirstChildVertexFromFaces()) &&
(_refinement.getFirstChildVertexFromFaces() <=
_refinement.getFirstChildVertexFromEdges()));
populateChildValuesFromVertexVertices();
populateChildValuesFromFaceVertices();
populateChildValuesFromEdgeVertices();

View File

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

View File

@ -966,10 +966,9 @@ QuadRefinement::markSparseFaceChildren() {
int marked = false;
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) {
int iPrev = i ? (i - 1) : (fVerts.size() - 1);
markSparseIndexNeighbor(fChildFaces[i]);
markSparseIndexNeighbor(fChildEdges[i]);

View File

@ -49,6 +49,8 @@ Refinement::Refinement(Level const & parent, Level & child, Sdc::Options const&
_child(&child),
_options(options),
_regFaceSize(-1),
_uniform(false),
_faceVertsFirst(false),
_childFaceFromFaceCount(0),
_childEdgeFromFaceCount(0),
_childEdgeFromEdgeCount(0),
@ -116,7 +118,8 @@ Refinement::refine(Options refineOptions) {
// This will become redundant when/if assigned on construction:
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...
bool refineOptions_ignoreFVarChannels = false;
@ -140,7 +143,7 @@ Refinement::refine(Options refineOptions) {
// (though we do require the vertex-face relation for refining FVar channels):
//
Relations relationsToPopulate;
if (refineOptions._faceTopologyOnly) {
if (refineOptions._minimalTopology) {
relationsToPopulate.setAll(false);
relationsToPopulate._faceVertices = true;
} else {
@ -222,18 +225,12 @@ void
Refinement::populateParentChildIndices() {
//
// Two vertex orderings are under consideration -- the original mode orders
// vertices originating from faces first (historically these were relied upon
// to compute the rest of the vertices) while ordering vertices from vertices
// first is being considered (advantageous as it preserves the index of a parent
// vertex at all subsequent levels).
//
// 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;
// Two vertex orderings are currently supported -- ordering vertices refined
// from vertices first, or those refined from faces first. Its possible this
// may be extended to more possibilities. Once the ordering is defined here,
// other than analogous initialization in FVarRefinement, the treatment of
// vertices in blocks based on origin should make the rest of the code
// invariant to ordering changes.
//
// These two blocks now differ only in the utility function that assigns the
// sequential values to the index vectors -- so parameterization/simplification
@ -252,7 +249,7 @@ Refinement::populateParentChildIndices() {
_childEdgeFromEdgeCount = sequenceFullIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge);
// child vertices:
if (faceVertsFirst) {
if (_faceVertsFirst) {
_firstChildVertFromFace = 0;
_childVertFromFaceCount = sequenceFullIndexVector(_faceChildVertIndex, _firstChildVertFromFace);
@ -284,7 +281,7 @@ Refinement::populateParentChildIndices() {
_childEdgeFromEdgeCount = sequenceSparseIndexVector(_edgeChildEdgeIndices, _firstChildEdgeFromEdge);
// child vertices:
if (faceVertsFirst) {
if (_faceVertsFirst) {
_firstChildVertFromFace = 0;
_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...

View File

@ -82,40 +82,36 @@ public:
Level& child() { return *_child; }
//
// Options associated with the actual refinement operation, which are going to get
// quite involved to ensure that the refinement of data that is not of interest can
// be suppressed. For now we have:
// Options associated with the actual refinement operation, which may end up
// quite involved if we want to allow for the refinement of data that is not
// of interest to be suppressed. For now we have:
//
// "sparse": the alternative to uniform refinement, which requires that
// 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
// and only generates what is necessary to define the list of faces.
// This is only one of the six possible topological relations that
// can be generated -- we may eventually want a flag for each.
// and only generates what is minimally necessary for interpolation --
// which requires at least the face-vertices for faces, but also the
// 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
// members associated with it -- it will trigger the computation and
// storage of mask weights for all child vertices. This is naively
// 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...
// These are strictly controlled right now, e.g. for sparse refinement, we
// currently enforce full topology at the finest level to allow for subsequent
// patch construction.
//
struct Options {
Options() : _sparse(0),
_faceTopologyOnly(0)
Options() : _sparse(false),
_faceVertsFirst(false),
_minimalTopology(false)
{ }
unsigned int _sparse : 1;
unsigned int _faceTopologyOnly : 1;
unsigned int _sparse : 1;
unsigned int _faceVertsFirst : 1;
unsigned int _minimalTopology : 1;
// Currently under consideration:
//unsigned int _childToParentMap : 1;
//unsigned int _ancestorFacePerFace : 1;
//unsigned int _computeMasks : 1;
// Still under consideration:
//unsigned int _childToParentMap : 1;
};
void refine(Options options = Options());
@ -156,6 +152,9 @@ public:
Index getChildVertexParentIndex(Index v) const { return _childVertexParentIndex[v]; }
// Child-to-"ancestor" relationships:
Index getChildFaceBaseFace(Index f) const { return _childFaceBaseFaceIndex[f]; }
//
// Non-public methods:
//
@ -263,6 +262,8 @@ protected:
void populateVertexTagsFromParentEdges();
void populateVertexTagsFromParentVertices();
void propagateBaseFace(Refinement const * previousRefinement);
//
// Methods (and types) involved in subdividing the topology -- though not
// fully exploited, any subset of the 6 relations can be generated:
@ -326,6 +327,7 @@ protected:
// Determined by the refinement options:
bool _uniform;
bool _faceVertsFirst;
//
// 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:
//
std::vector<FVarRefinement*> _fvarChannels;
//
// Child-to-base/ancestor mappings:
//
IndexVector _childFaceBaseFaceIndex;
};
inline ConstIndexArray