All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
halfedge.h
Go to the documentation of this file.
1 //
2 // Copyright 2013 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef HBRHALFEDGE_H
26 #define HBRHALFEDGE_H
27 
28 #include <assert.h>
29 #include <stddef.h>
30 #include <cstring>
31 #include <iostream>
32 
33 
34 #ifdef HBRSTITCH
35 #include "libgprims/stitch.h"
36 #include "libgprims/stitchInternal.h"
37 #endif
38 
39 #include "../version.h"
40 
41 namespace OpenSubdiv {
42 namespace OPENSUBDIV_VERSION {
43 
44 template <class T> class HbrFace;
45 template <class T> class HbrHalfedge;
46 template <class T> class HbrVertex;
47 template <class T> class HbrMesh;
48 
49 template <class T> std::ostream& operator<<(std::ostream& out, const HbrHalfedge<T>& edge);
50 
51 template <class T> class HbrHalfedge {
52 
53 private:
54  HbrHalfedge(): opposite(0), incidentVertex(-1), vchild(-1), sharpness(0.0f)
55 #ifdef HBRSTITCH
56  , stitchccw(1), raystitchccw(1)
57 #endif
58  , coarse(1)
59  {
60  }
61 
62  HbrHalfedge(const HbrHalfedge &/* edge */) {}
63 
64  ~HbrHalfedge();
65 
66  void Clear();
67 
68  // Finish the initialization of the halfedge. Should only be
69  // called by HbrFace
70  void Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* origin, unsigned int *fvarbits, HbrFace<T>* face);
71 public:
72 
73  // Returns the opposite half edge
74  HbrHalfedge<T>* GetOpposite() const { return opposite; }
75 
76  // Sets the opposite half edge
77  void SetOpposite(HbrHalfedge<T>* opposite) { this->opposite = opposite; sharpness = opposite->sharpness; }
78 
79  // Returns the next clockwise halfedge around the incident face
81  if (m_index == 4) {
82  const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
83  if (lastedge) {
84  return (HbrHalfedge<T>*) ((char*) this - (GetFace()->GetNumVertices() - 1) * edgesize);
85  } else {
86  return (HbrHalfedge<T>*) ((char*) this + edgesize);
87  }
88  } else {
89  if (lastedge) {
90  return (HbrHalfedge<T>*) ((char*) this - (m_index) * sizeof(HbrHalfedge<T>));
91  } else {
92  return (HbrHalfedge<T>*) ((char*) this + sizeof(HbrHalfedge<T>));
93  }
94  }
95  }
96 
97  // Returns the previous counterclockwise halfedge around the incident face
99  const size_t edgesize = (m_index == 4) ?
100  (sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*)) :
101  sizeof(HbrHalfedge<T>);
102  if (firstedge) {
103  return (HbrHalfedge<T>*) ((char*) this + (GetFace()->GetNumVertices() - 1) * edgesize);
104  } else {
105  return (HbrHalfedge<T>*) ((char*) this - edgesize);
106  }
107  }
108 
109  // Returns the incident vertex
111  return GetMesh()->GetVertex(incidentVertex);
112  }
113 
114  // Returns the incident vertex
116  return mesh->GetVertex(incidentVertex);
117  }
118 
119  // Returns the incident vertex
120  int GetVertexID() const {
121  return incidentVertex;
122  }
123 
124  // Returns the source vertex
126  return GetVertex();
127  }
128 
129  // Returns the source vertex
131  return GetVertex(mesh);
132  }
133 
134  // Returns the source vertex id
135  int GetOrgVertexID() const {
136  return incidentVertex;
137  }
138 
139  // Changes the origin vertex. Generally not a good idea to do
140  void SetOrgVertex(HbrVertex<T>* v) { incidentVertex = v->GetID(); }
141 
142  // Returns the destination vertex
143  HbrVertex<T>* GetDestVertex() const { return GetNext()->GetOrgVertex(); }
144 
145  // Returns the destination vertex
146  HbrVertex<T>* GetDestVertex(HbrMesh<T> *mesh) const { return GetNext()->GetOrgVertex(mesh); }
147 
148  // Returns the destination vertex ID
149  int GetDestVertexID() const { return GetNext()->GetOrgVertexID(); }
150 
151  // Returns the incident facet
152  HbrFace<T>* GetFace() const {
153  if (m_index == 4) {
154  // Pointer to face is stored after the data for the edge
155  return *(HbrFace<T>**)((char *) this + sizeof(HbrHalfedge<T>));
156  } else {
157  return (HbrFace<T>*) ((char*) this - (m_index) * sizeof(HbrHalfedge<T>) -
158  offsetof(HbrFace<T>, edges));
159  }
160  }
161 
162  // Returns the mesh to which this edge belongs
163  HbrMesh<T>* GetMesh() const { return GetFace()->GetMesh(); }
164 
165  // Returns the face on the right
166  HbrFace<T>* GetRightFace() const { return opposite ? opposite->GetLeftFace() : NULL; }
167 
168  // Return the face on the left of the halfedge
169  HbrFace<T>* GetLeftFace() const { return GetFace(); }
170 
171  // Returns whether this is a boundary edge
172  bool IsBoundary() const { return opposite == 0; }
173 
174  // Tag the edge as being an infinitely sharp facevarying edge
175  void SetFVarInfiniteSharp(int datum, bool infsharp) {
176  int intindex = datum >> 4;
177  unsigned int bits = infsharp << ((datum & 15) * 2);
178  getFVarInfSharp()[intindex] |= bits;
179  if (opposite) {
180  opposite->getFVarInfSharp()[intindex] |= bits;
181  }
182  }
183 
184  // Copy fvar infinite sharpness flags from another edge
186  unsigned int *fvarinfsharp = getFVarInfSharp();
187  if (fvarinfsharp) {
188  const int fvarcount = GetMesh()->GetFVarCount();
189  int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
190 
191  if (edge->IsSharp(true)) {
192  memset(fvarinfsharp, 0x55555555, fvarbitsSizePerEdge * sizeof(unsigned int));
193  } else {
194  memcpy(fvarinfsharp, edge->getFVarInfSharp(), fvarbitsSizePerEdge * sizeof(unsigned int));
195  }
196  }
197  }
198 
199  // Returns whether the edge is infinitely sharp in facevarying for
200  // a particular facevarying datum
201  bool GetFVarInfiniteSharp(int datum);
202 
203  // Returns whether the edge is infinitely sharp in any facevarying
204  // datum
206 
207  // Get the sharpness relative to facevarying data
208  float GetFVarSharpness(int datum, bool ignoreGeometry=false);
209 
210  // Returns the (raw) sharpness of the edge
211  float GetSharpness() const { return sharpness; }
212 
213  // Sets the sharpness of the edge
214  void SetSharpness(float sharp) { sharpness = sharp; if (opposite) opposite->sharpness = sharp; ClearMask(); }
215 
216  // Returns whether the edge is sharp at the current level of
217  // subdivision (next = false) or at the next level of subdivision
218  // (next = true).
219  bool IsSharp(bool next) const { return (next ? (sharpness > 0.0f) : (sharpness >= 1.0f)); }
220 
221  // Clears the masks of the adjacent edge vertices. Usually called
222  // when a change in edge sharpness occurs.
223  void ClearMask() { GetOrgVertex()->ClearMask(); GetDestVertex()->ClearMask(); }
224 
225  // Subdivide the edge into a vertex if needed and return
227 
228  // Make sure the edge has its opposite face
229  void GuaranteeNeighbor();
230 
231  // True if the edge has a subdivided child vertex
232  bool HasChild() const { return vchild!=-1; }
233 
234  // Remove the reference to subdivided vertex
235  void RemoveChild() { vchild = -1; }
236 
237  // Sharpness constants
238  enum Mask {
239  k_Smooth = 0,
240  k_Sharp = 1,
242  };
243 
244 #ifdef HBRSTITCH
245  StitchEdge* GetStitchEdge(int i) {
246  StitchEdge **stitchEdge = getStitchEdges();
247  // If the stitch edge exists, the ownership is transferred to
248  // the caller. Make sure the opposite edge loses ownership as
249  // well.
250  if (stitchEdge[i]) {
251  if (opposite) {
252  opposite->getStitchEdges()[i] = 0;
253  }
254  return StitchGetEdge(&stitchEdge[i]);
255  }
256  // If the stitch edge does not exist then we create one now.
257  // Make sure the opposite edge gets a copy of it too
258  else {
259  StitchGetEdge(&stitchEdge[i]);
260  if (opposite) {
261  opposite->getStitchEdges()[i] = stitchEdge[i];
262  }
263  return stitchEdge[i];
264  }
265  }
266 
267  // If stitch edge exists, and this edge has no opposite, destroy
268  // it
269  void DestroyStitchEdges(int stitchcount) {
270  if (!opposite) {
271  StitchEdge **stitchEdge = getStitchEdges();
272  for (int i = 0; i < stitchcount; ++i) {
273  if (stitchEdge[i]) {
274  StitchFreeEdge(stitchEdge[i]);
275  stitchEdge[i] = 0;
276  }
277  }
278  }
279  }
280 
281  StitchEdge* GetRayStitchEdge(int i) {
282  return GetStitchEdge(i + 2);
283  }
284 
285  // Splits our split edge between our children. We'd better have
286  // subdivided this edge by this point
287  void SplitStitchEdge(int i) {
288  StitchEdge* se = GetStitchEdge(i);
289  HbrHalfedge<T>* ea = GetOrgVertex()->Subdivide()->GetEdge(Subdivide());
290  HbrHalfedge<T>* eb = Subdivide()->GetEdge(GetDestVertex()->Subdivide());
291  StitchEdge **ease = ea->getStitchEdges();
292  StitchEdge **ebse = eb->getStitchEdges();
293  if (i >= 2) { // ray tracing stitches
294  if (!raystitchccw) {
295  StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
296  } else {
297  StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
298  }
299  ea->raystitchccw = eb->raystitchccw = raystitchccw;
300  if (eb->opposite) {
301  eb->opposite->getStitchEdges()[i] = ebse[i];
302  eb->opposite->raystitchccw = raystitchccw;
303  }
304  if (ea->opposite) {
305  ea->opposite->getStitchEdges()[i] = ease[i];
306  ea->opposite->raystitchccw = raystitchccw;
307  }
308  } else {
309  if (!stitchccw) {
310  StitchSplitEdge(se, &ease[i], &ebse[i], false, 0, 0, 0);
311  } else {
312  StitchSplitEdge(se, &ebse[i], &ease[i], true, 0, 0, 0);
313  }
314  ea->stitchccw = eb->stitchccw = stitchccw;
315  if (eb->opposite) {
316  eb->opposite->getStitchEdges()[i] = ebse[i];
317  eb->opposite->stitchccw = stitchccw;
318  }
319  if (ea->opposite) {
320  ea->opposite->getStitchEdges()[i] = ease[i];
321  ea->opposite->stitchccw = stitchccw;
322  }
323  }
324  }
325 
326  void SplitRayStitchEdge(int i) {
327  SplitStitchEdge(i + 2);
328  }
329 
330  void SetStitchEdge(int i, StitchEdge* edge) {
331  StitchEdge **stitchEdges = getStitchEdges();
332  stitchEdges[i] = edge;
333  if (opposite) {
334  opposite->getStitchEdges()[i] = edge;
335  }
336  }
337 
338  void SetRayStitchEdge(int i, StitchEdge* edge) {
339  StitchEdge **stitchEdges = getStitchEdges();
340  stitchEdges[i+2] = edge;
341  if (opposite) {
342  opposite->getStitchEdges()[i+2] = edge;
343  }
344  }
345 
346  void* GetStitchData() const {
347  if (stitchdatavalid) return GetMesh()->GetStitchData(this);
348  else return 0;
349  }
350 
351  void SetStitchData(void* data) {
352  GetMesh()->SetStitchData(this, data);
353  stitchdatavalid = data ? 1 : 0;
354  if (opposite) {
355  opposite->GetMesh()->SetStitchData(opposite, data);
356  opposite->stitchdatavalid = stitchdatavalid;
357  }
358  }
359 
360  bool GetStitchCCW(bool raytraced) const { return raytraced ? raystitchccw : stitchccw; }
361 
362  void ClearStitchCCW(bool raytraced) {
363  if (raytraced) {
364  raystitchccw = 0;
365  if (opposite) opposite->raystitchccw = 0;
366  } else {
367  stitchccw = 0;
368  if (opposite) opposite->stitchccw = 0;
369  }
370  }
371 
372  void ToggleStitchCCW(bool raytraced) {
373  if (raytraced) {
374  raystitchccw = 1 - raystitchccw;
375  if (opposite) opposite->raystitchccw = raystitchccw;
376  } else {
377  stitchccw = 1 - stitchccw;
378  if (opposite) opposite->stitchccw = stitchccw;
379  }
380  }
381 
382 #endif
383 
384  // Marks the edge as being "coarse" (belonging to the control
385  // mesh). Generally this distinction only needs to be made if
386  // we're worried about interpolateboundary behaviour
387  void SetCoarse(bool c) { coarse = c; }
388  bool IsCoarse() const { return coarse; }
389 
390  friend class HbrFace<T>;
391 
392 private:
393  HbrHalfedge<T>* opposite;
394  // Index of incident vertex
395  int incidentVertex;
396 
397  // Index of subdivided vertex child
398  int vchild;
399  float sharpness;
400 
401 #ifdef HBRSTITCH
402  unsigned short stitchccw:1;
403  unsigned short raystitchccw:1;
404  unsigned short stitchdatavalid:1;
405 #endif
406  unsigned short coarse:1;
407  unsigned short lastedge:1;
408  unsigned short firstedge:1;
409 
410  // If m_index = 0, 1, 2 or 3: we are the m_index edge of an
411  // incident face with 3 or 4 vertices.
412  // If m_index = 4: our incident face has more than 4 vertices, and
413  // we must do some extra math to determine what our actual index
414  // is. See getIndex()
415  unsigned short m_index:3;
416 
417  // Returns the index of the edge relative to its incident face.
418  // This relies on knowledge of the face's edge allocation pattern
419  int getIndex() const {
420  if (m_index < 4) {
421  return m_index;
422  } else {
423  // We allocate room for up to 4 values (to handle tri or
424  // quad) in the edges array. If there are more than that,
425  // they _all_ go in the faces' extraedges array.
426  HbrFace<T>* incidentFace = *(HbrFace<T>**)((char *) this + sizeof(HbrHalfedge<T>));
427  return int(((char *) this - incidentFace->extraedges) /
428  (sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*)));
429  }
430  }
431 
432  // Returns bitmask indicating whether a given facevarying datum
433  // for the edge is infinitely sharp. Each datum has two bits, and
434  // if those two bits are set to 3, it means the status has not
435  // been computed yet.
436  unsigned int *getFVarInfSharp() {
437  unsigned int *fvarbits = GetFace()->fvarbits;
438  if (fvarbits) {
439  int fvarbitsSizePerEdge = ((GetMesh()->GetFVarCount() + 15) / 16);
440  return fvarbits + getIndex() * fvarbitsSizePerEdge;
441  } else {
442  return 0;
443  }
444  }
445 
446 #ifdef HBRSTITCH
447  StitchEdge **getStitchEdges() {
448  return GetFace()->stitchEdges + GetMesh()->GetStitchCount() * getIndex();
449  }
450 #endif
451 
452 #ifdef HBR_ADAPTIVE
453 public:
454  struct adaptiveFlags {
455  unsigned isTransition:1;
456  unsigned isTriangleHead:1;
457  unsigned isWatertightCritical:1;
458 
459  adaptiveFlags() : isTransition(0),isTriangleHead(0),isWatertightCritical(0) { }
460  };
461 
462  adaptiveFlags _adaptiveFlags;
463 
464  bool IsInsideHole() const {
465 
466  HbrFace<T> * left = GetLeftFace();
467  if (left and (not left->IsHole()))
468  return false;
469 
470  HbrFace<T> * right = GetRightFace();
471  if (right and (not right->IsHole()))
472  return false;
473 
474  return true;
475  }
476 
477  bool IsTransition() const { return _adaptiveFlags.isTransition; }
478 
479  bool IsTriangleHead() const { return _adaptiveFlags.isTriangleHead; }
480 
481  bool IsWatertightCritical() const { return _adaptiveFlags.isWatertightCritical; }
482 #endif
483 };
484 
485 template <class T>
486 void
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) {
491  m_index = index;
492  } else {
493  m_index = 4;
494  // Assumes upstream allocation ensured we have extra storage
495  // for pointer to face after the halfedge data structure
496  // itself
497  *(HbrFace<T>**)((char *) this + sizeof(HbrHalfedge<T>)) = face;
498  }
499 
500  this->opposite = opposite;
501  incidentVertex = origin->GetID();
502  lastedge = (index == face->GetNumVertices() - 1);
503  firstedge = (index == 0);
504  if (opposite) {
505  sharpness = opposite->sharpness;
506 #ifdef HBRSTITCH
507  StitchEdge **stitchEdges = face->stitchEdges +
508  mesh->GetStitchCount() * index;
509  for (int i = 0; i < mesh->GetStitchCount(); ++i) {
510  stitchEdges[i] = opposite->getStitchEdges()[i];
511  }
512  stitchccw = opposite->stitchccw;
513  raystitchccw = opposite->raystitchccw;
514  stitchdatavalid = 0;
515  if (stitchEdges && opposite->GetStitchData()) {
516  mesh->SetStitchData(this, opposite->GetStitchData());
517  stitchdatavalid = 1;
518  }
519 #endif
520  if (fvarbits) {
521  const int fvarcount = mesh->GetFVarCount();
522  int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
523  memcpy(fvarbits, opposite->getFVarInfSharp(), fvarbitsSizePerEdge * sizeof(unsigned int));
524  }
525  } else {
526  sharpness = 0.0f;
527 #ifdef HBRSTITCH
528  StitchEdge **stitchEdges = getStitchEdges();
529  for (int i = 0; i < mesh->GetStitchCount(); ++i) {
530  stitchEdges[i] = 0;
531  }
532  stitchccw = 1;
533  raystitchccw = 1;
534  stitchdatavalid = 0;
535 #endif
536  if (fvarbits) {
537  const int fvarcount = mesh->GetFVarCount();
538  int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
539  memset(fvarbits, 0xff, fvarbitsSizePerEdge * sizeof(unsigned int));
540  }
541  }
542 }
543 
544 template <class T>
545 HbrHalfedge<T>::~HbrHalfedge() {
546  Clear();
547 }
548 
549 template <class T>
550 void
551 HbrHalfedge<T>::Clear() {
552  if (opposite) {
553  opposite->opposite = 0;
554  if (vchild != -1) {
555  // Transfer ownership of the vchild to the opposite ptr
556  opposite->vchild = vchild;
557 
558  HbrVertex<T> *vchildVert = GetMesh()->GetVertex(vchild);
559  // Done this way just for assertion sanity
560  vchildVert->SetParent(static_cast<HbrHalfedge*>(0));
561  vchildVert->SetParent(opposite);
562  vchild = -1;
563  }
564  opposite = 0;
565  }
566  // Orphan the child vertex
567  else if (vchild != -1) {
568  HbrVertex<T> *vchildVert = GetMesh()->GetVertex(vchild);
569  vchildVert->SetParent(static_cast<HbrHalfedge*>(0));
570  vchild = -1;
571  }
572 }
573 
574 template <class T>
575 HbrVertex<T>*
577  HbrMesh<T>* mesh = GetMesh();
578  if (vchild != -1) return mesh->GetVertex(vchild);
579  // Make sure that our opposite doesn't "own" a subdivided vertex
580  // already. If it does, use that
581  if (opposite && opposite->vchild != -1) return mesh->GetVertex(opposite->vchild);
582  HbrVertex<T>* vchildVert = mesh->GetSubdivision()->Subdivide(mesh, this);
583  vchild = vchildVert->GetID();
584  vchildVert->SetParent(this);
585  return vchildVert;
586 }
587 
588 template <class T>
589 void
591  HbrMesh<T>* mesh = GetMesh();
592  mesh->GetSubdivision()->GuaranteeNeighbor(mesh, this);
593 }
594 
595 // Determines whether an edge is infinitely sharp as far as its
596 // facevarying data is concerned. Happens if the faces on both sides
597 // disagree on the facevarying data at either of the shared vertices
598 // on the edge.
599 template <class T>
600 bool
602 
603  // Check to see if already initialized
604  int intindex = datum >> 4;
605  int shift = (datum & 15) << 1;
606  unsigned int *fvarinfsharp = getFVarInfSharp();
607  unsigned int bits = (fvarinfsharp[intindex] >> shift) & 0x3;
608  if (bits != 3) {
609  assert (bits != 2);
610  return bits ? true : false;
611  }
612 
613  // If there is no face varying data it can't be infinitely sharp!
614  const int fvarwidth = GetMesh()->GetTotalFVarWidth();
615  if (!fvarwidth) {
616  bits = ~(0x3 << shift);
617  fvarinfsharp[intindex] &= bits;
618  if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
619  return false;
620  }
621 
622  // If either incident face is missing, it's a geometric boundary
623  // edge, and also a facevarying boundary edge
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;
629  return true;
630  }
631 
632  // Look for the indices on each face which correspond to the
633  // origin and destination vertices of the edge
634  int lorg = -1, ldst = -1, rorg = -1, rdst = -1, i, nv;
635  HbrHalfedge<T>* e;
636  e = left->GetFirstEdge();
637  nv = left->GetNumVertices();
638  for (i = 0; i < nv; ++i) {
639  if (e->GetOrgVertex() == GetOrgVertex()) lorg = i;
640  if (e->GetOrgVertex() == GetDestVertex()) ldst = i;
641  e = e->GetNext();
642  }
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;
648  e = e->GetNext();
649  }
650  assert(lorg >= 0 && ldst >= 0 && rorg >= 0 && rdst >= 0);
651  // Compare the facevarying data to some tolerance
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;
659  return true;
660  }
661 
662  bits = ~(0x3 << shift);
663  fvarinfsharp[intindex] &= bits;
664  if (opposite) opposite->getFVarInfSharp()[intindex] &= bits;
665  return false;
666 }
667 
668 template <class T>
669 bool
671 
672  if (sharpness > k_Smooth) {
673  return true;
674  }
675 
676  for (int i = 0; i < GetMesh()->GetFVarCount(); ++i) {
677  if (GetFVarInfiniteSharp(i)) return true;
678  }
679  return false;
680 }
681 
682 template <class T>
683 float
684 HbrHalfedge<T>::GetFVarSharpness(int datum, bool ignoreGeometry) {
685 
686  if (GetFVarInfiniteSharp(datum)) return k_InfinitelySharp;
687 
688  if (!ignoreGeometry) {
689  // If it's a geometrically sharp edge it's going to be a
690  // facevarying sharp edge too
691  if (sharpness > k_Smooth) {
692  SetFVarInfiniteSharp(datum, true);
693  return k_InfinitelySharp;
694  }
695  }
696  return k_Smooth;
697 }
698 
699 
700 template <class T>
701 std::ostream&
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();
707  else
708  out << "(none)";
709  out << " to ";
710  if (edge.GetDestVertex()) {
711  out << *edge.GetDestVertex();
712  } else {
713  out << "(none)";
714  }
715  return out;
716 }
717 
718 // Sorts half edges by the relative ordering of the incident faces'
719 // paths.
720 template <class T>
722 public:
723  bool operator() (const HbrHalfedge<T>* a, HbrHalfedge<T>* b) const {
724  return (a->GetFace()->GetPath() < b->GetFace()->GetPath());
725  }
726 };
727 
728 template <class T>
730 public:
731  virtual void operator() (HbrHalfedge<T> &edge) = 0;
732  virtual ~HbrHalfedgeOperator() {}
733 };
734 
735 } // end namespace OPENSUBDIV_VERSION
736 using namespace OPENSUBDIV_VERSION;
737 
738 } // end namespace OpenSubdiv
739 
740 #endif /* HBRHALFEDGE_H */
741 
HbrFace< T > * GetRightFace() const
Definition: halfedge.h:166
HbrVertex< T > * GetVertex(int id) const
Definition: mesh.h:79
HbrVertex< T > * GetOrgVertex(HbrMesh< T > *mesh) const
Definition: halfedge.h:130
HbrVertex< T > * GetDestVertex(HbrMesh< T > *mesh) const
Definition: halfedge.h:146
void CopyFVarInfiniteSharpness(HbrHalfedge< T > *edge)
Definition: halfedge.h:185
HbrHalfedge< T > * GetFirstEdge() const
Definition: face.h:136
HbrVertex< T > * GetVertex() const
Definition: halfedge.h:110
HbrHalfedge< T > * GetNext() const
Definition: halfedge.h:80
HbrVertex< T > * GetDestVertex() const
Definition: halfedge.h:143
HbrSubdivision< T > * GetSubdivision() const
Definition: mesh.h:178
HbrFace< T > * GetLeftFace() const
Definition: halfedge.h:169
float GetFVarSharpness(int datum, bool ignoreGeometry=false)
Definition: halfedge.h:684
HbrFVarData< T > & GetFVarData(int index)
Definition: face.h:221
HbrVertex< T > * GetVertex(HbrMesh< T > *mesh) const
Definition: halfedge.h:115
bool operator()(const HbrHalfedge< T > *a, HbrHalfedge< T > *b) const
Definition: halfedge.h:723
HbrHalfedge< T > * GetOpposite() const
Definition: halfedge.h:74
HbrVertex< T > * GetOrgVertex() const
Definition: halfedge.h:125
void SetParent(HbrHalfedge< T > *edge)
Definition: vertex.h:225
void SetOpposite(HbrHalfedge< T > *opposite)
Definition: halfedge.h:77
void SetFVarInfiniteSharp(int datum, bool infsharp)
Definition: halfedge.h:175
void SetOrgVertex(HbrVertex< T > *v)
Definition: halfedge.h:140
virtual void operator()(HbrHalfedge< T > &edge)=0
HbrHalfedge< T > * GetPrev() const
Definition: halfedge.h:98