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