mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-15 05:10:12 +00:00
e96bf355e0
- fixed missing PatchDescriptor functionality for Loop triangle - add new PatchDescriptor::Type for Gregory triangle - extended PatchParam boundary mask from 4 to 5 bits (!) - added new PatchParam methods for parameterization of triangles - extended PatchMap to support triangular patches - added basis evaluation for triangular patch types
177 lines
5.8 KiB
C++
177 lines
5.8 KiB
C++
//
|
|
// Copyright 2014 DreamWorks Animation LLC.
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
#include "../far/patchMap.h"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace OpenSubdiv {
|
|
namespace OPENSUBDIV_VERSION {
|
|
|
|
namespace Far {
|
|
|
|
// Constructor
|
|
PatchMap::PatchMap( PatchTable const & patchTable ) {
|
|
initialize( patchTable );
|
|
}
|
|
|
|
// sets all the children to point to the patch of index patchIdx
|
|
void
|
|
PatchMap::QuadNode::SetChild(int patchIdx) {
|
|
for (int i=0; i<4; ++i) {
|
|
children[i].isSet=true;
|
|
children[i].isLeaf=true;
|
|
children[i].idx=patchIdx;
|
|
}
|
|
}
|
|
|
|
// sets the child in "quadrant" to point to the node or patch of the given index
|
|
void
|
|
PatchMap::QuadNode::SetChild(unsigned char quadrant, int idx, bool isLeaf) {
|
|
assert(quadrant<4);
|
|
children[quadrant].isSet = true;
|
|
children[quadrant].isLeaf = isLeaf;
|
|
children[quadrant].idx = idx;
|
|
}
|
|
|
|
// adds a child to a parent node and pushes it back on the tree
|
|
PatchMap::QuadNode *
|
|
PatchMap::addChild( QuadTree & quadtree, QuadNode * parent, int quadrant ) {
|
|
quadtree.push_back(QuadNode());
|
|
int idx = (int)quadtree.size()-1;
|
|
parent->SetChild(quadrant, idx, false);
|
|
return &(quadtree[idx]);
|
|
}
|
|
|
|
void
|
|
PatchMap::initialize( PatchTable const & patchTable ) {
|
|
|
|
_patchesAreTriangular =
|
|
patchTable.GetVaryingPatchDescriptor().GetNumControlVertices() == 3;
|
|
|
|
int nfaces = 0,
|
|
narrays = (int)patchTable.GetNumPatchArrays(),
|
|
npatches = (int)patchTable.GetNumPatchesTotal();
|
|
|
|
if (! narrays || ! npatches)
|
|
return;
|
|
|
|
// populate subpatch handles vector
|
|
_handles.resize(npatches);
|
|
|
|
for (int parray=0, current=0; parray<narrays; ++parray) {
|
|
|
|
ConstPatchParamArray params = patchTable.GetPatchParams(parray);
|
|
|
|
int ringsize = patchTable.GetPatchArrayDescriptor(parray).GetNumControlVertices();
|
|
|
|
for (Index j=0; j < patchTable.GetNumPatches(parray); ++j) {
|
|
|
|
Handle & h = _handles[current];
|
|
|
|
h.arrayIndex = parray;
|
|
h.patchIndex = current;
|
|
h.vertIndex = j * ringsize;
|
|
|
|
nfaces = std::max(nfaces, (int)params[j].GetFaceId());
|
|
|
|
++current;
|
|
}
|
|
}
|
|
++nfaces;
|
|
// temporary vector to hold the quadtree while under construction
|
|
std::vector<QuadNode> quadtree;
|
|
|
|
// reserve memory for the octree nodes (size is a worse-case approximation)
|
|
quadtree.reserve( nfaces + npatches );
|
|
|
|
// each coarse face has a root node associated to it that we need to initialize
|
|
quadtree.resize(nfaces);
|
|
|
|
// populate the quadtree from the FarPatchArrays sub-patches
|
|
for (Index parray=0, handleIndex=0; parray<narrays; ++parray) {
|
|
|
|
ConstPatchParamArray params = patchTable.GetPatchParams(parray);
|
|
|
|
for (int i=0; i < patchTable.GetNumPatches(parray); ++i, ++handleIndex) {
|
|
|
|
PatchParam const & param = params[i];
|
|
|
|
QuadNode * node = &quadtree[ param.GetFaceId() ];
|
|
|
|
int rootDepth = param.NonQuadRoot();
|
|
int depth = param.GetDepth();
|
|
|
|
if (depth == rootDepth) {
|
|
// special case : root level face with no sub-patches
|
|
node->SetChild( handleIndex );
|
|
continue;
|
|
}
|
|
|
|
// We can use the PatchParam bits directly to determine the quadrants
|
|
// in which to place the patch -- just need to adjust the UV bits for
|
|
// the special case of a rotated triangular patch:
|
|
//
|
|
int u = param.GetU();
|
|
int v = param.GetV();
|
|
|
|
if (_patchesAreTriangular && param.IsTriangleRotated()) {
|
|
u = (1 << depth) - u;
|
|
v = (1 << depth) - v;
|
|
}
|
|
|
|
for (int j = rootDepth + 1; j<= depth; ++j) {
|
|
int uBit = (u >> (depth - j)) & 1;
|
|
int vBit = (v >> (depth - j)) & 1;
|
|
|
|
int quadrant = (vBit << 1) | uBit;
|
|
|
|
if (j == depth) {
|
|
// we have reached the depth of the sub-patch : add a leaf
|
|
assert( ! node->children[quadrant].isSet );
|
|
node->SetChild(quadrant, handleIndex, true);
|
|
} else {
|
|
// travel down the child node of the corresponding quadrant
|
|
if (! node->children[quadrant].isSet) {
|
|
// create a new branch in the quadrant
|
|
node = addChild(quadtree, node, quadrant);
|
|
} else {
|
|
// travel down an existing branch
|
|
node = &(quadtree[ node->children[quadrant].idx ]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// copy the resulting quadtree to eliminate un-unused vector capacity
|
|
_quadtree = quadtree;
|
|
}
|
|
|
|
|
|
} // end namespace Far
|
|
|
|
} // end namespace OPENSUBDIV_VERSION
|
|
} // end namespace OpenSubdiv
|