28 using OpenSubdiv::Far::ConstPatchParamArray;
29 using OpenSubdiv::Far::Index;
30 using OpenSubdiv::Far::PatchParam;
31 using OpenSubdiv::Far::PatchParamTable;
32 using OpenSubdiv::Far::PatchTable;
35 namespace opensubdiv {
45 for (
int i = 0; i < 4; ++i) {
56 assert(!children[quadrant].isSet);
57 children[quadrant].isSet =
true;
58 children[quadrant].isLeaf = isLeaf;
59 children[quadrant].index = index;
62 inline void PatchMap::assignRootNode(
QuadNode *
node,
int index)
66 node->SetChildren(index);
79 node->SetChild(quadrant, index,
true);
82 if (
node->children[quadrant].isSet) {
83 return &_quadtree[
node->children[quadrant].index];
86 int newChildNodeIndex = (int)_quadtree.size();
87 _quadtree.push_back(QuadNode());
88 node->SetChild(quadrant, newChildNodeIndex,
false);
89 return &_quadtree[newChildNodeIndex];
97 : _minPatchFace(-1), _maxPatchFace(-1), _maxDepth(0)
100 _patchesAreTriangular = patchTable.GetVaryingPatchDescriptor().GetNumControlVertices() == 3;
102 if (patchTable.GetNumPatchesTotal() > 0) {
103 initializeHandles(patchTable);
104 initializeQuadtree(patchTable);
108 void PatchMap::initializeHandles(PatchTable
const &patchTable)
115 _minPatchFace = (int)patchTable.GetPatchParamTable()[0].GetFaceId();
116 _maxPatchFace = _minPatchFace;
118 int numArrays = (int)patchTable.GetNumPatchArrays();
119 int numPatches = (int)patchTable.GetNumPatchesTotal();
121 _handles.resize(numPatches);
123 for (
int pArray = 0, handleIndex = 0; pArray < numArrays; ++pArray) {
125 ConstPatchParamArray
params = patchTable.GetPatchParams(pArray);
127 int patchSize = patchTable.GetPatchArrayDescriptor(pArray).GetNumControlVertices();
129 for (Index j = 0; j < patchTable.GetNumPatches(pArray); ++j, ++handleIndex) {
131 Handle &h = _handles[handleIndex];
133 h.arrayIndex = pArray;
134 h.patchIndex = handleIndex;
135 h.vertIndex = j * patchSize;
137 int patchFaceId =
params[j].GetFaceId();
138 _minPatchFace =
std::min(_minPatchFace, patchFaceId);
139 _maxPatchFace =
std::max(_maxPatchFace, patchFaceId);
144 void PatchMap::initializeQuadtree(PatchTable
const &patchTable)
151 int nPatchFaces = (_maxPatchFace - _minPatchFace) + 1;
153 int nHandles = (int)_handles.size();
155 _quadtree.reserve(nPatchFaces + nHandles);
156 _quadtree.resize(nPatchFaces);
158 PatchParamTable
const &
params = patchTable.GetPatchParamTable();
160 for (
int handle = 0; handle < nHandles; ++handle) {
162 PatchParam
const ¶m =
params[handle];
164 int depth = param.GetDepth();
165 int rootDepth = param.NonQuadRoot();
167 _maxDepth =
std::max(_maxDepth, depth);
169 QuadNode *
node = &_quadtree[param.GetFaceId() - _minPatchFace];
171 if (depth == rootDepth) {
172 assignRootNode(
node, handle);
176 if (!_patchesAreTriangular) {
178 int u = param.GetU();
179 int v = param.GetV();
181 for (
int j = rootDepth + 1; j <= depth; ++j) {
182 int uBit = (u >> (depth - j)) & 1;
183 int vBit = (
v >> (depth - j)) & 1;
185 int quadrant = (vBit << 1) | uBit;
187 node = assignLeafOrChildNode(
node, (j == depth), quadrant, handle);
194 param.UnnormalizeTriangle(u,
v);
197 bool triRotated =
false;
199 for (
int j = rootDepth + 1; j <= depth; ++j, median *= 0.5) {
200 int quadrant = transformUVToTriQuadrant(median, u,
v, triRotated);
202 node = assignLeafOrChildNode(
node, (j == depth), quadrant, handle);
208 QuadTree tmpTree = _quadtree;
209 _quadtree.swap(tmpTree);
ATTR_WARN_UNUSED_RESULT const BMVert * v
PatchMap(OpenSubdiv::Far::PatchTable const &patchTable)
Constructor.
OpenSubdiv::Far::PatchTable::PatchHandle Handle
void SetChildren(int index)
void SetChild(int quadrant, int index, bool isLeaf)