diff --git a/opensubdiv/far/patchTables.h b/opensubdiv/far/patchTables.h index 31eb8d46..193752fc 100644 --- a/opensubdiv/far/patchTables.h +++ b/opensubdiv/far/patchTables.h @@ -208,15 +208,16 @@ public: typedef std::vector FVarDataTable; enum Type { - NON_PATCH = 0, // undefined - - QUADS, // quads-only mesh - TRIANGLES, // triangles-only mesh - POLYGONS, // general polygon mesh + NON_PATCH = 0, // undefined - LOOP, // Loop patch (unsupported) + POLYGONS, // general polygon mesh + + QUADS, // bilinear quads-only patches + TRIANGLES, // bilinear triangles-only mesh + + LOOP, // Loop patch (unsupported) - REGULAR, + REGULAR, // feature-adaptive bicubic patches BOUNDARY, CORNER, GREGORY, @@ -233,6 +234,23 @@ public: }; /// \brief Describes the type of a patch + /// + /// Uniquely identifies all the types of patches in a mesh : + /// + /// * Raw polygon meshes are identified as POLYGONS and can contain faces + /// with arbitrary number of vertices + /// + /// * Uniformly subdivided meshes contain bilinear patches of either QUADS + /// or TRIANGLES + /// + /// * Adaptively subdivided meshes contain bicubic patches of types REGULAR, + /// BOUNDARY, CORNER, GREGORY, GREGORY_BOUNDARY. These bicubic patches are + /// also further distinguished by a transition pattern as well as a rotational + /// orientation. + /// + /// An iterator class is provided as a convenience to enumerate over the set + /// of valid feature adaptive patch descriptors. + /// class Descriptor { public: @@ -263,9 +281,12 @@ public: return _rotation; } - /// Returns the number of control vertices expected for a patch of this type + /// Returns the number of control vertices expected for a patch of the + /// type described static short GetNumControlVertices( Type t ); + /// Returns the number of control vertices expected for a patch of the + /// type described short GetNumControlVertices() const { return GetNumControlVertices( this->GetType() ); } @@ -300,10 +321,12 @@ public: /// Descriptor Iterator class iterator; + /// Returns an iterator to the first type of patch (REGULAR NON_TRANSITION ROT0) static iterator begin() { return iterator( Descriptor(REGULAR, NON_TRANSITION, 0) ); } + /// Returns an iterator to the end of the list of patch types (NON_PATCH) static iterator end() { return iterator( Descriptor() ); } @@ -320,18 +343,25 @@ public: /// \brief Descriptor iterator class class Descriptor::iterator { public: + /// Constructor iterator() {} + /// Copy Constructor iterator(Descriptor desc) : pos(desc) { } + /// Iteration increment operator iterator & operator ++ () { ++pos; return *this; } + /// True of the two descriptors are identical bool operator == ( iterator const & other ) { return (pos==other.pos); } + /// True if the two descriptors are different bool operator != ( iterator const & other ) { return not (*this==other); } + /// Dereferencing operator Descriptor * operator -> () { return &pos; } + /// Dereferencing operator Descriptor & operator * () { return pos; } private: @@ -342,21 +372,24 @@ public: class PatchArray { public: - PatchArray( Descriptor const & desc, unsigned int vertIndex, unsigned int patchIndex, unsigned int npatches ) : - _desc(desc), _vertIndex(vertIndex), _patchIndex(patchIndex), _npatches(npatches) { } - + /// Returns a patch descriptor defining the type of patches in the array Descriptor GetDescriptor() const { return _desc; } + /// Returns the index of the first control vertex of the first patch + /// of this array in the global PTable unsigned int GetVertIndex() const { return _vertIndex; } + /// Returns the global index of the first patch in this array (Used to + /// access ptex / fvar table data) unsigned int GetPatchIndex() const { return _patchIndex; } + /// Returns the number of patches in the array unsigned int GetNumPatches() const { return _npatches; } @@ -364,7 +397,12 @@ public: private: template friend class FarPatchTablesFactory; - Descriptor _desc; + // Constructor. + PatchArray( Descriptor const & desc, unsigned int vertIndex, unsigned int patchIndex, unsigned int npatches ) : + _desc(desc), _vertIndex(vertIndex), _patchIndex(patchIndex), _npatches(npatches) { } + + Descriptor _desc; // type of patches in the array + unsigned int _vertIndex, // absolute index to the first control vertex of the first patch in the PTable _patchIndex, // absolute index of the first patch in the array _npatches; // number of patches in the array @@ -376,7 +414,7 @@ public: PTable const & GetPatchTable() const { return _patches; } /// Returns a pointer to the array of patches matching the descriptor - PatchArray * GetPatchArray( Descriptor desc ) const { + PatchArray const * GetPatchArray( Descriptor desc ) const { return const_cast(this)->findPatchArray( desc ); } @@ -417,6 +455,7 @@ private: template friend class FarPatchTablesFactory; template friend class FarMultiMeshFactory; + // Returns the array of patches of type "desc", or NULL if there aren't any in the primitive PatchArray * findPatchArray( Descriptor desc ); // Private constructor @@ -425,17 +464,16 @@ private: // Vector of descriptors for arrays of patches PatchArrayVector _patchArrays; - - PTable _patches; // Indices of the control vertices of the patches + PTable _patches; // Indices of the control vertices of the patches - VertexValenceTable _vertexValenceTable; // vertex valence table (for Gregory patches) + VertexValenceTable _vertexValenceTable; // vertex valence table (for Gregory patches) - QuadOffsetTable _quadOffsetTable; // quad offsets table (for Gregory patches) + QuadOffsetTable _quadOffsetTable; // quad offsets table (for Gregory patches) PtexCoordinateTable _ptexTable; - FVarDataTable _fvarTable; + FVarDataTable _fvarTable; // highest vertex valence allowed in the mesh (used for Gregory // vertexValance & quadOffset talbes) diff --git a/opensubdiv/far/patchTablesFactory.h b/opensubdiv/far/patchTablesFactory.h index a0cccee1..03b13215 100644 --- a/opensubdiv/far/patchTablesFactory.h +++ b/opensubdiv/far/patchTablesFactory.h @@ -125,8 +125,10 @@ private: // Number of faces in the Hbr mesh (cached for speed) int getNumFaces() const { return _nfaces; } + // The number of patch arrays in the mesh int getNumPatchArrays() const; + // A convenience container for the different types of feature adaptive patches template struct PatchTypes { TYPE R, // regular patch B[4], // boundary patch (4 rotations) @@ -136,39 +138,21 @@ private: PatchTypes() { memset(this, 0, sizeof(PatchTypes)); } // Returns the number of patches based on the patch type in the descriptor - TYPE & GetValue( FarPatchTables::Descriptor desc ) { - switch (desc.GetType()) { - case FarPatchTables::REGULAR : return R; - case FarPatchTables::BOUNDARY : return B[desc.GetRotation()]; - case FarPatchTables::CORNER : return C[desc.GetRotation()]; - case FarPatchTables::GREGORY : return G[0]; - case FarPatchTables::GREGORY_BOUNDARY : return G[1]; - default : assert(0); - } - } + TYPE & getValue( FarPatchTables::Descriptor desc ); // Counts the number of arrays required to store each type of patch used // in the primitive - int GetNumPatchArrays() const { - - int result=0; - - if (R) ++result; - for (int i=0; i<4; ++i) { - if (B[i]) ++result; - if (C[i]) ++result; - if ((i<2) and G[i]) ++result; - } - return result; - } + int getNumPatchArrays() const; }; - // Prepare some pointers - typedef PatchTypes IndexPointers; + // Useful typedefs + typedef PatchTypes CVPointers; typedef PatchTypes PtexPointers; typedef PatchTypes FVarPointers; typedef PatchTypes Counter; + // Creates a PatchArray and appends it to a vector and keeps track of both + // vertex and patch offsets void pushPatchArray( FarPatchTables::Descriptor desc, FarPatchTables::PatchArrayVector & parray, Counter & counter, @@ -497,13 +481,41 @@ FarPatchTablesFactory::FarPatchTablesFactory( HbrMesh const * mesh, int nf } } +template + template TYPE & +FarPatchTablesFactory::PatchTypes::getValue( FarPatchTables::Descriptor desc ) { + switch (desc.GetType()) { + case FarPatchTables::REGULAR : return R; + case FarPatchTables::BOUNDARY : return B[desc.GetRotation()]; + case FarPatchTables::CORNER : return C[desc.GetRotation()]; + case FarPatchTables::GREGORY : return G[0]; + case FarPatchTables::GREGORY_BOUNDARY : return G[1]; + default : assert(0); + } +} + +template + template int +FarPatchTablesFactory::PatchTypes::getNumPatchArrays() const { + + int result=0; + + if (R) ++result; + for (int i=0; i<4; ++i) { + if (B[i]) ++result; + if (C[i]) ++result; + if ((i<2) and G[i]) ++result; + } + return result; +} + template int FarPatchTablesFactory::getNumPatchArrays() const { - int result = _fullCtr.GetNumPatchArrays(); + int result = _fullCtr.getNumPatchArrays(); for (int i=0; i<5; ++i) - result += _transitionCtr[i].GetNumPatchArrays(); + result += _transitionCtr[i].getNumPatchArrays(); return result; } @@ -514,7 +526,7 @@ FarPatchTablesFactory::pushPatchArray( FarPatchTables::Descriptor desc, FarPatchTablesFactory::Counter & counter, int * voffset, int * poffset ) { - int npatches = counter.GetValue( desc ); + int npatches = counter.getValue( desc ); if (npatches>0) { parray.push_back( FarPatchTables::PatchArray(desc, *voffset, *poffset, npatches) ); @@ -555,7 +567,7 @@ FarPatchTablesFactory::Create( int maxlevel, int maxvalence, bool requirePtex fvarwidth = getMesh()->GetTotalFVarWidth(); // Reserve memory for the tables - result->_patches.reserve( nverts ); + result->_patches.resize( nverts ); if (requirePtexCoordinate) { result->_ptexTable.resize( npatches ); @@ -574,7 +586,7 @@ FarPatchTablesFactory::Create( int maxlevel, int maxvalence, bool requirePtex FarPatchTables::QuadOffsetTable::value_type *quad_G_C0_P = quad_G_C0.empty() ? 0 : &quad_G_C0[0]; FarPatchTables::QuadOffsetTable::value_type *quad_G_C1_P = quad_G_C1.empty() ? 0 : &quad_G_C1[0]; - IndexPointers iptrs[6]; + CVPointers iptrs[6]; PtexPointers pptrs[6]; FVarPointers fptrs[6]; @@ -585,9 +597,9 @@ FarPatchTablesFactory::Create( int maxlevel, int maxvalence, bool requirePtex if (not pa) continue; - iptrs[(int)pa->GetDescriptor().GetPattern()].GetValue( *it ) = &result->_patches[pa->GetVertIndex()]; - pptrs[(int)pa->GetDescriptor().GetPattern()].GetValue( *it ) = &result->_ptexTable[pa->GetPatchIndex()]; - fptrs[(int)pa->GetDescriptor().GetPattern()].GetValue( *it ) = &result->_fvarTable[pa->GetPatchIndex() * 4 * fvarwidth]; + iptrs[(int)pa->GetDescriptor().GetPattern()].getValue( *it ) = &result->_patches[pa->GetVertIndex()]; + pptrs[(int)pa->GetDescriptor().GetPattern()].getValue( *it ) = &result->_ptexTable[pa->GetPatchIndex()]; + fptrs[(int)pa->GetDescriptor().GetPattern()].getValue( *it ) = &result->_fvarTable[pa->GetPatchIndex() * 4 * fvarwidth]; } // Populate patch index tables with vertex indices