35 #include "libgprims/stitch.h" 
   36 #include "libgprims/stitchInternal.h" 
   39 #include "../version.h" 
   41 namespace OpenSubdiv {
 
   42 namespace OPENSUBDIV_VERSION {
 
   44 template <
class T> 
class HbrFace;
 
   45 template <
class T> 
class HbrHalfedge;
 
   46 template <
class T> 
class HbrVertex;
 
   47 template <
class T> 
class HbrMesh;
 
   49 template <
class T> std::ostream& operator<<(std::ostream& out, const HbrHalfedge<T>& edge);
 
   51 template <
class T> 
class HbrHalfedge {
 
   54     HbrHalfedge(): opposite(0), incidentVertex(-1), vchild(-1), sharpness(0.0f)
 
   56     , stitchccw(1), raystitchccw(1)
 
   62     HbrHalfedge(
const HbrHalfedge &) {}
 
   70     void Initialize(HbrHalfedge<T>* opposite, 
int index, HbrVertex<T>* origin, 
unsigned int *fvarbits, 
HbrFace<T>* face);
 
   99         const size_t edgesize = (m_index == 4) ? 
 
  111         return GetMesh()->GetVertex(incidentVertex);
 
  121         return incidentVertex;
 
  136         return incidentVertex;
 
  176         int intindex = datum >> 4;
 
  177         unsigned int bits = infsharp << ((datum & 15) * 2);
 
  178         getFVarInfSharp()[intindex] |= bits;
 
  180             opposite->getFVarInfSharp()[intindex] |= bits;
 
  186         unsigned int *fvarinfsharp = getFVarInfSharp();
 
  188             const int fvarcount = 
GetMesh()->GetFVarCount();
 
  189             int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
 
  191             if (edge->IsSharp(
true)) {
 
  192                 memset(fvarinfsharp, 0x55555555, fvarbitsSizePerEdge * 
sizeof(
unsigned int));
 
  194                 memcpy(fvarinfsharp, edge->getFVarInfSharp(), fvarbitsSizePerEdge * 
sizeof(
unsigned int));
 
  219     bool IsSharp(
bool next)
 const { 
return (next ? (sharpness > 0.0f) : (sharpness >= 1.0f)); }
 
  245     StitchEdge* GetStitchEdge(
int i) {
 
  246         StitchEdge **stitchEdge = getStitchEdges();
 
  252                 opposite->getStitchEdges()[i] = 0;
 
  254             return StitchGetEdge(&stitchEdge[i]);
 
  259             StitchGetEdge(&stitchEdge[i]);
 
  261                 opposite->getStitchEdges()[i] = stitchEdge[i];
 
  263             return stitchEdge[i];
 
  269     void DestroyStitchEdges(
int stitchcount) {
 
  271             StitchEdge **stitchEdge = getStitchEdges();
 
  272             for (
int i = 0; i < stitchcount; ++i) {
 
  274                     StitchFreeEdge(stitchEdge[i]);
 
  281     StitchEdge* GetRayStitchEdge(
int i) {
 
  282         return GetStitchEdge(i + 2);
 
  287     void SplitStitchEdge(
int i) {
 
  288         StitchEdge* se = GetStitchEdge(i);
 
  291         StitchEdge **ease = ea->getStitchEdges();
 
  292         StitchEdge **ebse = eb->getStitchEdges();
 
  295                 StitchSplitEdge(se, &ease[i], &ebse[i], 
false, 0, 0, 0);
 
  297                 StitchSplitEdge(se, &ebse[i], &ease[i], 
true, 0, 0, 0);
 
  299             ea->raystitchccw = eb->raystitchccw = raystitchccw;
 
  301                 eb->opposite->getStitchEdges()[i] = ebse[i];
 
  302                 eb->opposite->raystitchccw = raystitchccw;
 
  305                 ea->opposite->getStitchEdges()[i] = ease[i];
 
  306                 ea->opposite->raystitchccw = raystitchccw;
 
  310                 StitchSplitEdge(se, &ease[i], &ebse[i], 
false, 0, 0, 0);
 
  312                 StitchSplitEdge(se, &ebse[i], &ease[i], 
true, 0, 0, 0);
 
  314             ea->stitchccw = eb->stitchccw = stitchccw;
 
  316                 eb->opposite->getStitchEdges()[i] = ebse[i];
 
  317                 eb->opposite->stitchccw = stitchccw;
 
  320                 ea->opposite->getStitchEdges()[i] = ease[i];
 
  321                 ea->opposite->stitchccw = stitchccw;
 
  326     void SplitRayStitchEdge(
int i) {
 
  327         SplitStitchEdge(i + 2);
 
  330     void SetStitchEdge(
int i, StitchEdge* edge) {
 
  331         StitchEdge **stitchEdges = getStitchEdges();
 
  332         stitchEdges[i] = edge;
 
  334             opposite->getStitchEdges()[i] = edge;
 
  338     void SetRayStitchEdge(
int i, StitchEdge* edge) {
 
  339         StitchEdge **stitchEdges = getStitchEdges();
 
  340         stitchEdges[i+2] = edge;
 
  342             opposite->getStitchEdges()[i+2] = edge;
 
  346     void* GetStitchData()
 const {
 
  347         if (stitchdatavalid) 
return GetMesh()->GetStitchData(
this);
 
  351     void SetStitchData(
void* data) {
 
  352         GetMesh()->SetStitchData(
this, data);
 
  353         stitchdatavalid = data ? 1 : 0;
 
  355             opposite->GetMesh()->SetStitchData(opposite, data);
 
  356             opposite->stitchdatavalid = stitchdatavalid;
 
  360     bool GetStitchCCW(
bool raytraced)
 const { 
return raytraced ? raystitchccw : stitchccw; }
 
  362     void ClearStitchCCW(
bool raytraced) {
 
  365             if (opposite) opposite->raystitchccw = 0;
 
  368             if (opposite) opposite->stitchccw = 0;
 
  372     void ToggleStitchCCW(
bool raytraced) {
 
  374             raystitchccw = 1 - raystitchccw;
 
  375             if (opposite) opposite->raystitchccw = raystitchccw;
 
  377             stitchccw = 1 - stitchccw;
 
  378             if (opposite) opposite->stitchccw = stitchccw;
 
  402     unsigned short stitchccw:1;
 
  403     unsigned short raystitchccw:1;
 
  404     unsigned short stitchdatavalid:1;
 
  406     unsigned short coarse:1;
 
  407     unsigned short lastedge:1;
 
  408     unsigned short firstedge:1;
 
  415     unsigned short m_index:3;
 
  419     int getIndex()
 const {
 
  427             return int(((
char *) 
this - incidentFace->extraedges) /
 
  436     unsigned int *getFVarInfSharp() {
 
  437         unsigned int *fvarbits = 
GetFace()->fvarbits;
 
  439             int fvarbitsSizePerEdge = ((
GetMesh()->GetFVarCount() + 15) / 16);
 
  440             return fvarbits + getIndex() * fvarbitsSizePerEdge;
 
  447     StitchEdge **getStitchEdges() {
 
  448         return GetFace()->stitchEdges + 
GetMesh()->GetStitchCount() * getIndex();
 
  454     struct adaptiveFlags {
 
  455         unsigned isTransition:1;
 
  456         unsigned isTriangleHead:1;
 
  457         unsigned isWatertightCritical:1;
 
  459         adaptiveFlags() : isTransition(0),isTriangleHead(0),isWatertightCritical(0) { }
 
  462     adaptiveFlags _adaptiveFlags;
 
  464     bool IsInsideHole()
 const {
 
  467         if (left and (not left->IsHole()))
 
  471         if (right and (not right->IsHole()))
 
  477     bool IsTransition()
 const { 
return _adaptiveFlags.isTransition; }
 
  479     bool IsTriangleHead()
 const { 
return _adaptiveFlags.isTriangleHead; }
 
  481     bool IsWatertightCritical()
 const { 
return _adaptiveFlags.isWatertightCritical; }
 
  487 HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, 
int index, HbrVertex<T>* origin,
 
  488     unsigned int *fvarbits, HbrFace<T>* face) {
 
  489     HbrMesh<T> *mesh = face->GetMesh();
 
  490     if (face->GetNumVertices() <= 4) {
 
  497         *(HbrFace<T>**)((
char *) 
this + 
sizeof(HbrHalfedge<T>)) = face;
 
  500     this->opposite = opposite;
 
  501     incidentVertex = origin->GetID();
 
  502     lastedge = (index == face->GetNumVertices() - 1);
 
  503     firstedge = (index == 0);
 
  505         sharpness = opposite->sharpness;
 
  507         StitchEdge **stitchEdges = face->stitchEdges +
 
  508             mesh->GetStitchCount() * index;
 
  509         for (
int i = 0; i < mesh->GetStitchCount(); ++i) {
 
  510             stitchEdges[i] = opposite->getStitchEdges()[i];
 
  512         stitchccw = opposite->stitchccw;
 
  513         raystitchccw = opposite->raystitchccw;
 
  515         if (stitchEdges && opposite->GetStitchData()) {
 
  516             mesh->SetStitchData(
this, opposite->GetStitchData());
 
  521             const int fvarcount = mesh->GetFVarCount();
 
  522             int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
 
  523             memcpy(fvarbits, opposite->getFVarInfSharp(), fvarbitsSizePerEdge * 
sizeof(
unsigned int));
 
  528         StitchEdge **stitchEdges = getStitchEdges();
 
  529         for (
int i = 0; i < mesh->GetStitchCount(); ++i) {
 
  537             const int fvarcount = mesh->GetFVarCount();
 
  538             int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
 
  539             memset(fvarbits, 0xff, fvarbitsSizePerEdge * 
sizeof(
unsigned int));
 
  545 HbrHalfedge<T>::~HbrHalfedge() {
 
  551 HbrHalfedge<T>::Clear() {
 
  553         opposite->opposite = 0;
 
  556             opposite->vchild = vchild;
 
  558             HbrVertex<T> *vchildVert = GetMesh()->GetVertex(vchild);
 
  560             vchildVert->SetParent(static_cast<HbrHalfedge*>(0));
 
  561             vchildVert->SetParent(opposite);
 
  567     else if (vchild != -1) {
 
  568         HbrVertex<T> *vchildVert = GetMesh()->GetVertex(vchild);        
 
  569         vchildVert->SetParent(static_cast<HbrHalfedge*>(0));
 
  578     if (vchild != -1) 
return mesh->
GetVertex(vchild);
 
  581     if (opposite && opposite->vchild != -1) 
return mesh->
GetVertex(opposite->vchild);
 
  583     vchild = vchildVert->
GetID();
 
  604     int intindex = datum >> 4;
 
  605     int shift = (datum & 15) << 1;
 
  606     unsigned int *fvarinfsharp = getFVarInfSharp();
 
  607     unsigned int bits = (fvarinfsharp[intindex] >> shift) & 0x3;
 
  610         return bits ? 
true : 
false;
 
  614     const int fvarwidth = GetMesh()->GetTotalFVarWidth();
 
  616         bits = ~(0x3 << shift);
 
  617         fvarinfsharp[intindex] &= bits;
 
  618         if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
 
  624     HbrFace<T>* left = GetLeftFace(), *right = GetRightFace();
 
  625     if (!left || !right) {
 
  626         bits = ~(0x2 << shift);
 
  627         fvarinfsharp[intindex] &= bits;
 
  628         if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
 
  634     int lorg = -1, ldst = -1, rorg = -1, rdst = -1, i, nv;
 
  638     for (i = 0; i < nv; ++i) {
 
  639         if (e->GetOrgVertex() == GetOrgVertex()) lorg = i;
 
  640         if (e->GetOrgVertex() == GetDestVertex()) ldst = i;
 
  643     e = right->GetFirstEdge();
 
  644     nv = right->GetNumVertices();
 
  645     for (i = 0; i < nv; ++i) {
 
  646         if (e->GetOrgVertex() == GetOrgVertex()) rorg = i;
 
  647         if (e->GetOrgVertex() == GetDestVertex()) rdst = i;
 
  650     assert(lorg >= 0 && ldst >= 0 && rorg >= 0 && rdst >= 0);
 
  652     const int startindex = GetMesh()->GetFVarIndices()[datum];
 
  653     const int width = GetMesh()->GetFVarWidths()[datum];
 
  654     if (!right->GetFVarData(rorg).Compare(left->
GetFVarData(lorg), startindex, width, 0.001f) ||
 
  655         !right->GetFVarData(rdst).Compare(left->
GetFVarData(ldst), startindex, width, 0.001f)) {
 
  656         bits = ~(0x2 << shift);
 
  657         fvarinfsharp[intindex] &= bits;
 
  658         if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
 
  662     bits = ~(0x3 << shift);
 
  663     fvarinfsharp[intindex] &= bits;
 
  664     if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
 
  672     if (sharpness > k_Smooth) {
 
  676     for (
int i = 0; i < GetMesh()->GetFVarCount(); ++i) {
 
  677         if (GetFVarInfiniteSharp(i)) 
return true;
 
  686     if (GetFVarInfiniteSharp(datum)) 
return k_InfinitelySharp;
 
  688     if (!ignoreGeometry) {
 
  691         if (sharpness > k_Smooth) {
 
  692             SetFVarInfiniteSharp(datum, 
true);
 
  693             return k_InfinitelySharp;
 
  702 operator<<(std::ostream& out, const HbrHalfedge<T>& edge) {
 
  703     if (edge.IsBoundary()) out << 
"boundary ";
 
  704     out << 
"edge connecting ";
 
  705     if (edge.GetOrgVertex())
 
  706         out << *edge.GetOrgVertex();
 
  710     if (edge.GetDestVertex()) {
 
  711         out << *edge.GetDestVertex();
 
  724         return (a->GetFace()->GetPath() < b->GetFace()->GetPath());
 
  736 using namespace OPENSUBDIV_VERSION;
 
bool IsFVarInfiniteSharpAnywhere()
 
HbrFace< T > * GetRightFace() const 
 
HbrVertex< T > * GetVertex(int id) const 
 
HbrVertex< T > * GetOrgVertex(HbrMesh< T > *mesh) const 
 
HbrVertex< T > * GetDestVertex(HbrMesh< T > *mesh) const 
 
void CopyFVarInfiniteSharpness(HbrHalfedge< T > *edge)
 
HbrHalfedge< T > * GetFirstEdge() const 
 
float GetSharpness() const 
 
HbrVertex< T > * GetVertex() const 
 
HbrHalfedge< T > * GetNext() const 
 
HbrVertex< T > * GetDestVertex() const 
 
int GetOrgVertexID() const 
 
HbrSubdivision< T > * GetSubdivision() const 
 
HbrFace< T > * GetLeftFace() const 
 
float GetFVarSharpness(int datum, bool ignoreGeometry=false)
 
HbrFace< T > * GetFace() const 
 
bool IsSharp(bool next) const 
 
void SetSharpness(float sharp)
 
HbrFVarData< T > & GetFVarData(int index)
 
int GetNumVertices() const 
 
HbrVertex< T > * Subdivide()
 
HbrVertex< T > * GetVertex(HbrMesh< T > *mesh) const 
 
bool operator()(const HbrHalfedge< T > *a, HbrHalfedge< T > *b) const 
 
bool GetFVarInfiniteSharp(int datum)
 
int GetDestVertexID() const 
 
HbrHalfedge< T > * GetOpposite() const 
 
HbrVertex< T > * GetOrgVertex() const 
 
void SetParent(HbrHalfedge< T > *edge)
 
void SetOpposite(HbrHalfedge< T > *opposite)
 
virtual ~HbrHalfedgeOperator()
 
void SetFVarInfiniteSharp(int datum, bool infsharp)
 
friend class HbrFace< T >
 
HbrMesh< T > * GetMesh() const 
 
void SetOrgVertex(HbrVertex< T > *v)
 
virtual void operator()(HbrHalfedge< T > &edge)=0
 
HbrHalfedge< T > * GetPrev() const