From 647039a8eea551d6883c2bcb87bfb1d8b8e09242 Mon Sep 17 00:00:00 2001 From: barry Date: Sat, 28 Jul 2018 14:56:43 -0700 Subject: [PATCH] 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 --- opensubdiv/far/patchTable.cpp | 47 ++-- opensubdiv/far/patchTable.h | 216 +++++++++++++-- opensubdiv/far/patchTableFactory.cpp | 218 +++++++++++----- opensubdiv/far/patchTableFactory.h | 28 ++ opensubdiv/far/primvarRefiner.h | 133 ++++++---- opensubdiv/far/stencilBuilder.cpp | 188 ++++++++------ opensubdiv/far/stencilBuilder.h | 29 ++- opensubdiv/far/stencilTable.cpp | 105 +++++--- opensubdiv/far/stencilTable.h | 346 ++++++++++++++++--------- opensubdiv/far/stencilTableFactory.cpp | 144 +++++----- opensubdiv/far/stencilTableFactory.h | 159 +++++++++--- opensubdiv/far/topologyRefiner.h | 4 +- 12 files changed, 1097 insertions(+), 520 deletions(-) diff --git a/opensubdiv/far/patchTable.cpp b/opensubdiv/far/patchTable.cpp index 13c9a53c..89aba043 100644 --- a/opensubdiv/far/patchTable.cpp +++ b/opensubdiv/far/patchTable.cpp @@ -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; } diff --git a/opensubdiv/far/patchTable.h b/opensubdiv/far/patchTable.h index dfdfca9d..8c9daa39 100644 --- a/opensubdiv/far/patchTable.h +++ b/opensubdiv/far/patchTable.h @@ -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 + StencilTableReal const *GetLocalPointStencilTable() const; + + /// \brief Tests the precision of the stencil table to compute local point + /// vertex values + template 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 + StencilTableReal const *GetLocalPointVaryingStencilTable() const; + + /// \brief Tests the precision of the stencil table to compute local point + /// varying values + template 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 + StencilTableReal const * GetLocalPointFaceVaryingStencilTable(int channel = 0) const; + + /// \brief Tests the precision of the stencil table to compute local point + /// face-varying values + template 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_type; + typedef StencilTableReal 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 StencilTableReal * 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 _localPointFaceVaryingStencils; + std::vector _localPointFaceVaryingStencils; // // 'single-crease' patch sharpness tables @@ -607,21 +675,122 @@ private: std::vector _sharpnessIndices; // Indices of single-crease sharpness (one per patch) std::vector _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 * +PatchTable::StencilTableHandler::Get() const { return _fPtr; } + +template <> inline StencilTableReal * +PatchTable::StencilTableHandler::Get() const { return _dPtr; } + +template <> inline bool +PatchTable::IsLocalPointStencilPrecision() const { + return !_vertexPrecisionIsDouble; +} +template <> inline bool +PatchTable::IsLocalPointVaryingStencilPrecision() const { + return !_varyingPrecisionIsDouble; +} +template <> inline bool +PatchTable::IsLocalPointFaceVaryingStencilPrecision() const { + return !_faceVaryingPrecisionIsDouble; +} + +template <> inline bool +PatchTable::IsLocalPointStencilPrecision() const { + return _vertexPrecisionIsDouble; +} +template <> inline bool +PatchTable::IsLocalPointVaryingStencilPrecision() const { + return _varyingPrecisionIsDouble; +} +template <> inline bool +PatchTable::IsLocalPointFaceVaryingStencilPrecision() const { + return _faceVaryingPrecisionIsDouble; +} + +// +// StencilTable access -- backward compatible and generic: +// +inline StencilTable const * +PatchTable::GetLocalPointStencilTable() const { + assert(!_vertexPrecisionIsDouble); + return static_cast(_localPointStencils.Get()); +} +inline StencilTable const * +PatchTable::GetLocalPointVaryingStencilTable() const { + assert(!_varyingPrecisionIsDouble); + return static_cast( + _localPointVaryingStencils.Get()); +} +inline StencilTable const * +PatchTable::GetLocalPointFaceVaryingStencilTable(int channel) const { + assert(!_faceVaryingPrecisionIsDouble); + if (channel >= 0 && channel < (int)_localPointFaceVaryingStencils.size()) { + return static_cast( + _localPointFaceVaryingStencils[channel].Get()); + } + return NULL; +} + +template +inline StencilTableReal const * +PatchTable::GetLocalPointStencilTable() const { + assert(IsLocalPointStencilPrecision()); + return _localPointStencils.Get(); +} +template +inline StencilTableReal const * +PatchTable::GetLocalPointVaryingStencilTable() const { + assert(IsLocalPointVaryingStencilPrecision()); + return _localPointVaryingStencils.Get(); +} +template +inline StencilTableReal const * +PatchTable::GetLocalPointFaceVaryingStencilTable(int channel) const { + assert(IsLocalPointFaceVaryingStencilPrecision()); + if (channel >= 0 && channel < (int)_localPointFaceVaryingStencils.size()) { + return _localPointFaceVaryingStencils[channel].Get(); + } + return NULL; +} + + +// +// Computation of local point values: +// template inline void PatchTable::ComputeLocalPointValues(T const *src, T *dst) const { - if (_localPointStencils) { - _localPointStencils->UpdateValues(src, dst); + if (_localPointStencils.IsSet()) { + if (_vertexPrecisionIsDouble) { + _localPointStencils.Get()->UpdateValues(src, dst); + } else { + _localPointStencils.Get()->UpdateValues(src, dst); + } } } template inline void PatchTable::ComputeLocalPointValuesVarying(T const *src, T *dst) const { - if (_localPointVaryingStencils) { - _localPointVaryingStencils->UpdateValues(src, dst); + if (_localPointVaryingStencils.IsSet()) { + if (_varyingPrecisionIsDouble) { + _localPointVaryingStencils.Get()->UpdateValues(src, dst); + } else { + _localPointVaryingStencils.Get()->UpdateValues(src, dst); + } } } @@ -629,12 +798,17 @@ template 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()->UpdateValues(src, dst); + } else { + _localPointFaceVaryingStencils[channel].Get()->UpdateValues(src, dst); + } } } } + // // Basis evaluation overloads // diff --git a/opensubdiv/far/patchTableFactory.cpp b/opensubdiv/far/patchTableFactory.cpp index f29c74d5..8f99ff64 100644 --- a/opensubdiv/far/patchTableFactory.cpp +++ b/opensubdiv/far/patchTableFactory.cpp @@ -112,6 +112,8 @@ public: PatchTable * GetPatchTable() const { return _table; }; private: + typedef PatchTable::StencilTableHandler StencilTableHandler; + // Simple struct to store 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 matrix; + SparseMatrix fMatrix; + SparseMatrix 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 int AppendLocalPatchPoints(int levelIndex, Index faceIndex, - SparseMatrix const & conversionMatrix, + SparseMatrix 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 const & conversionMatrix, + template + void appendLocalPointStencil(SparseMatrix const & conversionMatrix, int stencilRow, Index const sourcePoints[], int sourcePointOffset); - void appendLocalPointStencils(SparseMatrix const & conversionMatrix, + template + void appendLocalPointStencils(SparseMatrix const & conversionMatrix, Index const sourcePoints[], int sourcePointOffset); // Methods for local point Varying stencils // XXXX -- hope to get rid of these... + template 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 _sharedCornerPoints; std::vector _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 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 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(0)); + if (_options.createVaryingTable) { + _stencilTableVarying.Set(new StencilTableReal(0)); + } + } else { + _stencilTable.Set(new StencilTableReal(0)); + if (_options.createVaryingTable) { + _stencilTableVarying.Set(new StencilTableReal(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()->reserve( + (int)numStencilsExpected, (int)numEntriesToReserve); + } else { + _stencilTable.Get()->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()->reserve( + (int)numStencilsExpected, (int)numStencilsExpected); + } else { + _stencilTableVarying.Get()->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()->finalize(); + } else { + stencilTable.Get()->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 void PatchTableBuilder::LocalPointHelper::appendLocalPointStencil( - SparseMatrix const & conversionMatrix, + SparseMatrix const & conversionMatrix, int stencilRow, Index const sourcePoints[], int sourcePointOffset) { int stencilSize = conversionMatrix.GetRowSize(stencilRow); ConstArray matrixColumns = conversionMatrix.GetRowColumns(stencilRow); - ConstArray matrixWeights = conversionMatrix.GetRowElements(stencilRow); + ConstArray matrixWeights = conversionMatrix.GetRowElements(stencilRow); - _stencilTable->_sizes.push_back(stencilSize); + StencilTableReal* stencilTable = _stencilTable.Get(); + + 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 void PatchTableBuilder::LocalPointHelper::appendLocalPointStencils( - SparseMatrix const & conversionMatrix, + SparseMatrix 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* stencilTable = _stencilTable.Get(); + 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 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* t = _stencilTableVarying.Get(); + + t->_sizes.push_back(1); + t->_indices.push_back(varyingPoint); + t->_weights.push_back((REAL) 1.0); } namespace { @@ -1547,10 +1626,11 @@ namespace { } } +template int PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints( int levelIndex, Index faceIndex, - SparseMatrix const & matrix, + SparseMatrix 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( varyingIndices, i, sourcePoints, sourcePointOffset); } } @@ -1611,7 +1691,7 @@ PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints( appendLocalPointStencil( matrix, i, sourcePoints, sourcePointOffset); if (applyVaryingStencils) { - appendLocalPointVaryingStencil( + appendLocalPointVaryingStencil( varyingIndices, i, sourcePoints, sourcePointOffset); } } @@ -1682,7 +1762,7 @@ PatchTableBuilder::LocalPointHelper::AppendLocalPatchPoints( appendLocalPointStencil( matrix, i, sourcePoints, sourcePointOffset); if (applyVaryingStencils) { - appendLocalPointVaryingStencil( + appendLocalPointVaryingStencil( varyingIndices, i, sourcePoints, sourcePointOffset); } } diff --git a/opensubdiv/far/patchTableFactory.h b/opensubdiv/far/patchTableFactory.h index 6334acbe..f1687bba 100644 --- a/opensubdiv/far/patchTableFactory.h +++ b/opensubdiv/far/patchTableFactory.h @@ -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 void SetPatchPrecision(); + + /// \brief Set precision of face-varying patches + template 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 PatchTagVector; }; + +template <> inline void PatchTableFactory::Options::SetPatchPrecision() { + setPatchPrecisionDouble = false; +} +template <> inline void PatchTableFactory::Options::SetFVarPatchPrecision() { + setFVarPatchPrecisionDouble = false; +} + +template <> inline void PatchTableFactory::Options::SetPatchPrecision() { + setPatchPrecisionDouble = true; +} +template <> inline void PatchTableFactory::Options::SetFVarPatchPrecision() { + setFVarPatchPrecisionDouble = true; +} + + } // end namespace Far } // end namespace OPENSUBDIV_VERSION diff --git a/opensubdiv/far/primvarRefiner.h b/opensubdiv/far/primvarRefiner.h index c6b39b13..6fa82638 100644 --- a/opensubdiv/far/primvarRefiner.h +++ b/opensubdiv/far/primvarRefiner.h @@ -49,15 +49,15 @@ namespace OPENSUBDIV_VERSION { namespace Far { - /// /// \brief Applies refinement operations to generic primvar data. /// -class PrimvarRefiner { +template +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 void interpFromFaces(int, T const &, U &) const; template 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 template inline void -PrimvarRefiner::Interpolate(int level, T const & src, U & dst) const { +PrimvarRefinerReal::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 template inline void -PrimvarRefiner::InterpolateFaceVarying(int level, T const & src, U & dst, int channel) const { +PrimvarRefinerReal::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 template inline void -PrimvarRefiner::Limit(T const & src, U & dst) const { +PrimvarRefinerReal::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 template inline void -PrimvarRefiner::Limit(T const & src, U & dstPos, U1 & dstTan1, U2 & dstTan2) const { +PrimvarRefinerReal::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 template inline void -PrimvarRefiner::LimitFaceVarying(T const & src, U & dst, int channel) const { +PrimvarRefinerReal::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 template inline void -PrimvarRefiner::InterpolateFaceUniform(int level, T const & src, U & dst) const { +PrimvarRefinerReal::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 template inline void -PrimvarRefiner::InterpolateVarying(int level, T const & src, U & dst) const { +PrimvarRefinerReal::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 template inline void -PrimvarRefiner::interpFromFaces(int level, T const & src, U & dst) const { +PrimvarRefinerReal::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(_refiner._subdivOptions); - Vtr::internal::StackBuffer fVertWeights(parent.getMaxValence()); + Vtr::internal::StackBuffer 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 template inline void -PrimvarRefiner::interpFromEdges(int level, T const & src, U & dst) const { +PrimvarRefinerReal::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 eFaceWeights(parent.getMaxEdgeFaces()); + Weight eVertWeights[2]; + Vtr::internal::StackBuffer 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 template inline void -PrimvarRefiner::interpFromVerts(int level, T const & src, U & dst) const { +PrimvarRefinerReal::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 weightBuffer(2*parent.getMaxValence()); + Vtr::internal::StackBuffer 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 template inline void -PrimvarRefiner::interpFVarFromFaces(int level, T const & src, U & dst, int channel) const { +PrimvarRefinerReal::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 fValueWeights(parentLevel.getMaxValence()); + Vtr::internal::StackBuffer 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 template inline void -PrimvarRefiner::interpFVarFromEdges(int level, T const & src, U & dst, int channel) const { +PrimvarRefinerReal::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 eFaceWeights(parentLevel.getMaxEdgeFaces()); + Weight eVertWeights[2]; + Vtr::internal::StackBuffer eFaceWeights(parentLevel.getMaxEdgeFaces()); Mask eMask(eVertWeights, 0, eFaceWeights); @@ -833,9 +845,10 @@ PrimvarRefiner::interpFVarFromEdges(int level, T const & src, U & dst, int chann } } +template template inline void -PrimvarRefiner::interpFVarFromVerts(int level, T const & src, U & dst, int channel) const { +PrimvarRefinerReal::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 weightBuffer(2*parentLevel.getMaxValence()); + Vtr::internal::StackBuffer weightBuffer(2*parentLevel.getMaxValence()); Vtr::internal::StackBuffer 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 template inline void -PrimvarRefiner::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr) const { +PrimvarRefinerReal::limit(T const & src, U & dstPos, U1 * dstTan1Ptr, U2 * dstTan2Ptr) const { Sdc::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 indexBuffer(maxWeightsPerMask); - Vtr::internal::StackBuffer weightBuffer(numMasks * maxWeightsPerMask); + Vtr::internal::StackBuffer 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 template inline void -PrimvarRefiner::limitFVar(T const & src, U & dst, int channel) const { +PrimvarRefinerReal::limitFVar(T const & src, U & dst, int channel) const { Sdc::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 weightBuffer(maxWeightsPerMask); + Vtr::internal::StackBuffer weightBuffer(maxWeightsPerMask); Vtr::internal::StackBuffer 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 { +public: + PrimvarRefiner(TopologyRefiner const & refiner) + : PrimvarRefinerReal(refiner) { } +}; + } // end namespace Far } // end namespace OPENSUBDIV_VERSION diff --git a/opensubdiv/far/stencilBuilder.cpp b/opensubdiv/far/stencilBuilder.cpp index a0dea2fd..4d3f1e1f 100644 --- a/opensubdiv/far/stencilBuilder.cpp +++ b/opensubdiv/far/stencilBuilder.cpp @@ -37,25 +37,27 @@ namespace { #pragma warning disable 1572 #endif - inline bool isWeightZero(float w) { return (w == 0.0f); } + template + inline bool isWeightZero(REAL w) { return (w == (REAL)0.0); } #ifdef __INTEL_COMPILER #pragma warning (pop) #endif } +template 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 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 class WeightTable { public: WeightTable(int coarseVerts, @@ -198,20 +202,20 @@ public: public: Point1stDerivAccumulator(WeightTable* tbl) : _tbl(tbl) { } - void PushBack(Point1stDerivWeight weight) { + void PushBack(Point1stDerivWeight 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 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 Get(size_t index) { + return Point1stDerivWeight(_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 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 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 Get(size_t index) { + return Point2ndDerivWeight(_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 const& GetSources() const { return _sources; } - std::vector const& + std::vector const& GetWeights() const { return _weights; } - std::vector const& + std::vector const& GetDuWeights() const { return _duWeights; } - std::vector const& + std::vector const& GetDvWeights() const { return _dvWeights; } - std::vector const& + std::vector const& GetDuuWeights() const { return _duuWeights; } - std::vector const& + std::vector const& GetDuvWeights() const { return _duvWeights; } - std::vector const& + std::vector const& GetDvvWeights() const { return _dvvWeights; } void SetCoarseVertCount(int numVerts) { @@ -387,12 +391,12 @@ private: // The actual stencil data. std::vector _sources; - std::vector _weights; - std::vector _duWeights; - std::vector _dvWeights; - std::vector _duuWeights; - std::vector _duvWeights; - std::vector _dvvWeights; + std::vector _weights; + std::vector _duWeights; + std::vector _dvWeights; + std::vector _duuWeights; + std::vector _duvWeights; + std::vector _dvvWeights; // Index data used to recover stencil-to-vertex mapping. std::vector _indices; @@ -405,29 +409,33 @@ private: bool _compactWeights; }; -StencilBuilder::StencilBuilder(int coarseVertCount, +template +StencilBuilder::StencilBuilder(int coarseVertCount, bool genCtrlVertStencils, bool compactWeights) - : _weightTable(new WeightTable(coarseVertCount, + : _weightTable(new WeightTable(coarseVertCount, genCtrlVertStencils, compactWeights)) { } -StencilBuilder::~StencilBuilder() +template +StencilBuilder::~StencilBuilder() { delete _weightTable; } +template size_t -StencilBuilder::GetNumVerticesTotal() const +StencilBuilder::GetNumVerticesTotal() const { return _weightTable->GetWeights().size(); } +template int -StencilBuilder::GetNumVertsInStencil(size_t stencilIndex) const +StencilBuilder::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 void -StencilBuilder::SetCoarseVertCount(int numVerts) +StencilBuilder::SetCoarseVertCount(int numVerts) { _weightTable->SetCoarseVertCount(numVerts); } +template std::vector const& -StencilBuilder::GetStencilOffsets() const { +StencilBuilder::GetStencilOffsets() const { return _weightTable->GetOffsets(); } +template std::vector const& -StencilBuilder::GetStencilSizes() const { +StencilBuilder::GetStencilSizes() const { return _weightTable->GetSizes(); } +template std::vector const& -StencilBuilder::GetStencilSources() const { +StencilBuilder::GetStencilSources() const { return _weightTable->GetSources(); } -std::vector const& -StencilBuilder::GetStencilWeights() const { +template +std::vector const& +StencilBuilder::GetStencilWeights() const { return _weightTable->GetWeights(); } -std::vector const& -StencilBuilder::GetStencilDuWeights() const { +template +std::vector const& +StencilBuilder::GetStencilDuWeights() const { return _weightTable->GetDuWeights(); } -std::vector const& -StencilBuilder::GetStencilDvWeights() const { +template +std::vector const& +StencilBuilder::GetStencilDvWeights() const { return _weightTable->GetDvWeights(); } -std::vector const& -StencilBuilder::GetStencilDuuWeights() const { +template +std::vector const& +StencilBuilder::GetStencilDuuWeights() const { return _weightTable->GetDuuWeights(); } -std::vector const& -StencilBuilder::GetStencilDuvWeights() const { +template +std::vector const& +StencilBuilder::GetStencilDuvWeights() const { return _weightTable->GetDuvWeights(); } -std::vector const& -StencilBuilder::GetStencilDvvWeights() const { +template +std::vector const& +StencilBuilder::GetStencilDvvWeights() const { return _weightTable->GetDvvWeights(); } +template void -StencilBuilder::Index::AddWithWeight(Index const & src, float weight) +StencilBuilder::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 void -StencilBuilder::Index::AddWithWeight(Stencil const& src, float weight) +StencilBuilder::Index::AddWithWeight(StencilReal 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 void -StencilBuilder::Index::AddWithWeight(Stencil const& src, - float weight, float du, float dv) +StencilBuilder::Index::AddWithWeight(StencilReal 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 wgt = Point1stDerivWeight(weight, du, dv) * w; _owner->_weightTable->AddWithWeight(srcIndex, _index, wgt, _owner->_weightTable->GetPoint1stDerivAccumulator()); } } +template void -StencilBuilder::Index::AddWithWeight(Stencil const& src, - float weight, float du, float dv, float duu, float duv, float dvv) +StencilBuilder::Index::AddWithWeight(StencilReal 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 wgt = Point2ndDerivWeight(weight, du, dv, duu, duv, dvv) * w; _owner->_weightTable->AddWithWeight(srcIndex, _index, wgt, _owner->_weightTable->GetPoint2ndDerivAccumulator()); } } +template class StencilBuilder; +template class StencilBuilder; + } // end namespace internal } // end namespace Far } // end namespace OPENSUBDIV_VERSION } // end namespace OpenSubdiv - diff --git a/opensubdiv/far/stencilBuilder.h b/opensubdiv/far/stencilBuilder.h index 76fefe8a..11b310ed 100644 --- a/opensubdiv/far/stencilBuilder.h +++ b/opensubdiv/far/stencilBuilder.h @@ -36,8 +36,9 @@ namespace OPENSUBDIV_VERSION { namespace Far { namespace internal { -class WeightTable; +template class WeightTable; +template class StencilBuilder { public: StencilBuilder(int coarseVertCount, @@ -63,12 +64,12 @@ public: std::vector const& GetStencilSources() const; // The individual vertex weights, each weight is paired with one source. - std::vector const& GetStencilWeights() const; - std::vector const& GetStencilDuWeights() const; - std::vector const& GetStencilDvWeights() const; - std::vector const& GetStencilDuuWeights() const; - std::vector const& GetStencilDuvWeights() const; - std::vector const& GetStencilDvvWeights() const; + std::vector const& GetStencilWeights() const; + std::vector const& GetStencilDuWeights() const; + std::vector const& GetStencilDvWeights() const; + std::vector const& GetStencilDuuWeights() const; + std::vector const& GetStencilDuvWeights() const; + std::vector 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 const& src, REAL weight); // Add with first derivative. - void AddWithWeight(Stencil const& src, - float weight, float du, float dv); + void AddWithWeight(StencilReal 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 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* _weightTable; }; } // end namespace internal diff --git a/opensubdiv/far/stencilTable.cpp b/opensubdiv/far/stencilTable.cpp index 3d7bb481..9a911d75 100644 --- a/opensubdiv/far/stencilTable.cpp +++ b/opensubdiv/far/stencilTable.cpp @@ -32,28 +32,29 @@ namespace Far { namespace { + template void copyStencilData(int numControlVerts, bool includeCoarseVerts, size_t firstOffset, - std::vector const* offsets, - std::vector * _offsets, - std::vector const* sizes, - std::vector * _sizes, - std::vector const* sources, - std::vector * _sources, - std::vector const* weights, - std::vector * _weights, - std::vector const* duWeights=NULL, - std::vector * _duWeights=NULL, - std::vector const* dvWeights=NULL, - std::vector * _dvWeights=NULL, - std::vector const* duuWeights=NULL, - std::vector * _duuWeights=NULL, - std::vector const* duvWeights=NULL, - std::vector * _duvWeights=NULL, - std::vector const* dvvWeights=NULL, - std::vector * _dvvWeights=NULL) { + std::vector const* offsets, + std::vector * _offsets, + std::vector const* sizes, + std::vector * _sizes, + std::vector const* sources, + std::vector * _sources, + std::vector const* weights, + std::vector * _weights, + std::vector const* duWeights=NULL, + std::vector * _duWeights=NULL, + std::vector const* dvWeights=NULL, + std::vector * _dvWeights=NULL, + std::vector const* duuWeights=NULL, + std::vector * _duuWeights=NULL, + std::vector const* duvWeights=NULL, + std::vector * _duvWeights=NULL, + std::vector const* dvvWeights=NULL, + std::vector * _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 +StencilTableReal::StencilTableReal(int numControlVerts, std::vector const& offsets, std::vector const& sizes, std::vector const& sources, - std::vector const& weights, + std::vector const& weights, bool includeCoarseVerts, size_t firstOffset) : _numControlVertices(numControlVerts) { @@ -158,8 +160,9 @@ StencilTable::StencilTable(int numControlVerts, &weights, &_weights); } +template void -StencilTable::Clear() { +StencilTableReal::Clear() { _numControlVertices=0; _sizes.clear(); _offsets.clear(); @@ -167,26 +170,28 @@ StencilTable::Clear() { _weights.clear(); } -LimitStencilTable::LimitStencilTable(int numControlVerts, +template +LimitStencilTableReal::LimitStencilTableReal( + int numControlVerts, std::vector const& offsets, std::vector const& sizes, std::vector const& sources, - std::vector const& weights, - std::vector const& duWeights, - std::vector const& dvWeights, - std::vector const& duuWeights, - std::vector const& duvWeights, - std::vector const& dvvWeights, + std::vector const& weights, + std::vector const& duWeights, + std::vector const& dvWeights, + std::vector const& duuWeights, + std::vector const& duvWeights, + std::vector const& dvvWeights, bool includeCoarseVerts, size_t firstOffset) - : StencilTable(numControlVerts) { + : StencilTableReal(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 void -LimitStencilTable::Clear() { - StencilTable::Clear(); +LimitStencilTableReal::Clear() { + StencilTableReal::Clear(); _duWeights.clear(); _dvWeights.clear(); _duuWeights.clear(); @@ -205,11 +211,24 @@ LimitStencilTable::Clear() { } +// +// Explicit instantiation for float and double: +// +template class StencilReal; +template class StencilReal; + +template class LimitStencilReal; +template class LimitStencilReal; + +template class StencilTableReal; +template class StencilTableReal; + +template class LimitStencilTableReal; +template class LimitStencilTableReal; + } // end namespace Far } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv - - diff --git a/opensubdiv/far/stencilTable.h b/opensubdiv/far/stencilTable.h index cc4ee760..dbaf33af 100644 --- a/opensubdiv/far/stencilTable.h +++ b/opensubdiv/far/stencilTable.h @@ -39,16 +39,22 @@ namespace OPENSUBDIV_VERSION { namespace Far { +// Forward declarations for friends: +class PatchTableBuilder; + +template class StencilTableFactoryReal; +template class LimitStencilTableFactoryReal; + /// \brief Vertex stencil descriptor /// /// Allows access and manipulation of a single stencil in a StencilTable. /// -class Stencil { - +template +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; + friend class LimitStencilTableFactoryReal; int * _size; - Index * _indices; - float * _weights; + Index * _indices; + REAL * _weights; }; +/// \brief Vertex stencil class wrapping the template for compatibility. +/// +class Stencil : public StencilReal { +protected: + typedef StencilReal 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 +class StencilTableReal { +protected: + StencilTableReal(int numControlVerts, std::vector const& offsets, std::vector const& sizes, std::vector const& sources, - std::vector const& weights, + std::vector 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 GetStencil(Index i) const; /// \brief Returns the number of control vertices of each stencil in the table std::vector const & GetSizes() const { @@ -164,12 +181,12 @@ public: } /// \brief Returns the stencil interpolation weights - std::vector const & GetWeights() const { + std::vector const & GetWeights() const { return _weights; } /// \brief Returns the stencil at index i in the table - Stencil operator[] (Index index) const; + StencilReal operator[] (Index index) const; /// \brief Updates point values based on the control values /// @@ -187,7 +204,7 @@ public: /// template 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 void update( T const *controlValues, T *values, - std::vector const & valueWeights, Index start, Index end) const; + template + void update( T const *controlValues, T *values, + std::vector 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; + friend class Far::PatchTableBuilder; int _numControlVertices; // number of control vertices std::vector _sizes; // number of coefficients for each stencil std::vector _offsets, // offset to the start of each stencil _indices; // indices of contributing coarse vertices - std::vector _weights; // stencil weight coefficients + std::vector _weights; // stencil weight coefficients +}; + +/// \brief Stencil table class wrapping the template for compatibility. +/// +class StencilTable : public StencilTableReal { +protected: + typedef StencilTableReal 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 const& offsets, + std::vector const& sizes, + std::vector const& sources, + std::vector 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 +class LimitStencilReal : public StencilReal { 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(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; + friend class LimitStencilTableFactoryReal; - 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 { +protected: + typedef LimitStencilReal 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 +class LimitStencilTableReal : public StencilTableReal { +protected: + LimitStencilTableReal( + int numControlVerts, std::vector const& offsets, std::vector const& sizes, std::vector const& sources, - std::vector const& weights, - std::vector const& duWeights, - std::vector const& dvWeights, - std::vector const& duuWeights, - std::vector const& duvWeights, - std::vector const& dvvWeights, + std::vector const& weights, + std::vector const& duWeights, + std::vector const& dvWeights, + std::vector const& duuWeights, + std::vector const& duvWeights, + std::vector const& dvvWeights, bool includeCoarseVerts, size_t firstOffset); public: /// \brief Returns a LimitStencil at index i in the table - LimitStencil GetLimitStencil(Index i) const; + LimitStencilReal GetLimitStencil(Index i) const; /// \brief Returns the limit stencil at index i in the table - LimitStencil operator[] (Index index) const; + LimitStencilReal operator[] (Index index) const; /// \brief Returns the 'u' derivative stencil interpolation weights - std::vector const & GetDuWeights() const { + std::vector const & GetDuWeights() const { return _duWeights; } /// \brief Returns the 'v' derivative stencil interpolation weights - std::vector const & GetDvWeights() const { + std::vector const & GetDvWeights() const { return _dvWeights; } /// \brief Returns the 'uu' derivative stencil interpolation weights - std::vector const & GetDuuWeights() const { + std::vector const & GetDuuWeights() const { return _duuWeights; } /// \brief Returns the 'uv' derivative stencil interpolation weights - std::vector const & GetDuvWeights() const { + std::vector const & GetDuvWeights() const { return _duvWeights; } /// \brief Returns the 'vv' derivative stencil interpolation weights - std::vector const & GetDvvWeights() const { + std::vector 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; // Resize the table arrays (factory helper) void resize(int nstencils, int nelems); private: - std::vector _duWeights, // u derivative limit stencil weights + std::vector _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 { +protected: + typedef LimitStencilTableReal 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 const& offsets, + std::vector const& sizes, + std::vector const& sources, + std::vector const& weights, + std::vector const& duWeights, + std::vector const& dvWeights, + std::vector const& duuWeights, + std::vector const& duvWeights, + std::vector 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 template void -StencilTable::update(T const *controlValues, T *values, - std::vector const &valueWeights, Index start, Index end) const { +StencilTableReal::update(T const *controlValues, T *values, + std::vector 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 inline void -StencilTable::generateOffsets() { +StencilTableReal::generateOffsets() { Index offset=0; int noffsets = (int)_sizes.size(); _offsets.resize(noffsets); @@ -489,93 +588,104 @@ StencilTable::generateOffsets() { } } +template inline void -StencilTable::resize(int nstencils, int nelems) { +StencilTableReal::resize(int nstencils, int nelems) { _sizes.resize(nstencils); _indices.resize(nelems); _weights.resize(nelems); } +template inline void -StencilTable::reserve(int nstencils, int nelems) { +StencilTableReal::reserve(int nstencils, int nelems) { _sizes.reserve(nstencils); _indices.reserve(nelems); _weights.reserve(nelems); } +template inline void -StencilTable::shrinkToFit() { +StencilTableReal::shrinkToFit() { std::vector(_sizes).swap(_sizes); std::vector(_indices).swap(_indices); - std::vector(_weights).swap(_weights); + std::vector(_weights).swap(_weights); } +template inline void -StencilTable::finalize() { +StencilTableReal::finalize() { shrinkToFit(); generateOffsets(); } // Returns a Stencil at index i in the table -inline Stencil -StencilTable::GetStencil(Index i) const { +template +inline StencilReal +StencilTableReal::GetStencil(Index i) const { assert((! _offsets.empty()) && i<(int)_offsets.size()); Index ofs = _offsets[i]; - return Stencil( const_cast(&_sizes[i]), - const_cast(&_indices[ofs]), - const_cast(&_weights[ofs]) ); + return StencilReal(const_cast(&_sizes[i]), + const_cast(&_indices[ofs]), + const_cast(&_weights[ofs])); } -inline Stencil -StencilTable::operator[] (Index index) const { +template +inline StencilReal +StencilTableReal::operator[] (Index index) const { return GetStencil(index); } +template inline void -LimitStencilTable::resize(int nstencils, int nelems) { - StencilTable::resize(nstencils, nelems); +LimitStencilTableReal::resize(int nstencils, int nelems) { + StencilTableReal::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 +inline LimitStencilReal +LimitStencilTableReal::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(&GetSizes()[i]), - const_cast(&GetControlIndices()[ofs]), - const_cast(&GetWeights()[ofs]), - const_cast(&GetDuWeights()[ofs]), - const_cast(&GetDvWeights()[ofs]), - const_cast(&GetDuuWeights()[ofs]), - const_cast(&GetDuvWeights()[ofs]), - const_cast(&GetDvvWeights()[ofs]) ); + return LimitStencilReal( + const_cast(&this->GetSizes()[i]), + const_cast(&this->GetControlIndices()[ofs]), + const_cast(&this->GetWeights()[ofs]), + const_cast(&GetDuWeights()[ofs]), + const_cast(&GetDvWeights()[ofs]), + const_cast(&GetDuuWeights()[ofs]), + const_cast(&GetDuvWeights()[ofs]), + const_cast(&GetDvvWeights()[ofs]) ); } else if (!_duWeights.empty() && !_dvWeights.empty()) { - return LimitStencil( const_cast(&GetSizes()[i]), - const_cast(&GetControlIndices()[ofs]), - const_cast(&GetWeights()[ofs]), - const_cast(&GetDuWeights()[ofs]), - const_cast(&GetDvWeights()[ofs]) ); + return LimitStencilReal( + const_cast(&this->GetSizes()[i]), + const_cast(&this->GetControlIndices()[ofs]), + const_cast(&this->GetWeights()[ofs]), + const_cast(&GetDuWeights()[ofs]), + const_cast(&GetDvWeights()[ofs]) ); } else { - return LimitStencil( const_cast(&GetSizes()[i]), - const_cast(&GetControlIndices()[ofs]), - const_cast(&GetWeights()[ofs]) ); + return LimitStencilReal( + const_cast(&this->GetSizes()[i]), + const_cast(&this->GetControlIndices()[ofs]), + const_cast(&this->GetWeights()[ofs]) ); } } -inline LimitStencil -LimitStencilTable::operator[] (Index index) const { +template +inline LimitStencilReal +LimitStencilTableReal::operator[] (Index index) const { return GetLimitStencil(index); } - } // end namespace Far } // end namespace OPENSUBDIV_VERSION diff --git a/opensubdiv/far/stencilTableFactory.cpp b/opensubdiv/far/stencilTableFactory.cpp index 7082be6c..8bd9e4e8 100644 --- a/opensubdiv/far/stencilTableFactory.cpp +++ b/opensubdiv/far/stencilTableFactory.cpp @@ -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 + inline bool isWeightZero(REAL w) { return (w == (REAL) 0.0); } #ifdef __INTEL_COMPILER #pragma warning (pop) @@ -54,15 +57,17 @@ namespace { //------------------------------------------------------------------------------ +template void -StencilTableFactory::generateControlVertStencils( - int numControlVerts, Stencil & dst) { +StencilTableFactoryReal::generateControlVertStencils( + int numControlVerts, + StencilReal & dst) { // Control vertices contribute a single index with a weight of 1.0 for (int i=0; i +StencilTableReal const * +StencilTableFactoryReal::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 * result = new StencilTableReal; result->_numControlVertices = numControlVertices; return result; } - internal::StencilBuilder builder(numControlVertices, + StencilBuilder 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::Index srcIndex(&builder, 0); + typename StencilBuilder::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 * result = + new StencilTableReal(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 +StencilTableReal const * +StencilTableFactoryReal::Create(int numTables, + StencilTableReal 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 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 * result = new StencilTableReal; 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 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 +StencilTableReal const * +StencilTableFactoryReal::AppendLocalPointStencilTable( TopologyRefiner const &refiner, - StencilTable const * baseStencilTable, - StencilTable const * localPointStencilTable, + StencilTableReal const * baseStencilTable, + StencilTableReal const * localPointStencilTable, bool factorize) { return appendLocalPointStencilTable( @@ -228,11 +237,12 @@ StencilTableFactory::AppendLocalPointStencilTable( factorize); } -StencilTable const * -StencilTableFactory::AppendLocalPointStencilTableFaceVarying( +template +StencilTableReal const * +StencilTableFactoryReal::AppendLocalPointStencilTableFaceVarying( TopologyRefiner const &refiner, - StencilTable const * baseStencilTable, - StencilTable const * localPointStencilTable, + StencilTableReal const * baseStencilTable, + StencilTableReal const * localPointStencilTable, int channel, bool factorize) { @@ -244,11 +254,12 @@ StencilTableFactory::AppendLocalPointStencilTableFaceVarying( factorize); } -StencilTable const * -StencilTableFactory::appendLocalPointStencilTable( +template +StencilTableReal const * +StencilTableFactoryReal::appendLocalPointStencilTable( TopologyRefiner const &refiner, - StencilTable const * baseStencilTable, - StencilTable const * localPointStencilTable, + StencilTableReal const * baseStencilTable, + StencilTableReal const * localPointStencilTable, int channel, bool factorize) { @@ -317,20 +328,20 @@ StencilTableFactory::appendLocalPointStencilTable( int nLocalPointStencils = localPointStencilTable->GetNumStencils(); int nLocalPointStencilsElements = 0; - internal::StencilBuilder builder(nControlVerts, + StencilBuilder builder(nControlVerts, /*genControlVerts*/ false, /*compactWeights*/ factorize); - internal::StencilBuilder::Index origin(&builder, 0); - internal::StencilBuilder::Index dst = origin; - internal::StencilBuilder::Index srcIdx = origin; + typename StencilBuilder::Index origin(&builder, 0); + typename StencilBuilder::Index dst = origin; + typename StencilBuilder::Index srcIdx = origin; for (int i = 0 ; i < nLocalPointStencils; ++i) { - Stencil src = localPointStencilTable->GetStencil(i); + StencilReal 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(weight)) continue; if (factorize) { dst.AddWithWeight( @@ -349,14 +360,14 @@ StencilTableFactory::appendLocalPointStencilTable( } // create new stencil table - StencilTable * result = new StencilTable; + StencilTableReal * result = new StencilTableReal; 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 +LimitStencilTableReal const * +LimitStencilTableFactoryReal::Create(TopologyRefiner const & refiner, LocationArrayVec const & locationArrays, - StencilTable const * cvStencilsIn, - PatchTable const * patchTableIn, - Options options) { + StencilTableReal 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 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::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::Create(refiner, stencilTableOptions); } else { // Sanity checks // @@ -447,6 +459,7 @@ LimitStencilTableFactory::Create(TopologyRefiner const & refiner, // patch table. PatchTableFactory::Options patchTableOptions; + patchTableOptions.SetPatchPrecision(); 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 const *localPointStencilTable = + patchtable->GetLocalPointStencilTable()) { + StencilTableReal const *table = + StencilTableFactoryReal::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 builder(refiner.GetLevel(0).GetNumVertices(), /*genControlVerts*/ false, /*compactWeights*/ true); - internal::StencilBuilder::Index origin(&builder, 0); - internal::StencilBuilder::Index dst = origin; + typename StencilBuilder::Index origin(&builder, 0); + typename StencilBuilder::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=0); for (int j=0; jGetPatchVertices(*handle); - StencilTable const & src = *cvstencils; + StencilTableReal 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 * result = new LimitStencilTableReal( 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; +template class StencilTableFactoryReal; + +template class LimitStencilTableFactoryReal; +template class LimitStencilTableFactoryReal; + + } // end namespace Far } // end namespace OPENSUBDIV_VERSION diff --git a/opensubdiv/far/stencilTableFactory.h b/opensubdiv/far/stencilTableFactory.h index 4400a05c..845b01a3 100644 --- a/opensubdiv/far/stencilTableFactory.h +++ b/opensubdiv/far/stencilTableFactory.h @@ -38,14 +38,17 @@ namespace Far { class TopologyRefiner; -class Stencil; -class StencilTable; -class LimitStencil; -class LimitStencilTable; +template class StencilReal; +template class StencilTableReal; + +template class LimitStencilReal; +template class LimitStencilTableReal; + /// \brief A specialized factory for StencilTable /// -class StencilTableFactory { +template +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 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 const * Create( + int numTables, StencilTableReal 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 const * AppendLocalPointStencilTable( + TopologyRefiner const &refiner, + StencilTableReal const *baseStencilTable, + StencilTableReal 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 const * AppendLocalPointStencilTableFaceVarying( + TopologyRefiner const &refiner, + StencilTableReal const *baseStencilTable, + StencilTableReal 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 & 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 const * appendLocalPointStencilTable( + TopologyRefiner const &refiner, + StencilTableReal const * baseStencilTable, + StencilTableReal 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 +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 const * Create( + TopologyRefiner const & refiner, + LocationArrayVec const & locationArrays, + StencilTableReal 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 { +private: + typedef StencilTableFactoryReal BaseFactory; + typedef StencilTableReal BaseTable; + +public: + static StencilTable const * Create( + TopologyRefiner const & refiner, Options options = Options()) { + + return static_cast( + BaseFactory::Create(refiner, options)); + } + + static StencilTable const * Create( + int numTables, StencilTable const ** tables) { + + return static_cast( + BaseFactory::Create(numTables, + reinterpret_cast(tables))); + } + + static StencilTable const * AppendLocalPointStencilTable( + TopologyRefiner const &refiner, + StencilTable const *baseStencilTable, + StencilTable const *localPointStencilTable, + bool factorize = true) { + + return static_cast( + BaseFactory::AppendLocalPointStencilTable(refiner, + static_cast(baseStencilTable), + static_cast(localPointStencilTable), + factorize)); + } + + static StencilTable const * AppendLocalPointStencilTableFaceVarying( + TopologyRefiner const &refiner, + StencilTable const *baseStencilTable, + StencilTable const *localPointStencilTable, + int channel = 0, + bool factorize = true) { + + return static_cast( + BaseFactory::AppendLocalPointStencilTableFaceVarying(refiner, + static_cast(baseStencilTable), + static_cast(localPointStencilTable), + channel, factorize)); + } +}; + +class LimitStencil; +class LimitStencilTable; + +/// \brief Stencil table factory class wrapping the template for compatibility. +/// +class LimitStencilTableFactory : public LimitStencilTableFactoryReal { +private: + typedef LimitStencilTableFactoryReal BaseFactory; + typedef LimitStencilTableReal 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( + BaseFactory::Create( + refiner, + locationArrays, + static_cast(cvStencils), + patchTable, + options)); + } +}; + } // end namespace Far } // end namespace OPENSUBDIV_VERSION diff --git a/opensubdiv/far/topologyRefiner.h b/opensubdiv/far/topologyRefiner.h index c1042aa8..15e3324b 100644 --- a/opensubdiv/far/topologyRefiner.h +++ b/opensubdiv/far/topologyRefiner.h @@ -42,6 +42,7 @@ namespace Far { namespace internal { class FeatureMask; } } namespace Far { +template class PrimvarRefinerReal; template class TopologyRefinerFactory; /// @@ -212,7 +213,8 @@ protected: friend class PatchTableBuilder; friend class PatchBuilder; friend class PtexIndices; - friend class PrimvarRefiner; + template + friend class PrimvarRefinerReal; Vtr::internal::Level & getLevel(int l) { return *_levels[l]; } Vtr::internal::Level const & getLevel(int l) const { return *_levels[l]; }