// // Copyright (C) Pixar. All rights reserved. // // This license governs use of the accompanying software. If you // use the software, you accept this license. If you do not accept // the license, do not use the software. // // 1. Definitions // The terms "reproduce," "reproduction," "derivative works," and // "distribution" have the same meaning here as under U.S. // copyright law. A "contribution" is the original software, or // any additions or changes to the software. // A "contributor" is any person or entity that distributes its // contribution under this license. // "Licensed patents" are a contributor's patent claims that read // directly on its contribution. // // 2. Grant of Rights // (A) Copyright Grant- Subject to the terms of this license, // including the license conditions and limitations in section 3, // each contributor grants you a non-exclusive, worldwide, // royalty-free copyright license to reproduce its contribution, // prepare derivative works of its contribution, and distribute // its contribution or any derivative works that you create. // (B) Patent Grant- Subject to the terms of this license, // including the license conditions and limitations in section 3, // each contributor grants you a non-exclusive, worldwide, // royalty-free license under its licensed patents to make, have // made, use, sell, offer for sale, import, and/or otherwise // dispose of its contribution in the software or derivative works // of the contribution in the software. // // 3. Conditions and Limitations // (A) No Trademark License- This license does not grant you // rights to use any contributor's name, logo, or trademarks. // (B) If you bring a patent claim against any contributor over // patents that you claim are infringed by the software, your // patent license from such contributor to the software ends // automatically. // (C) If you distribute any portion of the software, you must // retain all copyright, patent, trademark, and attribution // notices that are present in the software. // (D) If you distribute any portion of the software in source // code form, you may do so only under this license by including a // complete copy of this license with your distribution. If you // distribute any portion of the software in compiled or object // code form, you may only do so under a license that complies // with this license. // (E) The software is licensed "as-is." You bear the risk of // using it. The contributors give no express warranties, // guarantees or conditions. You may have additional consumer // rights under your local laws which this license cannot change. // To the extent permitted under your local laws, the contributors // exclude the implied warranties of merchantability, fitness for // a particular purpose and non-infringement. // #ifndef FAR_PATCH_TABLES_H #define FAR_PATCH_TABLES_H #include "../version.h" #include "../far/patchParam.h" #include #include #include #include #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { /// \brief Container for patch vertex indices tables /// /// FarPatchTables contain the lists of vertices for each patch of an adaptive /// mesh representation. /// class FarPatchTables { public: typedef std::vector PTable; typedef std::vector VertexValenceTable; typedef std::vector QuadOffsetTable; typedef std::vector PatchParamTable; typedef std::vector FVarDataTable; enum Type { NON_PATCH = 0, ///< undefined POINTS, ///< points (useful for cage drawing) LINES, ///< lines (useful for cage drawing) QUADS, ///< bilinear quads-only patches TRIANGLES, ///< bilinear triangles-only mesh LOOP, ///< Loop patch (unsupported) REGULAR, ///< feature-adaptive bicubic patches BOUNDARY, CORNER, GREGORY, GREGORY_BOUNDARY }; enum TransitionPattern { NON_TRANSITION = 0, PATTERN0, PATTERN1, PATTERN2, PATTERN3, PATTERN4, }; /// \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: /// \brief Default constructor. Descriptor() : _type(NON_PATCH), _pattern(NON_TRANSITION), _rotation(0) {} /// \brief Constructor Descriptor(int type, int pattern, unsigned char rotation) : _type(type), _pattern(pattern), _rotation(rotation) { } /// \brief Copy Constructor Descriptor( Descriptor const & d ) : _type(d.GetType()), _pattern(d.GetPattern()), _rotation(d.GetRotation()) { } /// \brief Returns the type of the patch Type GetType() const { return (Type)_type; } /// \brief Returns the transition pattern of the patch if any (5 types) TransitionPattern GetPattern() const { return (TransitionPattern)_pattern; } /// \brief Returns the rotation of the patch (4 rotations) unsigned char GetRotation() const { return _rotation; } /// \brief Returns the number of control vertices expected for a patch of the /// type described static short GetNumControlVertices( Type t ); /// \brief Returns the number of control vertices expected for a patch of the /// type described short GetNumControlVertices() const { return GetNumControlVertices( this->GetType() ); } /// \brief Iterates through the patches in the following preset order /// /// Order: /// /// NON_TRANSITION ( REGULAR /// BOUNDARY /// CORNER /// GREGORY /// GREGORY_BOUNDARY ) /// /// PATTERN0 ( REGULAR /// BOUNDARY ROT0 ROT1 ROT2 ROT3 /// CORNER ROT0 ROT1 ROT2 ROT3 ) /// /// PATTERN1 ( REGULAR /// BOUNDARY ROT0 ROT1 ROT2 ROT3 /// CORNER ROT0 ROT1 ROT2 ROT3 ) /// ... /// /// NON_TRANSITION NON_PATCH ROT0 (end) /// Descriptor & operator ++ (); /// \brief Allows ordering of patches by type bool operator < ( Descriptor const other ) const; /// \brief True if the descriptors are identical bool operator == ( Descriptor const other ) const; /// \brief Descriptor Iterator class iterator; /// \brief Returns an iterator to the first type of patch (REGULAR NON_TRANSITION ROT0) static iterator begin(); /// \brief Returns an iterator to the end of the list of patch types (NON_PATCH) static iterator end(); private: template friend class FarPatchTablesFactory; friend class iterator; unsigned int _type:4; unsigned int _pattern:3; unsigned int _rotation:2; }; /// \brief Describes an array of patches of the same type class PatchArray { public: /// \brief Constructor. /// /// @param desc descriptor information for the patches in /// the array /// /// @param vertIndex absolute index to the first control vertex /// of the first patch in the PTable /// /// @param patchIndex absolute index of the first patch in the /// array /// /// @param npatches number of patches in the array /// /// @param quadOffsetIndex absolute index of the first quad offset /// entry /// PatchArray( Descriptor desc, unsigned int vertIndex, unsigned int patchIndex, unsigned int npatches, unsigned int quadOffsetIndex ) : _desc(desc), _range(vertIndex, patchIndex, npatches, quadOffsetIndex) { } /// Returns a patch descriptor defining the type of patches in the array Descriptor GetDescriptor() const { return _desc; } /// \brief Describes the range of patches in a PatchArray struct ArrayRange { /// \brief Constructor /// /// @param vertIndex absolute index to the first control vertex /// of the first patch in the PTable /// /// @param patchIndex absolute index of the first patch in the /// array /// /// @param npatches number of patches in the array /// /// @param quadOffsetIndex absolute index of the first quad offset /// entry /// ArrayRange( unsigned int vertIndex, unsigned int patchIndex, unsigned int npatches, unsigned int quadOffsetIndex ) : vertIndex(vertIndex), patchIndex(patchIndex), npatches(npatches), quadOffsetIndex(quadOffsetIndex) { } 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 quadOffsetIndex; // absolute index of the first quad offset entry }; /// \brief Returns a array range struct ArrayRange const & GetArrayRange() const { return _range; } /// \brief Returns the index of the first control vertex of the first patch /// of this array in the global PTable unsigned int GetVertIndex() const { return _range.vertIndex; } /// \brief Returns the global index of the first patch in this array (Used to /// access param / fvar table data) unsigned int GetPatchIndex() const { return _range.patchIndex; } /// \brief Returns the number of patches in the array unsigned int GetNumPatches() const { return _range.npatches; } /// \brief Returns the index to the first entry in the QuadOffsetTable unsigned int GetQuadOffsetIndex() const { return _range.quadOffsetIndex; } private: template friend class FarPatchTablesFactory; Descriptor _desc; // type of patches in the array ArrayRange _range; // index locators in the array }; typedef std::vector PatchArrayVector; /// \brief Constructor /// /// @param patchArrays Vector of descriptors and ranges for arrays of patches /// /// @param patches Indices of the control vertices of the patches /// /// @param vertexValences Vertex valance table /// /// @param quadOffsets Quad offset table /// /// @param patchParams Local patch parameterization /// /// @param fvarData Face varying data table /// /// @param maxValence Highest vertex valence allowed in the mesh /// FarPatchTables(PatchArrayVector const & patchArrays, PTable const & patches, VertexValenceTable const * vertexValences, QuadOffsetTable const * quadOffsets, PatchParamTable const * patchParams, FVarDataTable const * fvarData, int maxValence); /// \brief Get the table of patch control vertices PTable const & GetPatchTable() const { return _patches; } /// \brief Returns a pointer to the array of patches matching the descriptor PatchArray const * GetPatchArray( Descriptor desc ) const { return const_cast(this)->findPatchArray( desc ); } /// \brief Returns all arrays of patches PatchArrayVector const & GetPatchArrayVector() const { return _patchArrays; } /// \brief Returns a pointer to the vertex indices of uniformly subdivided faces /// /// @param level the level of subdivision of the faces (returns the highest /// level by default) /// /// @return a pointer to the first vertex index or NULL if the mesh /// is not uniformly subdivided or the level cannot be found. /// unsigned int const * GetFaceVertices(int level=0) const; /// \brief Returns the number of faces in a uniformly subdivided mesh at a given level /// /// @param level the level of subdivision of the faces (returns the highest /// level by default) /// /// @return the number of faces in the mesh given the subdivision level /// or -1 if the mesh is not uniform or the level is incorrect. /// int GetNumFaces(int level=0) const; /// \brief Returns a vertex valence table used by Gregory patches VertexValenceTable const & GetVertexValenceTable() const { return _vertexValenceTable; } /// \brief Returns a quad offsets table used by Gregory patches QuadOffsetTable const & GetQuadOffsetTable() const { return _quadOffsetTable; } /// \brief Returns a PatchParamTable for each type of patch PatchParamTable const & GetPatchParamTable() const { return _paramTable; } /// \brief Returns an FVarDataTable for each type of patch /// The data is stored as a run of totalFVarWidth floats per-vertex per-face /// e.g.: for UV data it has the structure of float[p][4][2] where /// p=primitiveID and totalFVarWidth=2: /// [ [ uv uv uv uv ] [ uv uv uv uv ] [ ... ] ] /// prim 0 prim 1 FVarDataTable const & GetFVarDataTable() const { return _fvarTable; } /// \brief Ringsize of Regular Patches in table. static int GetRegularPatchRingsize() { return 16; } /// \brief Ringsize of Boundary Patches in table. static int GetBoundaryPatchRingsize() { return 12; } /// \brief Ringsize of Boundary Patches in table. static int GetCornerPatchRingsize() { return 9; } /// \brief Ringsize of Gregory (and Gregory Boundary) Patches in table. static int GetGregoryPatchRingsize() { return 4; } /// \brief Returns the total number of patches stored in the tables int GetNumPatches() const; /// \brief Returns the total number of control vertex indices in the tables int GetNumControlVertices() const; /// \brief Returns max vertex valence int GetMaxValence() const { return _maxValence; } /// \brief True if the patches are of feature adaptive types bool IsFeatureAdaptive() const; 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 FarPatchTables( int maxvalence ) : _maxValence(maxvalence) { } PatchArrayVector _patchArrays; // Vector of descriptors for arrays of patches PTable _patches; // Indices of the control vertices of the patches VertexValenceTable _vertexValenceTable; // vertex valence table (for Gregory patches) QuadOffsetTable _quadOffsetTable; // quad offsets table (for Gregory patches) PatchParamTable _paramTable; FVarDataTable _fvarTable; // highest vertex valence allowed in the mesh (used for Gregory // vertexValance & quadOffset tables) int _maxValence; }; /// \brief Descriptor iterator class class FarPatchTables::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 ) const { return (pos==other.pos); } /// True if the two descriptors are different bool operator != ( iterator const & other ) const { return not (*this==other); } /// Dereferencing operator Descriptor * operator -> () { return &pos; } /// Dereferencing operator Descriptor & operator * () { return pos; } private: Descriptor pos; }; // Returns an iterator to the first type of patch (REGULAR NON_TRANSITION ROT0) inline FarPatchTables::Descriptor::iterator FarPatchTables::Descriptor::begin() { return iterator( Descriptor(REGULAR, NON_TRANSITION, 0) ); } // Returns an iterator to the end of the list of patch types (NON_PATCH) inline FarPatchTables::Descriptor::iterator FarPatchTables::Descriptor::end() { return iterator( Descriptor() ); } // Constructor inline FarPatchTables::FarPatchTables(PatchArrayVector const & patchArrays, PTable const & patches, VertexValenceTable const * vertexValences, QuadOffsetTable const * quadOffsets, PatchParamTable const * patchParams, FVarDataTable const * fvarData, int maxValence) : _patchArrays(patchArrays), _patches(patches), _maxValence(maxValence) { // copy other tables if exist if (vertexValences) _vertexValenceTable = *vertexValences; if (quadOffsets) _quadOffsetTable = *quadOffsets; if (patchParams) _paramTable = *patchParams; if (fvarData) _fvarTable = *fvarData; } inline bool FarPatchTables::IsFeatureAdaptive() const { // the vertex valence table is only used by Gregory patches, so the PatchTables // contain feature adaptive patches if this is not empty. if (not _vertexValenceTable.empty()) return true; PatchArrayVector const & parrays = GetPatchArrayVector(); // otherwise, we have to check each patch array for (int i=0; i<(int)parrays.size(); ++i) { if (parrays[i].GetDescriptor().GetType() >= REGULAR and parrays[i].GetDescriptor().GetType() <= GREGORY_BOUNDARY) return true; } return false; } // Returns the number of control vertices expected for a patch of this type inline short FarPatchTables::Descriptor::GetNumControlVertices( FarPatchTables::Type type ) { switch (type) { case REGULAR : return FarPatchTables::GetRegularPatchRingsize(); case QUADS : return 4; case GREGORY : case GREGORY_BOUNDARY : return FarPatchTables::GetGregoryPatchRingsize(); case BOUNDARY : return FarPatchTables::GetBoundaryPatchRingsize(); case CORNER : return FarPatchTables::GetCornerPatchRingsize(); case TRIANGLES : return 3; case LINES : return 2; case POINTS : return 1; default : return -1; } } // Iterates in order through the patch types, patterns and rotation in a preset order inline FarPatchTables::Descriptor & FarPatchTables::Descriptor::operator ++ () { if (GetPattern()==NON_TRANSITION) { if (GetType()==GREGORY_BOUNDARY) { _type=REGULAR; ++_pattern; } else ++_type; } else { switch (GetType()) { case REGULAR : ++_type; _rotation=0; break; case BOUNDARY : if (GetRotation()==3) { ++_type; _rotation=0; } else { ++_rotation; }; break; case CORNER : if (GetRotation()==3) { if (GetPattern()!=PATTERN4) { _type=REGULAR; _rotation=0; ++_pattern; } else { *this = Descriptor(); } } else { ++_rotation; }; break; case NON_PATCH : break; default: assert(0); } } return *this; } // Returns a pointer to the vertex indices of uniformly subdivided faces inline unsigned int const * FarPatchTables::GetFaceVertices(int level) const { if (IsFeatureAdaptive()) return NULL; PatchArrayVector const & parrays = GetPatchArrayVector(); if (parrays.empty()) return NULL; if (level < 1) { return &GetPatchTable()[ parrays.rbegin()->GetVertIndex() ]; } else if ((level-1) < (int)parrays.size() ) { return &GetPatchTable()[ parrays[level-1].GetVertIndex() ]; } return NULL; } // Returns the number of faces in a uniformly subdivided mesh at a given level inline int FarPatchTables::GetNumFaces(int level) const { if (IsFeatureAdaptive()) return -1; PatchArrayVector const & parrays = GetPatchArrayVector(); if (parrays.empty()) return -1; if (level < 1) { return parrays.rbegin()->GetNumPatches(); } else if ( (level-1) < (int)parrays.size() ) { return parrays[level-1].GetNumPatches(); } return -1; } // Allows ordering of patches by type inline bool FarPatchTables::Descriptor::operator < ( Descriptor const other ) const { return _pattern < other._pattern or ((_pattern == other._pattern) and (_type < other._type or ((_type == other._type) and (_rotation < other._rotation)))); } // True if the descriptors are identical inline bool FarPatchTables::Descriptor::operator == ( Descriptor const other ) const { return _pattern == other._pattern and _type == other._type and _rotation == other._rotation; } // Returns a pointer to the array of patches matching the descriptor inline FarPatchTables::PatchArray * FarPatchTables::findPatchArray( FarPatchTables::Descriptor desc ) { for (int i=0; i<(int)_patchArrays.size(); ++i) { if (_patchArrays[i].GetDescriptor()==desc) return &_patchArrays[i]; } return 0; } // Returns the total number of patches stored in the tables inline int FarPatchTables::GetNumPatches() const { // there is one PatchParam record for each patch in the mesh return (int)GetPatchParamTable().size(); } // Returns the total number of control vertex indices in the tables inline int FarPatchTables::GetNumControlVertices() const { int result=0; for (int i=0; i<(int)_patchArrays.size(); ++i) { result += _patchArrays[i].GetDescriptor().GetNumControlVertices() * _patchArrays[i].GetNumPatches(); } return result; } } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #endif /* FAR_PATCH_TABLES */