mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-26 09:41:08 +00:00
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:
parent
9222c9e169
commit
898d68ae79
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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...
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user