All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mesh.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 HBRMESH_H
26 #define HBRMESH_H
27 
28 #ifdef PRMAN
29 #include "libtarget/TgMalloc.h" // only for alloca
30 #include "libtarget/TgThread.h"
31 #ifdef HBRSTITCH
32 #include "libtarget/TgHashMap.h"
33 #endif
34 #endif
35 
36 #include <algorithm>
37 #include <cstring>
38 #include <iterator>
39 #include <vector>
40 #include <set>
41 #include <iostream>
42 
43 #include "../hbr/vertex.h"
44 #include "../hbr/face.h"
45 #include "../hbr/hierarchicalEdit.h"
46 #include "../hbr/vertexEdit.h"
47 #include "../hbr/creaseEdit.h"
48 #include "../hbr/allocator.h"
49 
50 #include "../version.h"
51 
52 namespace OpenSubdiv {
53 namespace OPENSUBDIV_VERSION {
54 
55 template <class T> class HbrSubdivision;
56 template <class T> class HbrHalfedge;
57 
58 template <class T> class HbrMesh {
59 public:
60  HbrMesh(HbrSubdivision<T>* subdivision = 0, int fvarcount = 0, const int *fvarindices = 0, const int *fvarwidths = 0, int totalfvarwidth = 0
61 #ifdef HBRSTITCH
62  , int stitchCount = 0
63 #endif
64  );
65  ~HbrMesh();
66 
67  // Create vertex with the indicated ID and data
68  HbrVertex<T>* NewVertex(int id, const T &data);
69 
70  // Create vertex with the indicated data. The ID will be assigned
71  // by the mesh.
72  HbrVertex<T>* NewVertex(const T &data);
73 
74  // Create vertex without an ID - one will be assigned by the mesh,
75  // and the data implicitly created will share the same id
77 
78  // Ask for vertex with the indicated ID
79  HbrVertex<T>* GetVertex(int id) const {
80  if (id >= nvertices) {
81  return 0;
82  } else {
83  return vertices[id];
84  }
85  }
86 
87  // Ask for client data associated with the vertex with the indicated ID
88  void* GetVertexClientData(int id) const {
89  if (id >= vertexClientData.size()) {
90  return 0;
91  } else {
92  return vertexClientData[id];
93  }
94  }
95 
96  // Set client data associated with the vertex with the indicated ID
97  void SetVertexClientData(int id, void *data) {
98  if (id >= vertexClientData.size()) {
99  size_t oldsize = vertexClientData.size();
100  vertexClientData.resize(nvertices);
101  if (s_memStatsIncrement) {
102  s_memStatsIncrement((vertexClientData.size() - oldsize) * sizeof(void*));
103  }
104  }
105  vertexClientData[id] = data;
106  }
107 
108  // Create face from a list of vertex IDs
109  HbrFace<T>* NewFace(int nvertices, const int *vtx, int uindex);
110 
111  // Create face from a list of vertices
112  HbrFace<T>* NewFace(int nvertices, HbrVertex<T>** vtx, HbrFace<T>* parent, int childindex);
113 
114  // "Create" a new uniform index
115  int NewUniformIndex() { return ++maxUniformIndex; }
116 
117  // Finishes initialization of the mesh
118  void Finish();
119 
120  // Remove the indicated face from the mesh
121  void DeleteFace(HbrFace<T>* face);
122 
123  // Remove the indicated vertex from the mesh
124  void DeleteVertex(HbrVertex<T>* vertex);
125 
126  // Returns number of vertices in the mesh
127  int GetNumVertices() const;
128 
129  // Returns number of disconnected vertices in the mesh
130  int GetNumDisconnectedVertices() const;
131 
132  // Returns number of faces in the mesh
133  int GetNumFaces() const;
134 
135  // Returns number of coarse faces in the mesh
136  int GetNumCoarseFaces() const;
137 
138  // Ask for face with the indicated ID
139  HbrFace<T>* GetFace(int id) const;
140 
141  // Ask for client data associated with the face with the indicated ID
142  void* GetFaceClientData(int id) const {
143  if (id >= faceClientData.size()) {
144  return 0;
145  } else {
146  return faceClientData[id];
147  }
148  }
149 
150  // Set client data associated with the face with the indicated ID
151  void SetFaceClientData(int id, void *data) {
152  if (id >= faceClientData.size()) {
153  size_t oldsize = faceClientData.size();
154  faceClientData.resize(nfaces);
155  if (s_memStatsIncrement) {
156  s_memStatsIncrement((faceClientData.size() - oldsize) * sizeof(void*));
157  }
158  }
159  faceClientData[id] = data;
160  }
161 
162  // Returns a collection of all vertices in the mesh. This function
163  // requires an output iterator; to get the vertices into a
164  // std::vector, use GetVertices(std::back_inserter(myvector))
165  template <typename OutputIterator>
166  void GetVertices(OutputIterator vertices) const;
167 
168  // Applies operator to all vertices
170 
171  // Returns a collection of all faces in the mesh. This function
172  // requires an output iterator; to get the faces into a
173  // std::vector, use GetFaces(std::back_inserter(myvector))
174  template <typename OutputIterator>
175  void GetFaces(OutputIterator faces) const;
176 
177  // Returns the subdivision method
178  HbrSubdivision<T>* GetSubdivision() const { return subdivision; }
179 
180  // Return the number of facevarying variables
181  int GetFVarCount() const { return fvarcount; }
182 
183  // Return a table of the start index of each facevarying variable
184  const int *GetFVarIndices() const { return fvarindices; }
185 
186  // Return a table of the size of each facevarying variable
187  const int *GetFVarWidths() const { return fvarwidths; }
188 
189  // Return the sum size of facevarying variables per vertex
190  int GetTotalFVarWidth() const { return totalfvarwidth; }
191 
192 #ifdef HBRSTITCH
193  int GetStitchCount() const { return stitchCount; }
194 #endif
195 
196  void PrintStats(std::ostream& out);
197 
198  // Returns memory statistics
199  size_t GetMemStats() const { return m_memory; }
200 
201  // Interpolate boundary management
207  };
208 
209  InterpolateBoundaryMethod GetInterpolateBoundaryMethod() const { return interpboundarymethod; }
210  void SetInterpolateBoundaryMethod(InterpolateBoundaryMethod method) { interpboundarymethod = method; }
211  InterpolateBoundaryMethod GetFVarInterpolateBoundaryMethod() const { return fvarinterpboundarymethod; }
212  void SetFVarInterpolateBoundaryMethod(InterpolateBoundaryMethod method) { fvarinterpboundarymethod = method; }
213 
214  bool GetFVarPropagateCorners() const { return fvarpropagatecorners; }
215  void SetFVarPropagateCorners(bool p) { fvarpropagatecorners = p; }
216 
217  // Register routines for keeping track of memory usage
218  void RegisterMemoryRoutines(void (*increment)(unsigned long bytes), void (*decrement)(unsigned long bytes)) {
219  m_faceAllocator.SetMemStatsIncrement(increment);
220  m_faceAllocator.SetMemStatsDecrement(decrement);
221  m_vertexAllocator.SetMemStatsIncrement(increment);
222  m_vertexAllocator.SetMemStatsDecrement(decrement);
223  s_memStatsIncrement = increment;
224  s_memStatsDecrement = decrement;
225  }
226 
227  // Add a vertex to consider for garbage collection. All
228  // neighboring faces of that vertex will be examined to see if
229  // they can be deleted
231  if (!m_transientMode) {
232  assert(vertex);
233  if (!vertex->IsCollected()) {
234  gcVertices.push_back(vertex); vertex->SetCollected();
235  }
236  }
237  }
238 
239  // Apply garbage collection to the mesh
240  void GarbageCollect();
241 
242  // Add a new hierarchical edit to the mesh
244 
245  // Return the hierarchical edits associated with the mesh
246  const std::vector<HbrHierarchicalEdit<T>*> &GetHierarchicalEdits() const {
247  return hierarchicalEdits;
248  }
249 
250  // Return the hierarchical edits associated with the mesh at an
251  // offset
253  return &hierarchicalEdits[offset];
254  }
255 
256  // Whether the mesh has certain types of edits
257  bool HasVertexEdits() const { return hasVertexEdits; }
258  bool HasCreaseEdits() const { return hasCreaseEdits; }
259 
260  void Unrefine(int numCoarseVerts, int numCoarseFaces) {
261 
262  for (int i = numCoarseFaces; i < maxFaceID; ++i) {
263  HbrFace<T>* f = GetFace(i);
264  if(f and not f->IsCoarse())
265  DeleteFace(f);
266  }
267 
268  maxFaceID = numCoarseFaces;
269 
270  for(int i=numCoarseVerts; i<(int)vertices.size(); ++i ) {
271  HbrVertex<T>* v = GetVertex(i);
272  if(v and not v->IsReferenced())
273  DeleteVertex(v);
274  }
275  }
276 
277  // When mode is true, the mesh is put in a "transient" mode,
278  // i.e. all subsequent intermediate vertices/faces that are
279  // created by subdivision are deemed temporary. This transient
280  // data can be entirely freed by a subsequent call to
281  // FreeTransientData(). Essentially, the mesh is checkpointed and
282  // restored. This is useful when space is at a premium and
283  // subdivided results are cached elsewhere. On the other hand,
284  // repeatedly putting the mesh in and out of transient mode and
285  // performing the same evaluations comes at a significant compute
286  // cost.
287  void SetTransientMode(bool mode) {
288  m_transientMode = mode;
289  }
290 
291  // Frees transient subdivision data; returns the mesh to a
292  // checkpointed state prior to a call to SetTransientMode.
293  void FreeTransientData();
294 
295  // Create new face children block for use by HbrFace
297  return m_faceChildrenAllocator.Allocate();
298  }
299 
300  // Recycle face children block used by HbrFace
302  m_faceChildrenAllocator.Deallocate(facechildren);
303  }
304 
305 #ifdef HBRSTITCH
306  void * GetStitchData(const HbrHalfedge<T>* edge) const {
307  typename TgHashMap<const HbrHalfedge<T>*, void *>::const_iterator i =
308  stitchData.find(edge);
309  if (i != stitchData.end()) {
310  return i->second;
311  } else {
312  return NULL;
313  }
314  }
315 
316  void SetStitchData(const HbrHalfedge<T>* edge, void *data) {
317  stitchData[edge] = data;
318  }
319 #endif
320 
321 private:
322 
323  // Subdivision method used in this mesh
324  HbrSubdivision<T>* subdivision;
325 
326  // Number of facevarying datums
327  int fvarcount;
328 
329  // Start indices of the facevarying data we want to store
330  const int *fvarindices;
331 
332  // Individual widths of the facevarying data we want to store
333  const int *fvarwidths;
334 
335  // Total widths of the facevarying data
336  const int totalfvarwidth;
337 
338 #ifdef HBRSTITCH
339  // Number of stitch edges per halfedge
340  const int stitchCount;
341 
342  // Client (sparse) data used on some halfedges
343  TgHashMap<const HbrHalfedge<T>*, void *> stitchData;
344 #endif
345 
346  // Vertices which comprise this mesh
347  std::vector<HbrVertex<T> *> vertices;
348  int nvertices;
349 
350  // Client data associated with each face
351  std::vector<void *> vertexClientData;
352 
353  // Faces which comprise this mesh
354  std::vector<HbrFace<T> *> faces;
355  int nfaces;
356 
357  // Client data associated with each face
358  std::vector<void *> faceClientData;
359 
360  // Maximum vertex ID - may be needed when generating a unique
361  // vertex ID
362  int maxVertexID;
363 
364  // Maximum face ID - needed when generating a unique face ID
365  int maxFaceID;
366 
367  // Maximum uniform index - needed to generate a new uniform index
368  int maxUniformIndex;
369 
370  // Boundary interpolation method
371  InterpolateBoundaryMethod interpboundarymethod;
372 
373  // Facevarying boundary interpolation method
374  InterpolateBoundaryMethod fvarinterpboundarymethod;
375 
376  // Whether facevarying corners propagate their sharpness
377  bool fvarpropagatecorners;
378 
379  // Memory statistics tracking routines
380  HbrMemStatFunction s_memStatsIncrement;
381  HbrMemStatFunction s_memStatsDecrement;
382 
383  // Vertices which may be garbage collected
384  std::vector<HbrVertex<T>*> gcVertices;
385 
386  // List of vertex IDs which may be recycled
387  std::set<int> recycleIDs;
388 
389  // Hierarchical edits. This vector is left unsorted until Finish()
390  // is called, at which point it is sorted. After that point,
391  // HbrFaces have pointers directly into this array so manipulation
392  // of it should be avoided.
393  std::vector<HbrHierarchicalEdit<T>*> hierarchicalEdits;
394 
395  // Size of faces (including 4 facevarying bits and stitch edges)
396  const size_t m_faceSize;
397  HbrAllocator<HbrFace<T> > m_faceAllocator;
398 
399  // Size of vertices (includes storage for one piece of facevarying data)
400  const size_t m_vertexSize;
401  HbrAllocator<HbrVertex<T> > m_vertexAllocator;
402 
403  // Allocator for face children blocks used by HbrFace
404  HbrAllocator<HbrFaceChildren<T> > m_faceChildrenAllocator;
405 
406  // Memory used by this mesh alone, plus all its faces and vertices
407  size_t m_memory;
408 
409  // Number of coarse faces. Initialized at Finish()
410  int m_numCoarseFaces;
411 
412  // Flags which indicate whether the mesh has certain types of
413  // edits
414  unsigned hasVertexEdits:1;
415  unsigned hasCreaseEdits:1;
416 
417  // True if the mesh is in "transient" mode, meaning all
418  // vertices/faces that are created via NewVertex/NewFace should be
419  // deemed temporary
420  bool m_transientMode;
421 
422  // Vertices which are transient
423  std::vector<HbrVertex<T>*> m_transientVertices;
424 
425  // Faces which are transient
426  std::vector<HbrFace<T>*> m_transientFaces;
427 
428 #ifdef HBR_ADAPTIVE
429 public:
430  std::vector<std::pair<int, int> > const & GetSplitVertices() const {
431  return m_splitVertices;
432  }
433 
434 protected:
435  friend class HbrVertex<T>;
436 
437  void addSplitVertex(int splitIdx, int orgIdx) {
438  m_splitVertices.push_back(std::pair<int,int>(splitIdx, orgIdx));
439  }
440 
441 private:
442  std::vector<std::pair<int, int> > m_splitVertices;
443 #endif
444 };
445 
446 } // end namespace OPENSUBDIV_VERSION
447 using namespace OPENSUBDIV_VERSION;
448 
449 } // end namespace OpenSubdiv
450 
451 #include <algorithm>
452 #include "../hbr/mesh.h"
453 #include "../hbr/halfedge.h"
454 
455 namespace OpenSubdiv {
456 namespace OPENSUBDIV_VERSION {
457 
458 template <class T>
459 HbrMesh<T>::HbrMesh(HbrSubdivision<T>* s, int _fvarcount, const int *_fvarindices, const int *_fvarwidths, int _totalfvarwidth
460 #ifdef HBRSTITCH
461  , int _stitchCount
462 #endif
463  )
464  : subdivision(s), fvarcount(_fvarcount), fvarindices(_fvarindices),
465  fvarwidths(_fvarwidths), totalfvarwidth(_totalfvarwidth),
466 #ifdef HBRSTITCH
467  stitchCount(_stitchCount),
468 #endif
469  nvertices(0), nfaces(0), maxVertexID(0), maxFaceID(0), maxUniformIndex(0),
470  interpboundarymethod(k_InterpolateBoundaryNone),
471  fvarinterpboundarymethod(k_InterpolateBoundaryNone),
472  fvarpropagatecorners(false),
473  s_memStatsIncrement(0), s_memStatsDecrement(0),
474  m_faceSize(sizeof(HbrFace<T>) + 4 *
475  ((fvarcount + 15) / 16 * sizeof(unsigned int)
476 #ifdef HBRSTITCH
477  + stitchCount * sizeof(StitchEdge*)
478 #endif
479  )),
480  m_faceAllocator(&m_memory, 512, 0, 0, m_faceSize),
481  m_vertexSize(sizeof(HbrVertex<T>) +
482  (totalfvarwidth ? (sizeof(HbrFVarData<T>) + (totalfvarwidth - 1) * sizeof(float)) : 0)),
483  m_vertexAllocator(&m_memory, 512, 0, 0, m_vertexSize),
484  m_faceChildrenAllocator(&m_memory, 512, 0, 0),
485  m_memory(0),
486  m_numCoarseFaces(-1),
487  hasVertexEdits(0),
488  hasCreaseEdits(0),
489  m_transientMode(false) {
490 }
491 
492 template <class T>
494  GarbageCollect();
495 
496  int i;
497  if (!faces.empty()) {
498  for (i = 0; i < nfaces; ++i) {
499  if (faces[i]) {
500  faces[i]->Destroy();
501  m_faceAllocator.Deallocate(faces[i]);
502  }
503  }
504  if (s_memStatsDecrement) {
505  s_memStatsDecrement(faces.size() * sizeof(HbrFace<T>*));
506  }
507  }
508  if (!vertices.empty()) {
509  for (i = 0; i < nvertices; ++i) {
510  if (vertices[i]) {
511  vertices[i]->Destroy(this);
512  m_vertexAllocator.Deallocate(vertices[i]);
513  }
514  }
515  if (s_memStatsDecrement) {
516  s_memStatsDecrement(vertices.size() * sizeof(HbrVertex<T>*));
517  }
518  }
519  if (!vertexClientData.empty() && s_memStatsDecrement) {
520  s_memStatsDecrement(vertexClientData.size() * sizeof(void*));
521  }
522  if (!faceClientData.empty() && s_memStatsDecrement) {
523  s_memStatsDecrement(faceClientData.size() * sizeof(void*));
524  }
525  for (typename std::vector<HbrHierarchicalEdit<T>* >::iterator hi =
526  hierarchicalEdits.begin(); hi != hierarchicalEdits.end(); ++hi) {
527  delete *hi;
528  }
529 }
530 
531 template <class T>
533 HbrMesh<T>::NewVertex(int id, const T &data) {
534  HbrVertex<T>* v = 0;
535  if (nvertices <= id) {
536  while (nvertices <= maxVertexID) {
537  nvertices *= 2;
538  if (nvertices < 1) nvertices = 1;
539  }
540  size_t oldsize = vertices.size();
541  vertices.resize(nvertices);
542  if (s_memStatsIncrement) {
543  s_memStatsIncrement((vertices.size() - oldsize) * sizeof(HbrVertex<T>*));
544  }
545  }
546  v = vertices[id];
547  if (v) {
548  v->Destroy(this);
549  } else {
550  v = m_vertexAllocator.Allocate();
551  }
552  v->Initialize(id, data, GetTotalFVarWidth());
553  vertices[id] = v;
554 
555  if (id >= maxVertexID) {
556  maxVertexID = id + 1;
557  }
558 
559  // Newly created vertices are always candidates for garbage
560  // collection, until they get "owned" by someone who
561  // IncrementsUsage on the vertex.
562  AddGarbageCollectableVertex(v);
563 
564  // If mesh is in transient mode, add vertex to transient list
565  if (m_transientMode) {
566  m_transientVertices.push_back(v);
567  }
568  return v;
569 }
570 
571 template <class T>
573 HbrMesh<T>::NewVertex(const T &data) {
574  // Pick an ID - either the maximum vertex ID or a recycled ID if
575  // we can
576  int id = maxVertexID;
577  if (!recycleIDs.empty()) {
578  id = *recycleIDs.begin();
579  recycleIDs.erase(recycleIDs.begin());
580  }
581  if (id >= maxVertexID) {
582  maxVertexID = id + 1;
583  }
584  return NewVertex(id, data);
585 }
586 
587 template <class T>
590  // Pick an ID - either the maximum vertex ID or a recycled ID if
591  // we can
592  int id = maxVertexID;
593  if (!recycleIDs.empty()) {
594  id = *recycleIDs.begin();
595  recycleIDs.erase(recycleIDs.begin());
596  }
597  if (id >= maxVertexID) {
598  maxVertexID = id + 1;
599  }
600  T data(id);
601  data.Clear();
602  return NewVertex(id, data);
603 }
604 
605 template <class T>
606 HbrFace<T>*
607 HbrMesh<T>::NewFace(int nv, const int *vtx, int uindex) {
608  HbrVertex<T>** facevertices = reinterpret_cast<HbrVertex<T>**>(alloca(sizeof(HbrVertex<T>*) * nv));
609  int i;
610  for (i = 0; i < nv; ++i) {
611  facevertices[i] = GetVertex(vtx[i]);
612  if (!facevertices[i]) {
613  return 0;
614  }
615  }
616  HbrFace<T> *f = 0;
617  // Resize if needed
618  if (nfaces <= maxFaceID) {
619  while (nfaces <= maxFaceID) {
620  nfaces *= 2;
621  if (nfaces < 1) nfaces = 1;
622  }
623  size_t oldsize = faces.size();
624  faces.resize(nfaces);
625  if (s_memStatsIncrement) {
626  s_memStatsIncrement((faces.size() - oldsize) * sizeof(HbrVertex<T>*));
627  }
628  }
629  f = faces[maxFaceID];
630  if (f) {
631  f->Destroy();
632  } else {
633  f = m_faceAllocator.Allocate();
634  }
635  f->Initialize(this, NULL, -1, maxFaceID, uindex, nv, facevertices, totalfvarwidth, 0);
636  faces[maxFaceID] = f;
637  maxFaceID++;
638  // Update the maximum encountered uniform index
639  if (uindex > maxUniformIndex) maxUniformIndex = uindex;
640 
641  // If mesh is in transient mode, add face to transient list
642  if (m_transientMode) {
643  m_transientFaces.push_back(f);
644  }
645  return f;
646 }
647 
648 template <class T>
649 HbrFace<T>*
650 HbrMesh<T>::NewFace(int nv, HbrVertex<T> **vtx, HbrFace<T>* parent, int childindex) {
651  HbrFace<T> *f = 0;
652  // Resize if needed
653  if (nfaces <= maxFaceID) {
654  while (nfaces <= maxFaceID) {
655  nfaces *= 2;
656  if (nfaces < 1) nfaces = 1;
657  }
658  size_t oldsize = faces.size();
659  faces.resize(nfaces);
660  if (s_memStatsIncrement) {
661  s_memStatsIncrement((faces.size() - oldsize) * sizeof(HbrVertex<T>*));
662  }
663  }
664  f = faces[maxFaceID];
665  if (f) {
666  f->Destroy();
667  } else {
668  f = m_faceAllocator.Allocate();
669  }
670  f->Initialize(this, parent, childindex, maxFaceID, parent ? parent->GetUniformIndex() : 0, nv, vtx, totalfvarwidth, parent ? parent->GetDepth() + 1 : 0);
671  if (parent) {
672  f->SetPtexIndex(parent->GetPtexIndex());
673  }
674  faces[maxFaceID] = f;
675  maxFaceID++;
676 
677  // If mesh is in transient mode, add face to transient list
678  if (m_transientMode) {
679  m_transientFaces.push_back(f);
680  }
681  return f;
682 }
683 
684 template <class T>
685 void
687  int i, j;
688  m_numCoarseFaces = 0;
689  for (i = 0; i < nfaces; ++i) {
690  if (faces[i]) {
691  faces[i]->SetCoarse();
692  m_numCoarseFaces++;
693  }
694  }
695 
696  std::vector<HbrVertex<T>*> vertexlist;
697  GetVertices(std::back_inserter(vertexlist));
698  for (typename std::vector<HbrVertex<T>*>::iterator vi = vertexlist.begin();
699  vi != vertexlist.end(); ++vi) {
700  HbrVertex<T>* vertex = *vi;
701  if (vertex->IsConnected()) vertex->Finish();
702  }
703  // Finish may have added new vertices
704  vertexlist.clear();
705  GetVertices(std::back_inserter(vertexlist));
706 
707  // If interpolateboundary is on, process boundary edges
708  if (interpboundarymethod == k_InterpolateBoundaryEdgeOnly || interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
709  for (i = 0; i < nfaces; ++i) {
710  if (HbrFace<T>* face = faces[i]) {
711  int nv = face->GetNumVertices();
712  for (int k = 0; k < nv; ++k) {
713  HbrHalfedge<T>* edge = face->GetEdge(k);
714  if (edge->IsBoundary()) {
716  }
717  }
718  }
719  }
720  }
721  // Process corners
722  if (interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
723  for (typename std::vector<HbrVertex<T>*>::iterator vi = vertexlist.begin();
724  vi != vertexlist.end(); ++vi) {
725  HbrVertex<T>* vertex = *vi;
726  if (vertex && vertex->IsConnected() && vertex->OnBoundary() && vertex->GetCoarseValence() == 2) {
728  }
729  }
730  }
731 
732  // Sort the hierarchical edits
733  if (!hierarchicalEdits.empty()) {
735  int nHierarchicalEdits = (int)hierarchicalEdits.size();
736  std::sort(hierarchicalEdits.begin(), hierarchicalEdits.end(), cmp);
737  // Push a sentinel null value - we rely upon this sentinel to
738  // ensure face->GetHierarchicalEdits knows when to terminate
739  hierarchicalEdits.push_back(0);
740  j = 0;
741  // Link faces to hierarchical edits
742  for (i = 0; i < nfaces; ++i) {
743  if (faces[i]) {
744  while (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() < i) {
745  ++j;
746  }
747  if (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() == i) {
748  faces[i]->SetHierarchicalEdits(&hierarchicalEdits[j]);
749  }
750  }
751  }
752  }
753 }
754 
755 template <class T>
756 void
758  if (face->GetID() < nfaces) {
759  HbrFace<T>* f = faces[face->GetID()];
760  if (f == face) {
761  faces[face->GetID()] = 0;
762  face->Destroy();
763  m_faceAllocator.Deallocate(face);
764  }
765  }
766 }
767 
768 template <class T>
769 void
771  HbrVertex<T> *v = GetVertex(vertex->GetID());
772  if (v == vertex) {
773  recycleIDs.insert(vertex->GetID());
774  int id = vertex->GetID();
775  vertices[id] = 0;
776  vertex->Destroy(this);
777  m_vertexAllocator.Deallocate(vertex);
778  }
779 }
780 
781 template <class T>
782 int
784  int count = 0;
785  for (int i = 0; i < nvertices; ++i) {
786  if (vertices[i]) count++;
787  }
788  return count;
789 }
790 
791 template <class T>
792 int
794  int disconnected = 0;
795  for (int i = 0; i < nvertices; ++i) {
796  if (HbrVertex<T>* v = vertices[i]) {
797  if (!v->IsConnected()) {
798  disconnected++;
799  }
800  }
801  }
802  return disconnected;
803 }
804 
805 template <class T>
806 int
808  int count = 0;
809  for (int i = 0; i < nfaces; ++i) {
810  if (faces[i]) count++;
811  }
812  return count;
813 }
814 
815 template <class T>
816 int
818  // Use the value computed by Finish() if it exists
819  if (m_numCoarseFaces >= 0) return m_numCoarseFaces;
820  // Otherwise we have to just count it up now
821  int count = 0;
822  for (int i = 0; i < nfaces; ++i) {
823  if (faces[i] && faces[i]->IsCoarse()) count++;
824  }
825  return count;
826 }
827 
828 template <class T>
829 HbrFace<T>*
830 HbrMesh<T>::GetFace(int id) const {
831  if (id < nfaces) {
832  return faces[id];
833  }
834  return 0;
835 }
836 
837 template <class T>
838 template <typename OutputIterator>
839 void
840 HbrMesh<T>::GetVertices(OutputIterator lvertices) const {
841  for (int i = 0; i < nvertices; ++i) {
842  if (vertices[i]) *lvertices++ = vertices[i];
843  }
844 }
845 
846 template <class T>
847 void
849  for (int i = 0; i < nvertices; ++i) {
850  if (vertices[i]) op(*vertices[i]);
851  }
852 }
853 
854 template <class T>
855 template <typename OutputIterator>
856 void
857 HbrMesh<T>::GetFaces(OutputIterator lfaces) const {
858  for (int i = 0; i < nfaces; ++i) {
859  if (faces[i]) *lfaces++ = faces[i];
860  }
861 }
862 
863 template <class T>
864 void
865 HbrMesh<T>::PrintStats(std::ostream &out) {
866  int singular = 0;
867  int sumvalence = 0;
868  int i, nv = 0;
869  int disconnected = 0;
870  int extraordinary = 0;
871  for (i = 0; i < nvertices; ++i) {
872  if (HbrVertex<T>* v = vertices[i]) {
873  nv++;
874  if (v->IsSingular()) {
875  out << " singular: " << *v << "\n";
876  singular++;
877  } else if (!v->IsConnected()) {
878  out << " disconnected: " << *v << "\n";
879  disconnected++;
880  } else {
881  if (v->IsExtraordinary()) {
882  extraordinary++;
883  }
884  sumvalence += v->GetValence();
885  }
886  }
887  }
888  out << "Mesh has " << nv << " vertices\n";
889  out << "Total singular vertices " << singular << "\n";
890  out << "Total disconnected vertices " << disconnected << "\n";
891  out << "Total extraordinary vertices " << extraordinary << "\n";
892  out << "Average valence " << (float) sumvalence / nv << "\n";
893 
894  int sumsides = 0;
895  int numfaces = 0;
896  for (i = 0; i < nfaces; ++i) {
897  if (HbrFace<T>* f = faces[i]) {
898  numfaces++;
899  sumsides += f->GetNumVertices();
900  }
901  }
902  out << "Mesh has " << nfaces << " faces\n";
903  out << "Average sidedness " << (float) sumsides / nfaces << "\n";
904 }
905 
906 template <class T>
907 void
909  if (gcVertices.empty()) return;
910 
911  static const size_t gcthreshold = 4096;
912 
913  if (gcVertices.size() <= gcthreshold) return;
914  // Go through the list of garbage collectable vertices and gather
915  // up the neighboring faces of those vertices which can be garbage
916  // collected.
917  std::vector<HbrFace<T>*> killlist;
918  std::vector<HbrVertex<T>*> vlist;
919 
920  // Process the vertices in the same order as they were collected
921  // (gcVertices used to be declared as a std::deque, but that was
922  // causing unnecessary heap traffic).
923  int numprocessed = (int)gcVertices.size() - gcthreshold / 2;
924  for (int i = 0; i < numprocessed; ++i) {
925  HbrVertex<T>* v = gcVertices[i];
926  v->ClearCollected();
927  if (v->IsUsed()) continue;
928  vlist.push_back(v);
929  HbrHalfedge<T>* start = v->GetIncidentEdge(), *edge;
930  edge = start;
931  while (edge) {
932  HbrFace<T>* f = edge->GetLeftFace();
933  if (!f->IsCollected()) {
934  f->SetCollected();
935  killlist.push_back(f);
936  }
937  edge = v->GetNextEdge(edge);
938  if (edge == start) break;
939  }
940  }
941 
942  gcVertices.erase(gcVertices.begin(), gcVertices.begin() + numprocessed);
943 
944  // Delete those faces
945  for (typename std::vector<HbrFace<T>*>::iterator fi = killlist.begin(); fi != killlist.end(); ++fi) {
946  if ((*fi)->GarbageCollectable()) {
947  DeleteFace(*fi);
948  } else {
949  (*fi)->ClearCollected();
950  }
951  }
952 
953  // Delete as many vertices as we can
954  for (typename std::vector<HbrVertex<T>*>::iterator vi = vlist.begin(); vi != vlist.end(); ++vi) {
955  HbrVertex<T>* v = *vi;
956  if (!v->IsReferenced()) {
957  DeleteVertex(v);
958  }
959  }
960 }
961 
962 template <class T>
963 void
965  hierarchicalEdits.push_back(edit);
966  if (dynamic_cast<HbrVertexEdit<T>*>(edit) ||
967  dynamic_cast<HbrMovingVertexEdit<T>*>(edit)) {
968  hasVertexEdits = 1;
969  } else if (dynamic_cast<HbrCreaseEdit<T>*>(edit)) {
970  hasCreaseEdits = 1;
971  }
972 }
973 
974 template <class T>
975 void
977  // When purging transient data, we must clear the faces first
978  for (typename std::vector<HbrFace<T>*>::iterator fi = m_transientFaces.begin();
979  fi != m_transientFaces.end(); ++fi) {
980  DeleteFace(*fi);
981  }
982  // The vertices should now be trivial to purge after the transient
983  // faces have been cleared
984  for (typename std::vector<HbrVertex<T>*>::iterator vi = m_transientVertices.begin();
985  vi != m_transientVertices.end(); ++vi) {
986  DeleteVertex(*vi);
987  }
988  m_transientVertices.clear();
989  m_transientFaces.clear();
990  // Reset max face ID
991  int i;
992  for (i = nfaces - 1; i >= 0; --i) {
993  if (faces[i]) {
994  maxFaceID = i + 1;
995  break;
996  }
997  }
998  // Reset max vertex ID
999  for (i = nvertices - 1; i >= 0; --i) {
1000  if (vertices[i]) {
1001  maxVertexID = i + 1;
1002  break;
1003  }
1004  }
1005 }
1006 
1007 } // end namespace OPENSUBDIV_VERSION
1008 using namespace OPENSUBDIV_VERSION;
1009 
1010 } // end namespace OpenSubdiv
1011 
1012 #endif /* HBRMESH_H */
1013 
void SetVertexClientData(int id, void *data)
Definition: mesh.h:97
void DeleteFaceChildren(HbrFaceChildren< T > *facechildren)
Definition: mesh.h:301
HbrFaceChildren< T > * NewFaceChildren()
Definition: mesh.h:296
const int * GetFVarIndices() const
Definition: mesh.h:184
void GetVertices(OutputIterator vertices) const
Definition: mesh.h:840
HbrVertex< T > * GetVertex(int id) const
Definition: mesh.h:79
void SetFaceClientData(int id, void *data)
Definition: mesh.h:151
InterpolateBoundaryMethod GetFVarInterpolateBoundaryMethod() const
Definition: mesh.h:211
const std::vector< HbrHierarchicalEdit< T > * > & GetHierarchicalEdits() const
Definition: mesh.h:246
void * GetVertexClientData(int id) const
Definition: mesh.h:88
InterpolateBoundaryMethod GetInterpolateBoundaryMethod() const
Definition: mesh.h:209
HbrVertex< T > * NewVertex()
Definition: mesh.h:589
void SetInterpolateBoundaryMethod(InterpolateBoundaryMethod method)
Definition: mesh.h:210
HbrSubdivision< T > * GetSubdivision() const
Definition: mesh.h:178
HbrFace< T > * GetLeftFace() const
Definition: halfedge.h:169
void AddHierarchicalEdit(HbrHierarchicalEdit< T > *edit)
Definition: mesh.h:964
void ApplyOperatorAllVertices(HbrVertexOperator< T > &op) const
Definition: mesh.h:848
HbrHalfedge< T > * GetIncidentEdge() const
Definition: vertex.h:285
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)
Definition: face.h:448
HbrHalfedge< T > * GetNextEdge(const HbrHalfedge< T > *edge) const
Definition: vertex.h:990
void PrintStats(std::ostream &out)
Definition: mesh.h:865
void AddGarbageCollectableVertex(HbrVertex< T > *vertex)
Definition: mesh.h:230
HbrFace< T > * GetFace(int id) const
Definition: mesh.h:830
HbrHierarchicalEdit< T > ** GetHierarchicalEditsAtOffset(int offset)
Definition: mesh.h:252
void Destroy(HbrMesh< T > *mesh=0)
Definition: vertex.h:475
void GetFaces(OutputIterator faces) const
Definition: mesh.h:857
HbrFace< T > * NewFace(int nvertices, const int *vtx, int uindex)
Definition: mesh.h:607
void Initialize(int vid, const T &data, int fvarwidth)
Definition: vertex.h:438
void DeleteFace(HbrFace< T > *face)
Definition: mesh.h:757
void(* HbrMemStatFunction)(size_t bytes)
Definition: allocator.h:33
void RegisterMemoryRoutines(void(*increment)(unsigned long bytes), void(*decrement)(unsigned long bytes))
Definition: mesh.h:218
void DeleteVertex(HbrVertex< T > *vertex)
Definition: mesh.h:770
void Unrefine(int numCoarseVerts, int numCoarseFaces)
Definition: mesh.h:260
void SetFVarInterpolateBoundaryMethod(InterpolateBoundaryMethod method)
Definition: mesh.h:212
HbrMesh(HbrSubdivision< T > *subdivision=0, int fvarcount=0, const int *fvarindices=0, const int *fvarwidths=0, int totalfvarwidth=0)
Definition: mesh.h:459
const int * GetFVarWidths() const
Definition: mesh.h:187
void * GetFaceClientData(int id) const
Definition: mesh.h:142