Major public addition of class templates for multiple precision:

- converted classes for stencils, tables and factories to templates
    - added backward compatible class wrappers around new templates
    - extended PatchTable to support variable precision stencil tables
    - extended PatchTableBuilder to manage PatchTable's new stencil tables
    - templated PatchTableBuilder conversion from SparseMatrix to stencils
    - extended public PatchTableFactory interface to specify precision
    - converted PrimvarRefiner class to template and added wrapper class
This commit is contained in:
barry 2018-07-28 14:56:43 -07:00
parent f6172f9608
commit 647039a8ee
12 changed files with 1097 additions and 520 deletions

View File

@ -35,9 +35,12 @@ namespace Far {
PatchTable::PatchTable(int maxvalence) :
_maxValence(maxvalence),
_localPointStencils(NULL),
_localPointVaryingStencils(NULL),
_varyingDesc(Far::PatchDescriptor::QUADS) {
_localPointStencils(),
_localPointVaryingStencils(),
_varyingDesc(Far::PatchDescriptor::QUADS),
_vertexPrecisionIsDouble(false),
_varyingPrecisionIsDouble(false),
_faceVaryingPrecisionIsDouble(false) {
}
// Copy constructor
@ -55,31 +58,31 @@ PatchTable::PatchTable(PatchTable const & src) :
_varyingDesc(src._varyingDesc),
_fvarChannels(src._fvarChannels),
_sharpnessIndices(src._sharpnessIndices),
_sharpnessValues(src._sharpnessValues) {
_sharpnessValues(src._sharpnessValues),
_vertexPrecisionIsDouble(src._vertexPrecisionIsDouble),
_varyingPrecisionIsDouble(src._varyingPrecisionIsDouble),
_faceVaryingPrecisionIsDouble(src._faceVaryingPrecisionIsDouble) {
if (src._localPointStencils) {
_localPointStencils =
new StencilTable(*src._localPointStencils);
if (src._localPointStencils.IsSet()) {
_localPointStencils = src._localPointStencils.Clone();
}
if (src._localPointVaryingStencils) {
_localPointVaryingStencils =
new StencilTable(*src._localPointVaryingStencils);
if (src._localPointVaryingStencils.IsSet()) {
_localPointVaryingStencils = src._localPointVaryingStencils.Clone();
}
if (! src._localPointFaceVaryingStencils.empty()) {
_localPointFaceVaryingStencils.resize(src._localPointFaceVaryingStencils.size());
for (int fvc=0; fvc<(int)_localPointFaceVaryingStencils.size(); ++fvc) {
_localPointFaceVaryingStencils[fvc] =
new StencilTable(*src._localPointFaceVaryingStencils[fvc]);
}
_localPointFaceVaryingStencils[fvc] = src._localPointFaceVaryingStencils[fvc].Clone();
}
}
}
PatchTable::~PatchTable() {
delete _localPointStencils;
delete _localPointVaryingStencils;
_localPointStencils.Delete();
_localPointVaryingStencils.Delete();
for (int fvc=0; fvc<(int)_localPointFaceVaryingStencils.size(); ++fvc) {
delete _localPointFaceVaryingStencils[fvc];
}
_localPointFaceVaryingStencils[fvc].Delete();
}
}
//
@ -350,17 +353,17 @@ PatchTable::GetSingleCreasePatchSharpnessValue(int arrayIndex, int patchIndex) c
int
PatchTable::GetNumLocalPoints() const {
return _localPointStencils ? _localPointStencils->GetNumStencils() : 0;
return _localPointStencils.IsSet() ? _localPointStencils.Size() : 0;
}
int
PatchTable::GetNumLocalPointsVarying() const {
return _localPointVaryingStencils ? _localPointVaryingStencils->GetNumStencils() : 0;
return _localPointVaryingStencils.IsSet() ? _localPointVaryingStencils.Size() : 0;
}
int
PatchTable::GetNumLocalPointsFaceVarying(int channel) const {
if (channel>=0 && channel<(int)_localPointFaceVaryingStencils.size() &&
_localPointFaceVaryingStencils[channel]) {
return _localPointFaceVaryingStencils[channel]->GetNumStencils();
if (channel>=0 && channel<(int)_localPointFaceVaryingStencils.size()) {
return _localPointFaceVaryingStencils[channel].IsSet() ?
_localPointFaceVaryingStencils[channel].Size() : 0;
}
return 0;
}

View File

@ -173,9 +173,15 @@ public:
ComputeLocalPointValues(T const *src, T *dst) const;
/// \brief Returns the stencil table to compute local point vertex values
StencilTable const *GetLocalPointStencilTable() const {
return _localPointStencils;
}
StencilTable const *GetLocalPointStencilTable() const;
/// \brief Returns the stencil table to compute local point vertex values
template <typename REAL>
StencilTableReal<REAL> const *GetLocalPointStencilTable() const;
/// \brief Tests the precision of the stencil table to compute local point
/// vertex values
template <typename REAL> bool IsLocalPointStencilPrecision() const;
/// \brief Returns the number of local varying points.
int GetNumLocalPointsVarying() const;
@ -193,9 +199,15 @@ public:
ComputeLocalPointValuesVarying(T const *src, T *dst) const;
/// \brief Returns the stencil table to compute local point varying values
StencilTable const *GetLocalPointVaryingStencilTable() const {
return _localPointVaryingStencils;
}
StencilTable const *GetLocalPointVaryingStencilTable() const;
/// \brief Returns the stencil table to compute local point varying values
template <typename REAL>
StencilTableReal<REAL> const *GetLocalPointVaryingStencilTable() const;
/// \brief Tests the precision of the stencil table to compute local point
/// varying values
template <typename REAL> bool IsLocalPointVaryingStencilPrecision() const;
/// \brief Returns the number of local face-varying points for \p channel
int GetNumLocalPointsFaceVarying(int channel = 0) const;
@ -215,12 +227,15 @@ public:
ComputeLocalPointValuesFaceVarying(T const *src, T *dst, int channel = 0) const;
/// \brief Returns the stencil table to compute local point face-varying values
StencilTable const *GetLocalPointFaceVaryingStencilTable(int channel = 0) const {
if (channel >= 0 && channel < (int)_localPointFaceVaryingStencils.size()) {
return _localPointFaceVaryingStencils[channel];
}
return NULL;
}
StencilTable const *GetLocalPointFaceVaryingStencilTable(int channel = 0) const;
/// \brief Returns the stencil table to compute local point face-varying values
template <typename REAL>
StencilTableReal<REAL> const * GetLocalPointFaceVaryingStencilTable(int channel = 0) const;
/// \brief Tests the precision of the stencil table to compute local point
/// face-varying values
template <typename REAL> bool IsLocalPointFaceVaryingStencilPrecision() const;
//@}
@ -559,6 +574,58 @@ private:
PatchParamArray getFVarPatchParams(int channel);
PatchParam getPatchFVarPatchParam(int patch, int channel) const;
private:
//
// Private class to manage stencil table pointers of varying precision
//
// This implementation is still up for debate -- could be improved or
// could be entirely replaced...
//
class StencilTableHandler {
private:
typedef StencilTableReal<float> float_type;
typedef StencilTableReal<double> double_type;
void init() { _fPtr = 0, _isDouble = false; }
void init(float_type * ptr) { _fPtr = ptr, _isDouble = false; }
void init(double_type * ptr) { _dPtr = ptr, _isDouble = true; }
public:
StencilTableHandler() { init(); }
StencilTableHandler(float_type * ptr) { init(ptr); }
StencilTableHandler(double_type * ptr) { init(ptr); }
// Generic accessor and modifiers:
template <typename REAL> StencilTableReal<REAL> * Get() const;
void Set(float_type * ptr) { init(ptr); }
void Set(double_type * ptr) { init(ptr); }
// Other utilities
bool IsSet() const { return _fPtr != 0; }
bool IsDouble() const { return _isDouble; }
void Clear() { init(); }
int Size() const {
return _isDouble ? _dPtr->GetNumStencils() : _fPtr->GetNumStencils();
}
void Delete() {
if (_isDouble) delete _dPtr;
else delete _fPtr;
}
StencilTableHandler Clone() const {
return _isDouble ? StencilTableHandler(new double_type(*_dPtr))
: StencilTableHandler(new float_type(*_fPtr));
}
private:
union {
float_type * _fPtr;
double_type * _dPtr;
};
bool _isDouble;
};
private:
//
@ -582,8 +649,9 @@ private:
//
QuadOffsetsTable _quadOffsetsTable; // Quad offsets (for Gregory patches)
VertexValenceTable _vertexValenceTable; // Vertex valence table (for Gregory patches)
StencilTable const * _localPointStencils; // endcap basis conversion stencils
StencilTable const * _localPointVaryingStencils; // endcap varying stencils (for convenience)
StencilTableHandler _localPointStencils; // local point conversion stencils
StencilTableHandler _localPointVaryingStencils; // local point varying stencils
//
// Varying data
@ -599,7 +667,7 @@ private:
FVarPatchChannelVector _fvarChannels;
std::vector<StencilTable const *> _localPointFaceVaryingStencils;
std::vector<StencilTableHandler> _localPointFaceVaryingStencils;
//
// 'single-crease' patch sharpness tables
@ -607,21 +675,122 @@ private:
std::vector<Index> _sharpnessIndices; // Indices of single-crease sharpness (one per patch)
std::vector<float> _sharpnessValues; // Sharpness values.
//
// Precision -- only applies to local-point stencil tables
//
unsigned int _vertexPrecisionIsDouble : 1;
unsigned int _varyingPrecisionIsDouble : 1;
unsigned int _faceVaryingPrecisionIsDouble : 1;
};
//
// Template specializations for float/double -- to be defined before used:
//
template <> inline StencilTableReal<float> *
PatchTable::StencilTableHandler::Get<float>() const { return _fPtr; }
template <> inline StencilTableReal<double> *
PatchTable::StencilTableHandler::Get<double>() const { return _dPtr; }
template <> inline bool
PatchTable::IsLocalPointStencilPrecision<float>() const {
return !_vertexPrecisionIsDouble;
}
template <> inline bool
PatchTable::IsLocalPointVaryingStencilPrecision<float>() const {
return !_varyingPrecisionIsDouble;
}
template <> inline bool
PatchTable::IsLocalPointFaceVaryingStencilPrecision<float>() const {
return !_faceVaryingPrecisionIsDouble;
}
template <> inline bool
PatchTable::IsLocalPointStencilPrecision<double>() const {
return _vertexPrecisionIsDouble;
}
template <> inline bool
PatchTable::IsLocalPointVaryingStencilPrecision<double>() const {
return _varyingPrecisionIsDouble;
}
template <> inline bool
PatchTable::IsLocalPointFaceVaryingStencilPrecision<double>() const {
return _faceVaryingPrecisionIsDouble;
}
//
// StencilTable access -- backward compatible and generic:
//
inline StencilTable const *
PatchTable::GetLocalPointStencilTable() const {
assert(!_vertexPrecisionIsDouble);
return static_cast<StencilTable const *>(_localPointStencils.Get<float>());
}
inline StencilTable const *
PatchTable::GetLocalPointVaryingStencilTable() const {
assert(!_varyingPrecisionIsDouble);
return static_cast<StencilTable const *>(
_localPointVaryingStencils.Get<float>());
}
inline StencilTable const *
PatchTable::GetLocalPointFaceVaryingStencilTable(int channel) const {
assert(!_faceVaryingPrecisionIsDouble);
if (channel >= 0 && channel < (int)_localPointFaceVaryingStencils.size()) {
return static_cast<StencilTable const *>(
_localPointFaceVaryingStencils[channel].Get<float>());
}
return NULL;
}
template <typename REAL>
inline StencilTableReal<REAL> const *
PatchTable::GetLocalPointStencilTable() const {
assert(IsLocalPointStencilPrecision<REAL>());
return _localPointStencils.Get<REAL>();
}
template <typename REAL>
inline StencilTableReal<REAL> const *
PatchTable::GetLocalPointVaryingStencilTable() const {
assert(IsLocalPointVaryingStencilPrecision<REAL>());
return _localPointVaryingStencils.Get<REAL>();
}
template <typename REAL>
inline StencilTableReal<REAL> const *
PatchTable::GetLocalPointFaceVaryingStencilTable(int channel) const {
assert(IsLocalPointFaceVaryingStencilPrecision<REAL>());
if (channel >= 0 && channel < (int)_localPointFaceVaryingStencils.size()) {
return _localPointFaceVaryingStencils[channel].Get<REAL>();
}
return NULL;
}
//
// Computation of local point values:
//
template <class T>
inline void
PatchTable::ComputeLocalPointValues(T const *src, T *dst) const {
if (_localPointStencils) {
_localPointStencils->UpdateValues(src, dst);
if (_localPointStencils.IsSet()) {
if (_vertexPrecisionIsDouble) {
_localPointStencils.Get<double>()->UpdateValues(src, dst);
} else {
_localPointStencils.Get<float>()->UpdateValues(src, dst);
}
}
}
template <class T>
inline void
PatchTable::ComputeLocalPointValuesVarying(T const *src, T *dst) const {
if (_localPointVaryingStencils) {
_localPointVaryingStencils->UpdateValues(src, dst);
if (_localPointVaryingStencils.IsSet()) {
if (_varyingPrecisionIsDouble) {
_localPointVaryingStencils.Get<double>()->UpdateValues(src, dst);
} else {
_localPointVaryingStencils.Get<float>()->UpdateValues(src, dst);
}
}
}
@ -629,12 +798,17 @@ template <class T>
inline void
PatchTable::ComputeLocalPointValuesFaceVarying(T const *src, T *dst, int channel) const {
if (channel >= 0 && channel < (int)_localPointFaceVaryingStencils.size()) {
if (_localPointFaceVaryingStencils[channel]) {
_localPointFaceVaryingStencils[channel]->UpdateValues(src, dst);
if (_localPointFaceVaryingStencils[channel].IsSet()) {
if (_faceVaryingPrecisionIsDouble) {
_localPointFaceVaryingStencils[channel].Get<double>()->UpdateValues(src, dst);
} else {
_localPointFaceVaryingStencils[channel].Get<float>()->UpdateValues(src, dst);
}
}
}
}
//
// Basis evaluation overloads
//

View File

@ -112,6 +112,8 @@ public:
PatchTable * GetPatchTable() const { return _table; };
private:
typedef PatchTable::StencilTableHandler StencilTableHandler;
// Simple struct to store <face,level> pair for a patch:
struct PatchTuple {
PatchTuple(Index face, int level) : faceIndex(face), levelIndex(level) { }
@ -135,7 +137,8 @@ private:
Level::VSpan irregCornerSpans[4];
int paramBoundaryMask;
SparseMatrix<float> matrix;
SparseMatrix<float> fMatrix;
SparseMatrix<double> dMatrix;
};
private:
@ -161,12 +164,14 @@ private:
Options() : shareLocalPoints(false),
reuseSourcePoints(false),
createStencilTable(true),
createVaryingTable(false) { }
createVaryingTable(false),
doubleStencilTable(false) { }
unsigned int shareLocalPoints : 1;
unsigned int reuseSourcePoints : 1;
unsigned int createStencilTable : 1;
unsigned int createVaryingTable : 1;
unsigned int doubleStencilTable : 1;
};
public:
@ -179,36 +184,40 @@ private:
public:
int GetNumLocalPoints() const { return _numLocalPoints; }
template <typename REAL>
int AppendLocalPatchPoints(int levelIndex, Index faceIndex,
SparseMatrix<float> const & conversionMatrix,
SparseMatrix<REAL> const & conversionMatrix,
PatchDescriptor::Type patchType,
Index const sourcePoints[],
int sourcePointOffset,
Index patchPoints[]);
StencilTable * AcquireStencilTable() {
return acquireStencilTable(&_stencilTable);
StencilTableHandler AcquireStencilTable() {
return acquireStencilTable(_stencilTable);
}
private:
// Internal methods:
void appendLocalPointStencil(SparseMatrix<float> const & conversionMatrix,
template <typename REAL>
void appendLocalPointStencil(SparseMatrix<REAL> const & conversionMatrix,
int stencilRow,
Index const sourcePoints[],
int sourcePointOffset);
void appendLocalPointStencils(SparseMatrix<float> const & conversionMatrix,
template <typename REAL>
void appendLocalPointStencils(SparseMatrix<REAL> const & conversionMatrix,
Index const sourcePoints[],
int sourcePointOffset);
// Methods for local point Varying stencils
// XXXX -- hope to get rid of these...
template <typename REAL>
void appendLocalPointVaryingStencil(int const * varyingIndices,
int patchPointIndex,
Index const sourcePoints[],
int sourcePointOffset);
StencilTable * acquireStencilTable(StencilTable **stencilTableMember);
StencilTableHandler acquireStencilTable(StencilTableHandler& stencilTableMember);
Index findSharedCornerPoint(int levelIndex, Index valueIndex,
Index newIndex);
@ -227,16 +236,16 @@ private:
std::vector<IndexVector> _sharedCornerPoints;
std::vector<IndexVector> _sharedEdgePoints;
StencilTable * _stencilTable;
StencilTableHandler _stencilTable;
// This was hopefully transitional but will persist -- the should be
// no need for Varying local points or stencils associated with them.
public:
StencilTable * AcquireStencilTableVarying() {
return acquireStencilTable(&_stencilTableVarying);
StencilTableHandler AcquireStencilTableVarying() {
return acquireStencilTable(_stencilTableVarying);
}
StencilTable * _stencilTableVarying;
StencilTableHandler _stencilTableVarying;
};
private:
@ -428,6 +437,10 @@ PatchTableBuilder::PatchTableBuilder(
_table->_numPtexFaces = _ptexIndices.GetNumFaces();
_table->_vertexPrecisionIsDouble = _options.setPatchPrecisionDouble;
_table->_varyingPrecisionIsDouble = _options.setPatchPrecisionDouble;
_table->_faceVaryingPrecisionIsDouble = _options.setFVarPatchPrecisionDouble;
// State and helper to support LegacyGregory arrays in the PatchTable:
_requiresLegacyGregoryTables = !_refiner.IsUniform() &&
(_options.GetEndCapType() == Options::ENDCAP_LEGACY_GREGORY);
@ -457,6 +470,10 @@ PatchTableBuilder::identifyPatchTopology(PatchTuple const & patch,
patchInfo.isRegular = _patchBuilder->IsPatchRegular(
patchLevel, patchFace, fvarInTable);
bool useDoubleMatrix = (fvarInRefiner < 0)
? _options.setPatchPrecisionDouble
: _options.setFVarPatchPrecisionDouble;
if (patchInfo.isRegular) {
patchInfo.regBoundaryMask = _patchBuilder->GetRegularPatchBoundaryMask(
patchLevel, patchFace, fvarInRefiner);
@ -467,7 +484,7 @@ PatchTableBuilder::identifyPatchTopology(PatchTuple const & patch,
// If converting to another basis, get the change-of-basis matrix:
if (_requiresRegularLocalPoints) {
// _patchBuilder->GetRegularConversionMatrix(... patchInfo.matrix);
// _patchBuilder->GetRegularConversionMatrix(...);
}
//
@ -501,8 +518,13 @@ PatchTableBuilder::identifyPatchTopology(PatchTuple const & patch,
_patchBuilder->GetIrregularPatchCornerSpans(
patchLevel, patchFace, patchInfo.irregCornerSpans, fvarInRefiner);
_patchBuilder->GetIrregularPatchConversionMatrix(
patchLevel, patchFace, patchInfo.irregCornerSpans, patchInfo.matrix);
if (useDoubleMatrix) {
_patchBuilder->GetIrregularPatchConversionMatrix(
patchLevel, patchFace, patchInfo.irregCornerSpans, patchInfo.dMatrix);
} else {
_patchBuilder->GetIrregularPatchConversionMatrix(
patchLevel, patchFace, patchInfo.irregCornerSpans, patchInfo.fMatrix);
}
patchInfo.paramBoundaryMask = 0;
}
@ -539,6 +561,10 @@ PatchTableBuilder::assignPatchPointsAndStencils(PatchTuple const & patch,
? _levelVertOffsets[patch.levelIndex]
: _levelFVarValueOffsets[fvarInTable][patch.levelIndex];
bool useDoubleMatrix = (fvarInTable < 0)
? _options.setPatchPrecisionDouble
: _options.setFVarPatchPrecisionDouble;
int numPatchPoints = 0;
if (patchInfo.isRegular) {
if (!_requiresRegularLocalPoints) {
@ -571,18 +597,32 @@ PatchTableBuilder::assignPatchPointsAndStencils(PatchTuple const & patch,
*/
}
} else if (_requiresIrregularLocalPoints) {
StackBuffer<Index,64,true> sourcePoints(patchInfo.matrix.GetNumColumns());
int numSourcePoints = 0;
if (useDoubleMatrix) {
numSourcePoints = patchInfo.dMatrix.GetNumColumns();
numPatchPoints = patchInfo.dMatrix.GetNumRows();
} else {
numSourcePoints = patchInfo.fMatrix.GetNumColumns();
numPatchPoints = patchInfo.fMatrix.GetNumRows();
}
StackBuffer<Index,64,true> sourcePoints(numSourcePoints);
_patchBuilder->GetIrregularPatchSourcePoints(
patch.levelIndex, patch.faceIndex,
patchInfo.irregCornerSpans, sourcePoints, fvarInRefiner);
localHelper.AppendLocalPatchPoints(
patch.levelIndex, patch.faceIndex,
patchInfo.matrix, _patchBuilder->GetIrregularPatchType(),
sourcePoints, sourcePointOffset, patchPoints);
numPatchPoints = patchInfo.matrix.GetNumRows();
if (useDoubleMatrix) {
localHelper.AppendLocalPatchPoints(
patch.levelIndex, patch.faceIndex,
patchInfo.dMatrix, _patchBuilder->GetIrregularPatchType(),
sourcePoints, sourcePointOffset, patchPoints);
} else {
localHelper.AppendLocalPatchPoints(
patch.levelIndex, patch.faceIndex,
patchInfo.fMatrix, _patchBuilder->GetIrregularPatchType(),
sourcePoints, sourcePointOffset, patchPoints);
}
}
return numPatchPoints;
}
@ -1052,6 +1092,7 @@ PatchTableBuilder::populateAdaptivePatches() {
LocalPointHelper::Options opts;
opts.createStencilTable = true;
opts.createVaryingTable = _requiresVaryingLocalPoints;
opts.doubleStencilTable = _options.setPatchPrecisionDouble;
opts.shareLocalPoints = _options.shareEndCapPatchPoints;
opts.reuseSourcePoints = (_patchBuilder->GetIrregularPatchType() ==
_patchBuilder->GetNativePatchType() );
@ -1062,6 +1103,7 @@ PatchTableBuilder::populateAdaptivePatches() {
if (_requiresFVarPatches) {
opts.createStencilTable = true;
opts.createVaryingTable = false;
opts.doubleStencilTable = _options.setFVarPatchPrecisionDouble;
fvarLocalPointHelpers.SetSize((int)_fvarChannelIndices.size());
@ -1081,6 +1123,9 @@ PatchTableBuilder::populateAdaptivePatches() {
PatchInfo patchInfo;
PatchInfo fvarPatchInfo;
bool fvarPrecisionMatches = (_options.setPatchPrecisionDouble ==
_options.setFVarPatchPrecisionDouble);
for (int patchIndex = 0; patchIndex < (int)_patches.size(); ++patchIndex) {
PatchTuple const & patch = _patches[patchIndex];
@ -1138,7 +1183,8 @@ PatchTableBuilder::populateAdaptivePatches() {
// topology of the face in face-varying space matches the
// original patch:
//
bool fvcTopologyMatches = doesFVarTopologyMatch(patch, fvc);
bool fvcTopologyMatches = fvarPrecisionMatches &&
doesFVarTopologyMatch(patch, fvc);
PatchInfo & fvcPatchInfo = fvcTopologyMatches
? patchInfo : fvarPatchInfo;
@ -1298,16 +1344,23 @@ PatchTableBuilder::LocalPointHelper::LocalPointHelper(
TopologyRefiner const & refiner, Options const & options,
int fvarChannel, int numLocalPointsExpected) :
_refiner(refiner), _options(options), _fvarChannel(fvarChannel),
_numLocalPoints(0), _stencilTable(0), _stencilTableVarying(0) {
_numLocalPoints(0), _stencilTable(), _stencilTableVarying() {
_localPointOffset = (_fvarChannel < 0)
? _refiner.GetNumVerticesTotal()
: _refiner.GetNumFVarValuesTotal(_fvarChannel);
if (_options.createStencilTable) {
_stencilTable = new StencilTable(0);
if (_options.createVaryingTable) {
_stencilTableVarying = new StencilTable(0);
if (_options.doubleStencilTable) {
_stencilTable.Set(new StencilTableReal<double>(0));
if (_options.createVaryingTable) {
_stencilTableVarying.Set(new StencilTableReal<double>(0));
}
} else {
_stencilTable.Set(new StencilTableReal<float>(0));
if (_options.createVaryingTable) {
_stencilTableVarying.Set(new StencilTableReal<float>(0));
}
}
}
@ -1320,7 +1373,7 @@ PatchTableBuilder::LocalPointHelper::LocalPointHelper(
// The average number of entries per stencil has been historically set
// at 16, which seemed high and was reduced on further investigation.
//
if (_stencilTable) {
if (_stencilTable.IsSet()) {
// Historic note: limits to 100M (=800M bytes) entries for reserved size
size_t const MaxEntriesToReserve = 100 * 1024 * 1024;
size_t const AvgEntriesPerStencil = 9; // originally 16
@ -1331,37 +1384,54 @@ PatchTableBuilder::LocalPointHelper::LocalPointHelper(
size_t numEntriesToReserve = std::min(numStencilEntriesExpected,
MaxEntriesToReserve);
if (numEntriesToReserve) {
_stencilTable->reserve((int)numStencilsExpected,
(int)numEntriesToReserve);
if (_stencilTableVarying) {
if (_stencilTable.IsDouble()) {
_stencilTable.Get<double>()->reserve(
(int)numStencilsExpected, (int)numEntriesToReserve);
} else {
_stencilTable.Get<float>()->reserve(
(int)numStencilsExpected, (int)numEntriesToReserve);
}
if (_stencilTableVarying.IsSet()) {
// Varying stencils have only one entry per point
_stencilTableVarying->reserve((int)numStencilsExpected,
(int)numStencilsExpected);
if (_stencilTableVarying.IsDouble()) {
_stencilTableVarying.Get<double>()->reserve(
(int)numStencilsExpected, (int)numStencilsExpected);
} else {
_stencilTableVarying.Get<float>()->reserve(
(int)numStencilsExpected, (int)numStencilsExpected);
}
}
}
}
}
StencilTable *
PatchTableBuilder::StencilTableHandler
PatchTableBuilder::LocalPointHelper::acquireStencilTable(
StencilTable **stencilTableMember) {
StencilTableHandler& stencilTableMember) {
StencilTable * stencilTable = *stencilTableMember;
StencilTableHandler stencilTable = stencilTableMember;
if (stencilTable && (stencilTable->GetNumStencils() > 0)) {
stencilTable->finalize();
} else {
delete stencilTable;
stencilTable = 0;
if (stencilTable.IsSet()) {
if (stencilTable.Size() > 0) {
if (stencilTable.IsDouble()) {
stencilTable.Get<double>()->finalize();
} else {
stencilTable.Get<float>()->finalize();
}
} else {
stencilTable.Delete();
stencilTable.Clear();
}
}
*stencilTableMember = 0;
stencilTableMember.Clear();
return stencilTable;
}
PatchTableBuilder::LocalPointHelper::~LocalPointHelper() {
delete _stencilTable;
delete _stencilTableVarying;
_stencilTable.Delete();
_stencilTableVarying.Delete();
}
Index
@ -1412,28 +1482,32 @@ PatchTableBuilder::LocalPointHelper::findSharedEdgePoint(int levelIndex,
return assignedIndex;
}
template <typename REAL>
void
PatchTableBuilder::LocalPointHelper::appendLocalPointStencil(
SparseMatrix<float> const & conversionMatrix,
SparseMatrix<REAL> const & conversionMatrix,
int stencilRow,
Index const sourcePoints[],
int sourcePointOffset) {
int stencilSize = conversionMatrix.GetRowSize(stencilRow);
ConstArray<int> matrixColumns = conversionMatrix.GetRowColumns(stencilRow);
ConstArray<float> matrixWeights = conversionMatrix.GetRowElements(stencilRow);
ConstArray<REAL> matrixWeights = conversionMatrix.GetRowElements(stencilRow);
_stencilTable->_sizes.push_back(stencilSize);
StencilTableReal<REAL>* stencilTable = _stencilTable.Get<REAL>();
stencilTable->_sizes.push_back(stencilSize);
for (int i = 0; i < stencilSize; ++i) {
_stencilTable->_weights.push_back(matrixWeights[i]);
_stencilTable->_indices.push_back(
stencilTable->_weights.push_back(matrixWeights[i]);
stencilTable->_indices.push_back(
sourcePoints[matrixColumns[i]] + sourcePointOffset);
}
}
template <typename REAL>
void
PatchTableBuilder::LocalPointHelper::appendLocalPointStencils(
SparseMatrix<float> const & conversionMatrix,
SparseMatrix<REAL> const & conversionMatrix,
Index const sourcePoints[],
int sourcePointOffset) {
@ -1441,37 +1515,39 @@ PatchTableBuilder::LocalPointHelper::appendLocalPointStencils(
// Resize the StencilTable members to accomodate all rows and elements from
// the given set of points represented by the matrix
//
StencilTableReal<REAL>* stencilTable = _stencilTable.Get<REAL>();
int numNewStencils = conversionMatrix.GetNumRows();
int numNewElements = conversionMatrix.GetNumElements();
size_t numOldStencils = _stencilTable->_sizes.size();
size_t numOldElements = _stencilTable->_indices.size();
size_t numOldStencils = stencilTable->_sizes.size();
size_t numOldElements = stencilTable->_indices.size();
// Assign the sizes for the new stencils:
_stencilTable->_sizes.resize(numOldStencils + numNewStencils);
stencilTable->_sizes.resize(numOldStencils + numNewStencils);
int * newSizes = &_stencilTable->_sizes[numOldStencils];
int * newSizes = &stencilTable->_sizes[numOldStencils];
for (int i = 0; i < numNewStencils; ++i) {
newSizes[i] = conversionMatrix.GetRowSize(i);
}
// Assign remapped indices for the stencils:
_stencilTable->_indices.resize(numOldElements + numNewElements);
stencilTable->_indices.resize(numOldElements + numNewElements);
int const * mtxIndices = &conversionMatrix.GetColumns()[0];
int * newIndices = &_stencilTable->_indices[numOldElements];
int * newIndices = &stencilTable->_indices[numOldElements];
for (int i = 0; i < numNewElements; ++i) {
newIndices[i] = sourcePoints[mtxIndices[i]] + sourcePointOffset;
}
// Copy the stencil weights direct from the matrix elements:
_stencilTable->_weights.resize(numOldElements + numNewElements);
stencilTable->_weights.resize(numOldElements + numNewElements);
float const * mtxWeights = &conversionMatrix.GetElements()[0];
float * newWeights = &_stencilTable->_weights[numOldElements];
REAL const * mtxWeights = &conversionMatrix.GetElements()[0];
REAL * newWeights = &stencilTable->_weights[numOldElements];
std::memcpy(newWeights, mtxWeights, numNewElements * sizeof(float));
std::memcpy(newWeights, mtxWeights, numNewElements * sizeof(REAL));
}
//
@ -1505,6 +1581,7 @@ namespace {
}
}
template <typename REAL>
void
PatchTableBuilder::LocalPointHelper::appendLocalPointVaryingStencil(
int const * varyingIndices, int patchPointIndex,
@ -1513,9 +1590,11 @@ PatchTableBuilder::LocalPointHelper::appendLocalPointVaryingStencil(
Index varyingPoint =
sourcePoints[varyingIndices[patchPointIndex]] + sourcePointOffset;
_stencilTableVarying->_sizes.push_back(1);
_stencilTableVarying->_indices.push_back(varyingPoint);
_stencilTableVarying->_weights.push_back(1.0f);
StencilTableReal<REAL>* t = _stencilTableVarying.Get<REAL>();
t->_sizes.push_back(1);
t->_indices.push_back(varyingPoint);
t->_weights.push_back((REAL) 1.0);
}
namespace {
@ -1547,10 +1626,11 @@ namespace {
}
}
template <typename REAL>
int
PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints(
int levelIndex, Index faceIndex,
SparseMatrix<float> const & matrix,
SparseMatrix<REAL> const & matrix,
PatchDescriptor::Type patchType,
Index const sourcePoints[],
int sourcePointOffset,
@ -1571,11 +1651,11 @@ PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints(
bool shareLocalPointsForThisPatch = (shareBitsPerPoint != 0);
int const * varyingIndices = 0;
if (_stencilTableVarying) {
if (_stencilTableVarying.IsSet()) {
varyingIndices = GetVaryingIndicesPerType(patchType);
}
bool applyVertexStencils = (_stencilTable != 0);
bool applyVertexStencils = _stencilTable.IsSet();
bool applyVaryingStencils = (varyingIndices != 0);
//
@ -1592,7 +1672,7 @@ PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints(
matrix, sourcePoints, sourcePointOffset);
if (applyVaryingStencils) {
for (int i = 0; i < numPatchPoints; ++i) {
appendLocalPointVaryingStencil(
appendLocalPointVaryingStencil<REAL>(
varyingIndices, i, sourcePoints, sourcePointOffset);
}
}
@ -1611,7 +1691,7 @@ PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints(
appendLocalPointStencil(
matrix, i, sourcePoints, sourcePointOffset);
if (applyVaryingStencils) {
appendLocalPointVaryingStencil(
appendLocalPointVaryingStencil<REAL>(
varyingIndices, i, sourcePoints, sourcePointOffset);
}
}
@ -1682,7 +1762,7 @@ PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints(
appendLocalPointStencil(
matrix, i, sourcePoints, sourcePointOffset);
if (applyVaryingStencils) {
appendLocalPointVaryingStencil(
appendLocalPointVaryingStencil<REAL>(
varyingIndices, i, sourcePoints, sourcePointOffset);
}
}

View File

@ -63,6 +63,8 @@ public:
endCapType(ENDCAP_GREGORY_BASIS),
shareEndCapPatchPoints(true),
generateFVarTables(false),
setPatchPrecisionDouble(false),
setFVarPatchPrecisionDouble(false),
generateFVarLegacyLinearPatches(true),
generateLegacySharpCornerPatches(true),
numFVarChannels(-1),
@ -75,6 +77,12 @@ public:
/// \brief Set endcap patch type
void SetEndCapType(EndCapType e) { endCapType = e; }
/// \brief Set precision of vertex patches
template <typename REAL> void SetPatchPrecision();
/// \brief Set precision of face-varying patches
template <typename REAL> void SetFVarPatchPrecision();
unsigned int generateAllLevels : 1, ///< Include levels from 'firstLevel' to 'maxLevel' (Uniform mode only)
triangulateQuads : 1, ///< Triangulate 'QUADS' primitives (Uniform mode only)
useSingleCreasePatch : 1, ///< Use single crease patch
@ -89,6 +97,10 @@ public:
// face-varying
generateFVarTables : 1, ///< Generate face-varying patch tables
// precision
setPatchPrecisionDouble : 1, ///< Generate double-precision stencils for vertex patches
setFVarPatchPrecisionDouble : 1, ///< Generate double-precision stencils for face-varying patches
// legacy behaviors (default to true)
generateFVarLegacyLinearPatches : 1, ///< Generate all linear face-varying patches (legacy)
generateLegacySharpCornerPatches : 1; ///< Generate sharp regular patches at smooth corners (legacy)
@ -154,6 +166,22 @@ public:
typedef std::vector<PatchFaceTag> PatchTagVector;
};
template <> inline void PatchTableFactory::Options::SetPatchPrecision<float>() {
setPatchPrecisionDouble = false;
}
template <> inline void PatchTableFactory::Options::SetFVarPatchPrecision<float>() {
setFVarPatchPrecisionDouble = false;
}
template <> inline void PatchTableFactory::Options::SetPatchPrecision<double>() {
setPatchPrecisionDouble = true;
}
template <> inline void PatchTableFactory::Options::SetFVarPatchPrecision<double>() {
setFVarPatchPrecisionDouble = true;
}
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION

View File

@ -49,15 +49,15 @@ namespace OPENSUBDIV_VERSION {
namespace Far {
///
/// \brief Applies refinement operations to generic primvar data.
///
class PrimvarRefiner {
template <typename REAL>
class PrimvarRefinerReal {
public:
PrimvarRefiner(TopologyRefiner const & refiner) : _refiner(refiner) { }
~PrimvarRefiner() { }
PrimvarRefinerReal(TopologyRefiner const & refiner) : _refiner(refiner) { }
~PrimvarRefinerReal() { }
TopologyRefiner const & GetTopologyRefiner() const { return _refiner; }
@ -182,10 +182,11 @@ public:
//@}
private:
typedef REAL Weight;
// Non-copyable:
PrimvarRefiner(PrimvarRefiner const & src) : _refiner(src._refiner) { }
PrimvarRefiner & operator=(PrimvarRefiner const &) { return *this; }
PrimvarRefinerReal(PrimvarRefinerReal const & src) : _refiner(src._refiner) { }
PrimvarRefinerReal & operator=(PrimvarRefinerReal const &) { return *this; }
template <Sdc::SchemeType SCHEME, class T, class U> void interpFromFaces(int, T const &, U &) const;
template <Sdc::SchemeType SCHEME, class T, class U> void interpFromEdges(int, T const &, U &) const;
@ -202,7 +203,6 @@ private:
void limitFVar(T const & src, U & dst, int channel) const;
private:
TopologyRefiner const & _refiner;
private:
@ -211,7 +211,7 @@ private:
//
class Mask {
public:
typedef float Weight; // Also part of the expected interface
typedef REAL Weight; // Also part of the expected interface
public:
Mask(Weight* v, Weight* e, Weight* f) :
@ -261,9 +261,10 @@ private:
// use as a template parameter in subsequent implementation will be factored
// out of a later release:
//
template <typename REAL>
template <class T, class U>
inline void
PrimvarRefiner::Interpolate(int level, T const & src, U & dst) const {
PrimvarRefinerReal<REAL>::Interpolate(int level, T const & src, U & dst) const {
assert(level>0 && level<=(int)_refiner._refinements.size());
@ -286,9 +287,10 @@ PrimvarRefiner::Interpolate(int level, T const & src, U & dst) const {
}
}
template <typename REAL>
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceVarying(int level, T const & src, U & dst, int channel) const {
PrimvarRefinerReal<REAL>::InterpolateFaceVarying(int level, T const & src, U & dst, int channel) const {
assert(level>0 && level<=(int)_refiner._refinements.size());
@ -311,9 +313,10 @@ PrimvarRefiner::InterpolateFaceVarying(int level, T const & src, U & dst, int ch
}
}
template <typename REAL>
template <class T, class U>
inline void
PrimvarRefiner::Limit(T const & src, U & dst) const {
PrimvarRefinerReal<REAL>::Limit(T const & src, U & dst) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
@ -335,9 +338,10 @@ PrimvarRefiner::Limit(T const & src, U & dst) const {
}
}
template <typename REAL>
template <class T, class U, class U1, class U2>
inline void
PrimvarRefiner::Limit(T const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2) const {
PrimvarRefinerReal<REAL>::Limit(T const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
@ -359,9 +363,10 @@ PrimvarRefiner::Limit(T const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2) con
}
}
template <typename REAL>
template <class T, class U>
inline void
PrimvarRefiner::LimitFaceVarying(T const & src, U & dst, int channel) const {
PrimvarRefinerReal<REAL>::LimitFaceVarying(T const & src, U & dst, int channel) const {
if (_refiner.getLevel(_refiner.GetMaxLevel()).getNumVertexEdgesTotal() == 0) {
Error(FAR_RUNTIME_ERROR,
@ -383,9 +388,10 @@ PrimvarRefiner::LimitFaceVarying(T const & src, U & dst, int channel) const {
}
}
template <typename REAL>
template <class T, class U>
inline void
PrimvarRefiner::InterpolateFaceUniform(int level, T const & src, U & dst) const {
PrimvarRefinerReal<REAL>::InterpolateFaceUniform(int level, T const & src, U & dst) const {
assert(level>0 && level<=(int)_refiner._refinements.size());
@ -400,9 +406,10 @@ PrimvarRefiner::InterpolateFaceUniform(int level, T const & src, U & dst) const
}
}
template <typename REAL>
template <class T, class U>
inline void
PrimvarRefiner::InterpolateVarying(int level, T const & src, U & dst) const {
PrimvarRefinerReal<REAL>::InterpolateVarying(int level, T const & src, U & dst) const {
assert(level>0 && level<=(int)_refiner._refinements.size());
@ -423,7 +430,7 @@ PrimvarRefiner::InterpolateVarying(int level, T const & src, U & dst) const {
// Apply the weights to the parent face's vertices:
ConstIndexArray fVerts = parent.getFaceVertices(face);
float fVaryingWeight = 1.0f / (float) fVerts.size();
Weight fVaryingWeight = 1.0f / (Weight) fVerts.size();
dst[cVert].Clear();
for (int i = 0; i < fVerts.size(); ++i) {
@ -462,9 +469,10 @@ PrimvarRefiner::InterpolateVarying(int level, T const & src, U & dst) const {
// Internal implementation methods -- grouping vertices to be interpolated
// based on the type of parent component from which they originated:
//
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpFromFaces(int level, T const & src, U & dst) const {
PrimvarRefinerReal<REAL>::interpFromFaces(int level, T const & src, U & dst) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & parent = refinement.parent();
@ -473,7 +481,7 @@ PrimvarRefiner::interpFromFaces(int level, T const & src, U & dst) const {
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
Vtr::internal::StackBuffer<float,16> fVertWeights(parent.getMaxValence());
Vtr::internal::StackBuffer<Weight,16> fVertWeights(parent.getMaxValence());
for (int face = 0; face < parent.getNumFaces(); ++face) {
@ -499,9 +507,10 @@ PrimvarRefiner::interpFromFaces(int level, T const & src, U & dst) const {
}
}
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpFromEdges(int level, T const & src, U & dst) const {
PrimvarRefinerReal<REAL>::interpFromEdges(int level, T const & src, U & dst) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & parent = refinement.parent();
@ -511,8 +520,8 @@ PrimvarRefiner::interpFromEdges(int level, T const & src, U & dst) const {
Vtr::internal::EdgeInterface eHood(parent);
float eVertWeights[2];
Vtr::internal::StackBuffer<float,8> eFaceWeights(parent.getMaxEdgeFaces());
Weight eVertWeights[2];
Vtr::internal::StackBuffer<Weight,8> eFaceWeights(parent.getMaxEdgeFaces());
for (int edge = 0; edge < parent.getNumEdges(); ++edge) {
@ -568,9 +577,10 @@ PrimvarRefiner::interpFromEdges(int level, T const & src, U & dst) const {
}
}
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpFromVerts(int level, T const & src, U & dst) const {
PrimvarRefinerReal<REAL>::interpFromVerts(int level, T const & src, U & dst) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
Vtr::internal::Level const & parent = refinement.parent();
@ -580,7 +590,7 @@ PrimvarRefiner::interpFromVerts(int level, T const & src, U & dst) const {
Vtr::internal::VertexInterface vHood(parent, child);
Vtr::internal::StackBuffer<float,32> weightBuffer(2*parent.getMaxValence());
Vtr::internal::StackBuffer<Weight,32> weightBuffer(2*parent.getMaxValence());
for (int vert = 0; vert < parent.getNumVertices(); ++vert) {
@ -592,9 +602,9 @@ PrimvarRefiner::interpFromVerts(int level, T const & src, U & dst) const {
ConstIndexArray vEdges = parent.getVertexEdges(vert),
vFaces = parent.getVertexFaces(vert);
float vVertWeight,
* vEdgeWeights = weightBuffer,
* vFaceWeights = vEdgeWeights + vEdges.size();
Weight vVertWeight,
* vEdgeWeights = weightBuffer,
* vFaceWeights = vEdgeWeights + vEdges.size();
Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
@ -641,9 +651,10 @@ PrimvarRefiner::interpFromVerts(int level, T const & src, U & dst) const {
//
// Internal face-varying implementation details:
//
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpFVarFromFaces(int level, T const & src, U & dst, int channel) const {
PrimvarRefinerReal<REAL>::interpFVarFromFaces(int level, T const & src, U & dst, int channel) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
@ -657,7 +668,7 @@ PrimvarRefiner::interpFVarFromFaces(int level, T const & src, U & dst, int chann
Vtr::internal::FVarLevel const & parentFVar = parentLevel.getFVarLevel(channel);
Vtr::internal::FVarLevel const & childFVar = childLevel.getFVarLevel(channel);
Vtr::internal::StackBuffer<float,16> fValueWeights(parentLevel.getMaxValence());
Vtr::internal::StackBuffer<Weight,16> fValueWeights(parentLevel.getMaxValence());
for (int face = 0; face < parentLevel.getNumFaces(); ++face) {
@ -689,9 +700,10 @@ PrimvarRefiner::interpFVarFromFaces(int level, T const & src, U & dst, int chann
}
}
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpFVarFromEdges(int level, T const & src, U & dst, int channel) const {
PrimvarRefinerReal<REAL>::interpFVarFromEdges(int level, T const & src, U & dst, int channel) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
@ -708,8 +720,8 @@ PrimvarRefiner::interpFVarFromEdges(int level, T const & src, U & dst, int chann
// Allocate and initialize (if linearly interpolated) interpolation weights for
// the edge mask:
//
float eVertWeights[2];
Vtr::internal::StackBuffer<float,8> eFaceWeights(parentLevel.getMaxEdgeFaces());
Weight eVertWeights[2];
Vtr::internal::StackBuffer<Weight,8> eFaceWeights(parentLevel.getMaxEdgeFaces());
Mask eMask(eVertWeights, 0, eFaceWeights);
@ -833,9 +845,10 @@ PrimvarRefiner::interpFVarFromEdges(int level, T const & src, U & dst, int chann
}
}
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int channel) const {
PrimvarRefinerReal<REAL>::interpFVarFromVerts(int level, T const & src, U & dst, int channel) const {
Vtr::internal::Refinement const & refinement = _refiner.getRefinement(level-1);
@ -850,7 +863,7 @@ PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int chann
bool isLinearFVar = parentFVar.isLinear() || (_refiner._subdivType == Sdc::SCHEME_BILINEAR);
Vtr::internal::StackBuffer<float,32> weightBuffer(2*parentLevel.getMaxValence());
Vtr::internal::StackBuffer<Weight,32> weightBuffer(2*parentLevel.getMaxValence());
Vtr::internal::StackBuffer<Vtr::Index,16> vEdgeValues(parentLevel.getMaxValence());
@ -881,9 +894,9 @@ PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int chann
//
ConstIndexArray vEdges = parentLevel.getVertexEdges(vert);
float vVertWeight;
float * vEdgeWeights = weightBuffer;
float * vFaceWeights = vEdgeWeights + vEdges.size();
Weight vVertWeight;
Weight * vEdgeWeights = weightBuffer;
Weight * vFaceWeights = vEdgeWeights + vEdges.size();
Mask vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
@ -974,8 +987,8 @@ PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int chann
Index pEndValues[2];
parentFVar.getVertexCreaseEndValues(vert, pSibling, pEndValues);
float vWeight = 0.75f;
float eWeight = 0.125f;
Weight vWeight = 0.75f;
Weight eWeight = 0.125f;
//
// If semi-sharp we need to apply fractional weighting -- if made sharp because
@ -983,10 +996,10 @@ PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int chann
// other sibling (should only occur when there are 2):
//
if (pValueTags[pSibling].isSemiSharp()) {
float wCorner = pValueTags[pSibling].isDepSharp()
Weight wCorner = pValueTags[pSibling].isDepSharp()
? refineFVar.getFractionalWeight(vert, !pSibling, cVert, !cSibling)
: refineFVar.getFractionalWeight(vert, pSibling, cVert, cSibling);
float wCrease = 1.0f - wCorner;
Weight wCrease = 1.0f - wCorner;
vWeight = wCrease * 0.75f + wCorner;
eWeight = wCrease * 0.125f;
@ -1000,9 +1013,10 @@ PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int chann
}
}
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U, class U1, class U2>
inline void
PrimvarRefiner::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr) const {
PrimvarRefinerReal<REAL>::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr) const {
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
@ -1013,17 +1027,17 @@ PrimvarRefiner::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Pt
int numMasks = 1 + (hasTangents ? 2 : 0);
Vtr::internal::StackBuffer<Index,33> indexBuffer(maxWeightsPerMask);
Vtr::internal::StackBuffer<float,99> weightBuffer(numMasks * maxWeightsPerMask);
Vtr::internal::StackBuffer<Weight,99> weightBuffer(numMasks * maxWeightsPerMask);
float * vPosWeights = weightBuffer,
* ePosWeights = vPosWeights + 1,
* fPosWeights = ePosWeights + level.getMaxValence();
float * vTan1Weights = vPosWeights + maxWeightsPerMask,
* eTan1Weights = ePosWeights + maxWeightsPerMask,
* fTan1Weights = fPosWeights + maxWeightsPerMask;
float * vTan2Weights = vTan1Weights + maxWeightsPerMask,
* eTan2Weights = eTan1Weights + maxWeightsPerMask,
* fTan2Weights = fTan1Weights + maxWeightsPerMask;
Weight * vPosWeights = weightBuffer,
* ePosWeights = vPosWeights + 1,
* fPosWeights = ePosWeights + level.getMaxValence();
Weight * vTan1Weights = vPosWeights + maxWeightsPerMask,
* eTan1Weights = ePosWeights + maxWeightsPerMask,
* fTan1Weights = fPosWeights + maxWeightsPerMask;
Weight * vTan2Weights = vTan1Weights + maxWeightsPerMask,
* eTan2Weights = eTan1Weights + maxWeightsPerMask,
* fTan2Weights = fTan1Weights + maxWeightsPerMask;
Mask posMask( vPosWeights, ePosWeights, fPosWeights);
Mask tan1Mask(vTan1Weights, eTan1Weights, fTan1Weights);
@ -1134,9 +1148,10 @@ PrimvarRefiner::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Pt
}
}
template <typename REAL>
template <Sdc::SchemeType SCHEME, class T, class U>
inline void
PrimvarRefiner::limitFVar(T const & src, U & dst, int channel) const {
PrimvarRefinerReal<REAL>::limitFVar(T const & src, U & dst, int channel) const {
Sdc::Scheme<SCHEME> scheme(_refiner._subdivOptions);
@ -1145,7 +1160,7 @@ PrimvarRefiner::limitFVar(T const & src, U & dst, int channel) const {
int maxWeightsPerMask = 1 + 2 * level.getMaxValence();
Vtr::internal::StackBuffer<float,33> weightBuffer(maxWeightsPerMask);
Vtr::internal::StackBuffer<Weight,33> weightBuffer(maxWeightsPerMask);
Vtr::internal::StackBuffer<Index,16> vEdgeBuffer(level.getMaxValence());
// This is a bit obscure -- assign both parent and child as last level
@ -1178,9 +1193,9 @@ PrimvarRefiner::limitFVar(T const & src, U & dst, int channel) const {
// Assign the mask weights to the common buffer and compute the mask:
//
float * vWeights = weightBuffer,
* eWeights = vWeights + 1,
* fWeights = eWeights + vEdges.size();
Weight * vWeights = weightBuffer,
* eWeights = vWeights + 1,
* fWeights = eWeights + vEdges.size();
Mask vMask(vWeights, eWeights, fWeights);
@ -1242,6 +1257,12 @@ PrimvarRefiner::limitFVar(T const & src, U & dst, int channel) const {
}
}
class PrimvarRefiner : public PrimvarRefinerReal<float> {
public:
PrimvarRefiner(TopologyRefiner const & refiner)
: PrimvarRefinerReal<float>(refiner) { }
};
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION

View File

@ -37,25 +37,27 @@ namespace {
#pragma warning disable 1572
#endif
inline bool isWeightZero(float w) { return (w == 0.0f); }
template <typename REAL>
inline bool isWeightZero(REAL w) { return (w == (REAL)0.0); }
#ifdef __INTEL_COMPILER
#pragma warning (pop)
#endif
}
template <typename REAL>
struct Point1stDerivWeight {
float p;
float du;
float dv;
REAL p;
REAL du;
REAL dv;
Point1stDerivWeight()
: p(0.0f), du(0.0f), dv(0.0f)
{ }
Point1stDerivWeight(float w)
Point1stDerivWeight(REAL w)
: p(w), du(w), dv(w)
{ }
Point1stDerivWeight(float w, float wDu, float wDv)
Point1stDerivWeight(REAL w, REAL wDu, REAL wDv)
: p(w), du(wDu), dv(wDv)
{ }
@ -74,22 +76,23 @@ struct Point1stDerivWeight {
}
};
template <typename REAL>
struct Point2ndDerivWeight {
float p;
float du;
float dv;
float duu;
float duv;
float dvv;
REAL p;
REAL du;
REAL dv;
REAL duu;
REAL duv;
REAL dvv;
Point2ndDerivWeight()
: p(0.0f), du(0.0f), dv(0.0f), duu(0.0f), duv(0.0f), dvv(0.0f)
{ }
Point2ndDerivWeight(float w)
Point2ndDerivWeight(REAL w)
: p(w), du(w), dv(w), duu(w), duv(w), dvv(w)
{ }
Point2ndDerivWeight(float w, float wDu, float wDv,
float wDuu, float wDuv, float wDvv)
Point2ndDerivWeight(REAL w, REAL wDu, REAL wDv,
REAL wDuu, REAL wDuv, REAL wDvv)
: p(w), du(wDu), dv(wDv), duu(wDuu), duv(wDuv), dvv(wDvv)
{ }
@ -116,6 +119,7 @@ struct Point2ndDerivWeight {
/// Stencil table constructor set.
///
template <typename REAL>
class WeightTable {
public:
WeightTable(int coarseVerts,
@ -198,20 +202,20 @@ public:
public:
Point1stDerivAccumulator(WeightTable* tbl) : _tbl(tbl)
{ }
void PushBack(Point1stDerivWeight weight) {
void PushBack(Point1stDerivWeight<REAL> weight) {
_tbl->_weights.push_back(weight.p);
_tbl->_duWeights.push_back(weight.du);
_tbl->_dvWeights.push_back(weight.dv);
}
void Add(size_t i, Point1stDerivWeight weight) {
void Add(size_t i, Point1stDerivWeight<REAL> weight) {
_tbl->_weights[i] += weight.p;
_tbl->_duWeights[i] += weight.du;
_tbl->_dvWeights[i] += weight.dv;
}
Point1stDerivWeight Get(size_t index) {
return Point1stDerivWeight(_tbl->_weights[index],
_tbl->_duWeights[index],
_tbl->_dvWeights[index]);
Point1stDerivWeight<REAL> Get(size_t index) {
return Point1stDerivWeight<REAL>(_tbl->_weights[index],
_tbl->_duWeights[index],
_tbl->_dvWeights[index]);
}
};
Point1stDerivAccumulator GetPoint1stDerivAccumulator() {
@ -223,7 +227,7 @@ public:
public:
Point2ndDerivAccumulator(WeightTable* tbl) : _tbl(tbl)
{ }
void PushBack(Point2ndDerivWeight weight) {
void PushBack(Point2ndDerivWeight<REAL> weight) {
_tbl->_weights.push_back(weight.p);
_tbl->_duWeights.push_back(weight.du);
_tbl->_dvWeights.push_back(weight.dv);
@ -231,7 +235,7 @@ public:
_tbl->_duvWeights.push_back(weight.duv);
_tbl->_dvvWeights.push_back(weight.dvv);
}
void Add(size_t i, Point2ndDerivWeight weight) {
void Add(size_t i, Point2ndDerivWeight<REAL> weight) {
_tbl->_weights[i] += weight.p;
_tbl->_duWeights[i] += weight.du;
_tbl->_dvWeights[i] += weight.dv;
@ -239,13 +243,13 @@ public:
_tbl->_duvWeights[i] += weight.duv;
_tbl->_dvvWeights[i] += weight.dvv;
}
Point2ndDerivWeight Get(size_t index) {
return Point2ndDerivWeight(_tbl->_weights[index],
_tbl->_duWeights[index],
_tbl->_dvWeights[index],
_tbl->_duuWeights[index],
_tbl->_duvWeights[index],
_tbl->_dvvWeights[index]);
Point2ndDerivWeight<REAL> Get(size_t index) {
return Point2ndDerivWeight<REAL>(_tbl->_weights[index],
_tbl->_duWeights[index],
_tbl->_dvWeights[index],
_tbl->_duuWeights[index],
_tbl->_duvWeights[index],
_tbl->_dvvWeights[index]);
}
};
Point2ndDerivAccumulator GetPoint2ndDerivAccumulator() {
@ -257,13 +261,13 @@ public:
public:
ScalarAccumulator(WeightTable* tbl) : _tbl(tbl)
{ }
void PushBack(float weight) {
void PushBack(REAL weight) {
_tbl->_weights.push_back(weight);
}
void Add(size_t i, float w) {
void Add(size_t i, REAL w) {
_tbl->_weights[i] += w;
}
float Get(size_t index) {
REAL Get(size_t index) {
return _tbl->_weights[index];
}
};
@ -280,22 +284,22 @@ public:
std::vector<int> const&
GetSources() const { return _sources; }
std::vector<float> const&
std::vector<REAL> const&
GetWeights() const { return _weights; }
std::vector<float> const&
std::vector<REAL> const&
GetDuWeights() const { return _duWeights; }
std::vector<float> const&
std::vector<REAL> const&
GetDvWeights() const { return _dvWeights; }
std::vector<float> const&
std::vector<REAL> const&
GetDuuWeights() const { return _duuWeights; }
std::vector<float> const&
std::vector<REAL> const&
GetDuvWeights() const { return _duvWeights; }
std::vector<float> const&
std::vector<REAL> const&
GetDvvWeights() const { return _dvvWeights; }
void SetCoarseVertCount(int numVerts) {
@ -387,12 +391,12 @@ private:
// The actual stencil data.
std::vector<int> _sources;
std::vector<float> _weights;
std::vector<float> _duWeights;
std::vector<float> _dvWeights;
std::vector<float> _duuWeights;
std::vector<float> _duvWeights;
std::vector<float> _dvvWeights;
std::vector<REAL> _weights;
std::vector<REAL> _duWeights;
std::vector<REAL> _dvWeights;
std::vector<REAL> _duuWeights;
std::vector<REAL> _duvWeights;
std::vector<REAL> _dvvWeights;
// Index data used to recover stencil-to-vertex mapping.
std::vector<int> _indices;
@ -405,29 +409,33 @@ private:
bool _compactWeights;
};
StencilBuilder::StencilBuilder(int coarseVertCount,
template <typename REAL>
StencilBuilder<REAL>::StencilBuilder(int coarseVertCount,
bool genCtrlVertStencils,
bool compactWeights)
: _weightTable(new WeightTable(coarseVertCount,
: _weightTable(new WeightTable<REAL>(coarseVertCount,
genCtrlVertStencils,
compactWeights))
{
}
StencilBuilder::~StencilBuilder()
template <typename REAL>
StencilBuilder<REAL>::~StencilBuilder()
{
delete _weightTable;
}
template <typename REAL>
size_t
StencilBuilder::GetNumVerticesTotal() const
StencilBuilder<REAL>::GetNumVerticesTotal() const
{
return _weightTable->GetWeights().size();
}
template <typename REAL>
int
StencilBuilder::GetNumVertsInStencil(size_t stencilIndex) const
StencilBuilder<REAL>::GetNumVertsInStencil(size_t stencilIndex) const
{
if (stencilIndex > _weightTable->GetSizes().size() - 1)
return 0;
@ -435,59 +443,70 @@ StencilBuilder::GetNumVertsInStencil(size_t stencilIndex) const
return (int)_weightTable->GetSizes()[stencilIndex];
}
template <typename REAL>
void
StencilBuilder::SetCoarseVertCount(int numVerts)
StencilBuilder<REAL>::SetCoarseVertCount(int numVerts)
{
_weightTable->SetCoarseVertCount(numVerts);
}
template <typename REAL>
std::vector<int> const&
StencilBuilder::GetStencilOffsets() const {
StencilBuilder<REAL>::GetStencilOffsets() const {
return _weightTable->GetOffsets();
}
template <typename REAL>
std::vector<int> const&
StencilBuilder::GetStencilSizes() const {
StencilBuilder<REAL>::GetStencilSizes() const {
return _weightTable->GetSizes();
}
template <typename REAL>
std::vector<int> const&
StencilBuilder::GetStencilSources() const {
StencilBuilder<REAL>::GetStencilSources() const {
return _weightTable->GetSources();
}
std::vector<float> const&
StencilBuilder::GetStencilWeights() const {
template <typename REAL>
std::vector<REAL> const&
StencilBuilder<REAL>::GetStencilWeights() const {
return _weightTable->GetWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDuWeights() const {
template <typename REAL>
std::vector<REAL> const&
StencilBuilder<REAL>::GetStencilDuWeights() const {
return _weightTable->GetDuWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDvWeights() const {
template <typename REAL>
std::vector<REAL> const&
StencilBuilder<REAL>::GetStencilDvWeights() const {
return _weightTable->GetDvWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDuuWeights() const {
template <typename REAL>
std::vector<REAL> const&
StencilBuilder<REAL>::GetStencilDuuWeights() const {
return _weightTable->GetDuuWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDuvWeights() const {
template <typename REAL>
std::vector<REAL> const&
StencilBuilder<REAL>::GetStencilDuvWeights() const {
return _weightTable->GetDuvWeights();
}
std::vector<float> const&
StencilBuilder::GetStencilDvvWeights() const {
template <typename REAL>
std::vector<REAL> const&
StencilBuilder<REAL>::GetStencilDvvWeights() const {
return _weightTable->GetDvvWeights();
}
template <typename REAL>
void
StencilBuilder::Index::AddWithWeight(Index const & src, float weight)
StencilBuilder<REAL>::Index::AddWithWeight(Index const & src, REAL weight)
{
// Ignore no-op weights.
if (isWeightZero(weight)) {
@ -497,8 +516,9 @@ StencilBuilder::Index::AddWithWeight(Index const & src, float weight)
_owner->_weightTable->GetScalarAccumulator());
}
template <typename REAL>
void
StencilBuilder::Index::AddWithWeight(Stencil const& src, float weight)
StencilBuilder<REAL>::Index::AddWithWeight(StencilReal<REAL> const& src, REAL weight)
{
if (isWeightZero(weight)) {
return;
@ -506,25 +526,26 @@ StencilBuilder::Index::AddWithWeight(Stencil const& src, float weight)
int srcSize = *src.GetSizePtr();
Vtr::Index const * srcIndices = src.GetVertexIndices();
float const * srcWeights = src.GetWeights();
REAL const * srcWeights = src.GetWeights();
for (int i = 0; i < srcSize; ++i) {
float w = srcWeights[i];
REAL w = srcWeights[i];
if (isWeightZero(w)) {
continue;
}
Vtr::Index srcIndex = srcIndices[i];
float wgt = weight * w;
REAL wgt = weight * w;
_owner->_weightTable->AddWithWeight(srcIndex, _index, wgt,
_owner->_weightTable->GetScalarAccumulator());
}
}
template <typename REAL>
void
StencilBuilder::Index::AddWithWeight(Stencil const& src,
float weight, float du, float dv)
StencilBuilder<REAL>::Index::AddWithWeight(StencilReal<REAL> const& src,
REAL weight, REAL du, REAL dv)
{
if (isWeightZero(weight) && isWeightZero(du) && isWeightZero(dv)) {
return;
@ -532,25 +553,26 @@ StencilBuilder::Index::AddWithWeight(Stencil const& src,
int srcSize = *src.GetSizePtr();
Vtr::Index const * srcIndices = src.GetVertexIndices();
float const * srcWeights = src.GetWeights();
REAL const * srcWeights = src.GetWeights();
for (int i = 0; i < srcSize; ++i) {
float w = srcWeights[i];
REAL w = srcWeights[i];
if (isWeightZero(w)) {
continue;
}
Vtr::Index srcIndex = srcIndices[i];
Point1stDerivWeight wgt = Point1stDerivWeight(weight, du, dv) * w;
Point1stDerivWeight<REAL> wgt = Point1stDerivWeight<REAL>(weight, du, dv) * w;
_owner->_weightTable->AddWithWeight(srcIndex, _index, wgt,
_owner->_weightTable->GetPoint1stDerivAccumulator());
}
}
template <typename REAL>
void
StencilBuilder::Index::AddWithWeight(Stencil const& src,
float weight, float du, float dv, float duu, float duv, float dvv)
StencilBuilder<REAL>::Index::AddWithWeight(StencilReal<REAL> const& src,
REAL weight, REAL du, REAL dv, REAL duu, REAL duv, REAL dvv)
{
if (isWeightZero(weight) && isWeightZero(du) && isWeightZero(dv) &&
isWeightZero(duu) && isWeightZero(duv) && isWeightZero(dvv)) {
@ -559,24 +581,26 @@ StencilBuilder::Index::AddWithWeight(Stencil const& src,
int srcSize = *src.GetSizePtr();
Vtr::Index const * srcIndices = src.GetVertexIndices();
float const * srcWeights = src.GetWeights();
REAL const * srcWeights = src.GetWeights();
for (int i = 0; i < srcSize; ++i) {
float w = srcWeights[i];
REAL w = srcWeights[i];
if (isWeightZero(w)) {
continue;
}
Vtr::Index srcIndex = srcIndices[i];
Point2ndDerivWeight wgt = Point2ndDerivWeight(weight, du, dv, duu, duv, dvv) * w;
Point2ndDerivWeight<REAL> wgt = Point2ndDerivWeight<REAL>(weight, du, dv, duu, duv, dvv) * w;
_owner->_weightTable->AddWithWeight(srcIndex, _index, wgt,
_owner->_weightTable->GetPoint2ndDerivAccumulator());
}
}
template class StencilBuilder<float>;
template class StencilBuilder<double>;
} // end namespace internal
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
} // end namespace OpenSubdiv

View File

@ -36,8 +36,9 @@ namespace OPENSUBDIV_VERSION {
namespace Far {
namespace internal {
class WeightTable;
template <typename REAL> class WeightTable;
template <typename REAL>
class StencilBuilder {
public:
StencilBuilder(int coarseVertCount,
@ -63,12 +64,12 @@ public:
std::vector<int> const& GetStencilSources() const;
// The individual vertex weights, each weight is paired with one source.
std::vector<float> const& GetStencilWeights() const;
std::vector<float> const& GetStencilDuWeights() const;
std::vector<float> const& GetStencilDvWeights() const;
std::vector<float> const& GetStencilDuuWeights() const;
std::vector<float> const& GetStencilDuvWeights() const;
std::vector<float> const& GetStencilDvvWeights() const;
std::vector<REAL> const& GetStencilWeights() const;
std::vector<REAL> const& GetStencilDuWeights() const;
std::vector<REAL> const& GetStencilDvWeights() const;
std::vector<REAL> const& GetStencilDuuWeights() const;
std::vector<REAL> const& GetStencilDuvWeights() const;
std::vector<REAL> const& GetStencilDvvWeights() const;
// Vertex Facade.
class Index {
@ -79,16 +80,16 @@ public:
{}
// Add with point/vertex weight only.
void AddWithWeight(Index const & src, float weight);
void AddWithWeight(Stencil const& src, float weight);
void AddWithWeight(Index const & src, REAL weight);
void AddWithWeight(StencilReal<REAL> const& src, REAL weight);
// Add with first derivative.
void AddWithWeight(Stencil const& src,
float weight, float du, float dv);
void AddWithWeight(StencilReal<REAL> const& src,
REAL weight, REAL du, REAL dv);
// Add with first and second derivatives.
void AddWithWeight(Stencil const& src,
float weight, float du, float dv, float duu, float duv, float dvv);
void AddWithWeight(StencilReal<REAL> const& src,
REAL weight, REAL du, REAL dv, REAL duu, REAL duv, REAL dvv);
Index operator[](int index) const {
return Index(_owner, index+_index);
@ -103,7 +104,7 @@ public:
};
private:
WeightTable* _weightTable;
WeightTable<REAL>* _weightTable;
};
} // end namespace internal

View File

@ -32,28 +32,29 @@ namespace Far {
namespace {
template <typename REAL>
void
copyStencilData(int numControlVerts,
bool includeCoarseVerts,
size_t firstOffset,
std::vector<int> const* offsets,
std::vector<int> * _offsets,
std::vector<int> const* sizes,
std::vector<int> * _sizes,
std::vector<int> const* sources,
std::vector<int> * _sources,
std::vector<float> const* weights,
std::vector<float> * _weights,
std::vector<float> const* duWeights=NULL,
std::vector<float> * _duWeights=NULL,
std::vector<float> const* dvWeights=NULL,
std::vector<float> * _dvWeights=NULL,
std::vector<float> const* duuWeights=NULL,
std::vector<float> * _duuWeights=NULL,
std::vector<float> const* duvWeights=NULL,
std::vector<float> * _duvWeights=NULL,
std::vector<float> const* dvvWeights=NULL,
std::vector<float> * _dvvWeights=NULL) {
std::vector<int> const* offsets,
std::vector<int> * _offsets,
std::vector<int> const* sizes,
std::vector<int> * _sizes,
std::vector<int> const* sources,
std::vector<int> * _sources,
std::vector<REAL> const* weights,
std::vector<REAL> * _weights,
std::vector<REAL> const* duWeights=NULL,
std::vector<REAL> * _duWeights=NULL,
std::vector<REAL> const* dvWeights=NULL,
std::vector<REAL> * _dvWeights=NULL,
std::vector<REAL> const* duuWeights=NULL,
std::vector<REAL> * _duuWeights=NULL,
std::vector<REAL> const* duvWeights=NULL,
std::vector<REAL> * _duvWeights=NULL,
std::vector<REAL> const* dvvWeights=NULL,
std::vector<REAL> * _dvvWeights=NULL) {
size_t start = includeCoarseVerts ? 0 : firstOffset;
_offsets->resize(offsets->size());
@ -94,28 +95,28 @@ namespace {
std::memcpy(&(*_sources)[curOffset],
&(*sources)[off], sz*sizeof(int));
std::memcpy(&(*_weights)[curOffset],
&(*weights)[off], sz*sizeof(float));
&(*weights)[off], sz*sizeof(REAL));
if (_duWeights && !_duWeights->empty()) {
std::memcpy(&(*_duWeights)[curOffset],
&(*duWeights)[off], sz*sizeof(float));
&(*duWeights)[off], sz*sizeof(REAL));
}
if (_dvWeights && !_dvWeights->empty()) {
std::memcpy(&(*_dvWeights)[curOffset],
&(*dvWeights)[off], sz*sizeof(float));
&(*dvWeights)[off], sz*sizeof(REAL));
}
if (_duuWeights && !_duuWeights->empty()) {
std::memcpy(&(*_duuWeights)[curOffset],
&(*duuWeights)[off], sz*sizeof(float));
&(*duuWeights)[off], sz*sizeof(REAL));
}
if (_duvWeights && !_duvWeights->empty()) {
std::memcpy(&(*_duvWeights)[curOffset],
&(*duvWeights)[off], sz*sizeof(float));
&(*duvWeights)[off], sz*sizeof(REAL));
}
if (_dvvWeights && !_dvvWeights->empty()) {
std::memcpy(&(*_dvvWeights)[curOffset],
&(*dvvWeights)[off], sz*sizeof(float));
&(*dvvWeights)[off], sz*sizeof(REAL));
}
curOffset += sz;
@ -141,11 +142,12 @@ namespace {
}
};
StencilTable::StencilTable(int numControlVerts,
template <typename REAL>
StencilTableReal<REAL>::StencilTableReal(int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
std::vector<REAL> const& weights,
bool includeCoarseVerts,
size_t firstOffset)
: _numControlVertices(numControlVerts) {
@ -158,8 +160,9 @@ StencilTable::StencilTable(int numControlVerts,
&weights, &_weights);
}
template <typename REAL>
void
StencilTable::Clear() {
StencilTableReal<REAL>::Clear() {
_numControlVertices=0;
_sizes.clear();
_offsets.clear();
@ -167,26 +170,28 @@ StencilTable::Clear() {
_weights.clear();
}
LimitStencilTable::LimitStencilTable(int numControlVerts,
template <typename REAL>
LimitStencilTableReal<REAL>::LimitStencilTableReal(
int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
std::vector<float> const& duWeights,
std::vector<float> const& dvWeights,
std::vector<float> const& duuWeights,
std::vector<float> const& duvWeights,
std::vector<float> const& dvvWeights,
std::vector<REAL> const& weights,
std::vector<REAL> const& duWeights,
std::vector<REAL> const& dvWeights,
std::vector<REAL> const& duuWeights,
std::vector<REAL> const& duvWeights,
std::vector<REAL> const& dvvWeights,
bool includeCoarseVerts,
size_t firstOffset)
: StencilTable(numControlVerts) {
: StencilTableReal<REAL>(numControlVerts) {
copyStencilData(numControlVerts,
includeCoarseVerts,
firstOffset,
&offsets, &_offsets,
&sizes, &_sizes,
&sources, &_indices,
&weights, &_weights,
&offsets, &this->_offsets,
&sizes, &this->_sizes,
&sources, &this->_indices,
&weights, &this->_weights,
&duWeights, &_duWeights,
&dvWeights, &_dvWeights,
&duuWeights, &_duuWeights,
@ -194,9 +199,10 @@ LimitStencilTable::LimitStencilTable(int numControlVerts,
&dvvWeights, &_dvvWeights);
}
template <typename REAL>
void
LimitStencilTable::Clear() {
StencilTable::Clear();
LimitStencilTableReal<REAL>::Clear() {
StencilTableReal<REAL>::Clear();
_duWeights.clear();
_dvWeights.clear();
_duuWeights.clear();
@ -205,11 +211,24 @@ LimitStencilTable::Clear() {
}
//
// Explicit instantiation for float and double:
//
template class StencilReal<float>;
template class StencilReal<double>;
template class LimitStencilReal<float>;
template class LimitStencilReal<double>;
template class StencilTableReal<float>;
template class StencilTableReal<double>;
template class LimitStencilTableReal<float>;
template class LimitStencilTableReal<double>;
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION
using namespace OPENSUBDIV_VERSION;
} // end namespace OpenSubdiv

View File

@ -39,16 +39,22 @@ namespace OPENSUBDIV_VERSION {
namespace Far {
// Forward declarations for friends:
class PatchTableBuilder;
template <typename REAL> class StencilTableFactoryReal;
template <typename REAL> class LimitStencilTableFactoryReal;
/// \brief Vertex stencil descriptor
///
/// Allows access and manipulation of a single stencil in a StencilTable.
///
class Stencil {
template <typename REAL>
class StencilReal {
public:
/// \brief Default constructor
Stencil() {}
StencilReal() {}
/// \brief Constructor
///
@ -58,16 +64,11 @@ public:
///
/// @param weights Table pointer to the vertex weights of the stencil
///
Stencil(int * size,
Index * indices,
float * weights)
: _size(size),
_indices(indices),
_weights(weights) {
}
StencilReal(int * size, Index * indices, REAL * weights)
: _size(size), _indices(indices), _weights(weights) { }
/// \brief Copy constructor
Stencil(Stencil const & other) {
StencilReal(StencilReal const & other) {
_size = other._size;
_indices = other._indices;
_weights = other._weights;
@ -89,7 +90,7 @@ public:
}
/// \brief Returns the interpolation weights
float const * GetWeights() const {
REAL const * GetWeights() const {
return _weights;
}
@ -102,14 +103,28 @@ public:
}
protected:
friend class StencilTableFactory;
friend class LimitStencilTableFactory;
friend class StencilTableFactoryReal<REAL>;
friend class LimitStencilTableFactoryReal<REAL>;
int * _size;
Index * _indices;
float * _weights;
Index * _indices;
REAL * _weights;
};
/// \brief Vertex stencil class wrapping the template for compatibility.
///
class Stencil : public StencilReal<float> {
protected:
typedef StencilReal<float> BaseStencil;
public:
Stencil() : BaseStencil() { }
Stencil(BaseStencil const & other) : BaseStencil(other) { }
Stencil(int * size, Index * indices, float * weights)
: BaseStencil(size, indices, weights) { }
};
/// \brief Table of subdivision stencils.
///
/// Stencils are the most direct method of evaluation of locations on the limit
@ -122,18 +137,20 @@ protected:
/// recomputed simply by applying the blending weights to the series of coarse
/// control vertices.
///
class StencilTable {
StencilTable(int numControlVerts,
template <typename REAL>
class StencilTableReal {
protected:
StencilTableReal(int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
std::vector<REAL> const& weights,
bool includeCoarseVerts,
size_t firstOffset);
public:
virtual ~StencilTable() {};
virtual ~StencilTableReal() {};
/// \brief Returns the number of stencils in the table
int GetNumStencils() const {
@ -146,7 +163,7 @@ public:
}
/// \brief Returns a Stencil at index i in the table
Stencil GetStencil(Index i) const;
StencilReal<REAL> GetStencil(Index i) const;
/// \brief Returns the number of control vertices of each stencil in the table
std::vector<int> const & GetSizes() const {
@ -164,12 +181,12 @@ public:
}
/// \brief Returns the stencil interpolation weights
std::vector<float> const & GetWeights() const {
std::vector<REAL> const & GetWeights() const {
return _weights;
}
/// \brief Returns the stencil at index i in the table
Stencil operator[] (Index index) const;
StencilReal<REAL> operator[] (Index index) const;
/// \brief Updates point values based on the control values
///
@ -187,7 +204,7 @@ public:
///
template <class T>
void UpdateValues(T const *controlValues, T *values, Index start=-1, Index end=-1) const {
update(controlValues, values, _weights, start, end);
this->update(controlValues, values, _weights, start, end);
}
/// \brief Clears the stencils from the table
@ -196,8 +213,9 @@ public:
protected:
// Update values by applying cached stencil weights to new control values
template <class T> void update( T const *controlValues, T *values,
std::vector<float> const & valueWeights, Index start, Index end) const;
template <class T>
void update( T const *controlValues, T *values,
std::vector<REAL> const & valueWeights, Index start, Index end) const;
// Populate the offsets table from the stencil sizes in _sizes (factory helper)
void generateOffsets();
@ -215,27 +233,55 @@ protected:
void finalize();
protected:
StencilTable() : _numControlVertices(0) {}
StencilTable(int numControlVerts)
StencilTableReal() : _numControlVertices(0) {}
StencilTableReal(int numControlVerts)
: _numControlVertices(numControlVerts)
{ }
friend class StencilTableFactory;
friend class PatchTableBuilder;
friend class StencilTableFactoryReal<REAL>;
friend class Far::PatchTableBuilder;
int _numControlVertices; // number of control vertices
std::vector<int> _sizes; // number of coefficients for each stencil
std::vector<Index> _offsets, // offset to the start of each stencil
_indices; // indices of contributing coarse vertices
std::vector<float> _weights; // stencil weight coefficients
std::vector<REAL> _weights; // stencil weight coefficients
};
/// \brief Stencil table class wrapping the template for compatibility.
///
class StencilTable : public StencilTableReal<float> {
protected:
typedef StencilTableReal<float> BaseTable;
public:
Stencil GetStencil(Index index) const {
return Stencil(BaseTable::GetStencil(index));
}
Stencil operator[] (Index index) const {
return Stencil(BaseTable::GetStencil(index));
}
protected:
StencilTable() : BaseTable() { }
StencilTable(int numControlVerts) : BaseTable(numControlVerts) { }
StencilTable(int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
bool includeCoarseVerts,
size_t firstOffset)
: BaseTable(numControlVerts, offsets,
sizes, sources, weights, includeCoarseVerts, firstOffset) { }
};
/// \brief Limit point stencil descriptor
///
class LimitStencil : public Stencil {
template <typename REAL>
class LimitStencilReal : public StencilReal<REAL> {
public:
/// \brief Constructor
@ -256,15 +302,15 @@ public:
///
/// @param dvvWeights Table pointer to the 'vv' derivative weights
///
LimitStencil( int* size,
Index * indices,
float * weights,
float * duWeights=0,
float * dvWeights=0,
float * duuWeights=0,
float * duvWeights=0,
float * dvvWeights=0)
: Stencil(size, indices, weights),
LimitStencilReal( int* size,
Index * indices,
REAL * weights,
REAL * duWeights=0,
REAL * dvWeights=0,
REAL * duuWeights=0,
REAL * duvWeights=0,
REAL * dvvWeights=0)
: StencilReal<REAL>(size, indices, weights),
_duWeights(duWeights),
_dvWeights(dvWeights),
_duuWeights(duuWeights),
@ -273,36 +319,36 @@ public:
}
/// \brief Returns the u derivative weights
float const * GetDuWeights() const {
REAL const * GetDuWeights() const {
return _duWeights;
}
/// \brief Returns the v derivative weights
float const * GetDvWeights() const {
REAL const * GetDvWeights() const {
return _dvWeights;
}
/// \brief Returns the uu derivative weights
float const * GetDuuWeights() const {
REAL const * GetDuuWeights() const {
return _duuWeights;
}
/// \brief Returns the uv derivative weights
float const * GetDuvWeights() const {
REAL const * GetDuvWeights() const {
return _duvWeights;
}
/// \brief Returns the vv derivative weights
float const * GetDvvWeights() const {
REAL const * GetDvvWeights() const {
return _dvvWeights;
}
/// \brief Advance to the next stencil in the table
void Next() {
int stride = *_size;
++_size;
_indices += stride;
_weights += stride;
int stride = *this->_size;
++this->_size;
this->_indices += stride;
this->_weights += stride;
if (_duWeights) _duWeights += stride;
if (_dvWeights) _dvWeights += stride;
if (_duuWeights) _duuWeights += stride;
@ -312,63 +358,81 @@ public:
private:
friend class StencilTableFactory;
friend class LimitStencilTableFactory;
friend class StencilTableFactoryReal<REAL>;
friend class LimitStencilTableFactoryReal<REAL>;
float * _duWeights, // pointer to stencil u derivative limit weights
REAL * _duWeights, // pointer to stencil u derivative limit weights
* _dvWeights, // pointer to stencil v derivative limit weights
* _duuWeights, // pointer to stencil uu derivative limit weights
* _duvWeights, // pointer to stencil uv derivative limit weights
* _dvvWeights; // pointer to stencil vv derivative limit weights
};
/// \brief Limit point stencil class wrapping the template for compatibility.
///
class LimitStencil : LimitStencilReal<float> {
protected:
typedef LimitStencilReal<float> BaseStencil;
public:
LimitStencil(BaseStencil const & other) : BaseStencil(other) { }
LimitStencil(int* size, Index * indices, float * weights,
float * duWeights=0, float * dvWeights=0,
float * duuWeights=0, float * duvWeights=0, float * dvvWeights=0)
: BaseStencil(size, indices, weights,
duWeights, dvWeights, duuWeights, duvWeights, dvvWeights) { }
};
/// \brief Table of limit subdivision stencils.
///
///
class LimitStencilTable : public StencilTable {
LimitStencilTable(int numControlVerts,
template <typename REAL>
class LimitStencilTableReal : public StencilTableReal<REAL> {
protected:
LimitStencilTableReal(
int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
std::vector<float> const& duWeights,
std::vector<float> const& dvWeights,
std::vector<float> const& duuWeights,
std::vector<float> const& duvWeights,
std::vector<float> const& dvvWeights,
std::vector<REAL> const& weights,
std::vector<REAL> const& duWeights,
std::vector<REAL> const& dvWeights,
std::vector<REAL> const& duuWeights,
std::vector<REAL> const& duvWeights,
std::vector<REAL> const& dvvWeights,
bool includeCoarseVerts,
size_t firstOffset);
public:
/// \brief Returns a LimitStencil at index i in the table
LimitStencil GetLimitStencil(Index i) const;
LimitStencilReal<REAL> GetLimitStencil(Index i) const;
/// \brief Returns the limit stencil at index i in the table
LimitStencil operator[] (Index index) const;
LimitStencilReal<REAL> operator[] (Index index) const;
/// \brief Returns the 'u' derivative stencil interpolation weights
std::vector<float> const & GetDuWeights() const {
std::vector<REAL> const & GetDuWeights() const {
return _duWeights;
}
/// \brief Returns the 'v' derivative stencil interpolation weights
std::vector<float> const & GetDvWeights() const {
std::vector<REAL> const & GetDvWeights() const {
return _dvWeights;
}
/// \brief Returns the 'uu' derivative stencil interpolation weights
std::vector<float> const & GetDuuWeights() const {
std::vector<REAL> const & GetDuuWeights() const {
return _duuWeights;
}
/// \brief Returns the 'uv' derivative stencil interpolation weights
std::vector<float> const & GetDuvWeights() const {
std::vector<REAL> const & GetDuvWeights() const {
return _duvWeights;
}
/// \brief Returns the 'vv' derivative stencil interpolation weights
std::vector<float> const & GetDvvWeights() const {
std::vector<REAL> const & GetDvvWeights() const {
return _dvvWeights;
}
@ -393,8 +457,8 @@ public:
void UpdateDerivs(T const *controlValues, T *uderivs, T *vderivs,
int start=-1, int end=-1) const {
update(controlValues, uderivs, _duWeights, start, end);
update(controlValues, vderivs, _dvWeights, start, end);
this->update(controlValues, uderivs, _duWeights, start, end);
this->update(controlValues, vderivs, _dvWeights, start, end);
}
/// \brief Updates 2nd derivative values based on the control values
@ -421,37 +485,71 @@ public:
void Update2ndDerivs(T const *controlValues, T *uuderivs, T *uvderivs, T *vvderivs,
int start=-1, int end=-1) const {
update(controlValues, uuderivs, _duuWeights, start, end);
update(controlValues, uvderivs, _duvWeights, start, end);
update(controlValues, vvderivs, _dvvWeights, start, end);
this->update(controlValues, uuderivs, _duuWeights, start, end);
this->update(controlValues, uvderivs, _duvWeights, start, end);
this->update(controlValues, vvderivs, _dvvWeights, start, end);
}
/// \brief Clears the stencils from the table
void Clear();
private:
friend class LimitStencilTableFactory;
friend class LimitStencilTableFactoryReal<REAL>;
// Resize the table arrays (factory helper)
void resize(int nstencils, int nelems);
private:
std::vector<float> _duWeights, // u derivative limit stencil weights
std::vector<REAL> _duWeights, // u derivative limit stencil weights
_dvWeights, // v derivative limit stencil weights
_duuWeights, // uu derivative limit stencil weights
_duvWeights, // uv derivative limit stencil weights
_dvvWeights; // vv derivative limit stencil weights
};
/// \brief Limit stencil table class wrapping the template for compatibility.
///
class LimitStencilTable : public LimitStencilTableReal<float> {
protected:
typedef LimitStencilTableReal<float> BaseTable;
public:
LimitStencil GetLimitStencil(Index index) const {
return LimitStencil(BaseTable::GetLimitStencil(index));
}
LimitStencil operator[] (Index index) const {
return LimitStencil(BaseTable::GetLimitStencil(index));
}
protected:
LimitStencilTable(int numControlVerts,
std::vector<int> const& offsets,
std::vector<int> const& sizes,
std::vector<int> const& sources,
std::vector<float> const& weights,
std::vector<float> const& duWeights,
std::vector<float> const& dvWeights,
std::vector<float> const& duuWeights,
std::vector<float> const& duvWeights,
std::vector<float> const& dvvWeights,
bool includeCoarseVerts,
size_t firstOffset)
: BaseTable(numControlVerts,
offsets, sizes, sources, weights,
duWeights, dvWeights, duuWeights, duvWeights, dvvWeights,
includeCoarseVerts, firstOffset) { }
};
// Update values by applying cached stencil weights to new control values
template <typename REAL>
template <class T> void
StencilTable::update(T const *controlValues, T *values,
std::vector<float> const &valueWeights, Index start, Index end) const {
StencilTableReal<REAL>::update(T const *controlValues, T *values,
std::vector<REAL> const &valueWeights, Index start, Index end) const {
int const * sizes = &_sizes.at(0);
Index const * indices = &_indices.at(0);
float const * weights = &valueWeights.at(0);
REAL const * weights = &valueWeights.at(0);
if (start>0) {
assert(start<(Index)_offsets.size());
@ -478,8 +576,9 @@ StencilTable::update(T const *controlValues, T *values,
}
}
template <typename REAL>
inline void
StencilTable::generateOffsets() {
StencilTableReal<REAL>::generateOffsets() {
Index offset=0;
int noffsets = (int)_sizes.size();
_offsets.resize(noffsets);
@ -489,93 +588,104 @@ StencilTable::generateOffsets() {
}
}
template <typename REAL>
inline void
StencilTable::resize(int nstencils, int nelems) {
StencilTableReal<REAL>::resize(int nstencils, int nelems) {
_sizes.resize(nstencils);
_indices.resize(nelems);
_weights.resize(nelems);
}
template <typename REAL>
inline void
StencilTable::reserve(int nstencils, int nelems) {
StencilTableReal<REAL>::reserve(int nstencils, int nelems) {
_sizes.reserve(nstencils);
_indices.reserve(nelems);
_weights.reserve(nelems);
}
template <typename REAL>
inline void
StencilTable::shrinkToFit() {
StencilTableReal<REAL>::shrinkToFit() {
std::vector<int>(_sizes).swap(_sizes);
std::vector<Index>(_indices).swap(_indices);
std::vector<float>(_weights).swap(_weights);
std::vector<REAL>(_weights).swap(_weights);
}
template <typename REAL>
inline void
StencilTable::finalize() {
StencilTableReal<REAL>::finalize() {
shrinkToFit();
generateOffsets();
}
// Returns a Stencil at index i in the table
inline Stencil
StencilTable::GetStencil(Index i) const {
template <typename REAL>
inline StencilReal<REAL>
StencilTableReal<REAL>::GetStencil(Index i) const {
assert((! _offsets.empty()) && i<(int)_offsets.size());
Index ofs = _offsets[i];
return Stencil( const_cast<int*>(&_sizes[i]),
const_cast<Index *>(&_indices[ofs]),
const_cast<float *>(&_weights[ofs]) );
return StencilReal<REAL>(const_cast<int*>(&_sizes[i]),
const_cast<Index*>(&_indices[ofs]),
const_cast<REAL*>(&_weights[ofs]));
}
inline Stencil
StencilTable::operator[] (Index index) const {
template <typename REAL>
inline StencilReal<REAL>
StencilTableReal<REAL>::operator[] (Index index) const {
return GetStencil(index);
}
template <typename REAL>
inline void
LimitStencilTable::resize(int nstencils, int nelems) {
StencilTable::resize(nstencils, nelems);
LimitStencilTableReal<REAL>::resize(int nstencils, int nelems) {
StencilTableReal<REAL>::resize(nstencils, nelems);
_duWeights.resize(nelems);
_dvWeights.resize(nelems);
}
// Returns a LimitStencil at index i in the table
inline LimitStencil
LimitStencilTable::GetLimitStencil(Index i) const {
assert((! GetOffsets().empty()) && i<(int)GetOffsets().size());
template <typename REAL>
inline LimitStencilReal<REAL>
LimitStencilTableReal<REAL>::GetLimitStencil(Index i) const {
assert((! this->GetOffsets().empty()) && i<(int)this->GetOffsets().size());
Index ofs = GetOffsets()[i];
Index ofs = this->GetOffsets()[i];
if (!_duWeights.empty() && !_dvWeights.empty() &&
!_duuWeights.empty() && !_duvWeights.empty() && !_dvvWeights.empty()) {
return LimitStencil( const_cast<int *>(&GetSizes()[i]),
const_cast<Index *>(&GetControlIndices()[ofs]),
const_cast<float *>(&GetWeights()[ofs]),
const_cast<float *>(&GetDuWeights()[ofs]),
const_cast<float *>(&GetDvWeights()[ofs]),
const_cast<float *>(&GetDuuWeights()[ofs]),
const_cast<float *>(&GetDuvWeights()[ofs]),
const_cast<float *>(&GetDvvWeights()[ofs]) );
return LimitStencilReal<REAL>(
const_cast<int *>(&this->GetSizes()[i]),
const_cast<Index *>(&this->GetControlIndices()[ofs]),
const_cast<REAL *>(&this->GetWeights()[ofs]),
const_cast<REAL *>(&GetDuWeights()[ofs]),
const_cast<REAL *>(&GetDvWeights()[ofs]),
const_cast<REAL *>(&GetDuuWeights()[ofs]),
const_cast<REAL *>(&GetDuvWeights()[ofs]),
const_cast<REAL *>(&GetDvvWeights()[ofs]) );
} else if (!_duWeights.empty() && !_dvWeights.empty()) {
return LimitStencil( const_cast<int *>(&GetSizes()[i]),
const_cast<Index *>(&GetControlIndices()[ofs]),
const_cast<float *>(&GetWeights()[ofs]),
const_cast<float *>(&GetDuWeights()[ofs]),
const_cast<float *>(&GetDvWeights()[ofs]) );
return LimitStencilReal<REAL>(
const_cast<int *>(&this->GetSizes()[i]),
const_cast<Index *>(&this->GetControlIndices()[ofs]),
const_cast<REAL *>(&this->GetWeights()[ofs]),
const_cast<REAL *>(&GetDuWeights()[ofs]),
const_cast<REAL *>(&GetDvWeights()[ofs]) );
} else {
return LimitStencil( const_cast<int *>(&GetSizes()[i]),
const_cast<Index *>(&GetControlIndices()[ofs]),
const_cast<float *>(&GetWeights()[ofs]) );
return LimitStencilReal<REAL>(
const_cast<int *>(&this->GetSizes()[i]),
const_cast<Index *>(&this->GetControlIndices()[ofs]),
const_cast<REAL *>(&this->GetWeights()[ofs]) );
}
}
inline LimitStencil
LimitStencilTable::operator[] (Index index) const {
template <typename REAL>
inline LimitStencilReal<REAL>
LimitStencilTableReal<REAL>::operator[] (Index index) const {
return GetLimitStencil(index);
}
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION

View File

@ -39,13 +39,16 @@ namespace OPENSUBDIV_VERSION {
namespace Far {
using internal::StencilBuilder;
namespace {
#ifdef __INTEL_COMPILER
#pragma warning (push)
#pragma warning disable 1572
#endif
inline bool isWeightZero(float w) { return (w == 0.0f); }
template <typename REAL>
inline bool isWeightZero(REAL w) { return (w == (REAL) 0.0); }
#ifdef __INTEL_COMPILER
#pragma warning (pop)
@ -54,15 +57,17 @@ namespace {
//------------------------------------------------------------------------------
template <typename REAL>
void
StencilTableFactory::generateControlVertStencils(
int numControlVerts, Stencil & dst) {
StencilTableFactoryReal<REAL>::generateControlVertStencils(
int numControlVerts,
StencilReal<REAL> & dst) {
// Control vertices contribute a single index with a weight of 1.0
for (int i=0; i<numControlVerts; ++i) {
*dst._size = 1;
*dst._indices = i;
*dst._weights = 1.0f;
*dst._weights = (REAL) 1.0;
dst.Next();
}
}
@ -70,8 +75,9 @@ StencilTableFactory::generateControlVertStencils(
//
// StencilTable factory
//
StencilTable const *
StencilTableFactory::Create(TopologyRefiner const & refiner,
template <typename REAL>
StencilTableReal<REAL> const *
StencilTableFactoryReal<REAL>::Create(TopologyRefiner const & refiner,
Options options) {
bool interpolateVertex = options.interpolationMode==INTERPOLATE_VERTEX;
@ -84,12 +90,12 @@ StencilTableFactory::Create(TopologyRefiner const & refiner,
int maxlevel = std::min(int(options.maxLevel), refiner.GetMaxLevel());
if (maxlevel==0 && (! options.generateControlVerts)) {
StencilTable * result = new StencilTable;
StencilTableReal<REAL> * result = new StencilTableReal<REAL>;
result->_numControlVertices = numControlVertices;
return result;
}
internal::StencilBuilder builder(numControlVertices,
StencilBuilder<REAL> builder(numControlVertices,
/*genControlVerts*/ true,
/*compactWeights*/ true);
@ -99,8 +105,8 @@ StencilTableFactory::Create(TopologyRefiner const & refiner,
//
PrimvarRefiner primvarRefiner(refiner);
internal::StencilBuilder::Index srcIndex(&builder, 0);
internal::StencilBuilder::Index dstIndex(&builder, numControlVertices);
typename StencilBuilder<REAL>::Index srcIndex(&builder, 0);
typename StencilBuilder<REAL>::Index dstIndex(&builder, numControlVertices);
for (int level=1; level<=maxlevel; ++level) {
if (interpolateVertex) {
@ -134,8 +140,8 @@ StencilTableFactory::Create(TopologyRefiner const & refiner,
// Copy stencils from the StencilBuilder into the StencilTable.
// Always initialize numControlVertices (useful for torus case)
StencilTable * result =
new StencilTable(numControlVertices,
StencilTableReal<REAL> * result =
new StencilTableReal<REAL>(numControlVertices,
builder.GetStencilOffsets(),
builder.GetStencilSizes(),
builder.GetStencilSources(),
@ -147,8 +153,10 @@ StencilTableFactory::Create(TopologyRefiner const & refiner,
//------------------------------------------------------------------------------
StencilTable const *
StencilTableFactory::Create(int numTables, StencilTable const ** tables) {
template <typename REAL>
StencilTableReal<REAL> const *
StencilTableFactoryReal<REAL>::Create(int numTables,
StencilTableReal<REAL> const ** tables) {
// XXXtakahito:
// This function returns NULL for empty inputs or erroneous condition.
@ -166,7 +174,7 @@ StencilTableFactory::Create(int numTables, StencilTable const ** tables) {
for (int i=0; i<numTables; ++i) {
StencilTable const * st = tables[i];
StencilTableReal<REAL> const * st = tables[i];
// allow the tables could have a null entry.
if (!st) continue;
@ -182,21 +190,21 @@ StencilTableFactory::Create(int numTables, StencilTable const ** tables) {
return NULL;
}
StencilTable * result = new StencilTable;
StencilTableReal<REAL> * result = new StencilTableReal<REAL>;
result->resize(nstencils, nelems);
int * sizes = &result->_sizes[0];
Index * indices = &result->_indices[0];
float * weights = &result->_weights[0];
REAL * weights = &result->_weights[0];
for (int i=0; i<numTables; ++i) {
StencilTable const * st = tables[i];
StencilTableReal<REAL> const * st = tables[i];
if (!st) continue;
int st_nstencils = st->GetNumStencils(),
st_nelems = (int)st->_indices.size();
memcpy(sizes, &st->_sizes[0], st_nstencils*sizeof(int));
memcpy(indices, &st->_indices[0], st_nelems*sizeof(Index));
memcpy(weights, &st->_weights[0], st_nelems*sizeof(float));
memcpy(weights, &st->_weights[0], st_nelems*sizeof(REAL));
sizes += st_nstencils;
indices += st_nelems;
@ -213,11 +221,12 @@ StencilTableFactory::Create(int numTables, StencilTable const ** tables) {
//------------------------------------------------------------------------------
StencilTable const *
StencilTableFactory::AppendLocalPointStencilTable(
template <typename REAL>
StencilTableReal<REAL> const *
StencilTableFactoryReal<REAL>::AppendLocalPointStencilTable(
TopologyRefiner const &refiner,
StencilTable const * baseStencilTable,
StencilTable const * localPointStencilTable,
StencilTableReal<REAL> const * baseStencilTable,
StencilTableReal<REAL> const * localPointStencilTable,
bool factorize) {
return appendLocalPointStencilTable(
@ -228,11 +237,12 @@ StencilTableFactory::AppendLocalPointStencilTable(
factorize);
}
StencilTable const *
StencilTableFactory::AppendLocalPointStencilTableFaceVarying(
template <typename REAL>
StencilTableReal<REAL> const *
StencilTableFactoryReal<REAL>::AppendLocalPointStencilTableFaceVarying(
TopologyRefiner const &refiner,
StencilTable const * baseStencilTable,
StencilTable const * localPointStencilTable,
StencilTableReal<REAL> const * baseStencilTable,
StencilTableReal<REAL> const * localPointStencilTable,
int channel,
bool factorize) {
@ -244,11 +254,12 @@ StencilTableFactory::AppendLocalPointStencilTableFaceVarying(
factorize);
}
StencilTable const *
StencilTableFactory::appendLocalPointStencilTable(
template <typename REAL>
StencilTableReal<REAL> const *
StencilTableFactoryReal<REAL>::appendLocalPointStencilTable(
TopologyRefiner const &refiner,
StencilTable const * baseStencilTable,
StencilTable const * localPointStencilTable,
StencilTableReal<REAL> const * baseStencilTable,
StencilTableReal<REAL> const * localPointStencilTable,
int channel,
bool factorize) {
@ -317,20 +328,20 @@ StencilTableFactory::appendLocalPointStencilTable(
int nLocalPointStencils = localPointStencilTable->GetNumStencils();
int nLocalPointStencilsElements = 0;
internal::StencilBuilder builder(nControlVerts,
StencilBuilder<REAL> builder(nControlVerts,
/*genControlVerts*/ false,
/*compactWeights*/ factorize);
internal::StencilBuilder::Index origin(&builder, 0);
internal::StencilBuilder::Index dst = origin;
internal::StencilBuilder::Index srcIdx = origin;
typename StencilBuilder<REAL>::Index origin(&builder, 0);
typename StencilBuilder<REAL>::Index dst = origin;
typename StencilBuilder<REAL>::Index srcIdx = origin;
for (int i = 0 ; i < nLocalPointStencils; ++i) {
Stencil src = localPointStencilTable->GetStencil(i);
StencilReal<REAL> src = localPointStencilTable->GetStencil(i);
dst = origin[i];
for (int j = 0; j < src.GetSize(); ++j) {
Index index = src.GetVertexIndices()[j];
float weight = src.GetWeights()[j];
if (isWeightZero(weight)) continue;
REAL weight = src.GetWeights()[j];
if (isWeightZero<REAL>(weight)) continue;
if (factorize) {
dst.AddWithWeight(
@ -349,14 +360,14 @@ StencilTableFactory::appendLocalPointStencilTable(
}
// create new stencil table
StencilTable * result = new StencilTable;
StencilTableReal<REAL> * result = new StencilTableReal<REAL>;
result->_numControlVertices = nControlVerts;
result->resize(nBaseStencils + nLocalPointStencils,
nBaseStencilsElements + nLocalPointStencilsElements);
int* sizes = &result->_sizes[0];
Index * indices = &result->_indices[0];
float * weights = &result->_weights[0];
REAL * weights = &result->_weights[0];
// put base stencils first
memcpy(sizes, &baseStencilTable->_sizes[0],
@ -364,7 +375,7 @@ StencilTableFactory::appendLocalPointStencilTable(
memcpy(indices, &baseStencilTable->_indices[0],
nBaseStencilsElements*sizeof(Index));
memcpy(weights, &baseStencilTable->_weights[0],
nBaseStencilsElements*sizeof(float));
nBaseStencilsElements*sizeof(REAL));
sizes += nBaseStencils;
indices += nBaseStencilsElements;
@ -388,12 +399,13 @@ StencilTableFactory::appendLocalPointStencilTable(
}
//------------------------------------------------------------------------------
LimitStencilTable const *
LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
template <typename REAL>
LimitStencilTableReal<REAL> const *
LimitStencilTableFactoryReal<REAL>::Create(TopologyRefiner const & refiner,
LocationArrayVec const & locationArrays,
StencilTable const * cvStencilsIn,
PatchTable const * patchTableIn,
Options options) {
StencilTableReal<REAL> const * cvStencilsIn,
PatchTable const * patchTableIn,
Options options) {
// Compute the total number of stencils to generate
int numStencils=0, numLimitStencils=0;
@ -409,14 +421,14 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
int maxlevel = refiner.GetMaxLevel();
StencilTable const * cvstencils = cvStencilsIn;
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
StencilTableFactory::Options stencilTableOptions;
typename StencilTableFactoryReal<REAL>::Options stencilTableOptions;
stencilTableOptions.generateIntermediateLevels = uniform ? false :true;
stencilTableOptions.generateControlVerts = true;
stencilTableOptions.generateOffsets = true;
@ -424,7 +436,7 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
// PERFORMANCE: We could potentially save some mem-copies by not
// instantiating the stencil tables and work directly off the source
// data.
cvstencils = StencilTableFactory::Create(refiner, stencilTableOptions);
cvstencils = StencilTableFactoryReal<REAL>::Create(refiner, stencilTableOptions);
} else {
// Sanity checks
//
@ -447,6 +459,7 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
// patch table.
PatchTableFactory::Options patchTableOptions;
patchTableOptions.SetPatchPrecision<REAL>();
patchTableOptions.SetEndCapType(
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
patchTableOptions.useInfSharpPatch = !uniform &&
@ -456,10 +469,10 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
if (! cvStencilsIn) {
// if cvstencils is just created above, append endcap stencils
if (StencilTable const *localPointStencilTable =
patchtable->GetLocalPointStencilTable()) {
StencilTable const *table =
StencilTableFactory::AppendLocalPointStencilTable(
if (StencilTableReal<REAL> const *localPointStencilTable =
patchtable->GetLocalPointStencilTable<REAL>()) {
StencilTableReal<REAL> const *table =
StencilTableFactoryReal<REAL>::AppendLocalPointStencilTable(
refiner, cvstencils, localPointStencilTable);
delete cvstencils;
cvstencils = table;
@ -484,21 +497,20 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
//
// Generate limit stencils for locations
//
internal::StencilBuilder builder(refiner.GetLevel(0).GetNumVertices(),
StencilBuilder<REAL> builder(refiner.GetLevel(0).GetNumVertices(),
/*genControlVerts*/ false,
/*compactWeights*/ true);
internal::StencilBuilder::Index origin(&builder, 0);
internal::StencilBuilder::Index dst = origin;
typename StencilBuilder<REAL>::Index origin(&builder, 0);
typename StencilBuilder<REAL>::Index dst = origin;
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
REAL wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
for (size_t i=0; i<locationArrays.size(); ++i) {
LocationArray const & array = locationArrays[i];
assert(array.ptexIdx>=0);
for (int j=0; j<array.numLocations; ++j) { // for each face we're working on
float s = array.s[j],
REAL s = array.s[j],
t = array.t[j]; // for each target (s,t) point on that face
PatchMap::Handle const * handle =
@ -506,7 +518,7 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
if (handle) {
ConstIndexArray cvs = patchtable->GetPatchVertices(*handle);
StencilTable const & src = *cvstencils;
StencilTableReal<REAL> const & src = *cvstencils;
dst = origin[numLimitStencils];
if (options.generate2ndDerivatives) {
@ -548,7 +560,7 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
//
// Copy the proto-stencils into the limit stencil table
//
LimitStencilTable * result = new LimitStencilTable(
LimitStencilTableReal<REAL> * result = new LimitStencilTableReal<REAL>(
refiner.GetLevel(0).GetNumVertices(),
builder.GetStencilOffsets(),
builder.GetStencilSizes(),
@ -564,6 +576,16 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner,
return result;
}
//
// Explicit instantiation for float and double:
//
template class StencilTableFactoryReal<float>;
template class StencilTableFactoryReal<double>;
template class LimitStencilTableFactoryReal<float>;
template class LimitStencilTableFactoryReal<double>;
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION

View File

@ -38,14 +38,17 @@ namespace Far {
class TopologyRefiner;
class Stencil;
class StencilTable;
class LimitStencil;
class LimitStencilTable;
template <typename REAL> class StencilReal;
template <typename REAL> class StencilTableReal;
template <typename REAL> class LimitStencilReal;
template <typename REAL> class LimitStencilTableReal;
/// \brief A specialized factory for StencilTable
///
class StencilTableFactory {
template <typename REAL>
class StencilTableFactoryReal {
public:
@ -88,8 +91,8 @@ public:
///
/// @param options Options controlling the creation of the table
///
static StencilTable const * Create(TopologyRefiner const & refiner,
Options options = Options());
static StencilTableReal<REAL> const * Create(
TopologyRefiner const & refiner, Options options = Options());
/// \brief Instantiates StencilTable by concatenating an array of existing
@ -104,7 +107,8 @@ public:
///
/// @param tables Array of input StencilTables
///
static StencilTable const * Create(int numTables, StencilTable const ** tables);
static StencilTableReal<REAL> const * Create(
int numTables, StencilTableReal<REAL> const ** tables);
/// \brief Utility function for stencil splicing for local point stencils.
@ -121,11 +125,11 @@ public:
/// table so that the endcap points can be computed
/// directly from control vertices.
///
static StencilTable const * AppendLocalPointStencilTable(
TopologyRefiner const &refiner,
StencilTable const *baseStencilTable,
StencilTable const *localPointStencilTable,
bool factorize = true);
static StencilTableReal<REAL> const * AppendLocalPointStencilTable(
TopologyRefiner const &refiner,
StencilTableReal<REAL> const *baseStencilTable,
StencilTableReal<REAL> const *localPointStencilTable,
bool factorize = true);
/// \brief Utility function for stencil splicing for local point
/// face-varying stencils.
@ -144,25 +148,27 @@ public:
/// table so that the endcap points can be computed
/// directly from control vertices.
///
static StencilTable const * AppendLocalPointStencilTableFaceVarying(
TopologyRefiner const &refiner,
StencilTable const *baseStencilTable,
StencilTable const *localPointStencilTable,
int channel = 0,
bool factorize = true);
static StencilTableReal<REAL> const * AppendLocalPointStencilTableFaceVarying(
TopologyRefiner const &refiner,
StencilTableReal<REAL> const *baseStencilTable,
StencilTableReal<REAL> const *localPointStencilTable,
int channel = 0,
bool factorize = true);
private:
// Generate stencils for the coarse control-vertices (single weight = 1.0f)
static void generateControlVertStencils(int numControlVerts, Stencil & dst);
static void generateControlVertStencils(
int numControlVerts,
StencilReal<REAL> & dst);
// Internal method to splice local point stencils
static StencilTable const * appendLocalPointStencilTable(
TopologyRefiner const &refiner,
StencilTable const * baseStencilTable,
StencilTable const * localPointStencilTable,
int channel,
bool factorize);
static StencilTableReal<REAL> const * appendLocalPointStencilTable(
TopologyRefiner const &refiner,
StencilTableReal<REAL> const * baseStencilTable,
StencilTableReal<REAL> const * localPointStencilTable,
int channel,
bool factorize);
};
/// \brief A specialized factory for LimitStencilTable
@ -176,7 +182,8 @@ private:
/// normalized (s,t) patch coordinates. The factory exposes the LocationArray
/// struct as a container for these location descriptors.
///
class LimitStencilTableFactory {
template <typename REAL>
class LimitStencilTableFactoryReal {
public:
@ -188,7 +195,7 @@ public:
int ptexIdx, ///< ptex face index
numLocations; ///< number of (u,v) coordinates in the array
float const * s, ///< array of u coordinates
REAL const * s, ///< array of u coordinates
* t; ///< array of v coordinates
};
@ -221,15 +228,101 @@ public:
///
/// @param options Options controlling the creation of the table
///
static LimitStencilTable const * Create(TopologyRefiner const & refiner,
LocationArrayVec const & locationArrays,
StencilTable const * cvStencils=0,
PatchTable const * patchTable=0,
Options options=Options());
static LimitStencilTableReal<REAL> const * Create(
TopologyRefiner const & refiner,
LocationArrayVec const & locationArrays,
StencilTableReal<REAL> const * cvStencils = 0,
PatchTable const * patchTable = 0,
Options options = Options());
};
//
// Public wrapper classes for the templates
//
class Stencil;
class StencilTable;
/// \brief Stencil table factory class wrapping the template for compatibility.
///
class StencilTableFactory : public StencilTableFactoryReal<float> {
private:
typedef StencilTableFactoryReal<float> BaseFactory;
typedef StencilTableReal<float> BaseTable;
public:
static StencilTable const * Create(
TopologyRefiner const & refiner, Options options = Options()) {
return static_cast<StencilTable const *>(
BaseFactory::Create(refiner, options));
}
static StencilTable const * Create(
int numTables, StencilTable const ** tables) {
return static_cast<StencilTable const *>(
BaseFactory::Create(numTables,
reinterpret_cast<BaseTable const **>(tables)));
}
static StencilTable const * AppendLocalPointStencilTable(
TopologyRefiner const &refiner,
StencilTable const *baseStencilTable,
StencilTable const *localPointStencilTable,
bool factorize = true) {
return static_cast<StencilTable const *>(
BaseFactory::AppendLocalPointStencilTable(refiner,
static_cast<BaseTable const *>(baseStencilTable),
static_cast<BaseTable const *>(localPointStencilTable),
factorize));
}
static StencilTable const * AppendLocalPointStencilTableFaceVarying(
TopologyRefiner const &refiner,
StencilTable const *baseStencilTable,
StencilTable const *localPointStencilTable,
int channel = 0,
bool factorize = true) {
return static_cast<StencilTable const *>(
BaseFactory::AppendLocalPointStencilTableFaceVarying(refiner,
static_cast<BaseTable const *>(baseStencilTable),
static_cast<BaseTable const *>(localPointStencilTable),
channel, factorize));
}
};
class LimitStencil;
class LimitStencilTable;
/// \brief Stencil table factory class wrapping the template for compatibility.
///
class LimitStencilTableFactory : public LimitStencilTableFactoryReal<float> {
private:
typedef LimitStencilTableFactoryReal<float> BaseFactory;
typedef LimitStencilTableReal<float> BaseTable;
public:
static LimitStencilTable const * Create(
TopologyRefiner const & refiner,
LocationArrayVec const & locationArrays,
LimitStencilTable const * cvStencils = 0,
PatchTable const * patchTable = 0,
Options options = Options()) {
return static_cast<LimitStencilTable const *>(
BaseFactory::Create(
refiner,
locationArrays,
static_cast<BaseTable const *>(cvStencils),
patchTable,
options));
}
};
} // end namespace Far
} // end namespace OPENSUBDIV_VERSION

View File

@ -42,6 +42,7 @@ namespace Far { namespace internal { class FeatureMask; } }
namespace Far {
template <typename REAL> class PrimvarRefinerReal;
template <class MESH> class TopologyRefinerFactory;
///
@ -212,7 +213,8 @@ protected:
friend class PatchTableBuilder;
friend class PatchBuilder;
friend class PtexIndices;
friend class PrimvarRefiner;
template <typename REAL>
friend class PrimvarRefinerReal;
Vtr::internal::Level & getLevel(int l) { return *_levels[l]; }
Vtr::internal::Level const & getLevel(int l) const { return *_levels[l]; }