Add Chromium-only Blender WebEngine parity work
This commit is contained in:
993
blender-5.2.0/extern/opensubdiv-source/opensubdiv/vtr/quadRefinement.cpp
vendored
Normal file
993
blender-5.2.0/extern/opensubdiv-source/opensubdiv/vtr/quadRefinement.cpp
vendored
Normal file
@@ -0,0 +1,993 @@
|
||||
//
|
||||
// Copyright 2014 DreamWorks Animation LLC.
|
||||
//
|
||||
// Licensed under the terms set forth in the LICENSE.txt file available at
|
||||
// https://opensubdiv.org/license.
|
||||
//
|
||||
#include "../sdc/crease.h"
|
||||
#include "../vtr/types.h"
|
||||
#include "../vtr/level.h"
|
||||
#include "../vtr/quadRefinement.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Vtr {
|
||||
namespace internal {
|
||||
|
||||
//
|
||||
// Simple constructor, destructor and basic initializers:
|
||||
//
|
||||
QuadRefinement::QuadRefinement(Level const & parentArg, Level & childArg, Sdc::Options const & optionsArg) :
|
||||
Refinement(parentArg, childArg, optionsArg) {
|
||||
|
||||
_splitType = Sdc::SPLIT_TO_QUADS;
|
||||
_regFaceSize = 4;
|
||||
}
|
||||
|
||||
QuadRefinement::~QuadRefinement() {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Methods to construct the parent-to-child mapping
|
||||
//
|
||||
void
|
||||
QuadRefinement::allocateParentChildIndices() {
|
||||
|
||||
//
|
||||
// Initialize the vectors of indices mapping parent components to those child components
|
||||
// that will originate from each.
|
||||
//
|
||||
int faceChildFaceCount = (int) _parent->_faceVertIndices.size();
|
||||
int faceChildEdgeCount = (int) _parent->_faceEdgeIndices.size();
|
||||
int edgeChildEdgeCount = (int) _parent->_edgeVertIndices.size();
|
||||
|
||||
int faceChildVertCount = _parent->getNumFaces();
|
||||
int edgeChildVertCount = _parent->getNumEdges();
|
||||
int vertChildVertCount = _parent->getNumVertices();
|
||||
|
||||
//
|
||||
// First reference the parent Level's face-vertex counts/offsets -- they can be used
|
||||
// here for both the face-child-faces and face-child-edges as they both have one per
|
||||
// face-vertex.
|
||||
//
|
||||
// Given we will be ignoring initial values with uniform refinement and assigning all
|
||||
// directly, initializing here is a waste...
|
||||
//
|
||||
Index initValue = 0;
|
||||
|
||||
_faceChildFaceCountsAndOffsets = _parent->shareFaceVertCountsAndOffsets();
|
||||
_faceChildEdgeCountsAndOffsets = _parent->shareFaceVertCountsAndOffsets();
|
||||
|
||||
_faceChildFaceIndices.resize(faceChildFaceCount, initValue);
|
||||
_faceChildEdgeIndices.resize(faceChildEdgeCount, initValue);
|
||||
_edgeChildEdgeIndices.resize(edgeChildEdgeCount, initValue);
|
||||
|
||||
_faceChildVertIndex.resize(faceChildVertCount, initValue);
|
||||
_edgeChildVertIndex.resize(edgeChildVertCount, initValue);
|
||||
_vertChildVertIndex.resize(vertChildVertCount, initValue);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Methods to populate the face-vertex relation of the child Level:
|
||||
// - child faces only originate from parent faces
|
||||
//
|
||||
void
|
||||
QuadRefinement::populateFaceVertexRelation() {
|
||||
|
||||
// Both face-vertex and face-edge share the face-vertex counts/offsets within a
|
||||
// Level, so be sure not to re-initialize it if already done:
|
||||
//
|
||||
if (_child->_faceVertCountsAndOffsets.size() == 0) {
|
||||
populateFaceVertexCountsAndOffsets();
|
||||
}
|
||||
_child->_faceVertIndices.resize(_child->getNumFaces() * 4);
|
||||
|
||||
populateFaceVerticesFromParentFaces();
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateFaceVertexCountsAndOffsets() {
|
||||
|
||||
_child->_faceVertCountsAndOffsets.resize(_child->getNumFaces() * 2);
|
||||
|
||||
for (int i = 0; i < _child->getNumFaces(); ++i) {
|
||||
_child->_faceVertCountsAndOffsets[i*2 + 0] = 4;
|
||||
_child->_faceVertCountsAndOffsets[i*2 + 1] = i << 2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateFaceVerticesFromParentFaces() {
|
||||
|
||||
//
|
||||
// This is pretty straightforward, but is a good example for the case of
|
||||
// iterating through the parent faces rather than the child faces, as the
|
||||
// same topology information for the parent faces is required for each of
|
||||
// the child faces.
|
||||
//
|
||||
// For each of the child faces of a parent face, identify the child vertices
|
||||
// for its face-verts from the child vertices of the parent face, its edges
|
||||
// and its vertices.
|
||||
//
|
||||
for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
|
||||
ConstIndexArray pFaceVerts = _parent->getFaceVertices(pFace),
|
||||
pFaceEdges = _parent->getFaceEdges(pFace),
|
||||
pFaceChildren = getFaceChildFaces(pFace);
|
||||
|
||||
int pFaceSize = pFaceVerts.size();
|
||||
for (int j = 0; j < pFaceSize; ++j) {
|
||||
Index cFace = pFaceChildren[j];
|
||||
if (IndexIsValid(cFace)) {
|
||||
int jPrev = j ? (j - 1) : (pFaceSize - 1);
|
||||
|
||||
Index cVertOfFace = _faceChildVertIndex[pFace];
|
||||
Index cVertOfEPrev = _edgeChildVertIndex[pFaceEdges[jPrev]];
|
||||
Index cVertOfVert = _vertChildVertIndex[pFaceVerts[j]];
|
||||
Index cVertOfENext = _edgeChildVertIndex[pFaceEdges[j]];
|
||||
|
||||
IndexArray cFaceVerts = _child->getFaceVertices(cFace);
|
||||
|
||||
// Note orientation wrt parent face -- quad vs non-quad...
|
||||
if (pFaceSize == 4) {
|
||||
int jOpp = jPrev ? (jPrev - 1) : 3;
|
||||
int jNext = jOpp ? (jOpp - 1) : 3;
|
||||
|
||||
cFaceVerts[j] = cVertOfVert;
|
||||
cFaceVerts[jNext] = cVertOfENext;
|
||||
cFaceVerts[jOpp] = cVertOfFace;
|
||||
cFaceVerts[jPrev] = cVertOfEPrev;
|
||||
} else {
|
||||
cFaceVerts[0] = cVertOfVert;
|
||||
cFaceVerts[1] = cVertOfENext;
|
||||
cFaceVerts[2] = cVertOfFace;
|
||||
cFaceVerts[3] = cVertOfEPrev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Methods to populate the face-vertex relation of the child Level:
|
||||
// - child faces only originate from parent faces
|
||||
//
|
||||
void
|
||||
QuadRefinement::populateFaceEdgeRelation() {
|
||||
|
||||
// Both face-vertex and face-edge share the face-vertex counts/offsets, so be sure
|
||||
// not to re-initialize it if already done:
|
||||
//
|
||||
if (_child->_faceVertCountsAndOffsets.size() == 0) {
|
||||
populateFaceVertexCountsAndOffsets();
|
||||
}
|
||||
_child->_faceEdgeIndices.resize(_child->getNumFaces() * 4);
|
||||
|
||||
populateFaceEdgesFromParentFaces();
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateFaceEdgesFromParentFaces() {
|
||||
|
||||
//
|
||||
// This is fairly straightforward, but since we are dealing with edges here, we
|
||||
// occasionally have to deal with the limitation of them being undirected. Since
|
||||
// child faces from the same parent face share much in common, we iterate through
|
||||
// the parent faces.
|
||||
//
|
||||
// Each child face of the parent is based on a corner vertex from which we denote
|
||||
// a "previous" and "next" edge, which are child edges of the parent face's edges.
|
||||
// The two remaining edges per child faces are perpendicular to these prev/next
|
||||
// edges and share the child vertex of the parent face.
|
||||
//
|
||||
for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
|
||||
ConstIndexArray pFaceVerts = _parent->getFaceVertices(pFace),
|
||||
pFaceEdges = _parent->getFaceEdges(pFace),
|
||||
pFaceChildFaces = getFaceChildFaces(pFace),
|
||||
pFaceChildEdges = getFaceChildEdges(pFace);
|
||||
|
||||
int pFaceSize = pFaceVerts.size();
|
||||
|
||||
for (int j = 0; j < pFaceSize; ++j) {
|
||||
Index cFace = pFaceChildFaces[j];
|
||||
if (IndexIsValid(cFace)) {
|
||||
//
|
||||
// Identify the vertex pairs for the prev/next parent edges -- from
|
||||
// which we will determine the prev/next child edges:
|
||||
//
|
||||
int jPrev = j ? (j - 1) : (pFaceSize - 1);
|
||||
|
||||
Index pPrevEdge = pFaceEdges[jPrev];
|
||||
ConstIndexArray pPrevEdgeVerts = _parent->getEdgeVertices(pPrevEdge);
|
||||
|
||||
Index pNextEdge = pFaceEdges[j];
|
||||
ConstIndexArray pNextEdgeVerts = _parent->getEdgeVertices(pNextEdge);
|
||||
|
||||
//
|
||||
// Now identify the two prev/next child edges (beware of degenerate
|
||||
// edges here) and the two remaining perpendicular child edges:
|
||||
//
|
||||
Index pCornerVert = pFaceVerts[j];
|
||||
|
||||
int cornerInPrevEdge = (pPrevEdgeVerts[0] != pPrevEdgeVerts[1])
|
||||
? (pPrevEdgeVerts[0] != pCornerVert) : 1;
|
||||
|
||||
int cornerInNextEdge = (pNextEdgeVerts[0] != pNextEdgeVerts[1])
|
||||
? (pNextEdgeVerts[0] != pCornerVert) : 0;
|
||||
|
||||
Index cEdgeOfEdgePrev = getEdgeChildEdges(pPrevEdge)[cornerInPrevEdge];
|
||||
Index cEdgeOfEdgeNext = getEdgeChildEdges(pNextEdge)[cornerInNextEdge];
|
||||
|
||||
Index cEdgePerpEdgePrev = pFaceChildEdges[jPrev];
|
||||
Index cEdgePerpEdgeNext = pFaceChildEdges[j];
|
||||
|
||||
//
|
||||
// Assign the identified child edges to the child face's face-edges:
|
||||
//
|
||||
IndexArray cFaceEdges = _child->getFaceEdges(cFace);
|
||||
|
||||
// Note orientation wrt parent face -- quad vs non-quad...
|
||||
if (pFaceSize == 4) {
|
||||
int jOpp = jPrev ? (jPrev - 1) : 3;
|
||||
int jNext = jOpp ? (jOpp - 1) : 3;
|
||||
|
||||
cFaceEdges[j] = cEdgeOfEdgeNext;
|
||||
cFaceEdges[jNext] = cEdgePerpEdgeNext;
|
||||
cFaceEdges[jOpp] = cEdgePerpEdgePrev;
|
||||
cFaceEdges[jPrev] = cEdgeOfEdgePrev;
|
||||
} else {
|
||||
cFaceEdges[0] = cEdgeOfEdgeNext;
|
||||
cFaceEdges[1] = cEdgePerpEdgeNext;
|
||||
cFaceEdges[2] = cEdgePerpEdgePrev;
|
||||
cFaceEdges[3] = cEdgeOfEdgePrev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Methods to populate the edge-vertex relation of the child Level:
|
||||
// - child edges originate from parent faces and edges
|
||||
//
|
||||
void
|
||||
QuadRefinement::populateEdgeVertexRelation() {
|
||||
|
||||
_child->_edgeVertIndices.resize(_child->getNumEdges() * 2);
|
||||
|
||||
populateEdgeVerticesFromParentFaces();
|
||||
populateEdgeVerticesFromParentEdges();
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateEdgeVerticesFromParentFaces() {
|
||||
|
||||
//
|
||||
// This is straightforward. All child edges of parent faces are assigned
|
||||
// their first vertex from the child vertex of the face -- so it is common
|
||||
// to all. The second vertex is the child vertex of the parent edge to
|
||||
// which the new child edge is perpendicular.
|
||||
//
|
||||
for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
|
||||
ConstIndexArray pFaceEdges = _parent->getFaceEdges(pFace),
|
||||
pFaceChildEdges = getFaceChildEdges(pFace);
|
||||
|
||||
for (int j = 0; j < pFaceEdges.size(); ++j) {
|
||||
Index cEdge = pFaceChildEdges[j];
|
||||
if (IndexIsValid(cEdge)) {
|
||||
IndexArray cEdgeVerts = _child->getEdgeVertices(cEdge);
|
||||
|
||||
cEdgeVerts[0] = _faceChildVertIndex[pFace];
|
||||
cEdgeVerts[1] = _edgeChildVertIndex[pFaceEdges[j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateEdgeVerticesFromParentEdges() {
|
||||
|
||||
//
|
||||
// This is straightforward. All child edges of parent edges are assigned
|
||||
// their first vertex from the child vertex of the edge -- so it is common
|
||||
// to both. The second vertex is the child vertex of the vertex at the
|
||||
// end of the parent edge.
|
||||
//
|
||||
for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
|
||||
ConstIndexArray pEdgeVerts = _parent->getEdgeVertices(pEdge),
|
||||
pEdgeChildren = getEdgeChildEdges(pEdge);
|
||||
|
||||
// May want to unroll this trivial loop of 2...
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
Index cEdge = pEdgeChildren[j];
|
||||
if (IndexIsValid(cEdge)) {
|
||||
IndexArray cEdgeVerts = _child->getEdgeVertices(cEdge);
|
||||
|
||||
cEdgeVerts[0] = _edgeChildVertIndex[pEdge];
|
||||
cEdgeVerts[1] = _vertChildVertIndex[pEdgeVerts[j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Methods to populate the edge-face relation of the child Level:
|
||||
// - child edges originate from parent faces and edges
|
||||
// - sparse refinement poses challenges with allocation here
|
||||
// - we need to update the counts/offsets as we populate
|
||||
//
|
||||
void
|
||||
QuadRefinement::populateEdgeFaceRelation() {
|
||||
|
||||
//
|
||||
// Notes on allocating/initializing the edge-face counts/offsets vector:
|
||||
//
|
||||
// Be aware of scheme-specific decisions here, e.g.:
|
||||
// - inspection of sparse child faces for edges from faces
|
||||
// - no guaranteed "neighborhood" around Bilinear verts from verts
|
||||
//
|
||||
// If uniform subdivision, face count of a child edge will be:
|
||||
// - 2 for new interior edges from parent faces
|
||||
// == 2 * number of parent face verts for both quad- and tri-split
|
||||
// - same as parent edge for edges from parent edges
|
||||
// If sparse subdivision, face count of a child edge will be:
|
||||
// - 1 or 2 for new interior edge depending on child faces in parent face
|
||||
// - requires inspection if not all child faces present
|
||||
// ? same as parent edge for edges from parent edges
|
||||
// - given end vertex must have its full set of child faces
|
||||
// - not for Bilinear -- only if neighborhood is non-zero
|
||||
// - could at least make a quick traversal of components and use the above
|
||||
// two points to get much closer estimate than what is used for uniform
|
||||
//
|
||||
int childEdgeFaceIndexSizeEstimate = (int)_parent->_faceVertIndices.size() * 2 +
|
||||
(int)_parent->_edgeFaceIndices.size() * 2;
|
||||
|
||||
_child->_edgeFaceCountsAndOffsets.resize(_child->getNumEdges() * 2);
|
||||
_child->_edgeFaceIndices.resize( childEdgeFaceIndexSizeEstimate);
|
||||
_child->_edgeFaceLocalIndices.resize(childEdgeFaceIndexSizeEstimate);
|
||||
|
||||
// Update _maxEdgeFaces from the parent level before calling the
|
||||
// populateEdgeFacesFromParent methods below, as these may further
|
||||
// update _maxEdgeFaces.
|
||||
_child->_maxEdgeFaces = _parent->_maxEdgeFaces;
|
||||
|
||||
populateEdgeFacesFromParentFaces();
|
||||
populateEdgeFacesFromParentEdges();
|
||||
|
||||
// Revise the over-allocated estimate based on what is used (as indicated in the
|
||||
// count/offset for the last vertex) and trim the index vector accordingly:
|
||||
childEdgeFaceIndexSizeEstimate = _child->getNumEdgeFaces(_child->getNumEdges()-1) +
|
||||
_child->getOffsetOfEdgeFaces(_child->getNumEdges()-1);
|
||||
_child->_edgeFaceIndices.resize( childEdgeFaceIndexSizeEstimate);
|
||||
_child->_edgeFaceLocalIndices.resize(childEdgeFaceIndexSizeEstimate);
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateEdgeFacesFromParentFaces() {
|
||||
|
||||
//
|
||||
// This is straightforward topologically, but when refinement is sparse the
|
||||
// contents of the counts/offsets vector is not certain and is populated
|
||||
// incrementally. So there will be some resizing/trimming here.
|
||||
//
|
||||
// Topologically, the child edges from within a parent face will typically
|
||||
// have two incident child faces (only one or none if sparse). These child
|
||||
// edges and faces are interleaved within the parent and easily identified.
|
||||
// Note that the edge-face "local indices" are also needed here and that
|
||||
// orientation of child faces within their parent depends on it being a quad
|
||||
// or not.
|
||||
//
|
||||
for (Index pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
|
||||
ConstIndexArray pFaceChildFaces = getFaceChildFaces(pFace),
|
||||
pFaceChildEdges = getFaceChildEdges(pFace);
|
||||
|
||||
int pFaceSize = pFaceChildFaces.size();
|
||||
|
||||
for (int j = 0; j < pFaceSize; ++j) {
|
||||
Index cEdge = pFaceChildEdges[j];
|
||||
if (IndexIsValid(cEdge)) {
|
||||
//
|
||||
// Reserve enough edge-faces, populate and trim as needed:
|
||||
//
|
||||
_child->resizeEdgeFaces(cEdge, 2);
|
||||
|
||||
IndexArray cEdgeFaces = _child->getEdgeFaces(cEdge);
|
||||
LocalIndexArray cEdgeInFace = _child->getEdgeFaceLocalIndices(cEdge);
|
||||
|
||||
// One or two child faces may be assigned:
|
||||
int jNext = ((j + 1) < pFaceSize) ? (j + 1) : 0;
|
||||
|
||||
int cEdgeFaceCount = 0;
|
||||
if (IndexIsValid(pFaceChildFaces[j])) {
|
||||
// Note orientation wrt incident parent faces -- quad vs non-quad...
|
||||
cEdgeFaces[cEdgeFaceCount] = pFaceChildFaces[j];
|
||||
cEdgeInFace[cEdgeFaceCount] = (LocalIndex)((pFaceSize == 4) ? jNext : 1);
|
||||
cEdgeFaceCount++;
|
||||
}
|
||||
if (IndexIsValid(pFaceChildFaces[jNext])) {
|
||||
// Note orientation wrt incident parent faces -- quad vs non-quad...
|
||||
cEdgeFaces[cEdgeFaceCount] = pFaceChildFaces[jNext];
|
||||
cEdgeInFace[cEdgeFaceCount] = (LocalIndex)((pFaceSize == 4) ? ((jNext + 2) & 3) : 2);
|
||||
cEdgeFaceCount++;
|
||||
}
|
||||
_child->trimEdgeFaces(cEdge, cEdgeFaceCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateEdgeFacesFromParentEdges() {
|
||||
|
||||
//
|
||||
// Note -- the edge-face counts/offsets vector is not known
|
||||
// ahead of time and is populated incrementally, so we cannot
|
||||
// thread this yet...
|
||||
//
|
||||
for (Index pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
|
||||
ConstIndexArray pEdgeChildEdges = getEdgeChildEdges(pEdge);
|
||||
if (!IndexIsValid(pEdgeChildEdges[0]) && !IndexIsValid(pEdgeChildEdges[1])) continue;
|
||||
|
||||
ConstIndexArray pEdgeFaces = _parent->getEdgeFaces(pEdge);
|
||||
ConstLocalIndexArray pEdgeInFace = _parent->getEdgeFaceLocalIndices(pEdge);
|
||||
ConstIndexArray pEdgeVerts = _parent->getEdgeVertices(pEdge);
|
||||
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
Index cEdge = pEdgeChildEdges[j];
|
||||
if (!IndexIsValid(cEdge)) continue;
|
||||
|
||||
// Reserve enough edge-faces, populate and trim as needed:
|
||||
_child->resizeEdgeFaces(cEdge, pEdgeFaces.size());
|
||||
|
||||
IndexArray cEdgeFaces = _child->getEdgeFaces(cEdge);
|
||||
LocalIndexArray cEdgeInFace = _child->getEdgeFaceLocalIndices(cEdge);
|
||||
|
||||
//
|
||||
// Each parent face may contribute an incident child face:
|
||||
//
|
||||
int cEdgeFaceCount = 0;
|
||||
|
||||
for (int i = 0; i < pEdgeFaces.size(); ++i) {
|
||||
Index pFace = pEdgeFaces[i];
|
||||
int edgeInFace = pEdgeInFace[i];
|
||||
|
||||
ConstIndexArray pFaceVerts = _parent->getFaceVertices(pFace),
|
||||
pFaceChildren = getFaceChildFaces(pFace);
|
||||
|
||||
//
|
||||
// We need to first identify the potentially incident child-face and see
|
||||
// if it exists before we can assign it. Beware a degenerate edge here
|
||||
// when inspecting the undirected edge.
|
||||
//
|
||||
int childOfEdge = (pEdgeVerts[0] == pEdgeVerts[1]) ? j : (pFaceVerts[edgeInFace] != pEdgeVerts[j]);
|
||||
|
||||
int childInFace = edgeInFace + childOfEdge;
|
||||
if (childInFace == pFaceChildren.size()) childInFace = 0;
|
||||
|
||||
if (IndexIsValid(pFaceChildren[childInFace])) {
|
||||
// Note orientation wrt incident parent faces -- quad vs non-quad...
|
||||
cEdgeFaces[cEdgeFaceCount] = pFaceChildren[childInFace];
|
||||
cEdgeInFace[cEdgeFaceCount] = (LocalIndex)
|
||||
((pFaceVerts.size() == 4) ? edgeInFace : (childOfEdge ? 3 : 0));
|
||||
cEdgeFaceCount++;
|
||||
}
|
||||
}
|
||||
_child->trimEdgeFaces(cEdge, cEdgeFaceCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Methods to populate the vertex-face relation of the child Level:
|
||||
// - child vertices originate from parent faces, edges and vertices
|
||||
// - sparse refinement poses challenges with allocation here:
|
||||
// - we need to update the counts/offsets as we populate
|
||||
// - note this imposes ordering constraints and inhibits concurrency
|
||||
//
|
||||
void
|
||||
QuadRefinement::populateVertexFaceRelation() {
|
||||
|
||||
//
|
||||
// Notes on allocating/initializing the vertex-face counts/offsets vector:
|
||||
//
|
||||
// Be aware of scheme-specific decisions here, e.g.:
|
||||
// - no verts from parent faces for Loop (unless N-gons supported)
|
||||
// - more interior edges and faces for verts from parent edges for Loop
|
||||
// - no guaranteed "neighborhood" around Bilinear verts from verts
|
||||
//
|
||||
// If uniform subdivision, vert-face count will be (catmark or loop):
|
||||
// - 4 or 0 for verts from parent faces (for catmark)
|
||||
// - 2x or 3x number in parent edge for verts from parent edges
|
||||
// - same as parent vert for verts from parent verts
|
||||
// If sparse subdivision, vert-face count will be:
|
||||
// - the number of child faces in parent face
|
||||
// - 1 or 2x number in parent edge for verts from parent edges
|
||||
// - where the 1 or 2 is number of child edges of parent edge
|
||||
// - same as parent vert for verts from parent verts (catmark)
|
||||
//
|
||||
int childVertFaceIndexSizeEstimate = (int)_parent->_faceVertIndices.size()
|
||||
+ (int)_parent->_edgeFaceIndices.size() * 2
|
||||
+ (int)_parent->_vertFaceIndices.size();
|
||||
|
||||
_child->_vertFaceCountsAndOffsets.resize(_child->getNumVertices() * 2);
|
||||
_child->_vertFaceIndices.resize( childVertFaceIndexSizeEstimate);
|
||||
_child->_vertFaceLocalIndices.resize( childVertFaceIndexSizeEstimate);
|
||||
|
||||
if (getFirstChildVertexFromVertices() == 0) {
|
||||
populateVertexFacesFromParentVertices();
|
||||
populateVertexFacesFromParentFaces();
|
||||
populateVertexFacesFromParentEdges();
|
||||
} else {
|
||||
populateVertexFacesFromParentFaces();
|
||||
populateVertexFacesFromParentEdges();
|
||||
populateVertexFacesFromParentVertices();
|
||||
}
|
||||
|
||||
// Revise the over-allocated estimate based on what is used (as indicated in the
|
||||
// count/offset for the last vertex) and trim the index vectors accordingly:
|
||||
childVertFaceIndexSizeEstimate = _child->getNumVertexFaces(_child->getNumVertices()-1) +
|
||||
_child->getOffsetOfVertexFaces(_child->getNumVertices()-1);
|
||||
_child->_vertFaceIndices.resize( childVertFaceIndexSizeEstimate);
|
||||
_child->_vertFaceLocalIndices.resize(childVertFaceIndexSizeEstimate);
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateVertexFacesFromParentFaces() {
|
||||
|
||||
for (int pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
|
||||
int cVert = _faceChildVertIndex[pFace];
|
||||
if (!IndexIsValid(cVert)) continue;
|
||||
|
||||
ConstIndexArray pFaceChildren = getFaceChildFaces(pFace);
|
||||
int pFaceSize = pFaceChildren.size();
|
||||
|
||||
//
|
||||
// Reserve enough vert-faces, populate and trim to the actual size:
|
||||
//
|
||||
_child->resizeVertexFaces(cVert, pFaceSize);
|
||||
|
||||
IndexArray cVertFaces = _child->getVertexFaces(cVert);
|
||||
LocalIndexArray cVertInFace = _child->getVertexFaceLocalIndices(cVert);
|
||||
|
||||
//
|
||||
// Inspect each of the child faces of this parent face and add those that
|
||||
// exist as incident the child vertex of this face:
|
||||
//
|
||||
int cVertFaceCount = 0;
|
||||
for (int j = 0; j < pFaceSize; ++j) {
|
||||
if (IndexIsValid(pFaceChildren[j])) {
|
||||
// Note orientation wrt parent face -- quad vs non-quad...
|
||||
cVertFaces[cVertFaceCount] = pFaceChildren[j];
|
||||
cVertInFace[cVertFaceCount] = (LocalIndex)((pFaceSize == 4) ? ((j+2) & 3) : 2);
|
||||
cVertFaceCount++;
|
||||
}
|
||||
}
|
||||
_child->trimVertexFaces(cVert, cVertFaceCount);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateVertexFacesFromParentEdges() {
|
||||
|
||||
for (int pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
|
||||
int cVert = _edgeChildVertIndex[pEdge];
|
||||
if (!IndexIsValid(cVert)) continue;
|
||||
|
||||
ConstIndexArray pEdgeFaces = _parent->getEdgeFaces(pEdge);
|
||||
ConstLocalIndexArray pEdgeInFace = _parent->getEdgeFaceLocalIndices(pEdge);
|
||||
|
||||
//
|
||||
// Reserve enough vert-faces, populate and trim to the actual size:
|
||||
//
|
||||
_child->resizeVertexFaces(cVert, 2 * pEdgeFaces.size());
|
||||
|
||||
IndexArray cVertFaces = _child->getVertexFaces(cVert);
|
||||
LocalIndexArray cVertInFace = _child->getVertexFaceLocalIndices(cVert);
|
||||
|
||||
//
|
||||
// For each face incident the parent edge, identify its corresponding two child faces
|
||||
// and assign those of the two that exist. The second face is considered and added
|
||||
// first to preserve CC-wise ordering of faces wrt the vertex.
|
||||
//
|
||||
int cVertFaceCount = 0;
|
||||
for (int i = 0; i < pEdgeFaces.size(); ++i) {
|
||||
Index pFace = pEdgeFaces[i];
|
||||
int edgeInFace = pEdgeInFace[i];
|
||||
|
||||
ConstIndexArray pFaceChildren = getFaceChildFaces(pFace);
|
||||
int pFaceSize = pFaceChildren.size();
|
||||
|
||||
int faceChild0 = edgeInFace;
|
||||
int faceChild1 = edgeInFace + 1;
|
||||
if (faceChild1 == pFaceChildren.size()) faceChild1 = 0;
|
||||
|
||||
if (IndexIsValid(pFaceChildren[faceChild1])) {
|
||||
// Note orientation wrt incident parent faces -- quad vs non-quad...
|
||||
cVertFaces[cVertFaceCount] = pFaceChildren[faceChild1];
|
||||
cVertInFace[cVertFaceCount] = (LocalIndex)((pFaceSize == 4) ? faceChild0 : 3);
|
||||
cVertFaceCount++;
|
||||
}
|
||||
if (IndexIsValid(pFaceChildren[faceChild0])) {
|
||||
// Note orientation wrt incident parent faces -- quad vs non-quad...
|
||||
cVertFaces[cVertFaceCount] = pFaceChildren[faceChild0];
|
||||
cVertInFace[cVertFaceCount] = (LocalIndex)((pFaceSize == 4) ? faceChild1 : 1);
|
||||
cVertFaceCount++;
|
||||
}
|
||||
}
|
||||
_child->trimVertexFaces(cVert, cVertFaceCount);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateVertexFacesFromParentVertices() {
|
||||
|
||||
for (int pVert = 0; pVert < _parent->getNumVertices(); ++pVert) {
|
||||
int cVert = _vertChildVertIndex[pVert];
|
||||
if (!IndexIsValid(cVert)) continue;
|
||||
|
||||
ConstIndexArray pVertFaces = _parent->getVertexFaces(pVert);
|
||||
ConstLocalIndexArray pVertInFace = _parent->getVertexFaceLocalIndices(pVert);
|
||||
|
||||
//
|
||||
// Reserve enough vert-faces, populate and trim to the actual size:
|
||||
//
|
||||
_child->resizeVertexFaces(cVert, pVertFaces.size());
|
||||
|
||||
IndexArray cVertFaces = _child->getVertexFaces(cVert);
|
||||
LocalIndexArray cVertInFace = _child->getVertexFaceLocalIndices(cVert);
|
||||
|
||||
//
|
||||
// Inspect each of the faces incident the parent vertex and add those that
|
||||
// spawned a child face corresponding to (and so incident) this child vertex:
|
||||
//
|
||||
int cVertFaceCount = 0;
|
||||
for (int i = 0; i < pVertFaces.size(); ++i) {
|
||||
Index pFace = pVertFaces[i];
|
||||
LocalIndex vertInFace = pVertInFace[i];
|
||||
|
||||
ConstIndexArray pFaceChildren = getFaceChildFaces(pFace);
|
||||
|
||||
if (IndexIsValid(pFaceChildren[vertInFace])) {
|
||||
int pFaceSize = pFaceChildren.size();
|
||||
|
||||
// Note orientation wrt incident parent faces -- quad vs non-quad...
|
||||
cVertFaces[cVertFaceCount] = pFaceChildren[vertInFace];
|
||||
cVertInFace[cVertFaceCount] = (LocalIndex)((pFaceSize == 4) ? vertInFace : 0);
|
||||
cVertFaceCount++;
|
||||
}
|
||||
}
|
||||
_child->trimVertexFaces(cVert, cVertFaceCount);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Methods to populate the vertex-edge relation of the child Level:
|
||||
// - child vertices originate from parent faces, edges and vertices
|
||||
// - sparse refinement poses challenges with allocation here:
|
||||
// - we need to update the counts/offsets as we populate
|
||||
// - note this imposes ordering constraints and inhibits concurrency
|
||||
//
|
||||
void
|
||||
QuadRefinement::populateVertexEdgeRelation() {
|
||||
|
||||
//
|
||||
// Notes on allocating/initializing the vertex-edge counts/offsets vector:
|
||||
//
|
||||
// Be aware of scheme-specific decisions here, e.g.:
|
||||
// - no verts from parent faces for Loop
|
||||
// - more interior edges and faces for verts from parent edges for Loop
|
||||
// - no guaranteed "neighborhood" around Bilinear verts from verts
|
||||
//
|
||||
// If uniform subdivision, vert-edge count will be:
|
||||
// - 4 or 0 for verts from parent faces (for catmark)
|
||||
// - 2 + N or 2 + 2*N faces incident parent edge for verts from parent edges
|
||||
// - same as parent vert for verts from parent verts
|
||||
// If sparse subdivision, vert-edge count will be:
|
||||
// - non-trivial function of child faces in parent face
|
||||
// - 1 child face will always result in 2 child edges
|
||||
// * 2 child faces can mean 3 or 4 child edges
|
||||
// - 3 child faces will always result in 4 child edges
|
||||
// - 1 or 2 + N faces incident parent edge for verts from parent edges
|
||||
// - where the 1 or 2 is number of child edges of parent edge
|
||||
// - any end vertex will require all N child faces (catmark)
|
||||
// - same as parent vert for verts from parent verts (catmark)
|
||||
//
|
||||
int childVertEdgeIndexSizeEstimate = (int)_parent->_faceVertIndices.size()
|
||||
+ (int)_parent->_edgeFaceIndices.size() + _parent->getNumEdges() * 2
|
||||
+ (int)_parent->_vertEdgeIndices.size();
|
||||
|
||||
_child->_vertEdgeCountsAndOffsets.resize(_child->getNumVertices() * 2);
|
||||
_child->_vertEdgeIndices.resize( childVertEdgeIndexSizeEstimate);
|
||||
_child->_vertEdgeLocalIndices.resize( childVertEdgeIndexSizeEstimate);
|
||||
|
||||
if (getFirstChildVertexFromVertices() == 0) {
|
||||
populateVertexEdgesFromParentVertices();
|
||||
populateVertexEdgesFromParentFaces();
|
||||
populateVertexEdgesFromParentEdges();
|
||||
} else {
|
||||
populateVertexEdgesFromParentFaces();
|
||||
populateVertexEdgesFromParentEdges();
|
||||
populateVertexEdgesFromParentVertices();
|
||||
}
|
||||
|
||||
// Revise the over-allocated estimate based on what is used (as indicated in the
|
||||
// count/offset for the last vertex) and trim the index vectors accordingly:
|
||||
childVertEdgeIndexSizeEstimate = _child->getNumVertexEdges(_child->getNumVertices()-1) +
|
||||
_child->getOffsetOfVertexEdges(_child->getNumVertices()-1);
|
||||
_child->_vertEdgeIndices.resize( childVertEdgeIndexSizeEstimate);
|
||||
_child->_vertEdgeLocalIndices.resize(childVertEdgeIndexSizeEstimate);
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::populateVertexEdgesFromParentFaces() {
|
||||
|
||||
for (int pFace = 0; pFace < _parent->getNumFaces(); ++pFace) {
|
||||
int cVert = _faceChildVertIndex[pFace];
|
||||
if (!IndexIsValid(cVert)) continue;
|
||||
|
||||
ConstIndexArray pFaceVerts = _parent->getFaceVertices(pFace),
|
||||
pFaceChildEdges = getFaceChildEdges(pFace);
|
||||
|
||||
//
|
||||
// Reserve enough vert-edges, populate and trim to the actual size:
|
||||
//
|
||||
_child->resizeVertexEdges(cVert, pFaceVerts.size());
|
||||
|
||||
IndexArray cVertEdges = _child->getVertexEdges(cVert);
|
||||
LocalIndexArray cVertInEdge = _child->getVertexEdgeLocalIndices(cVert);
|
||||
|
||||
//
|
||||
// Need to ensure correct ordering here when complete -- we want the "leading"
|
||||
// edge of each child face first. The child vert is in the center of a new
|
||||
// face so new "boundaries" will only occur when the vertex is incomplete.
|
||||
//
|
||||
int cVertEdgeCount = 0;
|
||||
for (int j = 0; j < pFaceVerts.size(); ++j) {
|
||||
int jLeadingEdge = j ? (j - 1) : (pFaceVerts.size() - 1);
|
||||
if (IndexIsValid(pFaceChildEdges[jLeadingEdge])) {
|
||||
cVertEdges[cVertEdgeCount] = pFaceChildEdges[jLeadingEdge];
|
||||
cVertInEdge[cVertEdgeCount] = 0;
|
||||
cVertEdgeCount++;
|
||||
}
|
||||
}
|
||||
_child->trimVertexEdges(cVert, cVertEdgeCount);
|
||||
}
|
||||
}
|
||||
void
|
||||
QuadRefinement::populateVertexEdgesFromParentEdges() {
|
||||
|
||||
//
|
||||
// This relation turns out to be awkward to populate given the mixed parentage
|
||||
// of the incident edges of the child vertex of an edge -- two child edges
|
||||
// originate from the parent edge while one or more will originate from the
|
||||
// faces incident the parent edge. The need to interleave these for proper
|
||||
// CC-wise orientation is what really complicates this.
|
||||
//
|
||||
// Unlike other relations, we generate the results and then re-order them as
|
||||
// needed. In this case we assign the first two incident edges as the child
|
||||
// edges of the parent edge, followed then by those originating from a parent
|
||||
// face. We then swap the second and third (and possibly the first two) so
|
||||
// that we have the desired origin sequence beginning [edge, face, edge, ...]
|
||||
//
|
||||
for (int pEdge = 0; pEdge < _parent->getNumEdges(); ++pEdge) {
|
||||
int cVert = _edgeChildVertIndex[pEdge];
|
||||
if (!IndexIsValid(cVert)) continue;
|
||||
|
||||
ConstIndexArray pEdgeFaces = _parent->getEdgeFaces(pEdge);
|
||||
ConstLocalIndexArray pEdgeInFace = _parent->getEdgeFaceLocalIndices(pEdge);
|
||||
|
||||
ConstIndexArray pEdgeVerts = _parent->getEdgeVertices(pEdge),
|
||||
pEdgeChildEdges = getEdgeChildEdges(pEdge);
|
||||
|
||||
//
|
||||
// Reserve enough vert-edges, populate and trim to the actual size:
|
||||
//
|
||||
_child->resizeVertexEdges(cVert, pEdgeFaces.size() + 2);
|
||||
|
||||
IndexArray cVertEdges = _child->getVertexEdges(cVert);
|
||||
LocalIndexArray cVertInEdge = _child->getVertexEdgeLocalIndices(cVert);
|
||||
|
||||
//
|
||||
// Identify and assign the first two child edges of the parent edge -- until
|
||||
// we look more closely at the orientation of the parent edge in the first
|
||||
// face we don't know what order these two should be in, so just assign them
|
||||
// for now and swap them later if necessary:
|
||||
//
|
||||
int cVertEdgeCount = 0;
|
||||
|
||||
if (IndexIsValid(pEdgeChildEdges[0])) {
|
||||
cVertEdges[cVertEdgeCount] = pEdgeChildEdges[0];
|
||||
cVertInEdge[cVertEdgeCount] = 0;
|
||||
cVertEdgeCount++;
|
||||
}
|
||||
if (IndexIsValid(pEdgeChildEdges[1])) {
|
||||
cVertEdges[cVertEdgeCount] = pEdgeChildEdges[1];
|
||||
cVertInEdge[cVertEdgeCount] = 0;
|
||||
cVertEdgeCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// Append the interior edge of each incident parent face -- swapping the
|
||||
// first face-edge with the second edge-edge just added to get the desired
|
||||
// sequence of child edges originating from (edge, face0, edge, ...)
|
||||
//
|
||||
for (int i = 0; i < pEdgeFaces.size(); ++i) {
|
||||
Index pFace = pEdgeFaces[i];
|
||||
int edgeInFace = pEdgeInFace[i];
|
||||
|
||||
Index cEdgeOfFace = getFaceChildEdges(pFace)[edgeInFace];
|
||||
|
||||
if (IndexIsValid(cEdgeOfFace)) {
|
||||
cVertEdges[cVertEdgeCount] = cEdgeOfFace;
|
||||
cVertInEdge[cVertEdgeCount] = 1;
|
||||
cVertEdgeCount++;
|
||||
|
||||
// Check if swapping this first face-edge with the last edge-edge
|
||||
// is necessary:
|
||||
if ((i == 0) && (cVertEdgeCount == 3)) {
|
||||
// Remember to order the first of the two child edges according
|
||||
// to the parent edge's orientation in this first face:
|
||||
if ((pEdgeVerts[0] != pEdgeVerts[1]) &&
|
||||
(_parent->getFaceVertices(pFace)[edgeInFace] == pEdgeVerts[0])) {
|
||||
std::swap(cVertEdges[0], cVertEdges[1]);
|
||||
std::swap(cVertInEdge[0], cVertInEdge[1]);
|
||||
}
|
||||
std::swap(cVertEdges[1], cVertEdges[2]);
|
||||
std::swap(cVertInEdge[1], cVertInEdge[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
_child->trimVertexEdges(cVert, cVertEdgeCount);
|
||||
}
|
||||
}
|
||||
void
|
||||
QuadRefinement::populateVertexEdgesFromParentVertices() {
|
||||
|
||||
for (int pVert = 0; pVert < _parent->getNumVertices(); ++pVert) {
|
||||
int cVert = _vertChildVertIndex[pVert];
|
||||
if (!IndexIsValid(cVert)) continue;
|
||||
|
||||
ConstIndexArray pVertEdges = _parent->getVertexEdges(pVert);
|
||||
ConstLocalIndexArray pVertInEdge = _parent->getVertexEdgeLocalIndices(pVert);
|
||||
|
||||
//
|
||||
// Reserve enough vert-edges, populate and trim to the actual size:
|
||||
//
|
||||
_child->resizeVertexEdges(cVert, pVertEdges.size());
|
||||
|
||||
IndexArray cVertEdges = _child->getVertexEdges(cVert);
|
||||
LocalIndexArray cVertInEdge = _child->getVertexEdgeLocalIndices(cVert);
|
||||
|
||||
int cVertEdgeCount = 0;
|
||||
for (int i = 0; i < pVertEdges.size(); ++i) {
|
||||
Index pEdgeIndex = pVertEdges[i];
|
||||
LocalIndex pEdgeVert = pVertInEdge[i];
|
||||
|
||||
Index pEdgeChildIndex = getEdgeChildEdges(pEdgeIndex)[pEdgeVert];
|
||||
if (IndexIsValid(pEdgeChildIndex)) {
|
||||
cVertEdges[cVertEdgeCount] = pEdgeChildIndex;
|
||||
cVertInEdge[cVertEdgeCount] = 1;
|
||||
cVertEdgeCount++;
|
||||
}
|
||||
}
|
||||
_child->trimVertexEdges(cVert, cVertEdgeCount);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Methods to populate child-component indices for sparse selection:
|
||||
//
|
||||
// Need to find a better place for these anon helper methods now that they are required
|
||||
// both in the base class and the two subclasses for quad- and tri-splitting...
|
||||
//
|
||||
namespace {
|
||||
Index const IndexSparseMaskNeighboring = (1 << 0);
|
||||
Index const IndexSparseMaskSelected = (1 << 1);
|
||||
|
||||
inline void markSparseIndexNeighbor(Index& index) { index = IndexSparseMaskNeighboring; }
|
||||
inline void markSparseIndexSelected(Index& index) { index = IndexSparseMaskSelected; }
|
||||
}
|
||||
|
||||
void
|
||||
QuadRefinement::markSparseFaceChildren() {
|
||||
|
||||
assert(_parentFaceTag.size() > 0);
|
||||
|
||||
//
|
||||
// For each parent face:
|
||||
// All boundary edges will be adequately marked as a result of the pass over the
|
||||
// edges above and boundary vertices marked by selection. So all that remains is to
|
||||
// identify the child faces and interior child edges for a face requiring neighboring
|
||||
// child faces.
|
||||
// For each corner vertex selected, we need to mark the corresponding child face,
|
||||
// the two interior child edges and shared child vertex in the middle.
|
||||
//
|
||||
assert(_splitType == Sdc::SPLIT_TO_QUADS);
|
||||
|
||||
for (Index pFace = 0; pFace < parent().getNumFaces(); ++pFace) {
|
||||
//
|
||||
// Mark all descending child components of a selected face. Otherwise inspect
|
||||
// its incident vertices to see if anything neighboring has been selected --
|
||||
// requiring partial refinement of this face.
|
||||
//
|
||||
// Remember that a selected face cannot be transitional, and that only a
|
||||
// transitional face will be partially refined.
|
||||
//
|
||||
IndexArray fChildFaces = getFaceChildFaces(pFace);
|
||||
IndexArray fChildEdges = getFaceChildEdges(pFace);
|
||||
|
||||
ConstIndexArray fVerts = parent().getFaceVertices(pFace);
|
||||
|
||||
SparseTag& pFaceTag = _parentFaceTag[pFace];
|
||||
|
||||
if (pFaceTag._selected) {
|
||||
for (int i = 0; i < fVerts.size(); ++i) {
|
||||
markSparseIndexSelected(fChildFaces[i]);
|
||||
markSparseIndexSelected(fChildEdges[i]);
|
||||
}
|
||||
markSparseIndexSelected(_faceChildVertIndex[pFace]);
|
||||
|
||||
pFaceTag._transitional = 0;
|
||||
} else {
|
||||
int marked = false;
|
||||
|
||||
for (int i = 0; i < fVerts.size(); ++i) {
|
||||
if (_parentVertexTag[fVerts[i]]._selected) {
|
||||
int iPrev = i ? (i - 1) : (fVerts.size() - 1);
|
||||
|
||||
markSparseIndexNeighbor(fChildFaces[i]);
|
||||
|
||||
markSparseIndexNeighbor(fChildEdges[i]);
|
||||
markSparseIndexNeighbor(fChildEdges[iPrev]);
|
||||
|
||||
marked = true;
|
||||
}
|
||||
}
|
||||
if (marked) {
|
||||
markSparseIndexNeighbor(_faceChildVertIndex[pFace]);
|
||||
|
||||
//
|
||||
// Assign selection and transitional tags to faces when required:
|
||||
//
|
||||
// Only non-selected faces may be "transitional", and we need to inspect
|
||||
// all tags on its boundary edges to be sure. Since we're inspecting each
|
||||
// now (and may need to later) retain the transitional state of each in a
|
||||
// 4-bit mask that reflects the full transitional topology for later.
|
||||
//
|
||||
ConstIndexArray fEdges = parent().getFaceEdges(pFace);
|
||||
if (fEdges.size() == 4) {
|
||||
pFaceTag._transitional = (unsigned char)
|
||||
((_parentEdgeTag[fEdges[0]]._transitional << 0) |
|
||||
(_parentEdgeTag[fEdges[1]]._transitional << 1) |
|
||||
(_parentEdgeTag[fEdges[2]]._transitional << 2) |
|
||||
(_parentEdgeTag[fEdges[3]]._transitional << 3));
|
||||
} else if (fEdges.size() == 3) {
|
||||
pFaceTag._transitional = (unsigned char)
|
||||
((_parentEdgeTag[fEdges[0]]._transitional << 0) |
|
||||
(_parentEdgeTag[fEdges[1]]._transitional << 1) |
|
||||
(_parentEdgeTag[fEdges[2]]._transitional << 2));
|
||||
} else {
|
||||
pFaceTag._transitional = 0;
|
||||
for (int i = 0; i < fEdges.size(); ++i) {
|
||||
pFaceTag._transitional |= _parentEdgeTag[fEdges[i]]._transitional;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Vtr
|
||||
|
||||
} // end namespace OPENSUBDIV_VERSION
|
||||
} // end namespace OpenSubdiv
|
||||
Reference in New Issue
Block a user