// // Copyright 2013 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef FAR_SUBDIVISION_TABLES_H #define FAR_SUBDIVISION_TABLES_H #include "../version.h" #include #include #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { template class FarMesh; /// \brief FarSubdivisionTables are a serialized topological data representation. /// /// Subdivision tables store the indexing tables required in order to compute /// the refined positions of a mesh without the help of a hierarchical data /// structure. The advantage of this representation is its ability to be executed /// in a massively parallel environment without data dependencies. /// /// The vertex indexing tables require the vertex buffer to be sorted based on the /// nature of the parent of a given vertex : either a face, an edge, or a vertex. /// (note : the Loop subdivision scheme does not create vertices as a child of a /// face). /// /// Each type of vertex in the buffer is associated the following tables : /// - __IT : indices of all the adjacent vertices required by the compute kernels /// - __W : fractional weight of the vertex (based on sharpness & topology) /// - __ITa : codex for the two previous tables /// (where T denotes a face-vertex / edge-vertex / vertex-vertex) /// /// /// Because each subdivision scheme (Catmark / Loop / Bilinear) introduces variations /// in the subdivision rules, a derived class specialization is associated with /// each scheme. /// /// For more details see : "Feature Adaptive GPU Rendering of Catmull-Clark /// Subdivision Surfaces" (p.3 - par. 3.2) /// template class FarSubdivisionTables { public: enum Scheme { UNDEFINED=0, BILINEAR, CATMARK, LOOP }; enum TableType { E_IT, ///< edge-vertices adjacency indexing table E_W, ///< edge-vertices weights V_ITa, ///< vertex-vertices adjacency indexing table V_IT, ///< vertex-vertices indexing table V_W, ///< vertex-vertices weights F_ITa, ///< face-vertices adjacency indexing table F_IT, ///< face-vertices indexing table TABLE_TYPES_COUNT // number of different types of tables }; /// \brief Destructor virtual ~FarSubdivisionTables() {} /// \brief Return the highest level of subdivision possible with these tables int GetMaxLevel() const { return (int)(_vertsOffsets.size()-1); } /// \brief Memory required to store the indexing tables int GetMemoryUsed() const; /// \brief Pointer back to the mesh owning the table FarMesh * GetMesh() { return _mesh; } /// \brief The index of the first vertex that belongs to the level of subdivision /// represented by this set of FarCatmarkSubdivisionTables int GetFirstVertexOffset( int level ) const; /// \brief Returns the total number of vertex adressed by the tables (this is the /// length that a vertex buffer object should be allocating int GetNumVertices( ) const; /// \brief Returns the number of vertices at a given level int GetNumVertices( int level ) const; /// \brief Returns the summation of the number of vertices up to a given level int GetNumVerticesTotal( int level ) const; // Indexing tables accessors /// \brief Returns the face vertices codex table std::vector const & Get_F_ITa( ) const { return _F_ITa; } /// \brief Returns the face vertices indexing table std::vector const & Get_F_IT( ) const { return _F_IT; } /// \brief Returns the edge vertices indexing table std::vector const & Get_E_IT() const { return _E_IT; } /// \brief Returns the edge vertices weights table std::vector const & Get_E_W() const { return _E_W; } /// \brief Returns the vertex vertices codex table std::vector const & Get_V_ITa() const { return _V_ITa; } /// \brief Returns the vertex vertices indexing table std::vector const & Get_V_IT() const { return _V_IT; } /// \brief Returns the vertex vertices weights table std::vector const & Get_V_W() const { return _V_W; } /// \brief Returns the subdivision scheme of the tables /// (sidesteps typeinfo dependency) virtual Scheme GetScheme() const { return UNDEFINED; } /// \brief Returns the number of indexing tables needed to represent this particular /// subdivision scheme. virtual int GetNumTables() const { return 5; } protected: template friend class FarMeshFactory; template friend class FarMultiMeshFactory; FarSubdivisionTables( FarMesh * mesh, int maxlevel ); // mesh that owns this subdivisionTable FarMesh * _mesh; std::vector _F_ITa; // vertices from face refinement std::vector _F_IT; // indices of face vertices std::vector _E_IT; // vertices from edge refinement std::vector _E_W; // weigths std::vector _V_ITa; // vertices from vertex refinement std::vector _V_IT; // indices of adjacent vertices std::vector _V_W; // weights std::vector _vertsOffsets; // offset to the first vertex of each level }; template FarSubdivisionTables::FarSubdivisionTables( FarMesh * mesh, int maxlevel ) : _mesh(mesh), _vertsOffsets(maxlevel+2, 0) { assert( maxlevel > 0 ); } template int FarSubdivisionTables::GetFirstVertexOffset( int level ) const { assert(level>=0 and level<(int)_vertsOffsets.size()); return _vertsOffsets[level]; } template int FarSubdivisionTables::GetNumVertices( ) const { if (_vertsOffsets.empty()) { return 0; } else { // _vertsOffsets contains an extra offset at the end that is the position // of the first vertex 1 level above that of the tables return *_vertsOffsets.rbegin(); } } template int FarSubdivisionTables::GetNumVertices( int level ) const { assert(level>=0 and level<((int)_vertsOffsets.size()-1)); return _vertsOffsets[level+1] - _vertsOffsets[level]; } template int FarSubdivisionTables::GetNumVerticesTotal( int level ) const { assert(level>=0 and level<((int)_vertsOffsets.size()-1)); return _vertsOffsets[level+1]; } template int FarSubdivisionTables::GetMemoryUsed() const { return (int)(_F_ITa.size() * sizeof(int) + _F_IT.size() * sizeof(unsigned int) + _E_IT.size() * sizeof(int) + _E_W.size() * sizeof(float) + _V_ITa.size() * sizeof(int) + _V_IT.size() * sizeof(unsigned int) + _V_W.size() * sizeof(float)); } } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #endif /* FAR_SUBDIVISION_TABLES_H */