Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/opensubdiv/internal/evaluator/patch_map.h')
-rw-r--r--intern/opensubdiv/internal/evaluator/patch_map.h264
1 files changed, 264 insertions, 0 deletions
diff --git a/intern/opensubdiv/internal/evaluator/patch_map.h b/intern/opensubdiv/internal/evaluator/patch_map.h
new file mode 100644
index 00000000000..af804d6ca71
--- /dev/null
+++ b/intern/opensubdiv/internal/evaluator/patch_map.h
@@ -0,0 +1,264 @@
+// Original code 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.
+//
+// Modifications copyright 2021 Blender Foundation. All rights reserved.
+
+#ifndef OPENSUBDIV_PATCH_MAP_H_
+#define OPENSUBDIV_PATCH_MAP_H_
+
+#include <opensubdiv/far/patchTable.h>
+
+namespace blender {
+namespace opensubdiv {
+
+/// \brief An quadtree-based map connecting coarse faces to their sub-patches
+///
+/// PatchTable::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:
+ // Quadtree node with 4 children, tree is just a vector of nodes
+ struct QuadNode {
+ QuadNode()
+ {
+ std::memset(this, 0, sizeof(QuadNode));
+ }
+
+ struct Child {
+ unsigned int isSet : 1; // true if the child has been set
+ unsigned int isLeaf : 1; // true if the child is a QuadNode
+ unsigned int index : 30; // child index (either QuadNode or Handle)
+ };
+
+ // sets all the children to point to the patch of given index
+ void SetChildren(int index);
+
+ // sets the child in "quadrant" to point to the node or patch of the given index
+ void SetChild(int quadrant, int index, bool isLeaf);
+
+ Child children[4];
+ };
+
+ typedef OpenSubdiv::Far::PatchTable::PatchHandle Handle;
+
+ /// \brief Constructor
+ ///
+ /// @param patchTable A valid PatchTable
+ ///
+ PatchMap(OpenSubdiv::Far::PatchTable const &patchTable);
+
+ /// \brief Returns a handle to the sub-patch of the face at the given (u,v).
+ /// Note that the patch face ID corresponds to potentially quadrangulated
+ /// face indices and not the base face indices (see Far::PtexIndices for more
+ /// details).
+ ///
+ /// @param patchFaceId The index of the patch (Ptex) face
+ ///
+ /// @param u Local u parameter
+ ///
+ /// @param v Local v parameter
+ ///
+ /// @return A patch handle or 0 if the face is not supported (index
+ /// out of bounds) or is tagged as a hole
+ ///
+ Handle const *FindPatch(int patchFaceId, double u, double v) const;
+
+ int getMinPatchFace() const
+ {
+ return _minPatchFace;
+ }
+
+ int getMaxPatchFace() const
+ {
+ return _maxPatchFace;
+ }
+
+ int getMaxDepth() const
+ {
+ return _maxDepth;
+ }
+
+ bool getPatchesAreTriangular() const
+ {
+ return _patchesAreTriangular;
+ }
+
+ const std::vector<Handle> &getHandles()
+ {
+ return _handles;
+ }
+
+ const std::vector<QuadNode> &nodes()
+ {
+ return _quadtree;
+ }
+
+ private:
+ void initializeHandles(OpenSubdiv::Far::PatchTable const &patchTable);
+ void initializeQuadtree(OpenSubdiv::Far::PatchTable const &patchTable);
+
+ typedef std::vector<QuadNode> QuadTree;
+
+ // Internal methods supporting quadtree construction and queries
+ void assignRootNode(QuadNode *node, int index);
+ QuadNode *assignLeafOrChildNode(QuadNode *node, bool isLeaf, int quad, int index);
+
+ template<class T> static int transformUVToQuadQuadrant(T const &median, T &u, T &v);
+ template<class T>
+ static int transformUVToTriQuadrant(T const &median, T &u, T &v, bool &rotated);
+
+ private:
+ bool _patchesAreTriangular; // tri and quad assembly and search requirements differ
+
+ int _minPatchFace; // minimum patch face index supported by the map
+ int _maxPatchFace; // maximum patch face index supported by the map
+ int _maxDepth; // maximum depth of a patch in the tree
+
+ std::vector<Handle> _handles; // all the patches in the PatchTable
+ std::vector<QuadNode> _quadtree; // quadtree nodes
+};
+
+//
+// Given a median value for both U and V, these methods transform a (u,v) pair
+// into the quadrant that contains them and returns the quadrant index.
+//
+// Quadrant indexing for tri and quad patches -- consistent with PatchParam's
+// usage of UV bits:
+//
+// (0,1) o-----o-----o (1,1) (0,1) o (1,0) o-----o-----o (0,0)
+// | | | |\ \ 1 |\ 0 |
+// | 2 | 3 | | \ \ | \ |
+// | | | | 2 \ \| 3 \|
+// o-----o-----o o-----o o-----o
+// | | | |\ 3 |\ \ 2 |
+// | 0 | 1 | | \ | \ \ |
+// | | | | 0 \| 1 \ \|
+// (0,0) o-----o-----o (1,0) (0,0) o-----o-----o (1,0) o (0,1)
+//
+// The triangular case also takes and returns/affects the rotation of the
+// quadrant being searched and identified (quadrant 3 imparts a rotation).
+//
+template<class T> inline int PatchMap::transformUVToQuadQuadrant(T const &median, T &u, T &v)
+{
+
+ int uHalf = (u >= median);
+ if (uHalf)
+ u -= median;
+
+ int vHalf = (v >= median);
+ if (vHalf)
+ v -= median;
+
+ return (vHalf << 1) | uHalf;
+}
+
+template<class T>
+int inline PatchMap::transformUVToTriQuadrant(T const &median, T &u, T &v, bool &rotated)
+{
+
+ if (!rotated) {
+ if (u >= median) {
+ u -= median;
+ return 1;
+ }
+ if (v >= median) {
+ v -= median;
+ return 2;
+ }
+ if ((u + v) >= median) {
+ rotated = true;
+ return 3;
+ }
+ return 0;
+ }
+ else {
+ if (u < median) {
+ v -= median;
+ return 1;
+ }
+ if (v < median) {
+ u -= median;
+ return 2;
+ }
+ u -= median;
+ v -= median;
+ if ((u + v) < median) {
+ rotated = false;
+ return 3;
+ }
+ return 0;
+ }
+}
+
+/// Returns a handle to the sub-patch of the face at the given (u,v).
+inline PatchMap::Handle const *PatchMap::FindPatch(int faceid, double u, double v) const
+{
+
+ //
+ // Reject patch faces not supported by this map, or those corresponding
+ // to holes or otherwise unassigned (the root node for a patch will
+ // have all or no quadrants set):
+ //
+ if ((faceid < _minPatchFace) || (faceid > _maxPatchFace))
+ return 0;
+
+ QuadNode const *node = &_quadtree[faceid - _minPatchFace];
+
+ if (!node->children[0].isSet)
+ return 0;
+
+ //
+ // Search the tree for the sub-patch containing the given (u,v)
+ //
+ assert((u >= 0.0) && (u <= 1.0) && (v >= 0.0) && (v <= 1.0));
+
+ double median = 0.5;
+ bool triRotated = false;
+
+ for (int depth = 0; depth <= _maxDepth; ++depth, median *= 0.5) {
+
+ int quadrant = _patchesAreTriangular ? transformUVToTriQuadrant(median, u, v, triRotated) :
+ transformUVToQuadQuadrant(median, u, v);
+
+ // holes should have been rejected at the root node of the face
+ assert(node->children[quadrant].isSet);
+
+ if (node->children[quadrant].isLeaf) {
+ return &_handles[node->children[quadrant].index];
+ }
+ else {
+ node = &_quadtree[node->children[quadrant].index];
+ }
+ }
+ assert(0);
+ return 0;
+}
+} // namespace opensubdiv
+} // namespace blender
+
+#endif // OPENSUBDIV_PATCH_MAP_H_