Add a function to Far::TopologyRefiner to gather ptex adjacency for a given face / quadrant pair

- also refactor Vtr::Array 'FindIndex' functions
This commit is contained in:
manuelk 2014-09-26 15:10:57 -07:00
parent 19ed202965
commit aacd43a09b
4 changed files with 171 additions and 20 deletions

View File

@ -110,7 +110,9 @@ TopologyRefiner::GetNumFVarValuesTotal(int channel) const {
return sum;
}
//
// Ptex information accessors
//
template <Sdc::Type SCHEME_TYPE> void
computePtexIndices(Vtr::Level const & coarseLevel, std::vector<int> & ptexIndices) {
int nfaces = coarseLevel.getNumFaces();
@ -149,10 +151,135 @@ TopologyRefiner::GetPtexIndex(Index f) const {
if (_ptexIndices.empty()) {
initializePtexIndices();
}
if (f<((int)_ptexIndices.size()-1)) {
return _ptexIndices[f];
assert(f<(int)_ptexIndices.size());
return _ptexIndices[f];
}
namespace {
// Returns the face adjacent to 'face' along edge 'edge'
inline Index
getAdjacentFace(Vtr::Level const & level, Index edge, Index face) {
IndexArray adjFaces = level.getEdgeFaces(edge);
if (adjFaces.size()!=2) {
return -1;
}
return (adjFaces[0]==face) ? adjFaces[1] : adjFaces[0];
}
}
void
TopologyRefiner::GetPtexAdjacency(int face, int quadrant,
int adjFaces[4], int adjEdges[4]) const {
assert(GetSchemeType()==Sdc::TYPE_CATMARK);
if (_ptexIndices.empty()) {
initializePtexIndices();
}
Vtr::Level const & level = _levels[0];
IndexArray fedges = level.getFaceEdges(face);
if (fedges.size()==4) {
// Regular ptex quad face
for (int i=0; i<4; ++i) {
int edge = fedges[i];
IndexArray efaces = level.getEdgeFaces(edge);
Index adjface = getAdjacentFace(level, edge, face);
if (adjface==-1) {
adjFaces[i] = -1; // boundary or non-manifold
adjEdges[i] = 0;
} else {
IndexArray aedges = level.getFaceEdges(adjface);
if (aedges.size()==4) {
adjFaces[i] = _ptexIndices[adjface];
adjEdges[i] = aedges.FindIndexIn4Tuple(edge);
assert(adjEdges[i]!=-1);
} else {
// neighbor is a sub-face
adjFaces[i] = _ptexIndices[adjface] +
(aedges.FindIndex(edge)+1)%aedges.size();
adjEdges[i] = 3;
}
assert(adjFaces[i]!=-1);
}
}
} else {
// Ptex sub-face 'quadrant' (non-quad)
//
// Ptex adjacency pattern for non-quads:
//
// v2
/* o
// / \
// / \
// /0 3\
// / \
// o_ 1 2 _o
// / -_ _- \
// / 2 -o- 1 \
// /3 | 0\
// / 1|2 \
// / 0 | 3 \
// o----------o----------o
// v0 v1
*/
assert(quadrant>=0 and quadrant<fedges.size());
int nextQuadrant = (quadrant+1) % fedges.size(),
prevQuadrant = (quadrant+fedges.size()-1) % fedges.size();
{ // resolve neighbors within the sub-face (edges 1 & 2)
adjFaces[1] = _ptexIndices[face] + nextQuadrant;
adjEdges[1] = 2;
adjFaces[2] = _ptexIndices[face] + prevQuadrant;
adjEdges[2] = 1;
}
{ // resolve neighbor outisde the sub-face (edge 0)
int edge0 = fedges[quadrant];
Index adjface0 = getAdjacentFace(level, edge0, face);
if (adjface0==-1) {
adjFaces[0] = -1; // boundary or non-manifold
adjEdges[0] = 0;
} else {
IndexArray afedges = level.getFaceEdges(adjface0);
if (afedges.size()==4) {
adjFaces[0] = _ptexIndices[adjface0];
adjEdges[0] = afedges.FindIndexIn4Tuple(edge0);
} else {
int subedge = (afedges.FindIndex(edge0)+1)%afedges.size();
adjFaces[0] = _ptexIndices[adjface0] + subedge;
adjEdges[0] = 3;
}
assert(adjFaces[0]!=-1);
}
// resolve neighbor outisde the sub-face (edge 3)
int edge3 = fedges[prevQuadrant];
Index adjface3 = getAdjacentFace(level, edge3, face);
if (adjface3==-1) {
adjFaces[3]=-1; // boundary or non-manifold
adjEdges[3]=0;
} else {
IndexArray afedges = level.getFaceEdges(adjface3);
if (afedges.size()==4) {
adjFaces[3] = _ptexIndices[adjface3];
adjEdges[3] = afedges.FindIndexIn4Tuple(edge3);
} else {
int subedge = afedges.FindIndex(edge3);
adjFaces[3] = _ptexIndices[adjface3] + subedge;
adjEdges[3] = 0;
}
assert(adjFaces[3]!=-1);
}
}
}
return -1;
}
@ -280,7 +407,7 @@ TopologyRefiner::catmarkFeatureAdaptiveSelector(Vtr::SparseSelector& selector) {
// can identify an irregular face for all schemes):
//
if (faceVerts.size() != 4) {
//
//
// We need to also ensure that all adjacent faces to this are selected, so we
// select every face incident every vertex of the face. This is the only place
// where other faces are selected as a side effect and somewhat undermines the

View File

@ -377,6 +377,20 @@ public:
/// \brief Returns the ptex face index given a coarse face 'f' or -1
int GetPtexIndex(Index f) const;
/// \brief Returns ptex face adjacency information for a given coarse face
///
/// @param face coarse face index
///
/// @param quadrant quadrant index if 'face' is not a quad (the local ptex
// sub-face index). Must be less than the number of face
// vertices.
///
/// @param adjFaces ptex face indices of adjacent faces
///
/// @param adjFaces ptex edge indices of adjacent faces
///
void GetPtexAdjacency(int face, int quadrant,
int adjFaces[4], int adjEdges[4]) const;
//
// Debugging aides:
@ -474,7 +488,7 @@ private:
void initializePtexIndices() const;
private:
// The following should be private but leaving it open while still early...
Sdc::Type _subdivType;
Sdc::Options _subdivOptions;
@ -484,7 +498,7 @@ private:
std::vector<Vtr::Level> _levels;
std::vector<Vtr::Refinement> _refinements;
std::vector<Index> _ptexIndices;
std::vector<Index> _ptexIndices;
};
template <class T, class U>
@ -807,7 +821,7 @@ TopologyRefiner::InterpolateFaceVarying(T const * src, U * dst, int channel) con
for (int level=1; level<=GetMaxLevel(); ++level) {
InterpolateFaceVarying(level, src, dst, channel);
src = dst;
dst += _levels[level].getNumFVarValues();
}

View File

@ -26,6 +26,8 @@
#include "../version.h"
#include <cassert>
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
@ -78,6 +80,25 @@ public:
iterator begin() { return _begin; }
iterator end() { return _begin + _size; }
size_type FindIndexIn4Tuple(value_type value) const {
assert(_size>=4);
if (value == _begin[0]) return 0;
if (value == _begin[1]) return 1;
if (value == _begin[2]) return 2;
if (value == _begin[3]) return 3;
assert("FindIndexIn4Tuple() did not find expected value!" == 0);
return -1;
}
size_type FindIndex(value_type value) const {
for (size_type i=0; i<size(); ++i) {
if (value==_begin[i]) {
return i;
}
}
return -1;
}
protected:
value_type* _begin;
size_type _size;

View File

@ -480,17 +480,6 @@ Level::getFaceCompositeVTag(IndexArray const& faceVerts) const {
namespace {
template <typename INT_TYPE>
inline INT_TYPE fastMod4(INT_TYPE value) { return (value & 0x3); }
inline int
fastFindIn4(Index value, IndexArray const& array) {
if (value == array[0]) return 0;
if (value == array[1]) return 1;
if (value == array[2]) return 2;
if (value == array[3]) return 3;
assert("fastFindIn4() did not find expected value!" == 0);
return -1;
}
}
//
@ -592,7 +581,7 @@ Level::gatherQuadRegularInteriorPatchVertices(
IndexArray vFaces = level.getVertexFaces(v);
LocalIndexArray vInFaces = level.getVertexFaceLocalIndices(v);
int thisFaceInVFaces = fastFindIn4(thisFace, vFaces);
int thisFaceInVFaces = vFaces.FindIndexIn4Tuple(thisFace);
int intFaceInVFaces = fastMod4(thisFaceInVFaces + 2);
Index intFace = vFaces[intFaceInVFaces];