// // 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_PATCH_MAP_H #define FAR_PATCH_MAP_H #include "../version.h" #include "../far/patchTables.h" #include namespace OpenSubdiv { namespace OPENSUBDIV_VERSION { namespace Far { /// \brief An quadtree-based map connecting coarse faces to their sub-patches /// /// PatchTables::PatchArrays contain lists of patches that represent the limit /// surface of a mesh, sorted by their topological type. These arrays break the /// connection between coarse faces and their sub-patches. /// /// The PatchMap provides a quad-tree based lookup structure that, given a singular /// parametric location, can efficiently return a handle to the sub-patch that /// contains this location. /// class PatchMap { public: /// \brief Handle that can be used as unique patch identifier within PatchTables struct Handle { unsigned int patchArrayIdx, // OsdPatchArray containing the patch patchIdx, // Absolute index of the patch vertexOffset; // Offset to the first CV of the patch }; /// \brief Constructor /// /// @param patchTables A valid set of PatchTables /// PatchMap( PatchTables const & patchTables ); /// \brief Returns a handle to the sub-patch of the face at the given (u,v). /// Note : the faceid corresponds to quadrangulated face indices (ie. quads /// count as 1 index, non-quads add as many indices as they have vertices) /// /// @param faceid The index of the face /// /// @param u Local u parameter /// /// @param v Local v parameter /// /// @return A patch handle or NULL if the face does not exist or the /// limit surface is tagged as a hole at the given location /// Handle const * FindPatch( int faceid, float u, float v ) const; private: inline void initialize( PatchTables const & patchTables ); // Quadtree node with 4 children struct QuadNode { struct Child { unsigned int isSet:1, // true if the child has been set isLeaf:1, // true if the child is a QuadNode idx:30; // child index (either QuadNode or Handle) }; // sets all the children to point to the patch of index patchIdx void SetChild(int patchIdx); // sets the child in "quadrant" to point to the node or patch of the given index void SetChild(unsigned char quadrant, int child, bool isLeaf=true); Child children[4]; }; typedef std::vector QuadTree; // adds a child to a parent node and pushes it back on the tree static QuadNode * addChild( QuadTree & quadtree, QuadNode * parent, int quadrant ); // given a median, transforms the (u,v) to the quadrant they point to, and // return the quadrant index. // // Quadrants indexing: // // (0,0) o-----o-----o // | | | // | 0 | 3 | // | | | // o-----o-----o // | | | // | 1 | 2 | // | | | // o-----o-----o (1,1) // template static int resolveQuadrant(T & median, T & u, T & v); std::vector _handles; // all the patches in the PatchTable std::vector _quadtree; // quadtree nodes }; // given a median, transforms the (u,v) to the quadrant they point to, and // return the quadrant index. template int PatchMap::resolveQuadrant(T & median, T & u, T & v) { int quadrant = -1; if (u=(int)_quadtree.size()) return NULL; assert( (u>=0.0f) and (u<=1.0f) and (v>=0.0f) and (v<=1.0f) ); QuadNode const * node = &_quadtree[faceid]; float half = 0.5f; // 0xFF : we should never have depths greater than k_InfinitelySharp for (int depth=0; depth<0xFF; ++depth) { float delta = half * 0.5f; int quadrant = resolveQuadrant( half, u, v ); assert(quadrant>=0); // is the quadrant a hole ? if (not node->children[quadrant].isSet) return 0; if (node->children[quadrant].isLeaf) { return &_handles[node->children[quadrant].idx]; } else { node = &_quadtree[node->children[quadrant].idx]; } half = delta; } assert(0); return 0; } // Constructor } // end namespace Far } // end namespace OPENSUBDIV_VERSION using namespace OPENSUBDIV_VERSION; } // end namespace OpenSubdiv #endif /* FAR_PATCH_PARAM */