29 #include "libtarget/TgMalloc.h"
30 #include "libtarget/TgThread.h"
32 #include "libtarget/TgHashMap.h"
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"
50 #include "../version.h"
52 namespace OpenSubdiv {
53 namespace OPENSUBDIV_VERSION {
58 template <
class T>
class HbrMesh {
60 HbrMesh(
HbrSubdivision<T>* subdivision = 0,
int fvarcount = 0,
const int *fvarindices = 0,
const int *fvarwidths = 0,
int totalfvarwidth = 0
80 if (
id >= nvertices) {
89 if (
id >= vertexClientData.size()) {
92 return vertexClientData[id];
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*));
105 vertexClientData[id] = data;
143 if (
id >= faceClientData.size()) {
146 return faceClientData[id];
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*));
159 faceClientData[id] = data;
165 template <
typename OutputIterator>
174 template <
typename OutputIterator>
175 void GetFaces(OutputIterator faces)
const;
193 int GetStitchCount()
const {
return stitchCount; }
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;
231 if (!m_transientMode) {
247 return hierarchicalEdits;
253 return &hierarchicalEdits[offset];
260 void Unrefine(
int numCoarseVerts,
int numCoarseFaces) {
262 for (
int i = numCoarseFaces; i < maxFaceID; ++i) {
268 maxFaceID = numCoarseFaces;
270 for(
int i=numCoarseVerts; i<(int)vertices.size(); ++i ) {
288 m_transientMode = mode;
297 return m_faceChildrenAllocator.Allocate();
302 m_faceChildrenAllocator.Deallocate(facechildren);
307 typename TgHashMap<const HbrHalfedge<T>*,
void *>::const_iterator i =
308 stitchData.find(edge);
309 if (i != stitchData.end()) {
316 void SetStitchData(
const HbrHalfedge<T>* edge,
void *data) {
317 stitchData[edge] = data;
324 HbrSubdivision<T>* subdivision;
330 const int *fvarindices;
333 const int *fvarwidths;
336 const int totalfvarwidth;
340 const int stitchCount;
343 TgHashMap<const HbrHalfedge<T>*,
void *> stitchData;
347 std::vector<HbrVertex<T> *> vertices;
351 std::vector<void *> vertexClientData;
354 std::vector<HbrFace<T> *> faces;
358 std::vector<void *> faceClientData;
377 bool fvarpropagatecorners;
384 std::vector<HbrVertex<T>*> gcVertices;
387 std::set<int> recycleIDs;
393 std::vector<HbrHierarchicalEdit<T>*> hierarchicalEdits;
396 const size_t m_faceSize;
397 HbrAllocator<HbrFace<T> > m_faceAllocator;
400 const size_t m_vertexSize;
401 HbrAllocator<HbrVertex<T> > m_vertexAllocator;
404 HbrAllocator<HbrFaceChildren<T> > m_faceChildrenAllocator;
410 int m_numCoarseFaces;
414 unsigned hasVertexEdits:1;
415 unsigned hasCreaseEdits:1;
420 bool m_transientMode;
423 std::vector<HbrVertex<T>*> m_transientVertices;
426 std::vector<HbrFace<T>*> m_transientFaces;
430 std::vector<std::pair<int, int> >
const & GetSplitVertices()
const {
431 return m_splitVertices;
435 friend class HbrVertex<T>;
437 void addSplitVertex(
int splitIdx,
int orgIdx) {
438 m_splitVertices.push_back(std::pair<int,int>(splitIdx, orgIdx));
442 std::vector<std::pair<int, int> > m_splitVertices;
447 using namespace OPENSUBDIV_VERSION;
452 #include "../hbr/mesh.h"
453 #include "../hbr/halfedge.h"
455 namespace OpenSubdiv {
456 namespace OPENSUBDIV_VERSION {
464 : subdivision(s), fvarcount(_fvarcount), fvarindices(_fvarindices),
465 fvarwidths(_fvarwidths), totalfvarwidth(_totalfvarwidth),
467 stitchCount(_stitchCount),
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)
477 + stitchCount * sizeof(StitchEdge*)
480 m_faceAllocator(&m_memory, 512, 0, 0, m_faceSize),
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),
486 m_numCoarseFaces(-1),
489 m_transientMode(false) {
497 if (!faces.empty()) {
498 for (i = 0; i < nfaces; ++i) {
501 m_faceAllocator.Deallocate(faces[i]);
504 if (s_memStatsDecrement) {
505 s_memStatsDecrement(faces.size() *
sizeof(
HbrFace<T>*));
508 if (!vertices.empty()) {
509 for (i = 0; i < nvertices; ++i) {
511 vertices[i]->Destroy(
this);
512 m_vertexAllocator.Deallocate(vertices[i]);
515 if (s_memStatsDecrement) {
516 s_memStatsDecrement(vertices.size() *
sizeof(
HbrVertex<T>*));
519 if (!vertexClientData.empty() && s_memStatsDecrement) {
520 s_memStatsDecrement(vertexClientData.size() *
sizeof(
void*));
522 if (!faceClientData.empty() && s_memStatsDecrement) {
523 s_memStatsDecrement(faceClientData.size() *
sizeof(
void*));
526 hierarchicalEdits.begin(); hi != hierarchicalEdits.end(); ++hi) {
535 if (nvertices <=
id) {
536 while (nvertices <= maxVertexID) {
538 if (nvertices < 1) nvertices = 1;
540 size_t oldsize = vertices.size();
541 vertices.resize(nvertices);
542 if (s_memStatsIncrement) {
543 s_memStatsIncrement((vertices.size() - oldsize) *
sizeof(
HbrVertex<T>*));
550 v = m_vertexAllocator.Allocate();
555 if (
id >= maxVertexID) {
556 maxVertexID =
id + 1;
562 AddGarbageCollectableVertex(v);
565 if (m_transientMode) {
566 m_transientVertices.push_back(v);
576 int id = maxVertexID;
577 if (!recycleIDs.empty()) {
578 id = *recycleIDs.begin();
579 recycleIDs.erase(recycleIDs.begin());
581 if (
id >= maxVertexID) {
582 maxVertexID =
id + 1;
584 return NewVertex(
id, data);
592 int id = maxVertexID;
593 if (!recycleIDs.empty()) {
594 id = *recycleIDs.begin();
595 recycleIDs.erase(recycleIDs.begin());
597 if (
id >= maxVertexID) {
598 maxVertexID =
id + 1;
602 return NewVertex(
id, data);
610 for (i = 0; i < nv; ++i) {
611 facevertices[i] = GetVertex(vtx[i]);
612 if (!facevertices[i]) {
618 if (nfaces <= maxFaceID) {
619 while (nfaces <= maxFaceID) {
621 if (nfaces < 1) nfaces = 1;
623 size_t oldsize = faces.size();
624 faces.resize(nfaces);
625 if (s_memStatsIncrement) {
626 s_memStatsIncrement((faces.size() - oldsize) *
sizeof(
HbrVertex<T>*));
629 f = faces[maxFaceID];
633 f = m_faceAllocator.Allocate();
635 f->
Initialize(
this, NULL, -1, maxFaceID, uindex, nv, facevertices, totalfvarwidth, 0);
636 faces[maxFaceID] = f;
639 if (uindex > maxUniformIndex) maxUniformIndex = uindex;
642 if (m_transientMode) {
643 m_transientFaces.push_back(f);
653 if (nfaces <= maxFaceID) {
654 while (nfaces <= maxFaceID) {
656 if (nfaces < 1) nfaces = 1;
658 size_t oldsize = faces.size();
659 faces.resize(nfaces);
660 if (s_memStatsIncrement) {
661 s_memStatsIncrement((faces.size() - oldsize) *
sizeof(
HbrVertex<T>*));
664 f = faces[maxFaceID];
668 f = m_faceAllocator.Allocate();
674 faces[maxFaceID] = f;
678 if (m_transientMode) {
679 m_transientFaces.push_back(f);
688 m_numCoarseFaces = 0;
689 for (i = 0; i < nfaces; ++i) {
691 faces[i]->SetCoarse();
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) {
705 GetVertices(std::back_inserter(vertexlist));
708 if (interpboundarymethod == k_InterpolateBoundaryEdgeOnly || interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
709 for (i = 0; i < nfaces; ++i) {
711 int nv = face->GetNumVertices();
712 for (
int k = 0; k < nv; ++k) {
722 if (interpboundarymethod == k_InterpolateBoundaryEdgeAndCorner) {
723 for (
typename std::vector<
HbrVertex<T>*>::iterator vi = vertexlist.begin();
724 vi != vertexlist.end(); ++vi) {
733 if (!hierarchicalEdits.empty()) {
735 int nHierarchicalEdits = (int)hierarchicalEdits.size();
736 std::sort(hierarchicalEdits.begin(), hierarchicalEdits.end(), cmp);
739 hierarchicalEdits.push_back(0);
742 for (i = 0; i < nfaces; ++i) {
744 while (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() < i) {
747 if (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() == i) {
748 faces[i]->SetHierarchicalEdits(&hierarchicalEdits[j]);
758 if (face->
GetID() < nfaces) {
761 faces[face->
GetID()] = 0;
763 m_faceAllocator.Deallocate(face);
773 recycleIDs.insert(vertex->
GetID());
774 int id = vertex->
GetID();
777 m_vertexAllocator.Deallocate(vertex);
785 for (
int i = 0; i < nvertices; ++i) {
786 if (vertices[i]) count++;
794 int disconnected = 0;
795 for (
int i = 0; i < nvertices; ++i) {
797 if (!v->IsConnected()) {
809 for (
int i = 0; i < nfaces; ++i) {
810 if (faces[i]) count++;
819 if (m_numCoarseFaces >= 0)
return m_numCoarseFaces;
822 for (
int i = 0; i < nfaces; ++i) {
823 if (faces[i] && faces[i]->IsCoarse()) count++;
838 template <
typename OutputIterator>
841 for (
int i = 0; i < nvertices; ++i) {
842 if (vertices[i]) *lvertices++ = vertices[i];
849 for (
int i = 0; i < nvertices; ++i) {
850 if (vertices[i]) op(*vertices[i]);
855 template <
typename OutputIterator>
858 for (
int i = 0; i < nfaces; ++i) {
859 if (faces[i]) *lfaces++ = faces[i];
869 int disconnected = 0;
870 int extraordinary = 0;
871 for (i = 0; i < nvertices; ++i) {
874 if (v->IsSingular()) {
875 out <<
" singular: " << *v <<
"\n";
877 }
else if (!v->IsConnected()) {
878 out <<
" disconnected: " << *v <<
"\n";
881 if (v->IsExtraordinary()) {
884 sumvalence += v->GetValence();
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";
896 for (i = 0; i < nfaces; ++i) {
899 sumsides += f->GetNumVertices();
902 out <<
"Mesh has " << nfaces <<
" faces\n";
903 out <<
"Average sidedness " << (float) sumsides / nfaces <<
"\n";
909 if (gcVertices.empty())
return;
911 static const size_t gcthreshold = 4096;
913 if (gcVertices.size() <= gcthreshold)
return;
917 std::vector<HbrFace<T>*> killlist;
918 std::vector<HbrVertex<T>*> vlist;
923 int numprocessed = (int)gcVertices.size() - gcthreshold / 2;
924 for (
int i = 0; i < numprocessed; ++i) {
927 if (v->
IsUsed())
continue;
935 killlist.push_back(f);
938 if (edge == start)
break;
942 gcVertices.erase(gcVertices.begin(), gcVertices.begin() + numprocessed);
945 for (
typename std::vector<
HbrFace<T>*>::iterator fi = killlist.begin(); fi != killlist.end(); ++fi) {
946 if ((*fi)->GarbageCollectable()) {
949 (*fi)->ClearCollected();
954 for (
typename std::vector<
HbrVertex<T>*>::iterator vi = vlist.begin(); vi != vlist.end(); ++vi) {
965 hierarchicalEdits.push_back(edit);
978 for (
typename std::vector<
HbrFace<T>*>::iterator fi = m_transientFaces.begin();
979 fi != m_transientFaces.end(); ++fi) {
984 for (
typename std::vector<
HbrVertex<T>*>::iterator vi = m_transientVertices.begin();
985 vi != m_transientVertices.end(); ++vi) {
988 m_transientVertices.clear();
989 m_transientFaces.clear();
992 for (i = nfaces - 1; i >= 0; --i) {
999 for (i = nvertices - 1; i >= 0; --i) {
1001 maxVertexID = i + 1;
1008 using namespace OPENSUBDIV_VERSION;
bool HasVertexEdits() const
void SetVertexClientData(int id, void *data)
int GetNumVertices() const
int GetNumCoarseFaces() const
void DeleteFaceChildren(HbrFaceChildren< T > *facechildren)
HbrFaceChildren< T > * NewFaceChildren()
const int * GetFVarIndices() const
void GetVertices(OutputIterator vertices) const
HbrVertex< T > * GetVertex(int id) const
void SetFaceClientData(int id, void *data)
bool IsReferenced() const
InterpolateBoundaryMethod GetFVarInterpolateBoundaryMethod() const
const std::vector< HbrHierarchicalEdit< T > * > & GetHierarchicalEdits() const
bool GetFVarPropagateCorners() const
void * GetVertexClientData(int id) const
void SetTransientMode(bool mode)
InterpolateBoundaryMethod GetInterpolateBoundaryMethod() const
void SetFVarPropagateCorners(bool p)
HbrVertex< T > * NewVertex()
void SetInterpolateBoundaryMethod(InterpolateBoundaryMethod method)
HbrSubdivision< T > * GetSubdivision() const
HbrFace< T > * GetLeftFace() const
bool HasCreaseEdits() const
void AddHierarchicalEdit(HbrHierarchicalEdit< T > *edit)
void ApplyOperatorAllVertices(HbrVertexOperator< T > &op) const
int GetTotalFVarWidth() const
void SetSharpness(float sharp)
HbrHalfedge< T > * GetIncidentEdge() const
void SetSharpness(float sharp)
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)
HbrHalfedge< T > * GetNextEdge(const HbrHalfedge< T > *edge) const
int GetCoarseValence() const
void PrintStats(std::ostream &out)
void AddGarbageCollectableVertex(HbrVertex< T > *vertex)
HbrFace< T > * GetFace(int id) const
HbrHierarchicalEdit< T > ** GetHierarchicalEditsAtOffset(int offset)
void Destroy(HbrMesh< T > *mesh=0)
void GetFaces(OutputIterator faces) const
HbrFace< T > * NewFace(int nvertices, const int *vtx, int uindex)
void Initialize(int vid, const T &data, int fvarwidth)
InterpolateBoundaryMethod
void DeleteFace(HbrFace< T > *face)
void(* HbrMemStatFunction)(size_t bytes)
int GetUniformIndex() const
size_t GetMemStats() const
void RegisterMemoryRoutines(void(*increment)(unsigned long bytes), void(*decrement)(unsigned long bytes))
void DeleteVertex(HbrVertex< T > *vertex)
void Unrefine(int numCoarseVerts, int numCoarseFaces)
void SetFVarInterpolateBoundaryMethod(InterpolateBoundaryMethod method)
int GetNumDisconnectedVertices() const
HbrMesh(HbrSubdivision< T > *subdivision=0, int fvarcount=0, const int *fvarindices=0, const int *fvarwidths=0, int totalfvarwidth=0)
const int * GetFVarWidths() const
void * GetFaceClientData(int id) const