24 #ifndef FAR_TOPOLOGY_REFINER_H
25 #define FAR_TOPOLOGY_REFINER_H
27 #include "../version.h"
29 #include "../sdc/type.h"
30 #include "../sdc/options.h"
31 #include "../sdc/catmarkScheme.h"
32 #include "../vtr/level.h"
33 #include "../vtr/fvarLevel.h"
34 #include "../vtr/refinement.h"
35 #include "../vtr/fvarRefinement.h"
36 #include "../vtr/maskInterfaces.h"
37 #include "../far/types.h"
43 namespace OpenSubdiv {
44 namespace OPENSUBDIV_VERSION {
46 namespace Vtr {
class SparseSelector; }
108 void RefineUniform(
int maxLevel,
bool fullTopologyInLastLevel =
false);
117 void RefineAdaptive(
int maxLevel,
bool fullTopologyInLastLevel =
false);
125 #ifdef _VTR_COMPUTE_MASK_WEIGHTS_ENABLED
126 void ComputeMaskWeights();
145 template <
class T,
class U>
void Interpolate(T
const * src, U * dst)
const;
160 template <
class T,
class U>
void Interpolate(
int level, T
const * src, U * dst)
const;
192 template <
class T,
class U>
void InterpolateVarying(
int level, T
const * src, U * dst)
const;
199 template <
class T,
class U>
void InterpolateFaceVarying(
int level, T
const * src, U * dst,
int channel = 0)
const;
209 return _levels[level].getNumVertices();
214 return _levels[level].getNumEdges();
219 return _levels[level].getNumFaces();
224 return _levels[level].getNumFaceVerticesTotal();
229 return _levels[level].getEdgeSharpness(edge);
234 return _levels[level].getVertexSharpness(vert);
239 return _levels[level].getVertexRule(vert);
250 return _levels[level].getFaceVertices(face);
255 return _levels[level].getFaceEdges(face);
260 return _levels[level].getEdgeVertices(edge);
265 return _levels[level].getEdgeFaces(edge);
270 return _levels[level].getVertexFaces(vert);
275 return _levels[level].getVertexEdges(vert);
280 return _levels[level].getVertexFaceLocalIndices(vert);
285 return _levels[level].getVertexEdgeLocalIndices(vert);
291 return _levels[level].findEdge(v0, v1);
302 return _levels[0].getNumFVarChannels();
310 return _levels[level].getNumFVarValues(channel);
315 return _levels[level].getFVarFaceValues(face, channel);
327 return _refinements[level].getFaceChildFaces(f);
332 return _refinements[level].getFaceChildEdges(f);
337 return _refinements[level].getEdgeChildEdges(e);
342 return _refinements[level].getFaceChildVertex(f);
347 return _refinements[level].getEdgeChildVertex(e);
352 return _refinements[level].getVertexChildVertex(v);
374 return _levels[level].validateTopology();
379 _levels[level].print(children ? &_refinements[level] : 0);
388 template <
class MESH>
431 return _levels[0].createFVarChannel(numValues, _subdivOptions);
434 return _levels[0].createFVarChannel(numValues, options);
449 template <
class T,
class U>
void interpolateChildVertsFromFaces(
Vtr::Refinement const &, T
const * src, U * dst)
const;
450 template <
class T,
class U>
void interpolateChildVertsFromEdges(
Vtr::Refinement const &, T
const * src, U * dst)
const;
451 template <
class T,
class U>
void interpolateChildVertsFromVerts(
Vtr::Refinement const &, T
const * src, U * dst)
const;
453 template <
class T,
class U>
void varyingInterpolateChildVertsFromFaces(
Vtr::Refinement const &, T
const * src, U * dst)
const;
454 template <
class T,
class U>
void varyingInterpolateChildVertsFromEdges(
Vtr::Refinement const &, T
const * src, U * dst)
const;
455 template <
class T,
class U>
void varyingInterpolateChildVertsFromVerts(
Vtr::Refinement const &, T
const * src, U * dst)
const;
457 template <
class T,
class U>
void faceVaryingInterpolateChildVertsFromFaces(
Vtr::Refinement const &, T
const * src, U * dst,
int channel)
const;
458 template <
class T,
class U>
void faceVaryingInterpolateChildVertsFromEdges(
Vtr::Refinement const &, T
const * src, U * dst,
int channel)
const;
459 template <
class T,
class U>
void faceVaryingInterpolateChildVertsFromVerts(
Vtr::Refinement const &, T
const * src, U * dst,
int channel)
const;
462 void initializePtexIndices()
const;
472 std::vector<Vtr::Level> _levels;
473 std::vector<Vtr::Refinement> _refinements;
475 std::vector<Index> _ptexIndices;
478 template <
class T,
class U>
493 template <
class T,
class U>
497 assert(level>0 and level<=(
int)_refinements.size());
501 interpolateChildVertsFromFaces(refinement, src, dst);
502 interpolateChildVertsFromEdges(refinement, src, dst);
503 interpolateChildVertsFromVerts(refinement, src, dst);
506 template <
class T,
class U>
508 TopologyRefiner::interpolateChildVertsFromFaces(
515 float * fVertWeights = (
float *)alloca(parent.
getMaxValence()*
sizeof(float));
517 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
526 float fVaryingWeight = 1.0f / (float) fVerts.
size();
531 scheme.ComputeFaceVertexMask(fHood, fMask);
534 U & vdst = dst[cVert];
538 for (
int i = 0; i < fVerts.
size(); ++i) {
540 vdst.AddWithWeight(src[fVerts[i]], fVertWeights[i]);
542 vdst.AddVaryingWithWeight(src[fVerts[i]], fVaryingWeight);
547 template <
class T,
class U>
549 TopologyRefiner::interpolateChildVertsFromEdges(
550 Vtr::Refinement
const & refinement, T
const * src, U * dst)
const {
553 Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
555 const Vtr::Level& parent = refinement.parent();
556 const Vtr::Level& child = refinement.child();
558 Vtr::EdgeInterface eHood(parent);
560 float eVertWeights[2],
561 * eFaceWeights = (
float *)alloca(parent.getMaxEdgeFaces()*
sizeof(float));
563 for (
int edge = 0; edge < parent.getNumEdges(); ++edge) {
565 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
573 Vtr::MaskInterface eMask(eVertWeights, 0, eFaceWeights);
575 eHood.SetIndex(edge);
580 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
584 U & vdst = dst[cVert];
587 vdst.AddWithWeight(src[eVerts[0]], eVertWeights[0]);
588 vdst.AddWithWeight(src[eVerts[1]], eVertWeights[1]);
590 vdst.AddVaryingWithWeight(src[eVerts[0]], 0.5f);
591 vdst.AddVaryingWithWeight(src[eVerts[1]], 0.5f);
593 if (eMask.GetNumFaceWeights() > 0) {
595 for (
int i = 0; i < eFaces.size(); ++i) {
597 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
599 vdst.AddWithWeight(dst[cVertOfFace], eFaceWeights[i]);
605 template <
class T,
class U>
607 TopologyRefiner::interpolateChildVertsFromVerts(
608 Vtr::Refinement
const & refinement, T
const * src, U * dst)
const {
611 Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
613 const Vtr::Level& parent = refinement.parent();
614 const Vtr::Level& child = refinement.child();
616 Vtr::VertexInterface vHood(parent, child);
618 float * weightBuffer = (
float *)alloca(2*parent.getMaxValence()*
sizeof(float));
620 for (
int vert = 0; vert < parent.getNumVertices(); ++vert) {
622 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
631 * vEdgeWeights = weightBuffer,
632 * vFaceWeights = vEdgeWeights + vEdges.size();
634 Vtr::MaskInterface vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
636 vHood.SetIndex(vert, cVert);
641 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
645 U & vdst = dst[cVert];
648 vdst.AddWithWeight(src[vert], vVertWeight);
649 vdst.AddVaryingWithWeight(src[vert], 1.0f);
651 if (vMask.GetNumEdgeWeights() > 0) {
653 for (
int i = 0; i < vEdges.size(); ++i) {
656 Vtr::Index pVertOppositeEdge = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
658 vdst.AddWithWeight(src[pVertOppositeEdge], vEdgeWeights[i]);
661 if (vMask.GetNumFaceWeights() > 0) {
663 for (
int i = 0; i < vFaces.size(); ++i) {
665 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
667 vdst.AddWithWeight(dst[cVertOfFace], vFaceWeights[i]);
677 template <
class T,
class U>
692 template <
class T,
class U>
696 assert(level>0 and level<=(
int)_refinements.size());
700 varyingInterpolateChildVertsFromFaces(refinement, src, dst);
701 varyingInterpolateChildVertsFromEdges(refinement, src, dst);
702 varyingInterpolateChildVertsFromVerts(refinement, src, dst);
705 template <
class T,
class U>
707 TopologyRefiner::varyingInterpolateChildVertsFromFaces(
712 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
720 float fVaryingWeight = 1.0f / (float) fVerts.
size();
723 U & vdst = dst[cVert];
727 for (
int i = 0; i < fVerts.
size(); ++i) {
728 vdst.AddVaryingWithWeight(src[fVerts[i]], fVaryingWeight);
733 template <
class T,
class U>
735 TopologyRefiner::varyingInterpolateChildVertsFromEdges(
736 Vtr::Refinement
const & refinement, T
const * src, U * dst)
const {
740 const Vtr::Level& parent = refinement.parent();
742 for (
int edge = 0; edge < parent.getNumEdges(); ++edge) {
744 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
752 U & vdst = dst[cVert];
756 vdst.AddVaryingWithWeight(src[eVerts[0]], 0.5f);
757 vdst.AddVaryingWithWeight(src[eVerts[1]], 0.5f);
761 template <
class T,
class U>
763 TopologyRefiner::varyingInterpolateChildVertsFromVerts(
764 Vtr::Refinement
const & refinement, T
const * src, U * dst)
const {
768 const Vtr::Level& parent = refinement.parent();
770 for (
int vert = 0; vert < parent.getNumVertices(); ++vert) {
772 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
777 U & vdst = dst[cVert];
780 vdst.AddVaryingWithWeight(src[vert], 1.0f);
789 template <
class T,
class U>
800 dst += _levels[level].getNumFVarValues();
804 template <
class T,
class U>
808 assert(level>0 and level<=(
int)_refinements.size());
812 faceVaryingInterpolateChildVertsFromFaces(refinement, src, dst, channel);
813 faceVaryingInterpolateChildVertsFromEdges(refinement, src, dst, channel);
814 faceVaryingInterpolateChildVertsFromVerts(refinement, src, dst, channel);
817 template <
class T,
class U>
819 TopologyRefiner::faceVaryingInterpolateChildVertsFromFaces(
820 Vtr::Refinement const & refinement, T
const * src, U * dst,
int channel)
const {
826 float * fValueWeights = (
float *)alloca(parent.
getMaxValence()*
sizeof(float));
828 for (
int face = 0; face < parent.
getNumFaces(); ++face) {
845 scheme.ComputeFaceVertexMask(fHood, fMask);
848 U & vdst = dst[cVert];
852 for (
int i = 0; i < fValues.
size(); ++i) {
853 vdst.AddWithWeight(src[fValues[i]], fValueWeights[i]);
858 template <
class T,
class U>
860 TopologyRefiner::faceVaryingInterpolateChildVertsFromEdges(
861 Vtr::Refinement
const & refinement, T
const * src, U * dst,
int channel)
const {
864 Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
866 const Vtr::Level& parent = refinement.parent();
867 const Vtr::Level& child = refinement.child();
869 const Vtr::FVarRefinement& refineFVar = *refinement.
_fvarChannels[channel];
870 const Vtr::FVarLevel& parentFVar = *parent._fvarChannels[channel];
871 const Vtr::FVarLevel& childFVar = *child._fvarChannels[channel];
877 float eVertWeights[2],
878 * eFaceWeights = (
float *)alloca(parent.getMaxEdgeFaces()*
sizeof(float));
880 Vtr::MaskInterface eMask(eVertWeights, 0, eFaceWeights);
882 bool isLinearFVar = parentFVar._isLinear;
884 eMask.SetNumVertexWeights(2);
885 eMask.SetNumEdgeWeights(0);
886 eMask.SetNumFaceWeights(0);
888 eVertWeights[0] = 0.5f;
889 eVertWeights[1] = 0.5f;
892 Vtr::EdgeInterface eHood(parent);
894 for (
int edge = 0; edge < parent.getNumEdges(); ++edge) {
896 Vtr::Index cVert = refinement.getEdgeChildVertex(edge);
900 bool fvarEdgeVertMatchesVertex = childFVar.vertexTopologyMatches(cVert);
901 if (fvarEdgeVertMatchesVertex) {
906 eHood.SetIndex(edge);
911 scheme.ComputeEdgeVertexMask(eHood, eMask, pRule, cRule);
937 bool assumeMatchingNeighborhood =
false;
938 if (assumeMatchingNeighborhood) {
940 eVertValues[0] = eVerts[0];
941 eVertValues[1] = eVerts[1];
943 parentFVar.getEdgeFaceValues(edge, 0, eVertValues);
946 U & vdst = dst[cVert];
949 vdst.AddWithWeight(src[eVertValues[0]], eVertWeights[0]);
950 vdst.AddWithWeight(src[eVertValues[1]], eVertWeights[1]);
952 if (eMask.GetNumFaceWeights() > 0) {
956 for (
int i = 0; i < eFaces.size(); ++i) {
958 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(eFaces[i]);
960 vdst.AddWithWeight(dst[cVertOfFace], eFaceWeights[i]);
972 for (
int i = 0; i < childFVar.getNumVertexValues(cVert); ++i) {
974 int eFaceIndex = refineFVar.getChildValueParentSource(cVert, i);
975 assert(eFaceIndex == i);
977 parentFVar.getEdgeFaceValues(edge, eFaceIndex, eVertValues);
979 U & vdst = dst[childFVar.getVertexValue(cVert, i)];
982 vdst.AddWithWeight(src[eVertValues[0]], 0.5);
983 vdst.AddWithWeight(src[eVertValues[1]], 0.5);
989 template <
class T,
class U>
991 TopologyRefiner::faceVaryingInterpolateChildVertsFromVerts(
992 Vtr::Refinement
const & refinement, T
const * src, U * dst,
int channel)
const {
995 Sdc::Scheme<Sdc::TYPE_CATMARK> scheme(_subdivOptions);
997 const Vtr::Level& parent = refinement.parent();
998 const Vtr::Level& child = refinement.child();
1000 const Vtr::FVarRefinement& refineFVar = *refinement._fvarChannels[channel];
1001 const Vtr::FVarLevel& parentFVar = *parent._fvarChannels[channel];
1002 const Vtr::FVarLevel& childFVar = *child._fvarChannels[channel];
1004 bool isLinearFVar = parentFVar._isLinear;
1006 float * weightBuffer = (
float *)alloca(2*parent.getMaxValence()*
sizeof(float));
1010 Vtr::VertexInterface vHood(parent, child);
1012 for (
int vert = 0; vert < parent.getNumVertices(); ++vert) {
1014 Vtr::Index cVert = refinement.getVertexChildVertex(vert);
1018 bool fvarVertVertMatchesVertex = childFVar.vertexTopologyMatches(cVert);
1019 if (isLinearFVar && fvarVertVertMatchesVertex) {
1020 Vtr::Index pVertValue = parentFVar.getVertexValue(vert);
1023 U & vdst = dst[cVertValue];
1026 vdst.AddWithWeight(src[pVertValue], 1.0f);
1030 if (fvarVertVertMatchesVertex) {
1040 float * vEdgeWeights = weightBuffer;
1041 float * vFaceWeights = vEdgeWeights + vEdges.size();
1043 Vtr::MaskInterface vMask(&vVertWeight, vEdgeWeights, vFaceWeights);
1045 vHood.SetIndex(vert, cVert);
1050 scheme.ComputeVertexVertexMask(vHood, vMask, pRule, cRule);
1072 Vtr::Index pVertValue = parentFVar.getVertexValue(vert);
1075 U & vdst = dst[cVertValue];
1078 vdst.AddWithWeight(src[pVertValue], vVertWeight);
1080 if (vMask.GetNumEdgeWeights() > 0) {
1083 bool assumeMatchingNeighborhood =
false;
1084 if (assumeMatchingNeighborhood) {
1085 for (
int i = 0; i < vEdges.size(); ++i) {
1087 Vtr::Index pVertOppositeEdge = (eVerts[0] == vert) ? eVerts[1] : eVerts[0];
1089 vdst.AddWithWeight(src[pVertOppositeEdge], vEdgeWeights[i]);
1092 parentFVar.getVertexEdgeValues(vert, vEdgeValues);
1094 for (
int i = 0; i < vEdges.size(); ++i) {
1095 vdst.AddWithWeight(src[vEdgeValues[i]], vEdgeWeights[i]);
1100 if (vMask.GetNumFaceWeights() > 0) {
1104 for (
int i = 0; i < vFaces.size(); ++i) {
1106 Vtr::Index cVertOfFace = refinement.getFaceChildVertex(vFaces[i]);
1108 vdst.AddWithWeight(dst[cVertOfFace], vFaceWeights[i]);
1116 for (
int cSibling = 0; cSibling < childFVar.getNumVertexValues(cVert); ++cSibling) {
1117 int pSibling = refineFVar.getChildValueParentSource(cVert, cSibling);
1118 assert(pSibling == cSibling);
1120 Vtr::Index pVertValue = parentFVar.getVertexValue(vert, pSibling);
1121 Vtr::Index cVertValue = childFVar.getVertexValue(cVert, cSibling);
1123 U & vdst = dst[cVertValue];
1126 vdst.AddWithWeight(src[pVertValue], 1.0);
1135 using namespace OPENSUBDIV_VERSION;
int GetNumFaceVerticesTotal() const
Returns the total number of face vertices in all levels.
IndexArray setBaseFaceVertices(Index f)
IndexArray const GetFaceChildFaces(int level, Index f) const
Returns the child faces of face 'f' at 'level'.
Array< Index > IndexArray
int GetPtexIndex(Index f) const
Returns the ptex face index given a coarse face 'f' or -1.
int createFVarChannel(int numValues)
IndexArray const GetFaceEdges(int level, Index face) const
Returns the edges of a 'face' at 'level'.
std::vector< FVarLevel * > _fvarChannels
int GetNumFaces(int level) const
Returns the number of face vertex indices at a given level of refinement.
void populateLocalIndices()
LocalIndexArray const VertexEdgeLocalIndices(int level, Index vert) const
Returns the local edge indices of vertex 'vert' at 'level'.
int getNumBaseVertices() const
int GetNumFVarChannels() const
Returns the number of face-varying channels in the tables.
Level const & parent() const
void PrintTopology(int level, bool children=true) const
Prints topology information to console.
void setNumBaseFaces(int count)
void Unrefine()
Unrefine the topology (keep control cage)
float GetEdgeSharpness(int level, Index edge) const
Returns the sharpness of a given edge (at 'level' of refinement)
int GetNumVertices(int level) const
Returns the number of vertices at a given level of refinement.
void setNumBaseEdgeFaces(Index e, int count)
~TopologyRefiner()
Destructor.
float GetVertexSharpness(int level, Index vert) const
Returns the sharpness of a given vertex (at 'level' of refinement)
Index getFaceChildVertex(Index f) const
int getMaxValence() const
Sdc::Type GetSchemeType() const
Returns the subdivision scheme.
int GetNumFVarValues(int level, int channel=0) const
Returns the number of face-varying values at a given level of refinement.
int GetNumFaceVertices(int level) const
Returns the number of faces at a given level of refinement.
bool ValidateTopology(int level) const
Returns true if the topology of 'level' is valid.
IndexArray getBaseFVarFaceValues(Index face, int channel=0)
int GetNumEdges(int level) const
Returns the number of edges at a given level of refinement.
IndexArray setBaseEdgeFaces(Index e)
void completeFVarChannelTopology(int channel=0)
int GetNumFacesTotal() const
Returns the total number of edges in all levels.
void InterpolateFaceVarying(T const *src, U *dst, int channel=0) const
Apply face-varying interpolation weights to a primvar buffer.
LocalIndexArray setBaseVertexEdgeLocalIndices(Index v)
IndexArray const GetEdgeFaces(int level, Index edge) const
Returns the faces incident to 'edge' at 'level'.
Sdc::Options GetSchemeOptions() const
Returns the subdivision options.
int GetNumFVarValuesTotal(int channel=0) const
Returns the total number of face-varying values in all levels.
LocalIndexArray const VertexFaceLocalIndices(int level, Index vert) const
Returns the local face indices of vertex 'vert' at 'level'.
IndexArray const GetFaceVertices(int level, Index face) const
Returns the vertices of a 'face' at 'level'.
TopologyRefiner(Sdc::Type type, Sdc::Options options=Sdc::Options())
Constructor.
IndexArray const GetFaceChildEdges(int level, Index f) const
Returns the child edges of face 'f' at 'level'.
IndexArray const GetVertexFaces(int level, Index vert) const
Returns the faces incident to 'vertex' at 'level'.
IndexArray const GetVertexEdges(int level, Index vert) const
Returns the edges incident to 'vertex' at 'level'.
Sdc::Crease::Rule GetVertexRule(int level, Index vert) const
Returns the subdivision rule of a given vertex (at 'level' of refinement)
Vtr::Level & getLevel(int l)
int GetNumVerticesTotal() const
Returns the total number of vertices in all levels.
IndexArray setBaseEdgeVertices(Index e)
IndexArray const GetEdgeChildEdges(int level, Index e) const
Returns the child edges of edge 'e' at 'level'.
IndexArray const getFaceVertices(Index faceIndex) const
IndexArray const GetEdgeVertices(int level, Index edge) const
Returns the vertices of an 'edge' at 'level' (2 of them)
IndexArray setBaseFaceEdges(Index f)
int GetNumPtexFaces() const
Returns the number of ptex faces in the mesh.
void InterpolateVarying(T const *src, U *dst) const
Apply only varying interpolation weights to a primvar buffer.
void Interpolate(T const *src, U *dst) const
Apply vertex and varying interpolation weights to a primvar buffer.
void RefineAdaptive(int maxLevel, bool fullTopologyInLastLevel=false)
Feature Adaptive topology refinement.
IndexArray setBaseVertexEdges(Index v)
Index GetFaceChildVertex(int level, Index f) const
Returns the child vertex of face 'f' at 'level'.
void setNumBaseVertexEdges(Index v, int count)
int createFVarChannel(int numValues, Sdc::Options const &options)
int GetMaxLevel() const
Returns the highest level of refinement.
IndexArray setBaseVertexFaces(Index v)
bool IndexIsValid(Index index)
IndexArray const GetFVarFaceValues(int level, Index face, int channel=0) const
Returns the face-varying values of a 'face' at 'level'.
float & baseVertexSharpness(Index v)
void setNumBaseVertices(int count)
void setNumBaseVertexFaces(Index v, int count)
void setNumBaseEdges(int count)
float & baseEdgeSharpness(Index e)
IndexArray const getFVarFaceValues(Index faceIndex, int channel=0) const
bool IsUniform() const
Returns true if uniform subdivision has been applied.
Vtr::Level & getBaseLevel()
void populateLocalIndices()
Stores topology data for a specified set of refinement options.
Index GetVertexChildVertex(int level, Index v) const
Returns the child vertex of vertex 'v' at 'level'.
void RefineUniform(int maxLevel, bool fullTopologyInLastLevel=false)
Refine the topology uniformly.
Vtr::Refinement const & getRefinement(int l) const
Vtr::Level const & getLevel(int l) const
A specialized factory for feature adaptive PatchTables.
int GetNumEdgesTotal() const
Returns the total number of edges in all levels.
void setNumBaseFaceVertices(Index f, int count)
int getNumBaseFaces() const
LocalIndexArray setBaseVertexFaceLocalIndices(Index v)
Index GetEdgeChildVertex(int level, Index e) const
Returns the child vertex of edge 'e' at 'level'.
int getNumBaseEdges() const
void Clear()
Clear the topology entirely.
Index FindEdge(int level, Index v0, Index v1) const
Returns the edge with vertices'v0' and 'v1' (or -1 if they are not connected)