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 OPENSUBDIV3_HBRFACE_H
26 #define OPENSUBDIV3_HBRFACE_H
27
28 #include <assert.h>
29 #include <cstdio>
30 #include <functional>
31 #include <iostream>
32 #include <algorithm>
33 #include <vector>
34
35 #include "../hbr/fvarData.h"
36 #include "../hbr/allocator.h"
37 #ifdef HBRSTITCH
38 #include "libgprims/stitch.h"
39 #include "libgprims/stitchInternal.h"
40 #endif
41
42 #include "../version.h"
43
44 namespace OpenSubdiv {
45 namespace OPENSUBDIV_VERSION {
46
47 template <class T> class HbrVertex;
48 template <class T> class HbrHalfedge;
49 template <class T> class HbrFace;
50 template <class T> class HbrMesh;
51 template <class T> class HbrHierarchicalEdit;
52
53 template <class T> std::ostream& operator<<(std::ostream& out, const HbrFace<T>& face);
54
55 // A descriptor for a path to a face
56 struct HbrFacePath {
PrintHbrFacePath57 void Print() const {
58 printf("%d", topface);
59 for (std::vector<int>::const_reverse_iterator i = remainder.rbegin(); i != remainder.rend(); ++i) {
60 printf(" %d", *i);
61 }
62 printf("\n");
63 }
64
65 int topface;
66 // Note that the elements in remainder are stored in reverse order.
67 std::vector<int> remainder;
68 friend bool operator< (const HbrFacePath& x, const HbrFacePath& y);
69 };
70
71 inline bool operator< (const HbrFacePath& x, const HbrFacePath& y) {
72 if (x.topface != y.topface) {
73 return x.topface < y.topface;
74 } else if (x.remainder.size() != y.remainder.size()) {
75 return x.remainder.size() < y.remainder.size();
76 } else {
77 std::vector<int>::const_reverse_iterator i = x.remainder.rbegin();
78 std::vector<int>::const_reverse_iterator j = y.remainder.rbegin();
79 for ( ; i != x.remainder.rend(); ++i, ++j) {
80 if (*i != *j) return (*i < *j);
81 }
82 return true;
83 }
84 }
85
86 // A simple wrapper around an array of four children. Used to block
87 // allocate pointers to children of HbrFace in the common case
88 template <class T>
89 class HbrFaceChildren {
90 public:
91 HbrFace<T> *& operator[](const int index) {
92 return children[index];
93 }
94
95 const HbrFace<T> *& operator[](const int index) const {
96 return children[index];
97 }
98
99
100 private:
101 friend class HbrAllocator<HbrFaceChildren<T> >;
102
103 // Used by block allocator
GetNext()104 HbrFaceChildren<T>*& GetNext() { return (HbrFaceChildren<T>*&) children; }
105
HbrFaceChildren()106 HbrFaceChildren() {}
107
~HbrFaceChildren()108 ~HbrFaceChildren() {}
109
110 HbrFace<T> *children[4];
111 };
112
113 template <class T> class HbrFace {
114
115 private:
116 friend class HbrAllocator<HbrFace<T> >;
117 friend class HbrHalfedge<T>;
118 HbrFace();
119 ~HbrFace();
120
121 public:
122
123 void Initialize(HbrMesh<T>* mesh, HbrFace<T>* parent, int childindex, int id, int uindex, int nvertices, HbrVertex<T>** vertices, int fvarwidth = 0, int depth = 0);
124 void Destroy();
125
126 // Returns the mesh to which this face belongs
GetMesh()127 HbrMesh<T>* GetMesh() const { return mesh; }
128
129 // Return number of vertices
GetNumVertices()130 int GetNumVertices() const { return nvertices; }
131
132 // Return face ID
GetID()133 int GetID() const { return id; }
134
135 // Return the first halfedge of the face
GetFirstEdge()136 HbrHalfedge<T>* GetFirstEdge() const {
137 if (nvertices > 4) {
138 return (HbrHalfedge<T>*)(extraedges);
139 } else {
140 return const_cast<HbrHalfedge<T>*>(&edges[0]);
141 }
142 }
143
144 // Return the halfedge which originates at the vertex with the
145 // indicated origin index
146 HbrHalfedge<T>* GetEdge(int index) const;
147
148 // Return the vertex with the indicated index
149 HbrVertex<T>* GetVertex(int index) const;
150
151 // Return the ID of the vertex with the indicated index
152 int GetVertexID(int index) const;
153
154 // Return the parent of this face
GetParent()155 HbrFace<T>* GetParent() const {
156 if (parent == -1) return NULL;
157 return mesh->GetFace(parent);
158 }
159
160 // Set the child
161 void SetChild(int index, HbrFace<T>* face);
162
163 // Return the child with the indicated index
GetChild(int index)164 HbrFace<T>* GetChild(int index) const {
165 int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
166 if (!children.children || index < 0 || index >= nchildren) return 0;
167 if (nchildren > 4) {
168 return children.extrachildren[index];
169 } else {
170 return (*children.children)[index];
171 }
172 }
173
174 // Subdivide the face into a vertex if needed and return
175 HbrVertex<T>* Subdivide();
176
HasChildVertex()177 bool HasChildVertex() const { return vchild!=-1; }
178
179 // Remove the reference to subdivided vertex
RemoveChild()180 void RemoveChild() { vchild = -1; }
181
182 // "Hole" flags used by subdivision to drop faces
IsHole()183 bool IsHole() const { return hole; }
184 void SetHole(bool h=1) { hole = h; }
185
186 // Coarse faces are the top level faces of a mesh. This will be
187 // set by mesh->Finish()
IsCoarse()188 bool IsCoarse() const { return coarse; }
SetCoarse()189 void SetCoarse() { coarse = 1; }
190
191 // Protected faces cannot be garbage collected; this may be set on
192 // coarse level faces if the mesh is shared
IsProtected()193 bool IsProtected() const { return protect; }
SetProtected()194 void SetProtected() { protect = 1; }
ClearProtected()195 void ClearProtected() { protect = 0; }
196
197 // Simple bookkeeping needed for garbage collection by HbrMesh
IsCollected()198 bool IsCollected() const { return collected; }
SetCollected()199 void SetCollected() { collected = 1; }
ClearCollected()200 void ClearCollected() { collected = 0; }
201
202 // Refine the face
203 void Refine();
204
205 // Unrefine the face
206 void Unrefine();
207
208 // Returns true if the face has a limit surface
209 bool HasLimit();
210
211 // Returns memory statistics
212 unsigned long GetMemStats() const;
213
214 // Return facevarying data from the appropriate vertex index
215 // registered to this face. Note that this may either be "generic"
216 // facevarying item (data.GetFace() == 0) or one specifically
217 // registered to the face (data.GetFace() == this) - this is
218 // important when trying to figure out whether the vertex has
219 // created some storage for the item designed to store
220 // discontinuous values for this face.
GetFVarData(int index)221 HbrFVarData<T>& GetFVarData(int index) {
222 return GetVertex(index)->GetFVarData(this);
223 }
224
225 // Mark this face as being used, which in turn increments the
226 // usage counter of all vertices in the support for the face. A
227 // used face can not be garbage collected
228 void MarkUsage();
229
230 // Clears the usage of this face, which in turn decrements the
231 // usage counter of all vertices in the support for the face and
232 // marks the face as a candidate for garbage collection
233 void ClearUsage();
234
235 // A face can be cleaned if all of its vertices are not being
236 // used; has no children; and (for top level faces) deletion of
237 // its edges will not leave singular vertices
238 bool GarbageCollectable() const;
239
240 // Connect this face to a list of hierarchical edits
241 void SetHierarchicalEdits(HbrHierarchicalEdit<T>** edits);
242
243 // Return the list of hierarchical edits associated with this face
GetHierarchicalEdits()244 HbrHierarchicalEdit<T>** GetHierarchicalEdits() const {
245 if (editOffset == -1) {
246 return NULL;
247 }
248 return mesh->GetHierarchicalEditsAtOffset(editOffset);
249 }
250
251 // Whether the face has certain types of edits (not necessarily
252 // local - could apply to a subface)
HasVertexEdits()253 bool HasVertexEdits() const { return hasVertexEdits; }
MarkVertexEdits()254 void MarkVertexEdits() { hasVertexEdits = 1; }
255
256 // Return the depth of the face
GetDepth()257 int GetDepth() const { return static_cast<int>(depth); }
258
259 // Return the uniform index of the face. This is different
260 // from the ID because it may be shared with other faces
GetUniformIndex()261 int GetUniformIndex() const { return uindex; }
262
263 // Set the uniform index of the face
SetUniformIndex(int i)264 void SetUniformIndex(int i) { uindex = i; }
265
266 // Return the ptex index
GetPtexIndex()267 int GetPtexIndex() const { return ptexindex; }
268
269 // Set the ptex index of the face
SetPtexIndex(int i)270 void SetPtexIndex(int i) { ptexindex = i; }
271
272 // Used by block allocator
GetNext()273 HbrFace<T>*& GetNext() { return (HbrFace<T>*&) mesh; }
274
GetPath()275 HbrFacePath GetPath() const {
276 HbrFacePath path;
277 path.remainder.reserve(GetDepth());
278 const HbrFace<T>* f = this, *p = GetParent();
279 while (p) {
280 int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(p->nvertices);
281 if (nchildren > 4) {
282 for (int i = 0; i < nchildren; ++i) {
283 if (p->children.extrachildren[i] == f) {
284 path.remainder.push_back(i);
285 break;
286 }
287 }
288 } else {
289 for (int i = 0; i < nchildren; ++i) {
290 if ((*p->children.children)[i] == f) {
291 path.remainder.push_back(i);
292 break;
293 }
294 }
295 }
296 f = p;
297 p = f->GetParent();
298 }
299 path.topface = f->GetID();
300 assert(GetDepth() == 0 || static_cast<int>(path.remainder.size()) == GetDepth());
301 return path;
302 }
303
PrintPath()304 void PrintPath() const {
305 GetPath().Print();
306 }
307
308 // Returns the blind pointer to client data
GetClientData()309 void *GetClientData() const {
310 return mesh->GetFaceClientData(id);
311 }
312
313 // Sets the blind pointer to client data
SetClientData(void * data)314 void SetClientData(void *data) {
315 mesh->SetFaceClientData(id, data);
316 }
317
318 // Gets the list of vertices which are in the support for the face.
319 void GetSupportingVertices(std::vector<int> &support);
320
321 private:
322
323 // Mesh to which this face belongs
324 HbrMesh<T>* mesh;
325
326 // Unique id for this face
327 int id;
328
329 // Uniform index
330 int uindex;
331
332 // Ptex index
333 int ptexindex;
334
335 // Number of vertices (and number of edges)
336 int nvertices;
337
338 // Halfedge array for this face
339 HbrHalfedge<T> edges[4];
340
341 // Edge storage if this face is not a triangle or quad
342 char* extraedges;
343
344 // Pointer to children array. If there are four children or less,
345 // we use the HbrFaceChildren pointer, otherwise we use
346 // extrachildren
347 union {
348 HbrFaceChildren<T>* children;
349 HbrFace<T>** extrachildren;
350 } children;
351
352 // Bits used by halfedges to track facevarying sharpnesses
353 unsigned int *fvarbits;
354
355 #ifdef HBRSTITCH
356 // Pointers to stitch edges used by the half edges.
357 StitchEdge **stitchEdges;
358 #endif
359
360 // Index of parent face
361 int parent;
362
363 // Index of subdivided vertex child
364 int vchild;
365
366 // Offset to the mesh' list of hierarchical edits applicable to this face
367 int editOffset;
368
369 // Depth of the face in the mesh hierarchy - coarse faces are
370 // level 0. (Hmmm.. is it safe to assume that we'll never
371 // subdivide to greater than 255?)
372 unsigned char depth;
373
374 unsigned short hole:1;
375 unsigned short coarse:1;
376 unsigned short protect:1;
377 unsigned short collected:1;
378 unsigned short hasVertexEdits:1;
379 unsigned short initialized:1;
380 unsigned short destroyed:1;
381
382 #ifdef HBR_ADAPTIVE
383 public:
384 enum PatchType { kUnknown=0,
385 kFull=1,
386 kEnd=2,
387 kGregory=3 };
388
389 enum TransitionType { kTransition0=0,
390 kTransition1=1,
391 kTransition2=2,
392 kTransition3=3,
393 kTransition4=4,
394 kNone=5 };
395
396 struct AdaptiveFlags {
397 unsigned patchType:2;
398 unsigned transitionType:3;
399 unsigned rots:2;
400 unsigned brots:2;
401 unsigned bverts:2;
402 unsigned isCritical:1;
403 unsigned isExtraordinary:1;
404 unsigned isTagged:1;
405
AdaptiveFlagsAdaptiveFlags406 AdaptiveFlags() : patchType(0), transitionType(5), rots(0), brots(0), bverts(0), isCritical(0), isExtraordinary(0), isTagged(0) { }
407 };
408
409 AdaptiveFlags _adaptiveFlags;
410
isTransitionPatch()411 bool isTransitionPatch() const {
412 return (_adaptiveFlags.transitionType!=kNone);
413 }
414
hasTaggedVertices()415 bool hasTaggedVertices() {
416 int nv = GetNumVertices();
417 for (int i=0; i<nv; ++i) {
418 if (GetVertex(i)->_adaptiveFlags.wasTagged)
419 return true;
420 }
421 return false;
422 }
423 #endif
424 };
425
426 } // end namespace OPENSUBDIV_VERSION
427 using namespace OPENSUBDIV_VERSION;
428
429 } // end namespace OpenSubdiv
430
431 #include "../hbr/mesh.h"
432
433 namespace OpenSubdiv {
434 namespace OPENSUBDIV_VERSION {
435
436 template <class T>
HbrFace()437 HbrFace<T>::HbrFace()
438 : mesh(0), id(-1), uindex(-1), ptexindex(-1), nvertices(0), extraedges(0), fvarbits(0), parent(-1), vchild(-1),
439 #ifdef HBRSTITCH
440 stitchEdges(0),
441 #endif
442 editOffset(-1), depth(0), hole(0), coarse(0), protect(0), collected(0), hasVertexEdits(0), initialized(0), destroyed(0) {
443 children.children = 0;
444 }
445
446 template <class T>
447 void
Initialize(HbrMesh<T> * m,HbrFace<T> * _parent,int childindex,int fid,int _uindex,int nv,HbrVertex<T> ** vertices,int,int _depth)448 HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int fid, int _uindex, int nv, HbrVertex<T>** vertices, int /* fvarwidth */, int _depth) {
449 mesh = m;
450 id = fid;
451 uindex = _uindex;
452 ptexindex = -1;
453 nvertices = nv;
454 extraedges = 0;
455 children.children = 0;
456 vchild = -1;
457 fvarbits = 0;
458 #ifdef HBRSTITCH
459 stitchEdges = 0;
460 #endif
461 editOffset = -1;
462 depth = static_cast<unsigned char>(_depth);
463 hole = 0;
464 coarse = 0;
465 protect = 0;
466 collected = 0;
467 hasVertexEdits = 0;
468 initialized = 1;
469 destroyed = 0;
470
471 int i;
472 const int fvarcount = mesh->GetFVarCount();
473 int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
474
475 if (nv > 4) {
476
477 // If we have more than four vertices, we ignore the
478 // overallocation and allocate our own buffers for stitch
479 // edges and facevarying data.
480 #ifdef HBRSTITCH
481 if (mesh->GetStitchCount()) {
482 const size_t buffersize = nv * (mesh->GetStitchCount() * sizeof(StitchEdge*));
483 char *buffer = (char *) malloc(buffersize);
484 memset(buffer, 0, buffersize);
485 stitchEdges = (StitchEdge**) buffer;
486 }
487 #endif
488 if (fvarcount) {
489 // We allocate fvarbits in one chunk.
490 // fvarbits needs capacity for two bits per fvardatum per edge,
491 // minimum size one integer per edge
492 const size_t fvarbitsSize = nv * (fvarbitsSizePerEdge * sizeof(unsigned int));
493 char *buffer = (char*) malloc(fvarbitsSize);
494 fvarbits = (unsigned int*) buffer;
495 }
496
497 // We also ignore the edge array and allocate extra storage -
498 // this simplifies GetNext and GetPrev math in HbrHalfedge
499 const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
500 extraedges = (char *) malloc(nv * edgesize);
501 for (i = 0; i < nv; ++i) {
502 HbrHalfedge<T>* edge = (HbrHalfedge<T>*)(extraedges + i * edgesize);
503 new (edge) HbrHalfedge<T>();
504 }
505
506 } else {
507 // Under four vertices: upstream allocation for the class has
508 // been over allocated to include storage for stitchEdges
509 // and fvarbits. Just point our pointers at it.
510 char *buffer = ((char *) this + sizeof(*this));
511 #ifdef HBRSTITCH
512 if (mesh->GetStitchCount()) {
513 const size_t buffersize = 4 * (mesh->GetStitchCount() * sizeof(StitchEdge*));
514 memset(buffer, 0, buffersize);
515 stitchEdges = (StitchEdge**) buffer;
516 buffer += buffersize;
517 }
518 #endif
519 if (fvarcount) {
520 fvarbits = (unsigned int*) buffer;
521 }
522 }
523
524 // Must do this before we create edges
525 if (_parent) {
526 _parent->SetChild(childindex, this);
527 }
528
529 // Edges must be constructed in this two part approach: we must
530 // ensure that opposite/next/previous ptrs are all set up
531 // correctly, before we can begin adding incident edges to
532 // vertices.
533 int next;
534 unsigned int *curfvarbits = fvarbits;
535 HbrHalfedge<T>* edge;
536 size_t edgesize;
537 if (nv > 4) {
538 edge = (HbrHalfedge<T>*)(extraedges);
539 edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
540 } else {
541 edge = edges;
542 edgesize = sizeof(HbrHalfedge<T>);
543 }
544 for (i = 0, next = 1; i < nv; ++i, ++next) {
545 if (next == nv) next = 0;
546 HbrHalfedge<T>* opposite = vertices[next]->GetEdge(vertices[i]->GetID());
547 edge->Initialize(opposite, i, vertices[i], curfvarbits, this);
548 if (opposite) opposite->SetOpposite(edge);
549 if (fvarbits) {
550 curfvarbits = curfvarbits + fvarbitsSizePerEdge;
551 }
552 edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
553 }
554 if (nv > 4) {
555 edge = (HbrHalfedge<T>*)(extraedges);
556 } else {
557 edge = edges;
558 }
559 for (i = 0; i < nv; ++i) {
560 vertices[i]->AddIncidentEdge(edge);
561 edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
562 }
563 }
564
565 template <class T>
~HbrFace()566 HbrFace<T>::~HbrFace() {
567 Destroy();
568 }
569
570 template <class T>
571 void
Destroy()572 HbrFace<T>::Destroy() {
573 if (initialized && !destroyed) {
574 int i;
575 #ifdef HBRSTITCH
576 const int stitchCount = mesh->GetStitchCount();
577 #endif
578
579 // Remove children's references to self
580 if (children.children) {
581 int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
582 if (nchildren > 4) {
583 for (i = 0; i < nchildren; ++i) {
584 if (children.extrachildren[i]) {
585 children.extrachildren[i]->parent = -1;
586 children.extrachildren[i] = 0;
587 }
588 }
589 delete[] children.extrachildren;
590 children.extrachildren = 0;
591 } else {
592 for (i = 0; i < nchildren; ++i) {
593 if ((*children.children)[i]) {
594 (*children.children)[i]->parent = -1;
595 (*children.children)[i] = 0;
596 }
597 }
598 mesh->DeleteFaceChildren(children.children);
599 children.children = 0;
600 }
601 }
602
603 // Deleting the incident edges from the vertices in this way is
604 // the safest way of doing things. Doing it in the halfedge
605 // destructor will not work well because it disrupts cycle
606 // finding/incident edge replacement in the vertex code.
607 // We also take this time to clean up any orphaned stitches
608 // still belonging to the edges.
609 HbrHalfedge<T>* edge;
610 size_t edgesize;
611 if (nvertices > 4) {
612 edge = (HbrHalfedge<T>*)(extraedges);
613 edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
614 } else {
615 edge = edges;
616 edgesize = sizeof(HbrHalfedge<T>);
617 }
618 for (i = 0; i < nvertices; ++i) {
619 #ifdef HBRSTITCH
620 edge->DestroyStitchEdges(stitchCount);
621 #endif
622 HbrVertex<T>* vertex = mesh->GetVertex(edge->GetOrgVertexID());
623 if (fvarbits) {
624 HbrFVarData<T>& fvt = vertex->GetFVarData(this);
625 if (fvt.GetFaceID() == GetID()) {
626 fvt.SetFaceID(-1);
627 }
628 }
629 vertex->RemoveIncidentEdge(edge);
630 vertex->UnGuaranteeNeighbors();
631 edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
632 }
633 if (extraedges) {
634 edge = (HbrHalfedge<T>*)(extraedges);
635 for (i = 0; i < nvertices; ++i) {
636 edge->~HbrHalfedge<T>();
637 edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
638 }
639 free(extraedges);
640 extraedges = 0;
641 }
642
643 // Remove parent's reference to self
644 HbrFace<T> *parentFace = GetParent();
645 if (parentFace) {
646 bool parentHasOtherKids = false;
647 int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(parentFace->nvertices);
648 if (nchildren > 4) {
649 for (i = 0; i < nchildren; ++i) {
650 if (parentFace->children.extrachildren[i] == this) {
651 parentFace->children.extrachildren[i] = 0;
652 } else if (parentFace->children.extrachildren[i]) parentHasOtherKids = true;
653 }
654 // After cleaning the parent's reference to self, the parent
655 // may be able to clean itself up
656 if (!parentHasOtherKids) {
657 delete[] parentFace->children.extrachildren;
658 parentFace->children.extrachildren = 0;
659 if (parentFace->GarbageCollectable()) {
660 mesh->DeleteFace(parentFace);
661 }
662 }
663 } else {
664 for (i = 0; i < nchildren; ++i) {
665 if ((*parentFace->children.children)[i] == this) {
666 (*parentFace->children.children)[i] = 0;
667 } else if ((*parentFace->children.children)[i]) parentHasOtherKids = true;
668 }
669 // After cleaning the parent's reference to self, the parent
670 // may be able to clean itself up
671 if (!parentHasOtherKids) {
672 mesh->DeleteFaceChildren(parentFace->children.children);
673 parentFace->children.children = 0;
674 if (parentFace->GarbageCollectable()) {
675 mesh->DeleteFace(parentFace);
676 }
677 }
678 }
679 parent = -1;
680 }
681
682 // Orphan the child vertex
683 if (vchild != -1) {
684 HbrVertex<T> *vchildVert = mesh->GetVertex(vchild);
685 vchildVert->SetParent(static_cast<HbrFace*>(0));
686 vchild = -1;
687 }
688
689 if (nvertices > 4 && fvarbits) {
690 free(fvarbits);
691 #ifdef HBRSTITCH
692 if (stitchEdges) {
693 free(stitchEdges);
694 }
695 #endif
696 }
697 fvarbits = 0;
698 #ifdef HBRSTITCH
699 stitchEdges = 0;
700 #endif
701
702 // Make sure the four edges intrinsic to face are properly cleared
703 // if they were used
704 if (nvertices <= 4) {
705 for (i = 0; i < nvertices; ++i) {
706 edges[i].Clear();
707 }
708 }
709 nvertices = 0;
710 initialized = 0;
711 mesh = 0;
712 destroyed = 1;
713 }
714 }
715
716 template <class T>
717 HbrHalfedge<T>*
GetEdge(int index)718 HbrFace<T>::GetEdge(int index) const {
719 assert(index >= 0 && index < nvertices);
720 if (nvertices > 4) {
721 const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
722 return (HbrHalfedge<T>*)(extraedges + index * edgesize);
723 } else {
724 return const_cast<HbrHalfedge<T>*>(edges + index);
725 }
726 }
727
728 template <class T>
729 HbrVertex<T>*
GetVertex(int index)730 HbrFace<T>::GetVertex(int index) const {
731 assert(index >= 0 && index < nvertices);
732 if (nvertices > 4) {
733 const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
734 HbrHalfedge<T>* edge = (HbrHalfedge<T>*)(extraedges +
735 index * edgesize);
736 return mesh->GetVertex(edge->GetOrgVertexID());
737 } else {
738 return mesh->GetVertex(edges[index].GetOrgVertexID());
739 }
740 }
741
742 template <class T>
743 int
GetVertexID(int index)744 HbrFace<T>::GetVertexID(int index) const {
745 assert(index >= 0 && index < nvertices);
746 if (nvertices > 4) {
747 const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
748 HbrHalfedge<T>* edge = (HbrHalfedge<T>*)(extraedges +
749 index * edgesize);
750 return edge->GetOrgVertexID();
751 } else {
752 return edges[index].GetOrgVertexID();
753 }
754 }
755
756 template <class T>
757 void
SetChild(int index,HbrFace<T> * face)758 HbrFace<T>::SetChild(int index, HbrFace<T>* face) {
759 assert(id != -1);
760 int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
761 // Construct the children array if it doesn't already exist
762 if (!children.children) {
763 int i;
764 if (nchildren > 4) {
765 children.extrachildren = new HbrFace<T>*[nchildren];
766 for (i = 0; i < nchildren; ++i) {
767 children.extrachildren[i] = 0;
768 }
769 } else {
770 children.children = mesh->NewFaceChildren();
771 for (i = 0; i < nchildren; ++i) {
772 (*children.children)[i] = 0;
773 }
774 }
775 }
776 if (nchildren > 4) {
777 children.extrachildren[index] = face;
778 } else {
779 (*children.children)[index] = face;
780 }
781 face->parent = this->id;
782 }
783
784 template <class T>
785 HbrVertex<T>*
Subdivide()786 HbrFace<T>::Subdivide() {
787 if (vchild != -1) return mesh->GetVertex(vchild);
788 HbrVertex<T>* vchildVert = mesh->GetSubdivision()->Subdivide(mesh, this);
789 vchild = vchildVert->GetID();
790 vchildVert->SetParent(this);
791 return vchildVert;
792 }
793
794 template <class T>
795 void
Refine()796 HbrFace<T>::Refine() {
797 mesh->GetSubdivision()->Refine(mesh, this);
798 }
799
800 template <class T>
801 void
Unrefine()802 HbrFace<T>::Unrefine() {
803 // Delete the children, via the mesh (so that the mesh loses
804 // references to the children)
805 if (children.children) {
806 int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
807 if (nchildren > 4) {
808 for (int i = 0; i < nchildren; ++i) {
809 if (children.extrachildren[i]) mesh->DeleteFace(children.extrachildren[i]);
810 }
811 delete[] children.extrachildren;
812 children.extrachildren = 0;
813 } else {
814 for (int i = 0; i < nchildren; ++i) {
815 if ((*children.children)[i]) mesh->DeleteFace((*children.children)[i]);
816 }
817 mesh->DeleteFaceChildren(children.children);
818 children.children = 0;
819 }
820 }
821 }
822
823 template <class T>
824 bool
HasLimit()825 HbrFace<T>::HasLimit() {
826 return mesh->GetSubdivision()->HasLimit(mesh, this);
827 }
828
829 template <class T>
830 unsigned long
GetMemStats()831 HbrFace<T>::GetMemStats() const {
832 return sizeof(HbrFace<T>);
833 }
834
835 template <class T>
836 void
MarkUsage()837 HbrFace<T>::MarkUsage() {
838 // Must increment the usage on all vertices which are in the
839 // support for this face. Note well: this will increment vertices
840 // more than once. This doesn't really matter as long as
841 // ClearUsage also does the same number of decrements. If we
842 // really were concerned about ensuring single increments, we can
843 // use GetSupportingVertices, but that's slower.
844 HbrVertex<T>* v;
845 HbrHalfedge<T>* e, *ee, *eee, *start;
846 size_t edgesize, eedgesize;
847 if (nvertices > 4) {
848 e = (HbrHalfedge<T>*)(extraedges);
849 edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
850 } else {
851 e = edges;
852 edgesize = sizeof(HbrHalfedge<T>);
853 }
854 for (int i = 0; i < nvertices; ++i) {
855 v = mesh->GetVertex(e->GetOrgVertexID());
856 v->GuaranteeNeighbors();
857 start = v->GetIncidentEdge();
858 ee = start;
859 do {
860 HbrFace<T>* f = ee->GetLeftFace();
861 int nv = f->GetNumVertices();
862 if (nv > 4) {
863 eee = (HbrHalfedge<T>*)(f->extraedges);
864 eedgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
865 } else {
866 eee = f->edges;
867 eedgesize = sizeof(HbrHalfedge<T>);
868 }
869 for (int j = 0; j < nv; ++j) {
870 mesh->GetVertex(eee->GetOrgVertexID())->IncrementUsage();
871 eee = (HbrHalfedge<T>*)((char *) eee + eedgesize);
872 }
873 ee = v->GetNextEdge(ee);
874 if (ee == start) break;
875 } while (ee);
876 e = (HbrHalfedge<T>*)((char *) e + edgesize);
877 }
878 }
879
880 template <class T>
881 void
ClearUsage()882 HbrFace<T>::ClearUsage() {
883 bool gc = false;
884 // Must mark all vertices which may affect this face
885 HbrVertex<T>* v, *vv;
886 HbrHalfedge<T>* e, *ee, *eee, *start;
887 size_t edgesize, eedgesize;
888 if (nvertices > 4) {
889 e = (HbrHalfedge<T>*)(extraedges);
890 edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
891 } else {
892 e = edges;
893 edgesize = sizeof(HbrHalfedge<T>);
894 }
895 for (int i = 0; i < nvertices; ++i) {
896 v = mesh->GetVertex(e->GetOrgVertexID());
897 start = v->GetIncidentEdge();
898 ee = start;
899 do {
900 HbrFace<T>* f = ee->GetLeftFace();
901 int nv = f->GetNumVertices();
902 if (nv > 4) {
903 eee = (HbrHalfedge<T>*)(f->extraedges);
904 eedgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
905 } else {
906 eee = f->edges;
907 eedgesize = sizeof(HbrHalfedge<T>);
908 }
909 for (int j = 0; j < nv; ++j) {
910 HbrVertex<T>* vert = mesh->GetVertex(eee->GetOrgVertexID());
911 vert->DecrementUsage();
912 if (!vert->IsUsed()) {
913 mesh->AddGarbageCollectableVertex(vert);
914 gc = true;
915 }
916 eee = (HbrHalfedge<T>*)((char *) eee + eedgesize);
917 }
918 ee = v->GetNextEdge(ee);
919 if (ee == start) break;
920 } while (ee);
921 e = (HbrHalfedge<T>*)((char *) e + edgesize);
922 }
923 if (gc) mesh->GarbageCollect();
924 }
925
926 template <class T>
927 bool
GarbageCollectable()928 HbrFace<T>::GarbageCollectable() const {
929 if (children.children || protect) return false;
930 for (int i = 0; i < nvertices; ++i) {
931 HbrHalfedge<T>* edge = GetEdge(i);
932 HbrVertex<T>* vertex = edge->GetOrgVertex(mesh);
933 if (vertex->IsUsed()) return false;
934 if (!GetParent() && vertex->EdgeRemovalWillMakeSingular(edge)) {
935 return false;
936 }
937 }
938 return true;
939 }
940
941 template <class T>
942 void
SetHierarchicalEdits(HbrHierarchicalEdit<T> ** edits)943 HbrFace<T>::SetHierarchicalEdits(HbrHierarchicalEdit<T>** edits) {
944 HbrHierarchicalEdit<T>** faceedits = edits;
945 HbrHierarchicalEdit<T>** baseedit = mesh->GetHierarchicalEditsAtOffset(0);
946 editOffset = int(faceedits - baseedit);
947
948 // Walk the list of edits and look for any which apply locally.
949 while (HbrHierarchicalEdit<T>* edit = *faceedits) {
950 if (!edit->IsRelevantToFace(this)) break;
951 edit->ApplyEditToFace(this);
952 faceedits++;
953 }
954 }
955
956 template <class T>
957 void
GetSupportingVertices(std::vector<int> & support)958 HbrFace<T>::GetSupportingVertices(std::vector<int> &support) {
959 support.reserve(16);
960 HbrVertex<T>* v;
961 HbrHalfedge<T>* e, *ee, *eee, *start;
962 size_t edgesize, eedgesize;
963 if (nvertices > 4) {
964 e = (HbrHalfedge<T>*)(extraedges);
965 edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
966 } else {
967 e = edges;
968 edgesize = sizeof(HbrHalfedge<T>);
969 }
970 for (int i = 0; i < nvertices; ++i) {
971 v = mesh->GetVertex(e->GetOrgVertexID());
972 v->GuaranteeNeighbors();
973 start = v->GetIncidentEdge();
974 ee = start;
975 do {
976 HbrFace<T>* f = ee->GetLeftFace();
977 int nv = f->GetNumVertices();
978 if (nv > 4) {
979 eee = (HbrHalfedge<T>*)(f->extraedges);
980 eedgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
981 } else {
982 eee = f->edges;
983 eedgesize = sizeof(HbrHalfedge<T>);
984 }
985 for (int j = 0; j < nv; ++j) {
986 int id = eee->GetOrgVertexID();
987 std::vector<int>::iterator vi =
988 std::lower_bound(support.begin(), support.end(), id);
989 if (vi == support.end() || *vi != id) {
990 support.insert(vi, id);
991 }
992 eee = (HbrHalfedge<T>*)((char *) eee + eedgesize);
993 }
994 ee = v->GetNextEdge(ee);
995 if (ee == start) break;
996 } while (ee);
997 e = (HbrHalfedge<T>*)((char *) e + edgesize);
998 }
999 }
1000
1001 template <class T>
1002 std::ostream& operator<<(std::ostream& out, const HbrFace<T>& face) {
1003 out << "face " << face.GetID() << ", " << face.GetNumVertices() << " vertices (";
1004 for (int i = 0; i < face.GetNumVertices(); ++i) {
1005 HbrHalfedge<T>* e = face.GetEdge(i);
1006 out << *(e->GetOrgVertex());
1007 if (e->IsBoundary()) {
1008 out << " -/-> ";
1009 } else {
1010 out << " ---> ";
1011 }
1012 }
1013 out << ")";
1014 return out;
1015 }
1016
1017 template <class T>
1018 class HbrFaceOperator {
1019 public:
1020 virtual void operator() (HbrFace<T> &face) = 0;
~HbrFaceOperator()1021 virtual ~HbrFaceOperator() {}
1022 };
1023
1024 } // end namespace OPENSUBDIV_VERSION
1025 using namespace OPENSUBDIV_VERSION;
1026
1027 } // end namespace OpenSubdiv
1028
1029 #endif /* OPENSUBDIV3_HBRFACE_H */
1030