mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-24 04:20:21 +00:00
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:
parent
95c84b8f56
commit
f9dd284be0
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user