Some notes :

- still need to change these changes with other compilers (MSVC / clang...)

- had to add a -Wno-invalid-offsetof for GCC (still need to test w/ other compilers) : apparently gcc 4.4 is somewhat incorrect in tagging our templated class as POD.

- had to change fvarData.h to initialize bitfields to 0 as gcc generates truncated int warnings when trying to initialize 31 bits to -1

- in mesh.h replaced original tbb::concurrent_vector with std::vector until a better solution can be found

Fixes #93
This commit is contained in:
manuelk 2013-01-10 10:47:50 -08:00
parent 95c84b8f56
commit f9dd284be0
8 changed files with 736 additions and 506 deletions

View File

@ -98,6 +98,11 @@ set(CMAKE_MODULE_PATH
${CMAKE_CURRENT_SOURCE_DIR}/cmake
)
# Disable spurrious offsetof warning in gcc builds
if(CMAKE_COMPILER_IS_GNUCC)
add_definitions("-Wno-invalid-offsetof")
endif()
# Ignore rules that will re-run cmake (this will avoid constant
# reloading of the generated Visual Studio project).
set(CMAKE_SUPPRESS_REGENERATION TRUE)

View File

@ -167,7 +167,7 @@ public:
// Return the first halfedge of the face
HbrHalfedge<T>* GetFirstEdge() const {
if (nvertices > 4) {
return const_cast<HbrHalfedge<T>*>(&extraedges[0]);
return (HbrHalfedge<T>*)(extraedges);
} else {
return const_cast<HbrHalfedge<T>*>(&edges[0]);
}
@ -180,8 +180,14 @@ public:
// Return the vertex with the indicated index
HbrVertex<T>* GetVertex(int index) const;
// Return the ID of the vertex with the indicated index
int GetVertexID(int index) const;
// Return the parent of this face
HbrFace<T>* GetParent() const { return parent; }
HbrFace<T>* GetParent() const {
if (parent == -1) return NULL;
return mesh->GetFace(parent);
}
// Set the child
void SetChild(int index, HbrFace<T>* face);
@ -189,7 +195,7 @@ public:
// Return the child with the indicated index
HbrFace<T>* GetChild(int index) const {
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
if (!children.children || index < 0 || index >= nchildren) return 0;
if (!children.children || index < 0 || index >= nchildren) return 0;
if (nchildren > 4) {
return children.extrachildren[index];
} else {
@ -201,7 +207,7 @@ public:
HbrVertex<T>* Subdivide();
// Remove the reference to subdivided vertex
void RemoveChild() { vchild = 0; }
void RemoveChild() { vchild = -1; }
// "Hole" flags used by subdivision to drop faces
bool IsHole() const { return hole; }
@ -265,7 +271,12 @@ public:
void SetHierarchicalEdits(HbrHierarchicalEdit<T>** edits);
// Return the list of hierarchical edits associated with this face
HbrHierarchicalEdit<T>** GetHierarchicalEdits() const { return edits; }
HbrHierarchicalEdit<T>** GetHierarchicalEdits() const {
if (editOffset == -1) {
return NULL;
}
return mesh->GetHierarchicalEditsAtOffset(editOffset);
}
// Whether the face has certain types of edits (not necessarily
// local - could apply to a subface)
@ -289,7 +300,7 @@ public:
void SetPtexIndex(int i) { ptexindex = i; }
// Used by block allocator
HbrFace<T>*& GetNext() { return parent; }
HbrFace<T>*& GetNext() { return (HbrFace<T>*&) mesh; }
HbrFacePath GetPath() const {
HbrFacePath path;
@ -326,14 +337,16 @@ public:
// Returns the blind pointer to client data
void *GetClientData() const {
return clientData;
return mesh->GetFaceClientData(id);
}
// Sets the blind pointer to client data
void SetClientData(void *data) {
clientData = data;
mesh->SetFaceClientData(id, data);
}
// Gets the list of vertices which are in the support for the face.
void GetSupportingVertices(std::vector<int> &support);
private:
@ -353,14 +366,10 @@ private:
int nvertices;
// Halfedge array for this face
// HbrHalfedge::getIndex() relies on this being size 4
HbrHalfedge<T> edges[4];
// Edge storage if this face is not a triangle or quad
HbrHalfedge<T>* extraedges;
// Pointer to parent face
HbrFace<T>* parent;
char* extraedges;
// Pointer to children array. If there are four children or less,
// we use the HbrFaceChildren pointer, otherwise we use
@ -370,23 +379,22 @@ private:
HbrFace<T>** extrachildren;
} children;
// Subdivided vertex child
HbrVertex<T>* vchild;
// Bits used by halfedges to track facevarying sharpnesses
unsigned int *fvarbits;
#ifdef HBRSTITCH
// Pointers to stitch edges and data used by the half edges.
// Pointers to stitch edges used by the half edges.
StitchEdge **stitchEdges;
void **stitchDatas;
#endif
// Pointer to a list of hierarchical edits applicable to this face
HbrHierarchicalEdit<T>** edits;
// Index of parent face
int parent;
// Blind client data pointer
void * clientData;
// Index of subdivided vertex child
int vchild;
// Offset to the mesh' list of hierarchical edits applicable to this face
int editOffset;
// Depth of the face in the mesh hierarchy - coarse faces are
// level 0. (Hmmm.. is it safe to assume that we'll never
@ -441,7 +449,7 @@ public:
return true;
}
return false;
}
}
#endif
};
@ -457,12 +465,11 @@ namespace OPENSUBDIV_VERSION {
template <class T>
HbrFace<T>::HbrFace()
: mesh(0), id(-1), uindex(-1), ptexindex(-1), nvertices(0), extraedges(0), parent(0), vchild(0), fvarbits(0),
: mesh(0), id(-1), uindex(-1), ptexindex(-1), nvertices(0), extraedges(0), fvarbits(0), parent(-1), vchild(-1),
#ifdef HBRSTITCH
stitchEdges(0),
stitchDatas(0),
#endif
edits(0), clientData(0), depth(0), hole(0), coarse(0), protect(0), collected(0), hasVertexEdits(0), initialized(0), destroyed(0) {
editOffset(-1), depth(0), hole(0), coarse(0), protect(0), collected(0), hasVertexEdits(0), initialized(0), destroyed(0) {
children.children = 0;
}
@ -476,14 +483,12 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
nvertices = nv;
extraedges = 0;
children.children = 0;
vchild = 0;
vchild = -1;
fvarbits = 0;
#ifdef HBRSTITCH
stitchEdges = 0;
stitchDatas = 0;
#endif
clientData = 0;
edits = 0;
editOffset = -1;
depth = _depth;
hole = 0;
coarse = 0;
@ -504,14 +509,10 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
// edges and facevarying data.
#ifdef HBRSTITCH
if (mesh->GetStitchCount()) {
stitchEdges = new StitchEdge*[mesh->GetStitchCount() * nv];
stitchDatas = new void*[nv];
for (i = 0; i < mesh->GetStitchCount() * nv; ++i) {
stitchEdges[i] = 0;
}
for (i = 0; i < nv; ++i) {
stitchDatas[i] = 0;
}
const size_t buffersize = nv * (mesh->GetStitchCount() * sizeof(StitchEdge*));
char *buffer = (char *) malloc(buffersize);
memset(buffer, 0, buffersize);
stitchEdges = (StitchEdge**) buffer;
}
#endif
if (fvarcount) {
@ -525,7 +526,12 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
// We also ignore the edge array and allocate extra storage -
// this simplifies GetNext and GetPrev math in HbrHalfedge
extraedges = new HbrHalfedge<T>[nv];
const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
extraedges = (char *) malloc(nv * edgesize);
for (i = 0; i < nv; ++i) {
HbrHalfedge<T>* edge = (HbrHalfedge<T>*)(extraedges + i * edgesize);
new (edge) HbrHalfedge<T>();
}
} else {
// Under four vertices: upstream allocation for the class has
@ -534,16 +540,10 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
char *buffer = ((char *) this + sizeof(*this));
#ifdef HBRSTITCH
if (mesh->GetStitchCount()) {
const size_t buffersize = 4 * (mesh->GetStitchCount() * sizeof(StitchEdge*));
memset(buffer, 0, buffersize);
stitchEdges = (StitchEdge**) buffer;
buffer += 4 * mesh->GetStitchCount() * sizeof(StitchEdge*);
stitchDatas = (void**) buffer;
for (i = 0; i < mesh->GetStitchCount() * 4; ++i) {
stitchEdges[i] = 0;
}
for (i = 0; i < 4; ++i) {
stitchDatas[i] = 0;
}
buffer += 4 * sizeof(void*);
buffer += buffersize;
}
#endif
if (fvarcount) {
@ -562,17 +562,33 @@ HbrFace<T>::Initialize(HbrMesh<T>* m, HbrFace<T>* _parent, int childindex, int f
// vertices.
int next;
unsigned int *curfvarbits = fvarbits;
HbrHalfedge<T>* edge;
size_t edgesize;
if (nv > 4) {
edge = (HbrHalfedge<T>*)(extraedges);
edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
edge = edges;
edgesize = sizeof(HbrHalfedge<T>);
}
for (i = 0, next = 1; i < nv; ++i, ++next) {
if (next == nv) next = 0;
HbrHalfedge<T>* opposite = vertices[next]->GetEdge(vertices[i]);
GetEdge(i)->Initialize(opposite, i, vertices[i], curfvarbits, this);
if (opposite) opposite->SetOpposite(GetEdge(i));
HbrHalfedge<T>* opposite = vertices[next]->GetEdge(vertices[i]->GetID());
edge->Initialize(opposite, i, vertices[i], curfvarbits, this);
if (opposite) opposite->SetOpposite(edge);
if (fvarbits) {
curfvarbits = curfvarbits + fvarbitsSizePerEdge;
}
edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
}
if (nv > 4) {
edge = (HbrHalfedge<T>*)(extraedges);
} else {
edge = edges;
}
for (i = 0; i < nv; ++i) {
vertices[i]->AddIncidentEdge(GetEdge(i));
vertices[i]->AddIncidentEdge(edge);
edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
}
}
@ -596,7 +612,7 @@ HbrFace<T>::Destroy() {
if (nchildren > 4) {
for (i = 0; i < nchildren; ++i) {
if (children.extrachildren[i]) {
children.extrachildren[i]->parent = 0;
children.extrachildren[i]->parent = -1;
children.extrachildren[i] = 0;
}
}
@ -605,7 +621,7 @@ HbrFace<T>::Destroy() {
} else {
for (i = 0; i < nchildren; ++i) {
if ((*children.children)[i]) {
(*children.children)[i]->parent = 0;
(*children.children)[i]->parent = -1;
(*children.children)[i] = 0;
}
}
@ -620,96 +636,109 @@ HbrFace<T>::Destroy() {
// finding/incident edge replacement in the vertex code.
// We also take this time to clean up any orphaned stitches
// still belonging to the edges.
HbrHalfedge<T>* edge;
size_t edgesize;
if (nvertices > 4) {
edge = (HbrHalfedge<T>*)(extraedges);
edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
edge = edges;
edgesize = sizeof(HbrHalfedge<T>);
}
for (i = 0; i < nvertices; ++i) {
HbrHalfedge<T> *edge = GetEdge(i);
#ifdef HBRSTITCH
edge->DestroyStitchEdges(stitchCount);
#endif
HbrVertex<T>* vertex = edge->GetOrgVertex();
HbrVertex<T>* vertex = mesh->GetVertex(edge->GetOrgVertexID());
if (fvarbits) {
HbrFVarData<T>& fvt = vertex->GetFVarData(this);
if (fvt.GetFace() == this) {
fvt.SetFace(0);
if (fvt.GetFaceID() == GetID()) {
fvt.SetFaceID(-1);
}
}
vertex->RemoveIncidentEdge(edge);
vertex->UnGuaranteeNeighbors();
edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
}
if (extraedges) {
delete[] extraedges;
edge = (HbrHalfedge<T>*)(extraedges);
for (i = 0; i < nvertices; ++i) {
edge->~HbrHalfedge<T>();
edge = (HbrHalfedge<T>*)((char *) edge + edgesize);
}
free(extraedges);
extraedges = 0;
}
// Remove parent's reference to self
if (parent) {
HbrFace<T> *parentFace = GetParent();
if (parentFace) {
bool parentHasOtherKids = false;
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(parent->nvertices);
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(parentFace->nvertices);
if (nchildren > 4) {
for (i = 0; i < nchildren; ++i) {
if (parent->children.extrachildren[i] == this) {
parent->children.extrachildren[i] = 0;
} else if (parent->children.extrachildren[i]) parentHasOtherKids = true;
if (parentFace->children.extrachildren[i] == this) {
parentFace->children.extrachildren[i] = 0;
} else if (parentFace->children.extrachildren[i]) parentHasOtherKids = true;
}
// After cleaning the parent's reference to self, the parent
// may be able to clean itself up
if (!parentHasOtherKids) {
delete[] parent->children.extrachildren;
parent->children.extrachildren = 0;
if (parent->GarbageCollectable()) {
mesh->DeleteFace(parent);
delete[] parentFace->children.extrachildren;
parentFace->children.extrachildren = 0;
if (parentFace->GarbageCollectable()) {
mesh->DeleteFace(parentFace);
}
}
} else {
for (i = 0; i < nchildren; ++i) {
if ((*parent->children.children)[i] == this) {
(*parent->children.children)[i] = 0;
} else if ((*parent->children.children)[i]) parentHasOtherKids = true;
if ((*parentFace->children.children)[i] == this) {
(*parentFace->children.children)[i] = 0;
} else if ((*parentFace->children.children)[i]) parentHasOtherKids = true;
}
// After cleaning the parent's reference to self, the parent
// may be able to clean itself up
if (!parentHasOtherKids) {
mesh->DeleteFaceChildren(parent->children.children);
parent->children.children = 0;
if (parent->GarbageCollectable()) {
mesh->DeleteFace(parent);
mesh->DeleteFaceChildren(parentFace->children.children);
parentFace->children.children = 0;
if (parentFace->GarbageCollectable()) {
mesh->DeleteFace(parentFace);
}
}
}
parent = 0;
parent = -1;
}
// Orphan the child vertex
if (vchild) {
vchild->SetParent(static_cast<HbrFace*>(0));
vchild = 0;
if (vchild != -1) {
HbrVertex<T> *vchildVert = mesh->GetVertex(vchild);
vchildVert->SetParent(static_cast<HbrFace*>(0));
vchild = -1;
}
if (nvertices > 4 && fvarbits) {
free(fvarbits);
#ifdef HBRSTITCH
if (stitchEdges) {
delete[] stitchEdges;
}
if (stitchDatas) {
delete[] stitchDatas;
free(stitchEdges);
}
#endif
}
fvarbits = 0;
#ifdef HBRSTITCH
stitchEdges = 0;
stitchDatas = 0;
#endif
// Make sure the four edges intrinsic to face are properly cleared
// if they were used
if (nvertices <= 4) {
for (i = 0; i < nvertices; ++i) {
GetEdge(i)->Clear();
edges[i].Clear();
}
}
nvertices = 0;
initialized = 0;
mesh = 0;
destroyed = 1;
}
}
@ -719,7 +748,8 @@ HbrHalfedge<T>*
HbrFace<T>::GetEdge(int index) const {
assert(index >= 0 && index < nvertices);
if (nvertices > 4) {
return extraedges + index;
const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
return (HbrHalfedge<T>*)(extraedges + index * edgesize);
} else {
return const_cast<HbrHalfedge<T>*>(edges + index);
}
@ -730,15 +760,33 @@ HbrVertex<T>*
HbrFace<T>::GetVertex(int index) const {
assert(index >= 0 && index < nvertices);
if (nvertices > 4) {
return extraedges[index].GetOrgVertex();
const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
HbrHalfedge<T>* edge = (HbrHalfedge<T>*)(extraedges +
index * edgesize);
return mesh->GetVertex(edge->GetOrgVertexID());
} else {
return edges[index].GetOrgVertex();
return mesh->GetVertex(edges[index].GetOrgVertexID());
}
}
template <class T>
int
HbrFace<T>::GetVertexID(int index) const {
assert(index >= 0 && index < nvertices);
if (nvertices > 4) {
const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
HbrHalfedge<T>* edge = (HbrHalfedge<T>*)(extraedges +
index * edgesize);
return edge->GetOrgVertexID();
} else {
return edges[index].GetOrgVertexID();
}
}
template <class T>
void
HbrFace<T>::SetChild(int index, HbrFace<T>* face) {
assert(id != -1);
int nchildren = mesh->GetSubdivision()->GetFaceChildrenCount(nvertices);
// Construct the children array if it doesn't already exist
if (!children.children) {
@ -760,16 +808,17 @@ HbrFace<T>::SetChild(int index, HbrFace<T>* face) {
} else {
(*children.children)[index] = face;
}
face->parent = this;
face->parent = this->id;
}
template <class T>
HbrVertex<T>*
HbrFace<T>::Subdivide() {
if (vchild) return vchild;
vchild = mesh->GetSubdivision()->Subdivide(mesh, this);
vchild->SetParent(this);
return vchild;
if (vchild != -1) return mesh->GetVertex(vchild);
HbrVertex<T>* vchildVert = mesh->GetSubdivision()->Subdivide(mesh, this);
vchild = vchildVert->GetID();
vchildVert->SetParent(this);
return vchildVert;
}
template <class T>
@ -817,25 +866,44 @@ template <class T>
void
HbrFace<T>::MarkUsage() {
// Must increment the usage on all vertices which are in the
// support for this face
// support for this face. Note well: this will increment vertices
// more than once. This doesn't really matter as long as
// ClearUsage also does the same number of decrements. If we
// really were concerned about ensuring single increments, we can
// use GetSupportingVertices, but that's slower.
HbrVertex<T>* v;
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
HbrHalfedge<T>* e, *ee, *eee, *start;
size_t edgesize, eedgesize;
if (nvertices > 4) {
e = (HbrHalfedge<T>*)(extraedges);
edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
e = edges;
edgesize = sizeof(HbrHalfedge<T>);
}
for (int i = 0; i < nvertices; ++i) {
v = e->GetOrgVertex();
v = mesh->GetVertex(e->GetOrgVertexID());
v->GuaranteeNeighbors();
start = v->GetIncidentEdge();
ee = start;
do {
HbrFace<T>* f = ee->GetLeftFace();
eee = f->GetFirstEdge();
for (int j = 0; j < f->GetNumVertices(); ++j) {
eee->GetOrgVertex()->IncrementUsage();
eee = eee->GetNext();
int nv = f->GetNumVertices();
if (nv > 4) {
eee = (HbrHalfedge<T>*)(f->extraedges);
eedgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
eee = f->edges;
eedgesize = sizeof(HbrHalfedge<T>);
}
for (int j = 0; j < nv; ++j) {
mesh->GetVertex(eee->GetOrgVertexID())->IncrementUsage();
eee = (HbrHalfedge<T>*)((char *) eee + eedgesize);
}
ee = v->GetNextEdge(ee);
if (ee == start) break;
} while (ee);
e = e->GetNext();
e = (HbrHalfedge<T>*)((char *) e + edgesize);
}
}
@ -843,30 +911,44 @@ template <class T>
void
HbrFace<T>::ClearUsage() {
bool gc = false;
// Must mark all vertices which may affect this face
HbrVertex<T>* v, *vv;
HbrHalfedge<T>* e = GetFirstEdge(), *ee, *eee, *start;
HbrHalfedge<T>* e, *ee, *eee, *start;
size_t edgesize, eedgesize;
if (nvertices > 4) {
e = (HbrHalfedge<T>*)(extraedges);
edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
e = edges;
edgesize = sizeof(HbrHalfedge<T>);
}
for (int i = 0; i < nvertices; ++i) {
v = e->GetOrgVertex();
v = mesh->GetVertex(e->GetOrgVertexID());
start = v->GetIncidentEdge();
ee = start;
do {
HbrFace<T>* f = ee->GetLeftFace();
eee = f->GetFirstEdge();
for (int j = 0; j < f->GetNumVertices(); ++j) {
vv = eee->GetOrgVertex();
vv->DecrementUsage();
if (!vv->IsUsed()) {
mesh->AddGarbageCollectableVertex(vv);
int nv = f->GetNumVertices();
if (nv > 4) {
eee = (HbrHalfedge<T>*)(f->extraedges);
eedgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
eee = f->edges;
eedgesize = sizeof(HbrHalfedge<T>);
}
for (int j = 0; j < nv; ++j) {
HbrVertex<T>* vert = mesh->GetVertex(eee->GetOrgVertexID());
vert->DecrementUsage();
if (!vert->IsUsed()) {
mesh->AddGarbageCollectableVertex(vert);
gc = true;
}
eee = eee->GetNext();
eee = (HbrHalfedge<T>*)((char *) eee + eedgesize);
}
ee = v->GetNextEdge(ee);
if (ee == start) break;
} while (ee);
e = e->GetNext();
e = (HbrHalfedge<T>*)((char *) e + edgesize);
}
if (gc) mesh->GarbageCollect();
}
@ -877,7 +959,7 @@ HbrFace<T>::GarbageCollectable() const {
if (children.children || protect) return false;
for (int i = 0; i < nvertices; ++i) {
HbrHalfedge<T>* edge = GetEdge(i);
HbrVertex<T>* vertex = edge->GetOrgVertex();
HbrVertex<T>* vertex = edge->GetOrgVertex(mesh);
if (vertex->IsUsed()) return false;
if (!GetParent() && vertex->EdgeRemovalWillMakeSingular(edge)) {
return false;
@ -888,14 +970,61 @@ HbrFace<T>::GarbageCollectable() const {
template <class T>
void
HbrFace<T>::SetHierarchicalEdits(HbrHierarchicalEdit<T>** _edits) {
edits = _edits;
HbrFace<T>::SetHierarchicalEdits(HbrHierarchicalEdit<T>** edits) {
HbrHierarchicalEdit<T>** faceedits = edits;
HbrHierarchicalEdit<T>** baseedit = mesh->GetHierarchicalEditsAtOffset(0);
editOffset = faceedits - baseedit;
// Walk the list of edits and look for any which apply locally.
while (HbrHierarchicalEdit<T>* edit = *_edits) {
while (HbrHierarchicalEdit<T>* edit = *faceedits) {
if (!edit->IsRelevantToFace(this)) break;
edit->ApplyEditToFace(this);
_edits++;
faceedits++;
}
}
template <class T>
void
HbrFace<T>::GetSupportingVertices(std::vector<int> &support) {
support.reserve(16);
HbrVertex<T>* v;
HbrHalfedge<T>* e, *ee, *eee, *start;
size_t edgesize, eedgesize;
if (nvertices > 4) {
e = (HbrHalfedge<T>*)(extraedges);
edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
e = edges;
edgesize = sizeof(HbrHalfedge<T>);
}
for (int i = 0; i < nvertices; ++i) {
v = mesh->GetVertex(e->GetOrgVertexID());
v->GuaranteeNeighbors();
start = v->GetIncidentEdge();
ee = start;
do {
HbrFace<T>* f = ee->GetLeftFace();
int nv = f->GetNumVertices();
if (nv > 4) {
eee = (HbrHalfedge<T>*)(f->extraedges);
eedgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
} else {
eee = f->edges;
eedgesize = sizeof(HbrHalfedge<T>);
}
for (int j = 0; j < nv; ++j) {
int id = eee->GetOrgVertexID();
std::vector<int>::iterator vi =
std::lower_bound(support.begin(), support.end(), id);
if (vi == support.end() || *vi != id) {
support.insert(vi, id);
}
eee = (HbrHalfedge<T>*)((char *) eee + eedgesize);
}
ee = v->GetNextEdge(ee);
if (ee == start) break;
} while (ee);
e = (HbrHalfedge<T>*)((char *) e + edgesize);
}
}

View File

@ -128,10 +128,13 @@ public:
virtual void ApplyEditToFace(HbrFace<T>* face) {
if (HbrHierarchicalEdit<T>::GetNSubfaces() == face->GetDepth()) {
int oldUniformIndex = face->GetUniformIndex();
// Change the face's uniform index
// Any face below level 0 needs a new uniform index
if (face->GetDepth() > 0) {
face->SetUniformIndex(face->GetMesh()->NewUniformIndex());
}
// Apply edit
face->GetVertex(0)->GetData().ApplyFaceEdit(oldUniformIndex, face->GetUniformIndex(), *const_cast<const HbrFaceEdit<T>*>(this));

View File

@ -75,28 +75,28 @@ template <class T> class HbrFVarData {
public:
HbrFVarData(float *dataptr)
: initialized(false), face(0), data(dataptr) {
HbrFVarData()
: initialized(0), faceid( 0 ) {
}
~HbrFVarData() {
Uninitialize();
}
// Sets the face pointer
void SetFace(const HbrFace<T> *_face) {
face = _face;
// Sets the face id
void SetFaceID(int id) {
faceid = id;
}
// Returns the face pointer
const HbrFace<T> * GetFace() const {
return face;
// Returns the id of the face to which this data is bound
int GetFaceID() const {
return faceid;
}
// Clears the initialized flag
void Uninitialize() {
initialized = false;
face = 0;
initialized = 0;
faceid = 0;
}
// Returns initialized flag
@ -106,11 +106,11 @@ public:
// Sets initialized flag
void SetInitialized() {
initialized = true;
initialized = 1;
}
// Return the data from the NgpFVVector
float* GetData(int item) const { return &data[item]; }
float* GetData(int item) { return data + item; }
// Clears the indicates value of this item
void Clear(int startindex, int width) {
@ -119,14 +119,15 @@ public:
// Clears all values of this item
void ClearAll(int width) {
initialized = true;
initialized = 1;
memset(data, 0, width * sizeof(float));
}
// Set values of the indicated item (with the indicated weighing)
// on this item
void SetWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
float *dst = data + startindex, *src = fvvi.data + startindex;
float *dst = data + startindex;
const float *src = fvvi.data + startindex;
for (int i = 0; i < width; ++i) {
*dst++ = weight * *src++;
}
@ -135,7 +136,8 @@ public:
// Add values of the indicated item (with the indicated weighing)
// to this item
void AddWithWeight(const HbrFVarData& fvvi, int startindex, int width, float weight) {
float *dst = data + startindex, *src = fvvi.data + startindex;
float *dst = data + startindex;
const float *src = fvvi.data + startindex;
for (int i = 0; i < width; ++i) {
*dst++ += weight * *src++;
}
@ -144,7 +146,8 @@ public:
// Add all values of the indicated item (with the indicated
// weighing) to this item
void AddWithWeightAll(const HbrFVarData& fvvi, int width, float weight) {
float *dst = data, *src = fvvi.data;
float *dst = data;
const float *src = fvvi.data;
for (int i = 0; i < width; ++i) {
*dst++ += weight * *src++;
}
@ -162,7 +165,7 @@ public:
// Initializes data
void SetAllData(int width, const float *values) {
initialized = true;
initialized = 1;
memcpy(data, values, width * sizeof(float));
}
@ -179,9 +182,9 @@ public:
void ApplyFVarEdit(const HbrFVarEdit<T>& edit);
private:
bool initialized;
const HbrFace<T> *face;
float* const data;
unsigned int faceid:31;
unsigned int initialized:1;
float data[1];
};
} // end namespace OPENSUBDIV_VERSION
@ -211,7 +214,7 @@ HbrFVarData<T>::ApplyFVarEdit(const HbrFVarEdit<T>& edit) {
*dst++ -= *src++;
}
}
initialized = true;
initialized = 1;
}

View File

@ -124,7 +124,7 @@ public:
// copy of the existing data specific to the face (or use
// one that already exists) and modify that
HbrFVarData<T> &fvt = face->GetVertex(vertexid)->GetFVarData(face);
if (fvt.GetFace() != face) {
if (fvt.GetFaceID() != face->GetID()) {
// This is the generic fvt, allocate a new copy and edit it
HbrFVarData<T> &newfvt = face->GetVertex(vertexid)->NewFVarData(face);
newfvt.SetAllData(face->GetMesh()->GetTotalFVarWidth(), fvt.GetData(0));

View File

@ -58,6 +58,7 @@
#define HBRHALFEDGE_H
#include <assert.h>
#include <stddef.h>
#include <cstring>
#include <iostream>
@ -83,7 +84,7 @@ template <class T> class HbrHalfedge {
public:
HbrHalfedge(): opposite(0), incidentFace(0), incidentVertex(0), vchild(0), sharpness(0.0f)
HbrHalfedge(): opposite(0), incidentVertex(-1), vchild(-1), sharpness(0.0f)
#ifdef HBRSTITCH
, stitchccw(1), raystitchccw(1)
#endif
@ -107,63 +108,95 @@ public:
// Returns the next clockwise halfedge around the incident face
HbrHalfedge<T>* GetNext() const {
if (lastedge) {
return (HbrHalfedge<T>*) ((char*) this - (incidentFace->GetNumVertices() - 1) * sizeof(HbrHalfedge<T>));
if (m_index == 4) {
const size_t edgesize = sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*);
if (lastedge) {
return (HbrHalfedge<T>*) ((char*) this - (GetFace()->GetNumVertices() - 1) * edgesize);
} else {
return (HbrHalfedge<T>*) ((char*) this + edgesize);
}
} else {
return (HbrHalfedge<T>*) ((char*) this + sizeof(HbrHalfedge<T>));
if (lastedge) {
return (HbrHalfedge<T>*) ((char*) this - (m_index) * sizeof(HbrHalfedge<T>));
} else {
return (HbrHalfedge<T>*) ((char*) this + sizeof(HbrHalfedge<T>));
}
}
}
// Returns the previous counterclockwise halfedge around the incident face
HbrHalfedge<T>* GetPrev() const {
const size_t edgesize = (m_index == 4) ?
(sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*)) :
sizeof(HbrHalfedge<T>);
if (firstedge) {
return (HbrHalfedge<T>*) ((char*) this + (incidentFace->GetNumVertices() - 1) * sizeof(HbrHalfedge<T>));
return (HbrHalfedge<T>*) ((char*) this + (GetFace()->GetNumVertices() - 1) * edgesize);
} else {
return (HbrHalfedge<T>*) ((char*) this - sizeof(HbrHalfedge<T>));
}
}
// Returns the index of the edge relative to its incident face.
// This relies on knowledge of the face's edge allocation pattern
int GetIndex() const {
// we allocate room for up to 4 values (to handle tri or quad)
// in the edges array. If there are more than that, they _all_
// go in the extra edges array.
if (this >= incidentFace->edges &&
this < incidentFace->edges + 4) {
return int(this - incidentFace->edges);
} else {
return int(this - incidentFace->extraedges);
return (HbrHalfedge<T>*) ((char*) this - edgesize);
}
}
// Returns the incident vertex
HbrVertex<T>* GetVertex() const {
return GetMesh()->GetVertex(incidentVertex);
}
// Returns the incident vertex
HbrVertex<T>* GetVertex(HbrMesh<T> *mesh) const {
return mesh->GetVertex(incidentVertex);
}
// Returns the incident vertex
int GetVertexID() const {
return incidentVertex;
}
// Returns the source vertex
HbrVertex<T>* GetOrgVertex() const {
return GetVertex();
}
// Returns the source vertex
HbrVertex<T>* GetOrgVertex(HbrMesh<T> *mesh) const {
return GetVertex(mesh);
}
// Returns the source vertex id
int GetOrgVertexID() const {
return incidentVertex;
}
// Changes the origin vertex. Generally not a good idea to do
void SetOrgVertex(HbrVertex<T>* v) { incidentVertex = v; }
void SetOrgVertex(HbrVertex<T>* v) { incidentVertex = v->GetID(); }
// Returns the destination vertex
HbrVertex<T>* GetDestVertex() const { return GetNext()->GetOrgVertex(); }
// Returns the destination vertex
HbrVertex<T>* GetDestVertex(HbrMesh<T> *mesh) const { return GetNext()->GetOrgVertex(mesh); }
// Returns the destination vertex ID
int GetDestVertexID() const { return GetNext()->GetOrgVertexID(); }
// Returns the incident facet
HbrFace<T>* GetFace() const { return incidentFace; }
HbrFace<T>* GetFace() const {
if (m_index == 4) {
// Pointer to face is stored after the data for the edge
return *(HbrFace<T>**)((char *) this + sizeof(HbrHalfedge<T>));
} else {
return (HbrFace<T>*) ((char*) this - (m_index) * sizeof(HbrHalfedge<T>) -
offsetof(HbrFace<T>, edges));
}
}
// Returns the mesh to which this edge belongs
HbrMesh<T>* GetMesh() const { return incidentFace->GetMesh(); }
HbrMesh<T>* GetMesh() const { return GetFace()->GetMesh(); }
// Returns the face on the right
HbrFace<T>* GetRightFace() const { return opposite ? opposite->GetLeftFace() : NULL; }
// Return the face on the left of the halfedge
HbrFace<T>* GetLeftFace() const { return incidentFace; }
HbrFace<T>* GetLeftFace() const { return GetFace(); }
// Returns whether this is a boundary edge
bool IsBoundary() const { return opposite == 0; }
@ -221,7 +254,7 @@ public:
void GuaranteeNeighbor();
// Remove the reference to subdivided vertex
void RemoveChild() { vchild = 0; }
void RemoveChild() { vchild = -1; }
// Sharpness constants
enum Mask {
@ -333,15 +366,15 @@ public:
}
void* GetStitchData() const {
if (stitchdatavalid) return *(incidentFace->stitchDatas + GetIndex());
if (stitchdatavalid) return GetMesh()->GetStitchData(this);
else return 0;
}
void SetStitchData(void* data) {
*(incidentFace->stitchDatas + GetIndex()) = data;
GetMesh()->SetStitchData(this, data);
stitchdatavalid = data ? 1 : 0;
if (opposite) {
*(opposite->incidentFace->stitchDatas + opposite->GetIndex()) = data;
opposite->GetMesh()->SetStitchData(opposite, data);
opposite->stitchdatavalid = stitchdatavalid;
}
}
@ -378,32 +411,53 @@ public:
private:
HbrHalfedge<T>* opposite;
HbrFace<T>* incidentFace;
// Index of incident vertex
int incidentVertex;
HbrVertex<T>* incidentVertex;
// Child vertex
HbrVertex<T>* vchild;
// Index of subdivided vertex child
int vchild;
float sharpness;
#ifdef HBRSTITCH
unsigned char stitchccw:1;
unsigned char raystitchccw:1;
unsigned char stitchdatavalid:1;
unsigned short stitchccw:1;
unsigned short raystitchccw:1;
unsigned short stitchdatavalid:1;
#endif
unsigned char coarse:1;
unsigned char lastedge:1;
unsigned char firstedge:1;
unsigned short coarse:1;
unsigned short lastedge:1;
unsigned short firstedge:1;
// If m_index = 0, 1, 2 or 3: we are the m_index edge of an
// incident face with 3 or 4 vertices.
// If m_index = 4: our incident face has more than 4 vertices, and
// we must do some extra math to determine what our actual index
// is. See getIndex()
unsigned short m_index:3;
// Returns the index of the edge relative to its incident face.
// This relies on knowledge of the face's edge allocation pattern
int getIndex() const {
if (m_index < 4) {
return m_index;
} else {
// We allocate room for up to 4 values (to handle tri or
// quad) in the edges array. If there are more than that,
// they _all_ go in the faces' extraedges array.
HbrFace<T>* incidentFace = *(HbrFace<T>**)((char *) this + sizeof(HbrHalfedge<T>));
return ((char *) this - incidentFace->extraedges) /
(sizeof(HbrHalfedge<T>) + sizeof(HbrFace<T>*));
}
}
// Returns bitmask indicating whether a given facevarying datum
// for the edge is infinitely sharp. Each datum has two bits, and
// if those two bits are set to 3, it means the status has not
// been computed yet.
unsigned int *getFVarInfSharp() {
unsigned int *fvarbits = incidentFace->fvarbits;
unsigned int *fvarbits = GetFace()->fvarbits;
if (fvarbits) {
int fvarbitsSizePerEdge = ((GetMesh()->GetFVarCount() + 15) / 16);
return fvarbits + GetIndex() * fvarbitsSizePerEdge;
return fvarbits + getIndex() * fvarbitsSizePerEdge;
} else {
return 0;
}
@ -411,7 +465,7 @@ private:
#ifdef HBRSTITCH
StitchEdge **getStitchEdges() {
return incidentFace->stitchEdges + GetMesh()->GetStitchCount() * GetIndex();
return GetFace()->stitchEdges + GetMesh()->GetStitchCount() * getIndex();
}
#endif
@ -437,29 +491,41 @@ public:
template <class T>
void
HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* origin, unsigned int *fvarbits, HbrFace<T>* face) {
HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* origin,
unsigned int *fvarbits, HbrFace<T>* face) {
HbrMesh<T> *mesh = face->GetMesh();
if (face->GetNumVertices() <= 4) {
m_index = index;
} else {
m_index = 4;
// Assumes upstream allocation ensured we have extra storage
// for pointer to face after the halfedge data structure
// itself
*(HbrFace<T>**)((char *) this + sizeof(HbrHalfedge<T>)) = face;
}
this->opposite = opposite;
incidentVertex = origin;
incidentFace = face;
incidentVertex = origin->GetID();
lastedge = (index == face->GetNumVertices() - 1);
firstedge = (index == 0);
if (opposite) {
sharpness = opposite->sharpness;
#ifdef HBRSTITCH
StitchEdge **stitchEdges = getStitchEdges();
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
StitchEdge **stitchEdges = face->stitchEdges +
mesh->GetStitchCount() * index;
for (int i = 0; i < mesh->GetStitchCount(); ++i) {
stitchEdges[i] = opposite->getStitchEdges()[i];
}
stitchccw = opposite->stitchccw;
raystitchccw = opposite->raystitchccw;
stitchdatavalid = 0;
if (stitchEdges && opposite->GetStitchData()) {
*(incidentFace->stitchDatas + index) = opposite->GetStitchData();
mesh->SetStitchData(this, opposite->GetStitchData());
stitchdatavalid = 1;
}
#endif
if (fvarbits) {
const int fvarcount = face->GetMesh()->GetFVarCount();
const int fvarcount = mesh->GetFVarCount();
int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
memcpy(fvarbits, opposite->getFVarInfSharp(), fvarbitsSizePerEdge * sizeof(unsigned int));
}
@ -467,7 +533,7 @@ HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* or
sharpness = 0.0f;
#ifdef HBRSTITCH
StitchEdge **stitchEdges = getStitchEdges();
for (int i = 0; i < face->GetMesh()->GetStitchCount(); ++i) {
for (int i = 0; i < mesh->GetStitchCount(); ++i) {
stitchEdges[i] = 0;
}
stitchccw = 1;
@ -475,7 +541,7 @@ HbrHalfedge<T>::Initialize(HbrHalfedge<T>* opposite, int index, HbrVertex<T>* or
stitchdatavalid = 0;
#endif
if (fvarbits) {
const int fvarcount = face->GetMesh()->GetFVarCount();
const int fvarcount = mesh->GetFVarCount();
int fvarbitsSizePerEdge = ((fvarcount + 15) / 16);
memset(fvarbits, 0xff, fvarbitsSizePerEdge * sizeof(unsigned int));
}
@ -492,34 +558,38 @@ void
HbrHalfedge<T>::Clear() {
if (opposite) {
opposite->opposite = 0;
if (vchild) {
if (vchild != -1) {
// Transfer ownership of the vchild to the opposite ptr
opposite->vchild = vchild;
HbrVertex<T> *vchildVert = GetMesh()->GetVertex(vchild);
// Done this way just for assertion sanity
vchild->SetParent(static_cast<HbrHalfedge*>(0));
vchild->SetParent(opposite);
vchild = 0;
vchildVert->SetParent(static_cast<HbrHalfedge*>(0));
vchildVert->SetParent(opposite);
vchild = -1;
}
opposite = 0;
}
// Orphan the child vertex
else if (vchild) {
vchild->SetParent(static_cast<HbrHalfedge*>(0));
vchild = 0;
else if (vchild != -1) {
HbrVertex<T> *vchildVert = GetMesh()->GetVertex(vchild);
vchildVert->SetParent(static_cast<HbrHalfedge*>(0));
vchild = -1;
}
}
template <class T>
HbrVertex<T>*
HbrHalfedge<T>::Subdivide() {
if (vchild) return vchild;
HbrMesh<T>* mesh = GetMesh();
if (vchild != -1) return mesh->GetVertex(vchild);
// Make sure that our opposite doesn't "own" a subdivided vertex
// already. If it does, use that
if (opposite && opposite->vchild) return opposite->vchild;
HbrMesh<T>* mesh = GetMesh();
vchild = mesh->GetSubdivision()->Subdivide(mesh, this);
vchild->SetParent(this);
return vchild;
if (opposite && opposite->vchild != -1) return mesh->GetVertex(opposite->vchild);
HbrVertex<T>* vchildVert = mesh->GetSubdivision()->Subdivide(mesh, this);
vchild = vchildVert->GetID();
vchildVert->SetParent(this);
return vchildVert;
}
template <class T>

View File

@ -60,6 +60,9 @@
#ifdef PRMAN
#include "libtarget/TgMalloc.h" // only for alloca
#include "libtarget/TgThread.h"
#ifdef HBRSTITCH
#include "libtarget/TgHashMap.h"
#endif
#endif
#include <algorithm>
@ -82,6 +85,7 @@ namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
template <class T> class HbrSubdivision;
template <class T> class HbrHalfedge;
template <class T> class HbrMesh {
public:
@ -104,7 +108,34 @@ public:
HbrVertex<T>* NewVertex();
// Ask for vertex with the indicated ID
HbrVertex<T>* GetVertex(int id) const;
HbrVertex<T>* GetVertex(int id) const {
if (id >= nvertices) {
return 0;
} else {
return vertices[id];
}
}
// Ask for client data associated with the vertex with the indicated ID
void* GetVertexClientData(int id) const {
if (id >= vertexClientData.size()) {
return 0;
} else {
return vertexClientData[id];
}
}
// Set client data associated with the vertex with the indicated ID
void SetVertexClientData(int id, void *data) {
if (id >= vertexClientData.size()) {
size_t oldsize = vertexClientData.size();
vertexClientData.resize(nvertices);
if (s_memStatsIncrement) {
s_memStatsIncrement((vertexClientData.size() - oldsize) * sizeof(void*));
}
}
vertexClientData[id] = data;
}
// Create face from a list of vertex IDs
HbrFace<T>* NewFace(int nvertices, int *vtx, int uindex);
@ -139,6 +170,27 @@ public:
// Ask for face with the indicated ID
HbrFace<T>* GetFace(int id) const;
// Ask for client data associated with the face with the indicated ID
void* GetFaceClientData(int id) const {
if (id >= faceClientData.size()) {
return 0;
} else {
return faceClientData[id];
}
}
// Set client data associated with the face with the indicated ID
void SetFaceClientData(int id, void *data) {
if (id >= faceClientData.size()) {
size_t oldsize = faceClientData.size();
faceClientData.resize(nfaces);
if (s_memStatsIncrement) {
s_memStatsIncrement((faceClientData.size() - oldsize) * sizeof(void*));
}
}
faceClientData[id] = data;
}
// Returns a collection of all vertices in the mesh. This function
// requires an output iterator; to get the vertices into a
// std::vector, use GetVertices(std::back_inserter(myvector))
@ -227,6 +279,12 @@ public:
return hierarchicalEdits;
}
// Return the hierarchical edits associated with the mesh at an
// offset
HbrHierarchicalEdit<T>** GetHierarchicalEditsAtOffset(int offset) {
return &hierarchicalEdits[offset];
}
// Whether the mesh has certain types of edits
bool HasVertexEdits() const { return hasVertexEdits; }
bool HasCreaseEdits() const { return hasCreaseEdits; }
@ -237,23 +295,17 @@ public:
oldMaxFaceID = numCoarseFaces;
}
for (int i = numCoarseFaces; i < maxFaceID; ++i) {
if (faces[i]) {
HbrFace<T>* f = faces[i];
if(f && not f->IsCoarse())
HbrFace<T>* f = GetFace(i);
if(f and not f->IsCoarse())
DeleteFace(f);
}
}
//oldMaxFaceID = maxFaceID;
maxFaceID = numCoarseFaces;
int vert = numCoarseVerts % vsetsize;
for( int set=(numCoarseVerts/vsetsize); set<nvsets; set++ ) {
for( ; vert<vsetsize; vert++ ) {
HbrVertex<T>* v = vertices[set][vert];
if(v && not v->IsReferenced())
DeleteVertex(v);
}
vert = 0;
for(int i=numCoarseVerts; (int)vertices.size(); ++i ) {
HbrVertex<T>* v = GetVertex(i);
if(v and not v->IsReferenced())
DeleteVertex(v);
}
}
@ -285,15 +337,23 @@ public:
m_faceChildrenAllocator.Deallocate(facechildren);
}
private:
#ifdef PRMAN
// This code is intended to be shared with PRman which provides its own
// TgSpinLock mutex. Other clients are responsible for providing a Mutex
// object with public Lock() and Unlock() functions.
typedef TgSpinLock Mutex;
#ifdef HBRSTITCH
void * GetStitchData(const HbrHalfedge<T>* edge) const {
typename TgHashMap<const HbrHalfedge<T>*, void *>::const_iterator i =
stitchData.find(edge);
if (i != stitchData.end()) {
return i->second;
} else {
return NULL;
}
}
void SetStitchData(const HbrHalfedge<T>* edge, void *data) {
stitchData[edge] = data;
}
#endif
mutable Mutex m_mutex;
private:
// Subdivision method used in this mesh
HbrSubdivision<T>* subdivision;
@ -311,18 +371,27 @@ private:
const int totalfvarwidth;
#ifdef HBRSTITCH
// Number of stitch edges per halfedge
const int stitchCount;
// Client (sparse) data used on some halfedges
TgHashMap<const HbrHalfedge<T>*, void *> stitchData;
#endif
// Vertices which comprise this mesh
HbrVertex<T>*** vertices;
int nvsets;
const int vsetsize;
std::vector<HbrVertex<T> *> vertices;
int nvertices;
// Client data associated with each face
std::vector<void *> vertexClientData;
// Faces which comprise this mesh
HbrFace<T>** faces;
std::vector<HbrFace<T> *> faces;
int nfaces;
// Client data associated with each face
std::vector<void *> faceClientData;
// Maximum vertex ID - may be needed when generating a unique
// vertex ID
int maxVertexID;
@ -416,9 +485,7 @@ HbrMesh<T>::HbrMesh(HbrSubdivision<T>* s, int _fvarcount, const int *_fvarindice
#ifdef HBRSTITCH
stitchCount(_stitchCount),
#endif
vertices(0), nvsets(0),
vsetsize(2048), faces(0), nfaces(0),
maxVertexID(0), maxFaceID(0), maxUniformIndex(0),
nvertices(0), nfaces(0), maxVertexID(0), maxFaceID(0), maxUniformIndex(0),
interpboundarymethod(k_InterpolateBoundaryNone),
fvarinterpboundarymethod(k_InterpolateBoundaryNone),
fvarpropagatecorners(false),
@ -427,13 +494,11 @@ HbrMesh<T>::HbrMesh(HbrSubdivision<T>* s, int _fvarcount, const int *_fvarindice
((fvarcount + 15) / 16 * sizeof(unsigned int)
#ifdef HBRSTITCH
+ stitchCount * sizeof(StitchEdge*)
+ sizeof(void*) // for stitch data
#endif
)),
m_faceAllocator(&m_memory, 512, 0, 0, m_faceSize),
m_vertexSize(sizeof(HbrVertex<T>) +
sizeof(HbrHalfedge<T>*) + // for incidentEdges[1]
totalfvarwidth * sizeof(float) + sizeof(HbrFVarData<T>)),
(totalfvarwidth ? (sizeof(HbrFVarData<T>) + (totalfvarwidth - 1) * sizeof(float)) : 0)),
m_vertexAllocator(&m_memory, 512, 0, 0, m_vertexSize),
m_faceChildrenAllocator(&m_memory, 512, 0, 0),
m_memory(0),
@ -448,7 +513,7 @@ HbrMesh<T>::~HbrMesh() {
GarbageCollect();
int i;
if (faces) {
if (!faces.empty()) {
for (i = 0; i < nfaces; ++i) {
if (faces[i]) {
faces[i]->Destroy();
@ -456,28 +521,25 @@ HbrMesh<T>::~HbrMesh() {
}
}
if (s_memStatsDecrement) {
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
s_memStatsDecrement(faces.size() * sizeof(HbrFace<T>*));
}
m_memory -= nfaces * sizeof(HbrFace<T>*);
delete[] faces;
}
if (nvsets) {
for (int vi = 0; vi < nvsets; ++vi) {
HbrVertex<T>** vset = vertices[vi];
for (i = 0; i < vsetsize; ++i) {
if (vset[i]) {
vset[i]->Destroy();
m_vertexAllocator.Deallocate(vset[i]);
}
if (!vertices.empty()) {
for (i = 0; i < nvertices; ++i) {
if (vertices[i]) {
vertices[i]->Destroy(this);
m_vertexAllocator.Deallocate(vertices[i]);
}
delete[] vset;
if (s_memStatsDecrement) {
s_memStatsDecrement(vsetsize * sizeof(HbrVertex<T>*));
}
m_memory -= vsetsize * sizeof(HbrVertex<T>*);
}
delete[] vertices;
if (s_memStatsDecrement) {
s_memStatsDecrement(vertices.size() * sizeof(HbrVertex<T>*));
}
}
if (!vertexClientData.empty() && s_memStatsDecrement) {
s_memStatsDecrement(vertexClientData.size() * sizeof(void*));
}
if (!faceClientData.empty() && s_memStatsDecrement) {
s_memStatsDecrement(faceClientData.size() * sizeof(void*));
}
for (typename std::vector<HbrHierarchicalEdit<T>* >::iterator hi =
hierarchicalEdits.begin(); hi != hierarchicalEdits.end(); ++hi) {
@ -489,40 +551,25 @@ template <class T>
HbrVertex<T>*
HbrMesh<T>::NewVertex(int id, const T &data) {
HbrVertex<T>* v = 0;
int arrayindex = id / vsetsize;
int vertindex = id % vsetsize;
m_mutex.Lock();
HbrVertex<T>** vset = 0;
if (arrayindex >= nvsets) {
HbrVertex<T>*** nvertices = new HbrVertex<T>**[arrayindex + 1];
for (int i = 0; i < nvsets; ++i) {
nvertices[i] = vertices[i];
if (nvertices <= id) {
while (nvertices <= maxVertexID) {
nvertices *= 2;
if (nvertices < 1) nvertices = 1;
}
for (int i = nvsets; i < arrayindex + 1; ++i) {
vset = new HbrVertex<T>*[vsetsize];
if (s_memStatsIncrement) {
s_memStatsIncrement(vsetsize * sizeof(HbrVertex<T>*));
}
m_memory += vsetsize * sizeof(HbrVertex<T>*);
memset(vset, 0, vsetsize * sizeof(HbrVertex<T>*));
nvertices[i] = vset;
size_t oldsize = vertices.size();
vertices.resize(nvertices);
if (s_memStatsIncrement) {
s_memStatsIncrement((vertices.size() - oldsize) * sizeof(HbrVertex<T>*));
}
nvsets = arrayindex + 1;
delete[] vertices;
vertices = nvertices;
}
vset = vertices[arrayindex];
m_mutex.Unlock();
v = vset[vertindex];
v = vertices[id];
if (v) {
v->Destroy();
v->Destroy(this);
} else {
v = m_vertexAllocator.Allocate();
}
v->Initialize(id, data, GetTotalFVarWidth());
vset[vertindex] = v;
vertices[id] = v;
if (id >= maxVertexID) {
maxVertexID = id + 1;
@ -574,22 +621,6 @@ HbrMesh<T>::NewVertex() {
return NewVertex(id, data);
}
template <class T>
HbrVertex<T>*
HbrMesh<T>::GetVertex(int id) const {
int arrayindex = id / vsetsize;
int vertindex = id % vsetsize;
m_mutex.Lock();
if (arrayindex >= nvsets) {
m_mutex.Unlock();
return 0;
}
HbrVertex<T>** vset = vertices[arrayindex];
m_mutex.Unlock();
return vset[vertindex];
}
template <class T>
HbrFace<T>*
HbrMesh<T>::NewFace(int nv, int *vtx, int uindex) {
@ -604,31 +635,15 @@ HbrMesh<T>::NewFace(int nv, int *vtx, int uindex) {
HbrFace<T> *f = 0;
// Resize if needed
if (nfaces <= maxFaceID) {
int nnfaces = nfaces;
while (nnfaces <= maxFaceID) {
nnfaces *= 2;
if (nnfaces < 1) nnfaces = 1;
while (nfaces <= maxFaceID) {
nfaces *= 2;
if (nfaces < 1) nfaces = 1;
}
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
size_t oldsize = faces.size();
faces.resize(nfaces);
if (s_memStatsIncrement) {
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
s_memStatsIncrement((faces.size() - oldsize) * sizeof(HbrVertex<T>*));
}
m_memory += nnfaces * sizeof(HbrFace<T>*);
if (faces) {
for (i = 0; i < nfaces; ++i) {
newfaces[i] = faces[i];
}
if (s_memStatsDecrement) {
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
}
m_memory -= nfaces * sizeof(HbrFace<T>*);
delete[] faces;
}
for (i = nfaces; i < nnfaces; ++i) {
newfaces[i] = 0;
}
faces = newfaces;
nfaces = nnfaces;
}
f = faces[maxFaceID];
if (f) {
@ -655,31 +670,15 @@ HbrMesh<T>::NewFace(int nv, HbrVertex<T> **vtx, HbrFace<T>* parent, int childind
HbrFace<T> *f = 0;
// Resize if needed
if (nfaces <= maxFaceID) {
int nnfaces = nfaces;
while (nnfaces <= maxFaceID) {
nnfaces *= 2;
if (nnfaces < 1) nnfaces = 1;
while (nfaces <= maxFaceID) {
nfaces *= 2;
if (nfaces < 1) nfaces = 1;
}
HbrFace<T>** newfaces = new HbrFace<T>*[nnfaces];
size_t oldsize = faces.size();
faces.resize(nfaces);
if (s_memStatsIncrement) {
s_memStatsIncrement(nnfaces * sizeof(HbrFace<T>*));
s_memStatsIncrement((faces.size() - oldsize) * sizeof(HbrVertex<T>*));
}
m_memory += nnfaces * sizeof(HbrFace<T>*);
if (faces) {
for (int i = 0; i < nfaces; ++i) {
newfaces[i] = faces[i];
}
if (s_memStatsDecrement) {
s_memStatsDecrement(nfaces * sizeof(HbrFace<T>*));
}
m_memory -= nfaces * sizeof(HbrFace<T>*);
delete[] faces;
}
for (int i = nfaces; i < nnfaces; ++i) {
newfaces[i] = 0;
}
faces = newfaces;
nfaces = nnfaces;
}
f = faces[maxFaceID];
if (f) {
@ -757,18 +756,18 @@ HbrMesh<T>::Finish() {
// Push a sentinel null value - we rely upon this sentinel to
// ensure face->GetHierarchicalEdits knows when to terminate
hierarchicalEdits.push_back(0);
j = 0;
// Link faces to hierarchical edits
for (i = 0; i < nfaces; ++i) {
if (faces[i]) {
while (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() < i) {
++j;
}
if (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() == i) {
faces[i]->SetHierarchicalEdits(&hierarchicalEdits[j]);
}
}
}
j = 0;
// Link faces to hierarchical edits
for (i = 0; i < nfaces; ++i) {
if (faces[i]) {
while (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() < i) {
++j;
}
if (j < nHierarchicalEdits && hierarchicalEdits[j]->GetFaceID() == i) {
faces[i]->SetHierarchicalEdits(&hierarchicalEdits[j]);
}
}
}
}
}
@ -792,13 +791,8 @@ HbrMesh<T>::DeleteVertex(HbrVertex<T>* vertex) {
if (v == vertex) {
recycleIDs.insert(vertex->GetID());
int id = vertex->GetID();
int arrayindex = id / vsetsize;
m_mutex.Lock();
int vertindex = id % vsetsize;
HbrVertex<T>** vset = vertices[arrayindex];
m_mutex.Unlock();
vset[vertindex] = 0;
vertex->Destroy();
vertices[id] = 0;
vertex->Destroy(this);
m_vertexAllocator.Deallocate(vertex);
}
}
@ -807,14 +801,9 @@ template <class T>
int
HbrMesh<T>::GetNumVertices() const {
int count = 0;
m_mutex.Lock();
for (int vi = 0; vi < nvsets; ++vi) {
HbrVertex<T>** vset = vertices[vi];
for (int i = 0; i < vsetsize; ++i) {
if (vset[i]) count++;
}
for (int i = 0; i < nvertices; ++i) {
if (vertices[i]) count++;
}
m_mutex.Unlock();
return count;
}
@ -822,18 +811,13 @@ template <class T>
int
HbrMesh<T>::GetNumDisconnectedVertices() const {
int disconnected = 0;
m_mutex.Lock();
for (int vi = 0; vi < nvsets; ++vi) {
HbrVertex<T>** vset = vertices[vi];
for (int i = 0; i < vsetsize; ++i) {
if (HbrVertex<T>* v = vset[i]) {
for (int i = 0; i < nvertices; ++i) {
if (HbrVertex<T>* v = vertices[i]) {
if (!v->IsConnected()) {
disconnected++;
}
}
}
}
m_mutex.Unlock();
return disconnected;
}
@ -873,27 +857,17 @@ template <class T>
template <typename OutputIterator>
void
HbrMesh<T>::GetVertices(OutputIterator lvertices) const {
m_mutex.Lock();
for (int vi = 0; vi < nvsets; ++vi) {
HbrVertex<T>** vset = vertices[vi];
for (int i = 0; i < vsetsize; ++i) {
if (vset[i]) *lvertices++ = vset[i];
}
for (int i = 0; i < nvertices; ++i) {
if (vertices[i]) *lvertices++ = vertices[i];
}
m_mutex.Unlock();
}
template <class T>
void
HbrMesh<T>::ApplyOperatorAllVertices(HbrVertexOperator<T> &op) const {
m_mutex.Lock();
for (int vi = 0; vi < nvsets; ++vi) {
HbrVertex<T>** vset = vertices[vi];
for (int i = 0; i < vsetsize; ++i) {
if (vset[i]) op(*vset[i]);
}
for (int i = 0; i < nvertices; ++i) {
if (vertices[i]) op(*vertices[i]);
}
m_mutex.Unlock();
}
template <class T>
@ -913,24 +887,20 @@ HbrMesh<T>::PrintStats(std::ostream &out) {
int i, nv = 0;
int disconnected = 0;
int extraordinary = 0;
for (int vi = 0; vi < nvsets; ++vi) {
HbrVertex<T>** vset = vertices[vi];
for (i = 0; i < vsetsize; ++i) {
if (HbrVertex<T>* v = vset[i]) {
nv++;
if (v->IsSingular()) {
out << " singular: " << *v << "\n";
singular++;
}
else if (!v->IsConnected()) {
out << " disconnected: " << *v << "\n";
disconnected++;
} else {
if (v->IsExtraordinary()) {
extraordinary++;
}
sumvalence += v->GetValence();
for (i = 0; i < nvertices; ++i) {
if (HbrVertex<T>* v = vertices[i]) {
nv++;
if (v->IsSingular()) {
out << " singular: " << *v << "\n";
singular++;
} else if (!v->IsConnected()) {
out << " disconnected: " << *v << "\n";
disconnected++;
} else {
if (v->IsExtraordinary()) {
extraordinary++;
}
sumvalence += v->GetValence();
}
}
}
@ -1044,17 +1014,13 @@ HbrMesh<T>::FreeTransientData() {
break;
}
}
// Reset max vertex ID. Slightly more complicated
m_mutex.Lock();
for (i = (nvsets * vsetsize) - 1; i >= 0; --i) {
int arrayindex = i / vsetsize;
int vertindex = i % vsetsize;
if (vertices[arrayindex][vertindex]) {
// Reset max vertex ID
for (i = nvertices - 1; i >= 0; --i) {
if (vertices[i]) {
maxVertexID = i + 1;
break;
}
}
m_mutex.Unlock();
}
} // end namespace OPENSUBDIV_VERSION

View File

@ -85,7 +85,7 @@ public:
}
void Initialize(int vid, const T &data, int fvarwidth);
~HbrVertex();
void Destroy();
void Destroy(HbrMesh<T> *mesh = 0);
// Registers an incident edge with the vertex
void AddIncidentEdge(HbrHalfedge<T>* edge);
@ -137,6 +137,9 @@ public:
// Return an edge connected to dest
HbrHalfedge<T>* GetEdge(const HbrVertex<T>* dest) const;
// Return an edge connected to vertex with id dest
HbrHalfedge<T>* GetEdge(int dest) const;
// Given an edge, returns the next edge in counterclockwise order
// around this vertex. Note well: this is only the next halfedge,
// which means that all edges returned by this function are
@ -273,7 +276,7 @@ public:
}
// Remove the reference to subdivided vertex
void RemoveChild() { vchild = 0; }
void RemoveChild() { vchild = -1; }
// Returns true if the vertex still has an incident edge (in other
// words, it belongs to a face)
@ -308,7 +311,15 @@ public:
// Return an incident edge to this vertex, which happens to be the
// first halfedge of the cycles.
HbrHalfedge<T>* GetIncidentEdge() const { return nIncidentEdges ? incidentEdges[0] : 0; }
HbrHalfedge<T>* GetIncidentEdge() const {
if (nIncidentEdges > 1) {
return incident.edges[0];
} else if (nIncidentEdges == 1) {
return incident.edge;
} else {
return 0;
}
}
// Sharpness and mask constants
enum Mask {
@ -326,19 +337,19 @@ public:
void DecrementUsage() { used--; }
// Check the usage counter on the vertex
bool IsUsed() const { return used || vchild; }
bool IsUsed() const { return used || (vchild != -1); }
// Used by block allocator
HbrVertex<T>*& GetNext() { return vchild; }
HbrVertex<T>*& GetNext() { return parent.vertex; }
// Returns the blind pointer to client data
void *GetClientData() const {
return clientData;
void *GetClientData(HbrMesh<T>* mesh) const {
return mesh->GetVertexClientData(id);
}
// Sets the blind pointer to client data
void SetClientData(void *data) {
clientData = data;
void SetClientData(HbrMesh<T> *mesh, void *data) {
mesh->SetVertexClientData(id, data);
}
enum ParentType {
@ -353,15 +364,14 @@ private:
T data;
// Pointer to extra facevarying data. Space for this is allocated
// by NewFVarData
HbrFVarData<T> *morefvardata;
// by NewFVarData. This struct is actually overpadded.
struct morefvardata {
int count;
} *morefvar;
// Unique ID of this vertex
int id;
// Size of incident array
int nIncidentEdges;
// The number of halfedges which have this vertex as the incident
// edge. When references == 0, the vertex is safe to delete
int references;
@ -370,13 +380,15 @@ private:
// not be the same as references!
int used;
// Number of facevarying data allocated to this vertex in
// morefvardata
int nfvardata;
// Sharpness
float sharpness;
// Index of child vertex
int vchild;
// Size of incident array
unsigned short nIncidentEdges;
// Vertex masks, at this level of subdivision and at the next
// level of subdivision. Valid only when validmask = 1.
unsigned short mask0:3;
@ -410,14 +422,15 @@ private:
// List of edge cycles. For "singular" vertices, the corresponding
// set of adjacent halfedges may consist of several cycles, and we
// need to account for all of them here. In cases where
// nIncidentEdges is 1 or less (i.e. the general nonsingular
// case), this memory actually points at memory allocated after
// the end of this object. Otherwise, it's an actual separately
// allocated array.
HbrHalfedge<T>** incidentEdges;
// Child vertex
HbrVertex<T>* vchild;
// nIncidentEdges is 1, the edge field of the union points
// directly at the edge which starts the only incident cycle. If
// nIncidnetEdges is 2 or more, the edges field of the union is a
// separate allocated array and edge member of the array points at
// separate cycles.
union {
HbrHalfedge<T>* edge;
HbrHalfedge<T>** edges;
} incident;
union {
HbrFace<T>* face;
@ -425,9 +438,6 @@ private:
HbrVertex<T>* vertex;
} parent;
// Blind client data pointer
void * clientData;
#ifdef HBR_ADAPTIVE
public:
struct adaptiveFlags {
@ -444,16 +454,20 @@ public:
template <class T>
HbrVertex<T>::HbrVertex() :
morefvardata(0), id(-1), nIncidentEdges(0), references(0), used(0), nfvardata(0), sharpness(0.0f), extraordinary(0), validmask(0), volatil(0), neighborsguaranteed(0), collected(0), hasvertexedit(0), editsapplied(0), destroyed(0), parentType(k_ParentNone), incidentEdges(0), vchild(0), clientData(0) {
morefvar(0), id(-1), references(0), used(0),
sharpness(0.0f), vchild(-1), nIncidentEdges(0), extraordinary(0), validmask(0),
volatil(0), neighborsguaranteed(0), collected(0), hasvertexedit(0),
editsapplied(0), destroyed(0), parentType(k_ParentNone) {
ClearMask();
parent.vertex = 0;
incident.edge = 0;
}
template <class T>
void
HbrVertex<T>::Initialize(int vid, const T &vdata, int fvarwidth) {
data = vdata;
morefvardata = 0 ;
morefvar = 0 ;
id = vid;
references = 0;
used = 0;
@ -466,24 +480,18 @@ HbrVertex<T>::Initialize(int vid, const T &vdata, int fvarwidth) {
destroyed = 0;
sharpness = 0.0f;
nIncidentEdges = 0;
vchild = 0;
vchild = -1;
assert(!parent.vertex);
parentType = k_ParentVertex;
parent.vertex = 0;
clientData = 0;
// Upstream allocator ensured the class was padded by an extra
// amount for this
char *buffer = ((char*) this + sizeof(*this));
incidentEdges = (HbrHalfedge<T>**) buffer;
buffer += sizeof(HbrHalfedge<T>*);
if (fvarwidth) {
// Upstream allocator ensured the class was padded by the
// appropriate size. GetFVarData will return a pointer to this
// memory, but it needs to be properly initialized.
// Run placement new to initialize datum
new (buffer) HbrFVarData<T>((float*) (buffer + sizeof(HbrFVarData<T>)));
char *buffer = ((char*) this + sizeof(*this));
new (buffer) HbrFVarData<T>();
}
}
@ -494,7 +502,7 @@ HbrVertex<T>::~HbrVertex() {
template <class T>
void
HbrVertex<T>::Destroy() {
HbrVertex<T>::Destroy(HbrMesh<T> *mesh) {
if (!destroyed) {
// Vertices are only safe for deletion if the number of incident
// edges is exactly zero.
@ -513,16 +521,18 @@ HbrVertex<T>::Destroy() {
}
// Orphan the child vertex
if (vchild) {
vchild->SetParent(static_cast<HbrVertex*>(0));
vchild = 0;
if (vchild != -1) {
if (mesh) {
HbrVertex<T> *vchildVert = mesh->GetVertex(vchild);
vchildVert->SetParent(static_cast<HbrVertex*>(0));
}
vchild = -1;
}
// We're skipping the placement destructors here, in the
// assumption that HbrFVarData's destructor doesn't actually do
// anything much
if (nfvardata) {
free(morefvardata);
nfvardata = 0;
if (morefvar) {
free(morefvar);
}
destroyed = 1;
}
@ -539,6 +549,9 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
// can be immediately removed.
int i, newEdgeCount = 0;
bool edgeFound = false;
HbrHalfedge<T>** incidentEdges =
(nIncidentEdges > 1) ? incident.edges : &incident.edge;
for (i = 0; i < nIncidentEdges; ++i) {
if (incidentEdges[i] == edge) {
edgeFound = true;
@ -583,7 +596,7 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
if (nIncidentEdges > 1) {
delete [] incidentEdges;
}
incidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
incidentEdges = &incident.edge;
incidentEdges[0] = edge;
nIncidentEdges = 1;
}
@ -600,7 +613,7 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
if (newEdgeCount + 1 > 1) {
newIncidentEdges = new HbrHalfedge<T>*[newEdgeCount + 1];
} else {
newIncidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
newIncidentEdges = &incident.edge;
}
for (i = 0; i < newEdgeCount; ++i) {
newIncidentEdges[i] = incidentEdges[i];
@ -610,6 +623,9 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
}
nIncidentEdges = newEdgeCount + 1;
incidentEdges = newIncidentEdges;
if (nIncidentEdges > 1) {
incident.edges = newIncidentEdges;
}
}
incidentEdges[newEdgeCount] = edge;
} else {
@ -621,7 +637,7 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
if (newEdgeCount > 1) {
newIncidentEdges = new HbrHalfedge<T>*[newEdgeCount];
} else {
newIncidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
newIncidentEdges = &incident.edge;
}
for (i = 0; i < newEdgeCount; ++i) {
newIncidentEdges[i] = incidentEdges[i];
@ -631,6 +647,9 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
}
nIncidentEdges = newEdgeCount;
incidentEdges = newIncidentEdges;
if (nIncidentEdges > 1) {
incident.edges = newIncidentEdges;
}
}
}
}
@ -642,7 +661,7 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
if (newEdgeCount > 1) {
newIncidentEdges = new HbrHalfedge<T>*[newEdgeCount];
} else {
newIncidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
newIncidentEdges = &incident.edge;
}
for (i = 0; i < newEdgeCount; ++i) {
newIncidentEdges[i] = incidentEdges[i];
@ -652,6 +671,9 @@ HbrVertex<T>::AddIncidentEdge(HbrHalfedge<T>* edge) {
}
nIncidentEdges = newEdgeCount;
incidentEdges = newIncidentEdges;
if (nIncidentEdges > 1) {
incident.edges = newIncidentEdges;
}
}
}
@ -692,6 +714,8 @@ void
HbrVertex<T>::RemoveIncidentEdge(HbrHalfedge<T>* edge) {
int i, j;
HbrHalfedge<T>** incidentEdges =
(nIncidentEdges > 1) ? incident.edges : &incident.edge;
references--;
if (references) {
@ -729,7 +753,7 @@ HbrVertex<T>::RemoveIncidentEdge(HbrHalfedge<T>* edge) {
if (nIncidentEdges - 1 > 1) {
newIncidentEdges = new HbrHalfedge<T>*[nIncidentEdges - 1];
} else {
newIncidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
newIncidentEdges = &incident.edge;
}
j = 0;
for (i = 0; i < nIncidentEdges; ++i) {
@ -742,7 +766,9 @@ HbrVertex<T>::RemoveIncidentEdge(HbrHalfedge<T>* edge) {
delete[] incidentEdges;
}
nIncidentEdges--;
incidentEdges = newIncidentEdges;
if (nIncidentEdges > 1) {
incident.edges = newIncidentEdges;
}
return;
}
// Now deal with the case where we remove an edge
@ -775,7 +801,7 @@ HbrVertex<T>::RemoveIncidentEdge(HbrHalfedge<T>* edge) {
if (nIncidentEdges + 1 > 1) {
newIncidentEdges = new HbrHalfedge<T>*[nIncidentEdges + 1];
} else {
newIncidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
newIncidentEdges = &incident.edge;
}
for (i = 0; i < nIncidentEdges; ++i) {
newIncidentEdges[i] = incidentEdges[i];
@ -785,13 +811,14 @@ HbrVertex<T>::RemoveIncidentEdge(HbrHalfedge<T>* edge) {
delete[] incidentEdges;
}
nIncidentEdges++;
incidentEdges = newIncidentEdges;
if (nIncidentEdges > 1) {
incident.edges = newIncidentEdges;
}
}
} else {
// No references left, we can just clear all the cycles
if (nIncidentEdges > 1) {
delete[] incidentEdges;
incidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
}
nIncidentEdges = 0;
}
@ -814,7 +841,7 @@ HbrVertex<T>::EdgeRemovalWillMakeSingular(HbrHalfedge<T>* edge) const {
// This is the incident edge starting a single cycle. Removal of
// the edge will replace the start of the cycle with the next
// edge, and we keep a single cycle.
else if (nIncidentEdges == 1 && incidentEdges[0] == edge) {
else if (nIncidentEdges == 1 && incident.edge == edge) {
return false;
}
// Check the single cycle: was it interrupted? (i.e. a
@ -823,7 +850,7 @@ HbrVertex<T>::EdgeRemovalWillMakeSingular(HbrHalfedge<T>* edge) const {
// edge in the cycle, we still don't need to split the any further
// cycle. Otherwise we must split the cycle, which would result in
// a singular vertex
else if (!incidentEdges[0]->IsBoundary()) {
else if (!GetIncidentEdge()->IsBoundary()) {
return false;
} else if (GetNextEdge(edge)) {
return true;
@ -850,7 +877,8 @@ int
HbrVertex<T>::GetValence() const {
int valence = 0;
assert(!IsSingular());
HbrHalfedge<T>* start = incidentEdges[0];
HbrHalfedge<T>* start =
(nIncidentEdges > 1) ? incident.edges[0] : incident.edge;
HbrHalfedge<T>* edge = start;
if (edge) do {
valence++;
@ -867,7 +895,8 @@ int
HbrVertex<T>::GetCoarseValence() const {
int valence = 0;
assert(!IsSingular());
HbrHalfedge<T>* start = incidentEdges[0];
HbrHalfedge<T>* start =
(nIncidentEdges > 1) ? incident.edges[0] : incident.edge;
HbrHalfedge<T>* edge = start;
if (edge) do {
if (edge->IsCoarse()) {
@ -887,11 +916,11 @@ HbrFVarData<T>&
HbrVertex<T>::GetFVarData(const HbrFace<T>* face) {
// See if there are any extra facevarying datum associated with
// this vertex, and whether any of them match the face.
if (nfvardata) {
size_t fvtsize = sizeof(HbrFVarData<T>) + sizeof(float) * GetMesh()->GetTotalFVarWidth();
HbrFVarData<T> *fvt = morefvardata;
for (int i = 0; i < nfvardata; ++i) {
if (fvt->GetFace() == face) {
if (morefvar) {
size_t fvtsize = sizeof(HbrFVarData<T>) + sizeof(float) * (GetMesh()->GetTotalFVarWidth() - 1);
HbrFVarData<T> *fvt = (HbrFVarData<T> *)((char *) morefvar + sizeof(int));
for (int i = 0; i < morefvar->count; ++i) {
if (fvt->GetFaceID() == face->GetID()) {
return *fvt;
}
fvt = (HbrFVarData<T>*)((char*) fvt + fvtsize);
@ -899,37 +928,39 @@ HbrVertex<T>::GetFVarData(const HbrFace<T>* face) {
}
// Otherwise, return the default facevarying datum, which lives
// in the overallocated space after the end of this object
return *((HbrFVarData<T>*) ((char*) this + sizeof(*this) + sizeof(HbrHalfedge<T>*)));
return *((HbrFVarData<T>*) ((char*) this + sizeof(*this)));
}
template <class T>
HbrFVarData<T>&
HbrVertex<T>::NewFVarData(const HbrFace<T>* face) {
const int fvarwidth = GetMesh()->GetTotalFVarWidth();
size_t fvtsize = sizeof(HbrFVarData<T>) + fvarwidth * sizeof(float);
if (nfvardata) {
HbrFVarData<T> *newfvardata = (HbrFVarData<T>*) malloc((nfvardata + 1) * fvtsize);
HbrFVarData<T> *newfvt = newfvardata, *oldfvt = morefvardata;
for (int i = 0; i < nfvardata; ++i) {
new (newfvt) HbrFVarData<T>((float*) ((char*) newfvt + sizeof(HbrFVarData<T>)));
size_t fvtsize = sizeof(HbrFVarData<T>) + (fvarwidth - 1) * sizeof(float);
if (morefvar) {
struct morefvardata *newmorefvar =
(struct morefvardata *) malloc(sizeof(int) + (morefvar->count + 1) * fvtsize);
HbrFVarData<T> *newfvt = (HbrFVarData<T> *)((char *) newmorefvar + sizeof(int));
HbrFVarData<T> *oldfvt = (HbrFVarData<T> *)((char *) morefvar + sizeof(int));
for (int i = 0; i < morefvar->count; ++i) {
new (newfvt) HbrFVarData<T>();
newfvt->SetAllData(fvarwidth, oldfvt->GetData(0));
newfvt->SetFace(oldfvt->GetFace());
newfvt->SetFaceID(oldfvt->GetFaceID());
oldfvt = (HbrFVarData<T>*)((char*) oldfvt + fvtsize);
newfvt = (HbrFVarData<T>*)((char*) newfvt + fvtsize);
}
new (newfvt) HbrFVarData<T>((float*) ((char*) newfvt + sizeof(HbrFVarData<T>)));
newfvt->SetFace(face);
free(morefvardata);
morefvardata = newfvardata;
nfvardata++;
new (newfvt) HbrFVarData<T>();
newfvt->SetFaceID(face->GetID());
newmorefvar->count = morefvar->count + 1;
free(morefvar);
morefvar = newmorefvar;
return *newfvt;
} else {
morefvardata = (HbrFVarData<T>*) malloc(fvtsize);
new (morefvardata) HbrFVarData<T>((float*) ((char*) morefvardata + sizeof(HbrFVarData<T>)));
morefvardata->SetFace(face);
nfvardata = 1;
return *morefvardata;
morefvar = (struct morefvardata *) malloc(sizeof(int) + fvtsize);
HbrFVarData<T> *newfvt = (HbrFVarData<T> *)((char *) morefvar + sizeof(int));
new (newfvt) HbrFVarData<T>();
newfvt->SetFaceID(face->GetID());
morefvar->count = 1;
return *newfvt;
}
}
@ -952,7 +983,8 @@ HbrHalfedge<T>*
HbrVertex<T>::GetEdge(const HbrVertex<T>* dest) const {
// Here, we generally want to go through all halfedge cycles
for (int i = 0; i < nIncidentEdges; ++i) {
HbrHalfedge<T>* cycle = incidentEdges[i];
HbrHalfedge<T>* cycle =
(nIncidentEdges > 1) ? incident.edges[i] : incident.edge;
HbrHalfedge<T>* edge = cycle;
if (edge) do {
if (edge->GetDestVertex() == dest) {
@ -964,6 +996,24 @@ HbrVertex<T>::GetEdge(const HbrVertex<T>* dest) const {
return 0;
}
template <class T>
HbrHalfedge<T>*
HbrVertex<T>::GetEdge(int dest) const {
// Here, we generally want to go through all halfedge cycles
for (int i = 0; i < nIncidentEdges; ++i) {
HbrHalfedge<T>* cycle =
(nIncidentEdges > 1) ? incident.edges[i] : incident.edge;
HbrHalfedge<T>* edge = cycle;
if (edge) do {
if (edge->GetDestVertexID() == dest) {
return edge;
}
edge = GetNextEdge(edge);
} while (edge && edge != cycle);
}
return 0;
}
template <class T>
HbrHalfedge<T>*
HbrVertex<T>::GetNextEdge(const HbrHalfedge<T>* edge) const {
@ -1093,7 +1143,7 @@ bool
HbrVertex<T>::OnBoundary() const {
// We really only need to check the first incident edge, since
// singular vertices by definition are on the boundary
return incidentEdges[0]->IsBoundary();
return GetIncidentEdge()->IsBoundary();
}
template <class T>
@ -1348,10 +1398,11 @@ template <class T>
template <typename OutputIterator>
void
HbrVertex<T>::GetSurroundingVertices(OutputIterator vertices) const {
HbrMesh<T>* mesh = GetMesh();
HbrHalfedge<T>* start = GetIncidentEdge(), *edge, *next;
edge = start;
while (edge) {
*vertices++ = edge->GetDestVertex();
*vertices++ = edge->GetDestVertex(mesh);
next = GetNextEdge(edge);
if (next == start) {
break;
@ -1359,7 +1410,7 @@ HbrVertex<T>::GetSurroundingVertices(OutputIterator vertices) const {
// Special case for the last edge in a cycle: the last
// vertex on that cycle is not the destination of an
// outgoing halfedge
*vertices++ = edge->GetPrev()->GetOrgVertex();
*vertices++ = edge->GetPrev()->GetOrgVertex(mesh);
break;
} else {
edge = next;
@ -1370,14 +1421,15 @@ HbrVertex<T>::GetSurroundingVertices(OutputIterator vertices) const {
template <class T>
void
HbrVertex<T>::ApplyOperatorSurroundingVertices(HbrVertexOperator<T> &op) const {
HbrMesh<T>* mesh = GetMesh();
HbrHalfedge<T>* start = GetIncidentEdge(), *edge, *next;
edge = start;
while (edge) {
op(*edge->GetDestVertex());
op(*edge->GetDestVertex(mesh));
next = GetNextEdge(edge);
if (next == start) return;
else if (!next) {
op(*edge->GetPrev()->GetOrgVertex());
op(*edge->GetPrev()->GetOrgVertex(mesh));
return;
} else {
edge = next;
@ -1400,11 +1452,12 @@ HbrVertex<T>::ApplyOperatorSurroundingFaces(HbrFaceOperator<T> &op) const {
template <class T>
HbrVertex<T>*
HbrVertex<T>::Subdivide() {
if (vchild) return vchild;
HbrMesh<T>* mesh = GetMesh();
vchild = mesh->GetSubdivision()->Subdivide(mesh, this);
vchild->SetParent(this);
return vchild;
if (vchild != -1) return mesh->GetVertex(vchild);
HbrVertex<T>* vchildVert = mesh->GetSubdivision()->Subdivide(mesh, this);
vchild = vchildVert->GetID();
vchildVert->SetParent(this);
return vchildVert;
}
template <class T>
@ -1458,6 +1511,8 @@ void
HbrVertex<T>::splitSingular() {
HbrMesh<T>* mesh = GetMesh();
HbrHalfedge<T>* e;
HbrHalfedge<T>** incidentEdges =
(nIncidentEdges > 1) ? incident.edges : &incident.edge;
// Go through each edge cycle after the first
std::vector<HbrHalfedge<T>*> edges;
@ -1504,8 +1559,7 @@ HbrVertex<T>::splitSingular() {
delete[] incidentEdges;
}
nIncidentEdges = 1;
incidentEdges = (HbrHalfedge<T>**) ((char*) this + sizeof(*this));
incidentEdges[0] = e;
incident.edge = e;
}
template <class T>