Added support for creation of face-varying Far::LimitStencilTables:

- added necessary options to struct LimitStencilTableFactory...::Options
    - updated Create() to support creation of varying and face-varying stencils
    - updated Create() to provide clarity and stricter compatibility checks for
      the optional StencilTable and PatchTable arguments
    - modified Doxygen comments for Create() to clarify requirements of the
      optional table arguments
    - added missing StencilTableFactory::AppendLocalPointStencilTableVarying()
This commit is contained in:
barry 2018-10-29 10:46:03 -07:00
parent 968f6e001c
commit c59c801e9c
2 changed files with 181 additions and 59 deletions

View File

@ -427,74 +427,109 @@ LimitStencilTableFactoryReal<REAL>::Create(TopologyRefiner const & refiner,
return 0;
}
bool uniform = refiner.IsUniform();
bool uniform = refiner.IsUniform();
int maxlevel = refiner.GetMaxLevel();
int maxlevel = refiner.GetMaxLevel();
bool interpolateVertex = (options.interpolationMode == INTERPOLATE_VERTEX);
bool interpolateVarying = (options.interpolationMode == INTERPOLATE_VARYING);
bool interpolateFaceVarying = (options.interpolationMode == INTERPOLATE_FACE_VARYING);
int fvarChannel = options.fvarChannel;
//
// Quick sanity checks for given PatchTable and/or StencilTables -- more to
// come once a PatchTable is built and the number of local points known:
//
int nRefinedStencils = 0;
if (uniform) {
nRefinedStencils = refiner.GetLevel(maxlevel).GetNumVertices();
} else if (!interpolateFaceVarying) {
nRefinedStencils = refiner.GetNumVerticesTotal();
} else {
nRefinedStencils = refiner.GetNumFVarValuesTotal(fvarChannel);
}
if (cvStencilsIn && (cvStencilsIn->GetNumStencils() < nRefinedStencils)) {
// Too few stencils in given StencilTable
return 0;
}
if (patchTableIn && (patchTableIn->IsFeatureAdaptive() == uniform)) {
// Adaptive/uniform mismatch with given PatchTable and refiner
return 0;
}
// If an appropriate StencilTable was given, use it, otherwise, create a new one
StencilTableReal<REAL> const * cvstencils = cvStencilsIn;
if (! cvstencils) {
//
// Generate stencils for the control vertices - this is necessary to
// properly factorize patches with control vertices at level 0 (natural
// regular patches, such as in a torus)
// note: the control vertices of the mesh are added as single-index
// stencils of weight 1.0f
//
typename StencilTableFactoryReal<REAL>::Options stencilTableOptions;
stencilTableOptions.generateIntermediateLevels = uniform ? false :true;
stencilTableOptions.generateControlVerts = true;
stencilTableOptions.generateOffsets = true;
stencilTableOptions.interpolationMode = options.interpolationMode;
stencilTableOptions.fvarChannel = options.fvarChannel;
// PERFORMANCE: We could potentially save some mem-copies by not
// instantiating the stencil tables and work directly off the source
// data.
cvstencils = StencilTableFactoryReal<REAL>::Create(refiner, stencilTableOptions);
} else {
// Sanity checks
//
// Note that the input cvStencils could be larger than the number of
// refiner's vertices, due to the existence of the end cap stencils.
if (cvstencils->GetNumStencils() < (uniform ?
refiner.GetLevel(maxlevel).GetNumVertices() :
refiner.GetNumVerticesTotal())) {
return 0;
}
assert(cvstencils->GetNumStencils() == nRefinedStencils);
}
// If a stencil table was given, use it, otherwise, create a new one
// If an appropriate PatchTable was given, use it, otherwise, create a new one
PatchTable const * patchtable = patchTableIn;
if (! patchtable) {
// XXXX (manuelk) If no patch-table was passed, we should be able to
// infer the patches fairly easily from the refiner. Once more tags
// have been added to the refiner, maybe we can remove the need for the
// patch table.
//
// Ideally we could create a sparse PatchTable here for the given
// Locations, but that requires inverting the ptex/base-face relation.
// so the caller must deal with that and provide such a PatchTable
//
PatchTableFactory::Options patchTableOptions;
patchTableOptions.SetPatchPrecision<REAL>();
patchTableOptions.generateVaryingTables = interpolateVarying;
patchTableOptions.generateFVarTables = interpolateFaceVarying;
if (interpolateFaceVarying) {
patchTableOptions.numFVarChannels = 1;
patchTableOptions.fvarChannelIndices = &fvarChannel;
patchTableOptions.generateFVarLegacyLinearPatches = uniform ||
!refiner.GetAdaptiveOptions().considerFVarChannels;
}
patchTableOptions.SetEndCapType(
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
patchTableOptions.useInfSharpPatch = !uniform &&
refiner.GetAdaptiveOptions().useInfSharpPatch;
patchtable = PatchTableFactory::Create(refiner, patchTableOptions);
}
if (! cvStencilsIn) {
// if cvstencils is just created above, append endcap stencils
if (StencilTableReal<REAL> const *localPointStencilTable =
patchtable->GetLocalPointStencilTable<REAL>()) {
StencilTableReal<REAL> const *table =
StencilTableFactoryReal<REAL>::AppendLocalPointStencilTable(
refiner, cvstencils, localPointStencilTable);
delete cvstencils;
cvstencils = table;
}
}
// Append local point stencils and further verfiy size of given StencilTable:
StencilTableReal<REAL> const * localstencils = 0;
if (interpolateVertex) {
localstencils = patchtable->GetLocalPointStencilTable<REAL>();
} else if (interpolateFaceVarying) {
localstencils = patchtable->GetLocalPointFaceVaryingStencilTable<REAL>(fvarChannel);
} else {
// Sanity checks
if (patchtable->IsFeatureAdaptive()==uniform) {
if (! cvStencilsIn) {
assert(cvstencils && cvstencils!=cvStencilsIn);
delete cvstencils;
}
localstencils = patchtable->GetLocalPointVaryingStencilTable<REAL>();
}
if (localstencils && (cvstencils->GetNumStencils() == nRefinedStencils)) {
StencilTableReal<REAL> const *refinedstencils = cvstencils;
if (interpolateFaceVarying) {
cvstencils = StencilTableFactoryReal<REAL>::AppendLocalPointStencilTableFaceVarying(
refiner, refinedstencils, localstencils, fvarChannel);
} else {
cvstencils = StencilTableFactoryReal<REAL>::AppendLocalPointStencilTable(
refiner, refinedstencils, localstencils);
}
if (!cvStencilsIn) delete refinedstencils;
} else if (cvStencilsIn) {
int nLocalStencils = localstencils ? localstencils->GetNumStencils() : 0;
if (cvstencils->GetNumStencils() != (nRefinedStencils + nLocalStencils)) {
// Stencil count mismatch with PatchTable and given StencilTable
// (previously undetected and subject to crashing)
if (!patchTableIn) delete patchtable;
return 0;
}
}
@ -507,7 +542,9 @@ LimitStencilTableFactoryReal<REAL>::Create(TopologyRefiner const & refiner,
//
// Generate limit stencils for locations
//
StencilBuilder<REAL> builder(refiner.GetLevel(0).GetNumVertices(),
StencilBuilder<REAL> builder(!interpolateFaceVarying
? refiner.GetLevel(0).GetNumVertices()
: refiner.GetLevel(0).GetNumFVarValues(fvarChannel),
/*genControlVerts*/ false,
/*compactWeights*/ true);
typename StencilBuilder<REAL>::Index origin(&builder, 0);
@ -526,27 +563,61 @@ LimitStencilTableFactoryReal<REAL>::Create(TopologyRefiner const & refiner,
PatchMap::Handle const * handle =
patchmap.FindPatch(array.ptexIdx, s, t);
if (handle) {
ConstIndexArray cvs = patchtable->GetPatchVertices(*handle);
ConstIndexArray cvs;
if (interpolateVertex) {
cvs = patchtable->GetPatchVertices(*handle);
} else if (interpolateFaceVarying) {
cvs = patchtable->GetPatchFVarValues(*handle, fvarChannel);
} else {
cvs = patchtable->GetPatchVaryingVertices(*handle);
}
StencilTableReal<REAL> const & src = *cvstencils;
dst = origin[numLimitStencils];
if (options.generate2ndDerivatives) {
patchtable->EvaluateBasis(*handle, s, t, wP, wDs, wDt, wDss, wDst, wDtt);
if (interpolateVertex) {
patchtable->EvaluateBasis<REAL>(
*handle, s, t, wP, wDs, wDt, wDss, wDst, wDtt);
} else if (interpolateFaceVarying) {
patchtable->EvaluateBasisFaceVarying<REAL>(
*handle, s, t, wP, wDs, wDt, wDss, wDst, wDtt, fvarChannel);
} else {
patchtable->EvaluateBasisVarying<REAL>(
*handle, s, t, wP, wDs, wDt, wDss, wDst, wDtt);
}
dst.Clear();
for (int k = 0; k < cvs.size(); ++k) {
dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k], wDss[k], wDst[k], wDtt[k]);
}
} else if (options.generate1stDerivatives) {
patchtable->EvaluateBasis(*handle, s, t, wP, wDs, wDt);
if (interpolateVertex) {
patchtable->EvaluateBasis<REAL>(
*handle, s, t, wP, wDs, wDt);
} else if (interpolateFaceVarying) {
patchtable->EvaluateBasisFaceVarying<REAL>(
*handle, s, t, wP, wDs, wDt, 0, 0, 0, fvarChannel);
} else {
patchtable->EvaluateBasisVarying<REAL>(
*handle, s, t, wP, wDs, wDt);
}
dst.Clear();
for (int k = 0; k < cvs.size(); ++k) {
dst.AddWithWeight(src[cvs[k]], wP[k], wDs[k], wDt[k]);
}
} else {
patchtable->EvaluateBasis(*handle, s, t, wP);
if (interpolateVertex) {
patchtable->EvaluateBasis<REAL>(
*handle, s, t, wP);
} else if (interpolateFaceVarying) {
patchtable->EvaluateBasisFaceVarying<REAL>(
*handle, s, t, wP, 0, 0, 0, 0, 0, fvarChannel);
} else {
patchtable->EvaluateBasisVarying<REAL>(
*handle, s, t, wP);
}
dst.Clear();
for (int k = 0; k < cvs.size(); ++k) {

View File

@ -131,6 +131,29 @@ public:
StencilTableReal<REAL> const *localPointStencilTable,
bool factorize = true);
/// \brief Utility function for stencil splicing for local point varying stencils.
///
/// @param refiner The TopologyRefiner containing the topology
///
/// @param baseStencilTable Input StencilTable for refined vertices
///
/// @param localPointStencilTable
/// StencilTable for the change of basis patch points.
///
/// @param factorize If factorize set to true, endcap stencils will be
/// factorized with supporting vertices from baseStencil
/// table so that the endcap points can be computed
/// directly from control vertices.
///
static StencilTableReal<REAL> const * AppendLocalPointStencilTableVarying(
TopologyRefiner const &refiner,
StencilTableReal<REAL> const *baseStencilTable,
StencilTableReal<REAL> const *localPointStencilTable,
bool factorize = true) {
return AppendLocalPointStencilTable(
refiner, baseStencilTable, localPointStencilTable, factorize);
}
/// \brief Utility function for stencil splicing for local point
/// face-varying stencils.
///
@ -187,6 +210,25 @@ class LimitStencilTableFactoryReal {
public:
enum Mode {
INTERPOLATE_VERTEX=0, ///< vertex primvar stencils
INTERPOLATE_VARYING, ///< varying primvar stencils
INTERPOLATE_FACE_VARYING ///< face-varying primvar stencils
};
struct Options {
Options() : interpolationMode(INTERPOLATE_VERTEX),
generate1stDerivatives(true),
generate2ndDerivatives(false),
fvarChannel(0) { }
unsigned int interpolationMode : 2, ///< interpolation mode
generate1stDerivatives : 1, ///< Generate weights for 1st derivatives
generate2ndDerivatives : 1; ///< Generate weights for 2nd derivatives
unsigned int fvarChannel; ///< face-varying channel to use
};
/// \brief Descriptor for limit surface locations
struct LocationArray {
@ -201,15 +243,6 @@ public:
typedef std::vector<LocationArray> LocationArrayVec;
struct Options {
Options() : generate1stDerivatives(true),
generate2ndDerivatives(false) { }
unsigned int generate1stDerivatives : 1, ///< Generate weights for 1st derivatives
generate2ndDerivatives : 1; ///< Generate weights for 2nd derivatives
};
/// \brief Instantiates LimitStencilTable from a TopologyRefiner that has
/// been refined either uniformly or adaptively.
///
@ -218,13 +251,18 @@ public:
/// @param locationArrays An array of surface location descriptors
/// (see LocationArray)
///
/// @param cvStencils A set of StencilTable generated from the
/// TopologyRefiner (optional: prevents redundant
/// instantiation of the table if available)
/// @param cvStencils A StencilTable generated from the TopologyRefiner
/// (Optional: prevents redundant instantiation of the
/// table if available. The given table must at least
/// contain stencils for all control points and all
/// refined points -- any stencils for local points of
/// a PatchTable must match the PatchTable provided or
/// internally generated)
///
/// @param patchTable A set of PatchTable generated from the
/// TopologyRefiner (optional: prevents redundant
/// instantiation of the table if available)
/// @param patchTable A PatchTable generated from the TopologyRefiner
/// (Optional: prevents redundant instantiation of the
/// table if available. The given table must match
/// the optional StencilTable if also provided)
///
/// @param options Options controlling the creation of the table
///
@ -280,6 +318,19 @@ public:
factorize));
}
static StencilTable const * AppendLocalPointStencilTableVarying(
TopologyRefiner const &refiner,
StencilTable const *baseStencilTable,
StencilTable const *localPointStencilTable,
bool factorize = true) {
return static_cast<StencilTable const *>(
BaseFactory::AppendLocalPointStencilTableVarying(refiner,
static_cast<BaseTable const *>(baseStencilTable),
static_cast<BaseTable const *>(localPointStencilTable),
factorize));
}
static StencilTable const * AppendLocalPointStencilTableFaceVarying(
TopologyRefiner const &refiner,
StencilTable const *baseStencilTable,