diff options
Diffstat (limited to 'thirdparty/thekla_atlas/nvmesh/halfedge')
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp | 57 | ||||
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h | 70 | ||||
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp | 268 | ||||
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Face.h | 106 | ||||
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp | 1284 | ||||
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h | 274 | ||||
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp | 94 | ||||
-rw-r--r-- | thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h | 221 |
8 files changed, 0 insertions, 2374 deletions
diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp deleted file mode 100644 index 671650296c..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// This code is in the public domain -- castanyo@yahoo.es - -#include "nvmesh.h" // pch - -#include "Edge.h" -#include "Vertex.h" - -#include "nvmath/Vector.inl" - -using namespace nv; -using namespace HalfEdge; - -Vector3 Edge::midPoint() const -{ - return (to()->pos + from()->pos) * 0.5f; -} - -float Edge::length() const -{ - return ::length(to()->pos - from()->pos); -} - -// Return angle between this edge and the previous one. -float Edge::angle() const { - Vector3 p = vertex->pos; - Vector3 a = prev->vertex->pos; - Vector3 b = next->vertex->pos; - - Vector3 v0 = a - p; - Vector3 v1 = b - p; - - return acosf(dot(v0, v1) / (nv::length(v0) * nv::length(v1))); -} - -bool Edge::isValid() const -{ - // null face is OK. - if (next == NULL || prev == NULL || pair == NULL || vertex == NULL) return false; - if (next->prev != this) return false; - if (prev->next != this) return false; - if (pair->pair != this) return false; - return true; -} - -/* -Edge * Edge::nextBoundary() { - nvDebugCheck(this->m_pair == NULL); - -} - -Edge * Edge::prevBoundary() { - nvDebugCheck(this->m_pair == NULL); - -} -*/ - - diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h deleted file mode 100644 index 25c47f4860..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Edge.h +++ /dev/null @@ -1,70 +0,0 @@ -// This code is in the public domain -- castanyo@yahoo.es - -#pragma once -#ifndef NV_MESH_HALFEDGE_EDGE_H -#define NV_MESH_HALFEDGE_EDGE_H - -#include "nvmath/Vector.h" - -namespace nv -{ - namespace HalfEdge { class Vertex; class Face; class Edge; } - - /// Half edge edge. - class HalfEdge::Edge - { - NV_FORBID_COPY(Edge); - public: - - uint id; - - Edge * next; - Edge * prev; // This is not strictly half-edge, but makes algorithms easier and faster. - Edge * pair; - Vertex * vertex; - Face * face; - - - // Default constructor. - Edge(uint id) : id(id), next(NULL), prev(NULL), pair(NULL), vertex(NULL), face(NULL) - { - } - - - // Vertex queries. - const Vertex * from() const { return vertex; } - Vertex * from() { return vertex; } - - const Vertex * to() const { return pair->vertex; } // This used to be 'next->vertex', but that changed often when the connectivity of the mesh changes. - Vertex * to() { return pair->vertex; } - - - // Edge queries. - void setNext(Edge * e) { next = e; if (e != NULL) e->prev = this; } - void setPrev(Edge * e) { prev = e; if (e != NULL) e->next = this; } - - // @@ Add these helpers: - //Edge * nextBoundary(); - //Edge * prevBoundary(); - - - // @@ It would be more simple to only check m_pair == NULL - // Face queries. - bool isBoundary() const { return !(face && pair->face); } - - // @@ This is not exactly accurate, we should compare the texture coordinates... - bool isSeam() const { return vertex != pair->next->vertex || next->vertex != pair->vertex; } - - bool isValid() const; - - // Geometric queries. - Vector3 midPoint() const; - float length() const; - float angle() const; - - }; - -} // nv namespace - - -#endif // NV_MESH_HALFEDGE_EDGE_H diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp deleted file mode 100644 index 9f6987154e..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.cpp +++ /dev/null @@ -1,268 +0,0 @@ -// This code is in the public domain -- castanyo@yahoo.es - -#include "nvmesh.h" // pch - -#include "Face.h" -#include "Vertex.h" - -#include "nvmath/Fitting.h" -#include "nvmath/Plane.h" -#include "nvmath/Vector.inl" - -#include "nvcore/Array.h" - - -using namespace nv; -using namespace HalfEdge; - -/// Get face area. -float Face::area() const -{ - float area = 0; - const Vector3 & v0 = edge->from()->pos; - - for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance()) - { - const Edge * e = it.current(); - - const Vector3 & v1 = e->vertex->pos; - const Vector3 & v2 = e->next->vertex->pos; - - area += length(cross(v1-v0, v2-v0)); - } - - return area * 0.5f; -} - -float Face::parametricArea() const -{ - float area = 0; - const Vector2 & v0 = edge->from()->tex; - - for (ConstEdgeIterator it(edges(edge->next)); it.current() != edge->prev; it.advance()) - { - const Edge * e = it.current(); - - const Vector2 & v1 = e->vertex->tex; - const Vector2 & v2 = e->next->vertex->tex; - - area += triangleArea(v0, v1, v2); - } - - return area * 0.5f; -} - - -/// Get boundary length. -float Face::boundaryLength() const -{ - float bl = 0; - - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - const Edge * edge = it.current(); - bl += edge->length(); - } - - return bl; -} - - -/// Get face normal. -Vector3 Face::normal() const -{ - Vector3 n(0); - - const Vertex * vertex0 = NULL; - - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - const Edge * edge = it.current(); - nvCheck(edge != NULL); - - if (vertex0 == NULL) - { - vertex0 = edge->vertex; - } - else if (edge->next->vertex != vertex0) - { - const HalfEdge::Vertex * vertex1 = edge->from(); - const HalfEdge::Vertex * vertex2 = edge->to(); - - const Vector3 & p0 = vertex0->pos; - const Vector3 & p1 = vertex1->pos; - const Vector3 & p2 = vertex2->pos; - - Vector3 v10 = p1 - p0; - Vector3 v20 = p2 - p0; - - n += cross(v10, v20); - } - } - - return normalizeSafe(n, Vector3(0, 0, 1), 0.0f); - - - // Get face points eliminating duplicates. - /*Array<Vector3> points(4); - - points.append(m_edge->prev()->from()->pos); - - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - const Edge * edge = it.current(); - nvDebugCheck(edge != NULL); - - const Vector3 & p = edge->from()->pos; - if (points.back() != p) - { - points.append(edge->from()->pos); - } - } - - points.popBack(); - - if (points.count() < 3) - { - // Invalid normal. - return Vector3(0.0f); - } - else - { - // Compute regular normal. - Vector3 normal = normalizeSafe(cross(points[1] - points[0], points[2] - points[0]), Vector3(0.0f), 0.0f); - -#pragma NV_MESSAGE("TODO: make sure these three points are not colinear") - - if (points.count() > 3) - { - // Compute best fitting plane to the points. - Plane plane = Fit::bestPlane(points.count(), points.buffer()); - - // Adjust normal orientation. - if (dot(normal, plane.vector()) > 0) { - normal = plane.vector(); - } - else { - normal = -plane.vector(); - } - } - - nvDebugCheck(isNormalized(normal)); - return normal; - }*/ -} - -Vector3 Face::centroid() const -{ - Vector3 sum(0.0f); - uint count = 0; - - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - const Edge * edge = it.current(); - sum += edge->from()->pos; - count++; - } - - return sum / float(count); -} - - -bool Face::isValid() const -{ - uint count = 0; - - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - const Edge * edge = it.current(); - if (edge->face != this) return false; - if (!edge->isValid()) return false; - if (!edge->pair->isValid()) return false; - count++; - } - - if (count < 3) return false; - - return true; -} - - -// Determine if this face contains the given edge. -bool Face::contains(const Edge * e) const -{ - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - if(it.current() == e) return true; - } - return false; -} - -// Returns index in this face of the given edge. -uint Face::edgeIndex(const Edge * e) const -{ - int i = 0; - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance(), i++) - { - if(it.current() == e) return i; - } - return NIL; -} - - -Edge * Face::edgeAt(uint idx) -{ - int i = 0; - for(EdgeIterator it(edges()); !it.isDone(); it.advance(), i++) { - if (i == idx) return it.current(); - } - return NULL; -} -const Edge * Face::edgeAt(uint idx) const -{ - int i = 0; - for(ConstEdgeIterator it(edges()); !it.isDone(); it.advance(), i++) { - if (i == idx) return it.current(); - } - return NULL; -} - - -// Count the number of edges in this face. -uint Face::edgeCount() const -{ - uint count = 0; - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) { ++count; } - return count; -} - -// Determine if this is a boundary face. -bool Face::isBoundary() const -{ - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - const Edge * edge = it.current(); - nvDebugCheck(edge->pair != NULL); - - if (edge->pair->face == NULL) { - return true; - } - } - return false; -} - -// Count the number of boundary edges in the face. -uint Face::boundaryCount() const -{ - uint count = 0; - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) - { - const Edge * edge = it.current(); - nvDebugCheck(edge->pair != NULL); - - if (edge->pair->face == NULL) { - count++; - } - } - return count; -} diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Face.h deleted file mode 100644 index 677f8666f0..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Face.h +++ /dev/null @@ -1,106 +0,0 @@ -// This code is in the public domain -- castanyo@yahoo.es - -#pragma once -#ifndef NV_MESH_HALFEDGE_FACE_H -#define NV_MESH_HALFEDGE_FACE_H - -#include <nvmesh/halfedge/Edge.h> - -namespace nv -{ - namespace HalfEdge { class Vertex; class Face; class Edge; } - - /// Face of a half-edge mesh. - class HalfEdge::Face - { - NV_FORBID_COPY(Face); - public: - - uint id; - uint16 group; - uint16 material; - Edge * edge; - - - Face(uint id) : id(id), group(~0), material(~0), edge(NULL) {} - - float area() const; - float parametricArea() const; - float boundaryLength() const; - Vector3 normal() const; - Vector3 centroid() const; - - bool isValid() const; - - bool contains(const Edge * e) const; - uint edgeIndex(const Edge * e) const; - - Edge * edgeAt(uint idx); - const Edge * edgeAt(uint idx) const; - - uint edgeCount() const; - bool isBoundary() const; - uint boundaryCount() const; - - - // The iterator that visits the edges of this face in clockwise order. - class EdgeIterator //: public Iterator<Edge *> - { - public: - EdgeIterator(Edge * e) : m_end(NULL), m_current(e) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->next; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual Edge * current() const { return m_current; } - Vertex * vertex() const { return m_current->vertex; } - - private: - Edge * m_end; - Edge * m_current; - }; - - EdgeIterator edges() { return EdgeIterator(edge); } - EdgeIterator edges(Edge * e) - { - nvDebugCheck(contains(e)); - return EdgeIterator(e); - } - - // The iterator that visits the edges of this face in clockwise order. - class ConstEdgeIterator //: public Iterator<const Edge *> - { - public: - ConstEdgeIterator(const Edge * e) : m_end(NULL), m_current(e) { } - ConstEdgeIterator(const EdgeIterator & it) : m_end(NULL), m_current(it.current()) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->next; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual const Edge * current() const { return m_current; } - const Vertex * vertex() const { return m_current->vertex; } - - private: - const Edge * m_end; - const Edge * m_current; - }; - - ConstEdgeIterator edges() const { return ConstEdgeIterator(edge); } - ConstEdgeIterator edges(const Edge * e) const - { - nvDebugCheck(contains(e)); - return ConstEdgeIterator(e); - } - }; - -} // nv namespace - -#endif // NV_MESH_HALFEDGE_FACE_H diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp deleted file mode 100644 index 0012513bce..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.cpp +++ /dev/null @@ -1,1284 +0,0 @@ -// This code is in the public domain -- castanyo@yahoo.es - -#include "nvmesh.h" // pch - -#include "Mesh.h" -#include "Edge.h" -#include "Vertex.h" -#include "Face.h" - -#include "nvmesh/TriMesh.h" -#include "nvmesh/QuadTriMesh.h" -#include "nvmesh/MeshBuilder.h" - -#include "nvmath/Vector.inl" -#include "nvcore/Array.inl" -#include "nvcore/HashMap.inl" - - -using namespace nv; -using namespace HalfEdge; - -Mesh::Mesh() : m_colocalVertexCount(0) -{ - errorCount = 0; -} - -Mesh::Mesh(const Mesh * mesh) -{ - errorCount = 0; - - // Copy mesh vertices. - const uint vertexCount = mesh->vertexCount(); - m_vertexArray.resize(vertexCount); - - for (uint v = 0; v < vertexCount; v++) - { - const Vertex * vertex = mesh->vertexAt(v); - nvDebugCheck(vertex->id == v); - - m_vertexArray[v] = new Vertex(v); - m_vertexArray[v]->pos = vertex->pos; - m_vertexArray[v]->nor = vertex->nor; - m_vertexArray[v]->tex = vertex->tex; - } - - m_colocalVertexCount = vertexCount; - - - // Copy mesh faces. - const uint faceCount = mesh->faceCount(); - - Array<uint> indexArray(3); - - for (uint f = 0; f < faceCount; f++) - { - const Face * face = mesh->faceAt(f); - - for(Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) { - const Vertex * vertex = it.current()->from(); - indexArray.append(vertex->id); - } - - addFace(indexArray); - indexArray.clear(); - } -} - -Mesh::~Mesh() -{ - clear(); -} - - -void Mesh::clear() -{ - deleteAll(m_vertexArray); - m_vertexArray.clear(); - - foreach(i, m_edgeMap) - { - delete m_edgeMap[i].value; - } - //deleteAll(m_edgeArray); // edgeArray only contains 1/2 of the edges! - m_edgeArray.clear(); - m_edgeMap.clear(); - - deleteAll(m_faceArray); - m_faceArray.clear(); -} - - -Vertex * Mesh::addVertex(const Vector3 & pos) -{ - nvDebugCheck(isFinite(pos)); - - Vertex * v = new Vertex(m_vertexArray.count()); - v->pos = pos; - m_vertexArray.append(v); - - return v; - -// return addVertex(m_vertexArray.count(), pos); -} - -/*Vertex * Mesh::addVertex(uint id, const Vector3 & pos) -{ - nvDebugCheck(isFinite(pos)); - - Vertex * v = new Vertex(id); - v->pos = pos; - m_vertexArray.append(v); - - return v; -}*/ - -/*void Mesh::addVertices(const Mesh * mesh) -{ -nvCheck(mesh != NULL); - -// Add mesh vertices -for (uint v = 0; v < vertexCount; v++) -{ -const Vertex * vertex = mesh->vertexAt(v); -nvDebugCheck(vertex != NULL); - -Vertex * v = addVertex(vertex->pos()); -nvDebugCheck(v != NULL); - -v->setNor(vertex->nor()); -v->setTex(vertex->tex()); -} -}*/ - - -/// Link colocal vertices based on geometric location only. -void Mesh::linkColocals() -{ - nvDebug("--- Linking colocals:\n"); - - const uint vertexCount = this->vertexCount(); - HashMap<Vector3, Vertex *> vertexMap(vertexCount); - - for (uint v = 0; v < vertexCount; v++) - { - Vertex * vertex = vertexAt(v); - - Vertex * colocal; - if (vertexMap.get(vertex->pos, &colocal)) - { - colocal->linkColocal(vertex); - } - else - { - vertexMap.add(vertex->pos, vertex); - } - } - - m_colocalVertexCount = vertexMap.count(); - - nvDebug("--- %d vertex positions.\n", m_colocalVertexCount); - - // @@ Remove duplicated vertices? or just leave them as colocals? -} - -void Mesh::linkColocalsWithCanonicalMap(const Array<uint> & canonicalMap) -{ - nvDebug("--- Linking colocals:\n"); - - uint vertexMapSize = 0; - foreach(i, canonicalMap) { - vertexMapSize = max(vertexMapSize, canonicalMap[i] + 1); - } - - Array<Vertex *> vertexMap; - vertexMap.resize(vertexMapSize, NULL); - - m_colocalVertexCount = 0; - - const uint vertexCount = this->vertexCount(); - for (uint v = 0; v < vertexCount; v++) - { - Vertex * vertex = vertexAt(v); - - Vertex * colocal = vertexMap[canonicalMap[v]]; - if (colocal != NULL) - { - nvDebugCheck(vertex->pos == colocal->pos); - colocal->linkColocal(vertex); - } - else - { - vertexMap[canonicalMap[v]] = vertex; - m_colocalVertexCount++; - } - } - - nvDebug("--- %d vertex positions.\n", m_colocalVertexCount); -} - - -Face * Mesh::addFace() -{ - Face * f = new Face(m_faceArray.count()); - m_faceArray.append(f); - return f; -} - -Face * Mesh::addFace(uint v0, uint v1, uint v2) -{ - Array<uint> indexArray(3); - indexArray << v0 << v1 << v2; - return addFace(indexArray, 0, 3); -} - -Face * Mesh::addFace(uint v0, uint v1, uint v2, uint v3) -{ - Array<uint> indexArray(4); - indexArray << v0 << v1 << v2 << v3; - return addFace(indexArray, 0, 4); -} - -Face * Mesh::addFace(const Array<uint> & indexArray) -{ - return addFace(indexArray, 0, indexArray.count()); -} - - -Face * Mesh::addFace(const Array<uint> & indexArray, uint first, uint num) -{ - nvDebugCheck(first < indexArray.count()); - nvDebugCheck(num <= indexArray.count()-first); - nvDebugCheck(num > 2); - - if (!canAddFace(indexArray, first, num)) { - errorCount++; - return NULL; - } - - Face * f = new Face(m_faceArray.count()); - - Edge * firstEdge = NULL; - Edge * last = NULL; - Edge * current = NULL; - - for(uint i = 0; i < num-1; i++) - { - current = addEdge(indexArray[first+i], indexArray[first+i+1]); - nvCheck(current != NULL && current->face == NULL); - - current->face = f; - - if (last != NULL) last->setNext(current); - else firstEdge = current; - - last = current; - } - - current = addEdge(indexArray[first+num-1], indexArray[first]); - nvCheck(current != NULL && current->face == NULL); - - current->face = f; - - last->setNext(current); - current->setNext(firstEdge); - - f->edge = firstEdge; - m_faceArray.append(f); - - return f; -} - -/*void Mesh::addFaces(const Mesh * mesh) -{ -nvCheck(mesh != NULL); - -Array indexArray; -// Add faces - -}*/ - - -// Return true if the face can be added to the manifold mesh. -bool Mesh::canAddFace(const Array<uint> & indexArray, uint first, uint num) const -{ - for (uint j = num - 1, i = 0; i < num; j = i++) { - if (!canAddEdge(indexArray[first+j], indexArray[first+i])) { - errorIndex0 = indexArray[first+j]; - errorIndex1 = indexArray[first+i]; - return false; - } - } - - // We also have to make sure the face does not have any duplicate edge! - for (uint i = 0; i < num; i++) { - - int i0 = indexArray[first + i + 0]; - int i1 = indexArray[first + (i + 1)%num]; - - for (uint j = i + 1; j < num; j++) { - int j0 = indexArray[first + j + 0]; - int j1 = indexArray[first + (j + 1)%num]; - - if (i0 == j0 && i1 == j1) { - return false; - } - } - } - - return true; -} - -// Return true if the edge doesn't exist or doesn't have any adjacent face. -bool Mesh::canAddEdge(uint i, uint j) const -{ - if (i == j) { - // Skip degenerate edges. - return false; - } - - // Same check, but taking into account colocal vertices. - const Vertex * v0 = vertexAt(i); - const Vertex * v1 = vertexAt(j); - - for(Vertex::ConstVertexIterator it(v0->colocals()); !it.isDone(); it.advance()) - { - if (it.current() == v1) - { - // Skip degenerate edges. - return false; - } - } - - // Make sure edge has not been added yet. - Edge * edge = findEdge(i, j); - - return edge == NULL || edge->face == NULL; // We ignore edges that don't have an adjacent face yet, since this face could become the edge's face. -} - -Edge * Mesh::addEdge(uint i, uint j) -{ - nvCheck(i != j); - - Edge * edge = findEdge(i, j); - - if (edge != NULL) { - // Edge may already exist, but its face must not be set. - nvDebugCheck(edge->face == NULL); - - // Nothing else to do! - - } - else { - // Add new edge. - - // Lookup pair. - Edge * pair = findEdge(j, i); - - if (pair != NULL) - { - // Create edge with same id. - edge = new Edge(pair->id + 1); - - // Link edge pairs. - edge->pair = pair; - pair->pair = edge; - - // @@ I'm not sure this is necessary! - pair->vertex->setEdge(pair); - } - else - { - // Create edge. - edge = new Edge(2*m_edgeArray.count()); - - // Add only unpaired edges. - m_edgeArray.append(edge); - } - - edge->vertex = m_vertexArray[i]; - m_edgeMap.add(Key(i,j), edge); - } - - // Face and Next are set by addFace. - - return edge; -} - - -/// Find edge, test all colocals. -Edge * Mesh::findEdge(uint i, uint j) const -{ - Edge * edge = NULL; - - const Vertex * v0 = vertexAt(i); - const Vertex * v1 = vertexAt(j); - - // Test all colocal pairs. - for(Vertex::ConstVertexIterator it0(v0->colocals()); !it0.isDone(); it0.advance()) - { - for(Vertex::ConstVertexIterator it1(v1->colocals()); !it1.isDone(); it1.advance()) - { - Key key(it0.current()->id, it1.current()->id); - - if (edge == NULL) { - m_edgeMap.get(key, &edge); -#if !defined(_DEBUG) - if (edge != NULL) return edge; -#endif - } - else { - // Make sure that only one edge is found. - nvDebugCheck(!m_edgeMap.get(key)); - } - } - } - - return edge; -} - -/// Link boundary edges once the mesh has been created. -void Mesh::linkBoundary() -{ - nvDebug("--- Linking boundaries:\n"); - - int num = 0; - - // Create boundary edges. - uint edgeCount = this->edgeCount(); - for(uint e = 0; e < edgeCount; e++) - { - Edge * edge = edgeAt(e); - if (edge != NULL && edge->pair == NULL) { - Edge * pair = new Edge(edge->id + 1); - - uint i = edge->from()->id; - uint j = edge->next->from()->id; - - Key key(j,i); - nvCheck(!m_edgeMap.get(key)); - - pair->vertex = m_vertexArray[j]; - m_edgeMap.add(key, pair); - - edge->pair = pair; - pair->pair = edge; - - num++; - } - } - - // Link boundary edges. - for (uint e = 0; e < edgeCount; e++) { - Edge * edge = edgeAt(e); - if (edge != NULL && edge->pair->face == NULL) { - linkBoundaryEdge(edge->pair); - } - } - - nvDebug("--- %d boundary edges.\n", num); -} - -/// Link this boundary edge. -void Mesh::linkBoundaryEdge(Edge * edge) -{ - nvCheck(edge->face == NULL); - - // Make sure next pointer has not been set. @@ We want to be able to relink boundary edges after mesh changes. - //nvCheck(edge->next() == NULL); - - Edge * next = edge; - while(next->pair->face != NULL) { - // Get pair prev - Edge * e = next->pair->next; - while (e->next != next->pair) { - e = e->next; - } - next = e; - } - edge->setNext(next->pair); - - // Adjust vertex edge, so that it's the boundary edge. (required for isBoundary()) - if (edge->vertex->edge != edge) - { - // Multiple boundaries in the same edge. - //nvCheck( edge->vertex()->edge() == NULL || edge->vertex()->edge()->face() != NULL ); - edge->vertex->edge = edge; - } -} - - -/// Convert to tri mesh. -TriMesh * Mesh::toTriMesh() const -{ - uint triangleCount = 0; - - // Count triangle faces. - const uint faceCount = this->faceCount(); - for(uint f = 0; f < faceCount; f++) - { - const Face * face = faceAt(f); - triangleCount += face->edgeCount() - 2; - } - - TriMesh * triMesh = new TriMesh(triangleCount, vertexCount()); - - // Add vertices. - Array<TriMesh::Vertex> & vertices = triMesh->vertices(); - - const uint vertexCount = this->vertexCount(); - for(uint v = 0; v < vertexCount; v++) - { - const Vertex * vertex = vertexAt(v); - - TriMesh::Vertex triVertex; - triVertex.id = vertices.count(); - triVertex.pos = vertex->pos; - triVertex.nor = vertex->nor; - triVertex.tex = vertex->tex; - - vertices.append(triVertex); - } - - // Add triangles. - Array<TriMesh::Face> & triangles = triMesh->faces(); - - for(uint f = 0; f < faceCount; f++) - { - const Face * face = faceAt(f); - - // @@ Triangulate arbitrary polygons correctly. - const uint v0 = face->edge->vertex->id; - uint v1 = face->edge->next->vertex->id; - - for(Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) - { - uint v2 = it.current()->vertex->id; - - // Skip the first two vertices. - if (v2 == v0 || v2 == v1) continue; - - TriMesh::Face triangle; - triangle.id = triangles.count(); - triangle.v[0] = v0; - triangle.v[1] = v1; - triangle.v[2] = v2; - - v1 = v2; - - triangles.append(triangle); - } - } - - return triMesh; -} - -QuadTriMesh * Mesh::toQuadTriMesh() const -{ - MeshBuilder builder; - - const uint vertexCount = this->vertexCount(); - builder.hintVertexCount(vertexCount); - - for(uint v = 0; v < vertexCount; v++) - { - const Vertex * vertex = vertexAt(v); - - builder.addPosition(vertex->pos); - builder.addNormal(vertex->nor); - builder.addTexCoord(vertex->tex); - } - - const uint faceCount = this->faceCount(); - builder.hintTriangleCount(faceCount); - - for(uint f = 0; f < faceCount; f++) - { - const Face * face = faceAt(f); - - builder.beginPolygon(); - - for(Face::ConstEdgeIterator it(face->edges()); !it.isDone(); it.advance()) - { - uint v = it.current()->vertex->id; - builder.addVertex(v, v, v); - } - - builder.endPolygon(); - } - - builder.done(); - - return builder.buildQuadTriMesh(); -} - - -// Triangulate in place. -void Mesh::triangulate() { - - bool all_triangles = true; - - const uint faceCount = m_faceArray.count(); - for (uint f = 0; f < faceCount; f++) { - Face * face = m_faceArray[f]; - if (face->edgeCount() != 3) { - all_triangles = false; - break; - } - } - - if (all_triangles) { - return; - } - - - // Do not touch vertices, but rebuild edges and faces. - Array<Edge *> edgeArray; - Array<Face *> faceArray; - - swap(edgeArray, m_edgeArray); - swap(faceArray, m_faceArray); - m_edgeMap.clear(); - - for (uint f = 0; f < faceCount; f++) { - Face * face = faceArray[f]; - - // Trivial fan-like triangulation. - const uint v0 = face->edge->vertex->id; - uint v2, v1 = -1; - - for (Face::EdgeIterator it(face->edges()); !it.isDone(); it.advance()) { - Edge * edge = it.current(); - v2 = edge->to()->id; - if (v2 == v0) break; - if (v1 != -1) addFace(v0, v1, v2); - v1 = v2; - } - } - - nvDebugCheck(m_faceArray.count() > faceCount); // triangle count > face count - - linkBoundary(); - - deleteAll(edgeArray); - deleteAll(faceArray); -} - - -/* -Fixing T-junctions. - -- Find T-junctions. Find vertices that are on an edge. - - This test is approximate. - - Insert edges on a spatial index to speedup queries. - - Consider only open edges, that is edges that have no pairs. - - Consider only vertices on boundaries. -- Close T-junction. - - Split edge. - -*/ -bool Mesh::splitBoundaryEdges() { - - Array<Vertex *> boundaryVertices; - - foreach(i, m_vertexArray) { - Vertex * v = m_vertexArray[i]; - if (v->isBoundary()) { - boundaryVertices.append(v); - } - } - - nvDebug("Fixing T-junctions:\n"); - - int splitCount = 0; - - foreach(v, boundaryVertices) { - Vertex * vertex = boundaryVertices[v]; - - Vector3 x0 = vertex->pos; - - // Find edges that this vertex overlaps with. - foreach(e, m_edgeArray) { - //for (uint e = 0; e < m_edgeArray.count(); e++) { - Edge * edge = m_edgeArray[e]; - if (edge != NULL && edge->isBoundary()) { - - if (edge->from() == vertex || edge->to() == vertex) { - continue; - } - - Vector3 x1 = edge->from()->pos; - Vector3 x2 = edge->to()->pos; - - Vector3 v01 = x0 - x1; - Vector3 v21 = x2 - x1; - - float l = length(v21); - float d = length(cross(v01, v21)) / l; - - if (isZero(d)) { - float t = dot(v01, v21) / (l * l); - - // @@ Snap x0 to x1 or x2, if too close? No, do vertex snapping elsewhere. - /*if (equal(t, 0.0f, 0.01f)) { - //vertex->setPos(x1); - } - else if (equal(t, 1.0f, 0.01f)) { - //vertex->setPos(x2); - } - else*/ - if (t > 0.0f + NV_EPSILON && t < 1.0f - NV_EPSILON) { - nvDebugCheck(equal(lerp(x1, x2, t), x0)); - - Vertex * splitVertex = splitBoundaryEdge(edge, t, x0); - vertex->linkColocal(splitVertex); // @@ Should we do this here? - splitCount++; - } - } - } - } - } - - nvDebug(" - %d edges split.\n", splitCount); - - nvDebugCheck(isValid()); - - return splitCount != 0; -} - - -// For this to be effective, we have to fix the boundary junctions first. -Edge * Mesh::sewBoundary(Edge * startEdge) { - nvDebugCheck(startEdge->face == NULL); - - // @@ We may want to be more conservative linking colocals in order to preserve the input topology. One way of doing that is by linking colocals only - // if the vertices next to them are linked as well. That is, by sewing boundaries after detecting them. If any pair of consecutive edges have their first - // and last vertex in the same position, then it can be linked. - - Edge * lastBoundarySeen = startEdge; - - nvDebug("Sewing Boundary:\n"); - - int count = 0; - int sewnCount = 0; - - Edge * edge = startEdge; - do { - nvDebugCheck(edge->face == NULL); - - Edge * edge_a = edge; - Edge * edge_b = edge->prev; - - Edge * pair_a = edge_a->pair; - Edge * pair_b = edge_b->pair; - - Vertex * v0a = edge_a->to(); - Vertex * v0b = edge_b->from(); - Vertex * v1a = edge_a->from(); - Vertex * v1b = edge_b->to(); - - nvDebugCheck(v1a->isColocal(v1b)); - - /* - v0b + _+ v0a - \ / - b \ / a - \|/ - v1b + v1a - */ - - // @@ This should not happen while sewing, but it may be produced somewhere else. - nvDebugCheck(edge_a != edge_b); - - if (v0a->pos == v0b->pos) { - - // Link vertices. - v0a->linkColocal(v0b); - - // Remove edges to be collapsed. - disconnect(edge_a); - disconnect(edge_b); - disconnect(pair_a); - disconnect(pair_b); - - // Link new boundary edges. - Edge * prevBoundary = edge_b->prev; - Edge * nextBoundary = edge_a->next; - if (nextBoundary != NULL) { - nvDebugCheck(nextBoundary->face == NULL); - nvDebugCheck(prevBoundary->face == NULL); - nextBoundary->setPrev(prevBoundary); - - // Make sure boundary vertex points to boundary edge. - v0a->setEdge(nextBoundary); // This updates all colocals. - } - lastBoundarySeen = prevBoundary; - - // Creat new edge. - Edge * newEdge_a = addEdge(v0a->id, v1a->id); // pair_a->from()->id, pair_a->to()->id - Edge * newEdge_b = addEdge(v1b->id, v0b->id); - - newEdge_a->pair = newEdge_b; - newEdge_b->pair = newEdge_a; - - newEdge_a->face = pair_a->face; - newEdge_b->face = pair_b->face; - - newEdge_a->setNext(pair_a->next); - newEdge_a->setPrev(pair_a->prev); - - newEdge_b->setNext(pair_b->next); - newEdge_b->setPrev(pair_b->prev); - - delete edge_a; - delete edge_b; - delete pair_a; - delete pair_b; - - edge = nextBoundary; // If nextBoundary is NULL we have closed the loop. - sewnCount++; - } - else { - edge = edge->next; - } - - count++; - } while(edge != NULL && edge != lastBoundarySeen); - - nvDebug(" - Sewn %d out of %d.\n", sewnCount, count); - - if (lastBoundarySeen != NULL) { - nvDebugCheck(lastBoundarySeen->face == NULL); - } - - return lastBoundarySeen; -} - - -// @@ We must always disconnect edge pairs simultaneously. -void Mesh::disconnect(Edge * edge) { - nvDebugCheck(edge != NULL); - - // Remove from edge list. - if ((edge->id & 1) == 0) { - nvDebugCheck(m_edgeArray[edge->id / 2] == edge); - m_edgeArray[edge->id / 2] = NULL; - } - - // Remove edge from map. @@ Store map key inside edge? - nvDebugCheck(edge->from() != NULL && edge->to() != NULL); - bool removed = m_edgeMap.remove(Key(edge->from()->id, edge->to()->id)); - nvDebugCheck(removed == true); - - // Disconnect from vertex. - if (edge->vertex != NULL) { - if (edge->vertex->edge == edge) { - if (edge->prev && edge->prev->pair) { - edge->vertex->edge = edge->prev->pair; - } - else if (edge->pair && edge->pair->next) { - edge->vertex->edge = edge->pair->next; - } - else { - edge->vertex->edge = NULL; - // @@ Remove disconnected vertex? - } - } - //edge->setVertex(NULL); - } - - // Disconnect from face. - if (edge->face != NULL) { - if (edge->face->edge == edge) { - if (edge->next != NULL && edge->next != edge) { - edge->face->edge = edge->next; - } - else if (edge->prev != NULL && edge->prev != edge) { - edge->face->edge = edge->prev; - } - else { - edge->face->edge = NULL; - // @@ Remove disconnected face? - } - } - //edge->setFace(NULL); - } - - // @@ Hack, we don't disconnect from pair, because pair needs us to remove itself from the map. - // Disconect from pair. - /*if (edge->pair != NULL) { - if (edge->pair->pair == edge) { - edge->pair->setPair(NULL); - } - //edge->setPair(NULL); - }*/ - - // Disconnect from previous. - if (edge->prev) { - if (edge->prev->next == edge) { - edge->prev->setNext(NULL); - } - //edge->setPrev(NULL); - } - - // Disconnect from next. - if (edge->next) { - if (edge->next->prev == edge) { - edge->next->setPrev(NULL); - } - //edge->setNext(NULL); - } -} - - -void Mesh::remove(Edge * edge) { - nvDebugCheck(edge != NULL); - - disconnect(edge); - - delete edge; -} - -void Mesh::remove(Vertex * vertex) { - nvDebugCheck(vertex != NULL); - - // Remove from vertex list. - m_vertexArray[vertex->id] = NULL; - - // Disconnect from colocals. - vertex->unlinkColocal(); - - // Disconnect from edges. - if (vertex->edge != NULL) { - // @@ Removing a connected vertex is asking for trouble... - if (vertex->edge->vertex == vertex) { - // @@ Connect edge to a colocal? - vertex->edge->vertex = NULL; - } - - vertex->setEdge(NULL); - } - - delete vertex; -} - -void Mesh::remove(Face * face) { - nvDebugCheck(face != NULL); - - // Remove from face list. - m_faceArray[face->id] = NULL; - - // Disconnect from edges. - if (face->edge != NULL) { - nvDebugCheck(face->edge->face == face); - - face->edge->face = NULL; - - face->edge = NULL; - } - - delete face; -} - - -void Mesh::compactEdges() { - const uint edgeCount = m_edgeArray.count(); - - uint c = 0; - for (uint i = 0; i < edgeCount; i++) { - if (m_edgeArray[i] != NULL) { - if (i != c) { - m_edgeArray[c] = m_edgeArray[i]; - m_edgeArray[c]->id = 2 * c; - if (m_edgeArray[c]->pair != NULL) { - m_edgeArray[c]->pair->id = 2 * c + 1; - } - } - c++; - } - } - - m_edgeArray.resize(c); -} - - -void Mesh::compactVertices() { - const uint vertexCount = m_vertexArray.count(); - - uint c = 0; - for (uint i = 0; i < vertexCount; i++) { - if (m_vertexArray[i] != NULL) { - if (i != c) { - m_vertexArray[c] = m_vertexArray[i]; - m_vertexArray[c]->id = c; - } - c++; - } - } - - m_vertexArray.resize(c); - - // @@ Generate xref array for external attributes. -} - - -void Mesh::compactFaces() { - const uint faceCount = m_faceArray.count(); - - uint c = 0; - for (uint i = 0; i < faceCount; i++) { - if (m_faceArray[i] != NULL) { - if (i != c) { - m_faceArray[c] = m_faceArray[i]; - m_faceArray[c]->id = c; - } - c++; - } - } - - m_faceArray.resize(c); -} - - -Vertex * Mesh::splitBoundaryEdge(Edge * edge, float t, const Vector3 & pos) { - - /* - We want to go from this configuration: - - + + - | ^ - edge |<->| pair - v | - + + - - To this one: - - + + - | ^ - e0 |<->| p0 - v | - vertex + + - | ^ - e1 |<->| p1 - v | - + + - - */ - - - Edge * pair = edge->pair; - - // Make sure boundaries are linked. - nvDebugCheck(pair != NULL); - - // Make sure edge is a boundary edge. - nvDebugCheck(pair->face == NULL); - - // Add new vertex. - Vertex * vertex = addVertex(pos); - vertex->nor = lerp(edge->from()->nor, edge->to()->nor, t); - vertex->tex = lerp(edge->from()->tex, edge->to()->tex, t); - vertex->col = lerp(edge->from()->col, edge->to()->col, t); - - disconnect(edge); - disconnect(pair); - - // Add edges. - Edge * e0 = addEdge(edge->from()->id, vertex->id); - Edge * p0 = addEdge(vertex->id, pair->to()->id); - - Edge * e1 = addEdge(vertex->id, edge->to()->id); - Edge * p1 = addEdge(pair->from()->id, vertex->id); - - // Link edges. - e0->setNext(e1); - p1->setNext(p0); - - e0->setPrev(edge->prev); - e1->setNext(edge->next); - - p1->setPrev(pair->prev); - p0->setNext(pair->next); - - nvDebugCheck(e0->next == e1); - nvDebugCheck(e1->prev == e0); - - nvDebugCheck(p1->next == p0); - nvDebugCheck(p0->prev == p1); - - nvDebugCheck(p0->pair == e0); - nvDebugCheck(e0->pair == p0); - - nvDebugCheck(p1->pair == e1); - nvDebugCheck(e1->pair == p1); - - // Link faces. - e0->face = edge->face; - e1->face = edge->face; - - // Link vertices. - edge->from()->setEdge(e0); - vertex->setEdge(e1); - - delete edge; - delete pair; - - return vertex; -} - -#if 0 -// Without introducing new vertices. -void Mesh::splitBoundaryEdge(Edge * edge, Vertex * vertex) { - - /* - We want to go from this configuration: - - | | pn - + + - | ^ - | | - edge |<->| pair - | | - v | - + + - | | pp - - To this one: - \ / - \ / - + + - | ^ - e0 |<->| p0 - v | - vertex + + - | ^ - e1 |<->| p1 - v | - + + - / \ - / \ - */ - - - Edge * pair = edge->pair; - Edge * pn = pair->next(); - Edge * pp = pair->prev(); - - // Make sure boundaries are linked. - nvDebugCheck(pair != NULL); - - // Make sure edge is a boundary edge. - nvDebugCheck(pair->face() == NULL); - - nvDebugCheck(edge->isValid()); - nvDebugCheck(pair->isValid()); - - disconnect(edge); - disconnect(pair); - - // Add edges. - Edge * e0 = addEdge(edge->from()->id(), vertex->id()); - Edge * e1 = addEdge(vertex->id(), edge->to()->id()); - - // Link faces. - e0->setFace(edge->face()); - e1->setFace(edge->face()); - - // Link pairs. - Edge * p0 = findEdge(vertex->id(), pair->to()->id()); - if (p0 == NULL) { - p0 = addEdge(vertex->id(), pair->to()->id()); - pn->setPrev(p0); - } - else { - nvDebugCheck(p0->face() != NULL); - if (e0->prev() != NULL) { - pn->setPrev(e0->prev()); - } - else { - nvDebugCheck(pn == e0); - } - } - - Edge * p1 = findEdge(pair->from()->id(), vertex->id()); - if (p1 == NULL) { - p1 = addEdge(pair->from()->id(), vertex->id()); - pp->setNext(p1); - } - else { - nvDebugCheck(p1->face() != NULL); - if (e1->next() != NULL) { - pp->setPrev(e1->next()); - } - else { - nvDebugCheck(pp == e1); - } - } - - // Link edges. - e0->setNext(e1); // e1->setPrev(e0) - - if (p0->face() == p1->face()) { // can be null - p1->setNext(p0); // p0->setPrev(p1) - } - else { - //if (p1->face() == NULL) p1->setNext( - } - - - e0->setPrev(edge->prev()); - e1->setNext(edge->next()); - - nvDebugCheck(e0->pair == p0); - nvDebugCheck(e1->pair == p1); - nvDebugCheck(p0->pair == e0); - nvDebugCheck(p1->pair == e1); - - nvDebugCheck(e0->isValid()); - nvDebugCheck(e1->isValid()); - nvDebugCheck(pp->isValid()); - nvDebugCheck(pn->isValid()); - - nvDebugCheck(e0->pair->isValid()); - nvDebugCheck(e1->pair->isValid()); - nvDebugCheck(pp->pair->isValid()); - nvDebugCheck(pn->pair->isValid()); - - nvDebugCheck(edge->face->isValid()); - - if (pn->pair->face != NULL) { - nvDebugCheck(pn->pair->face->isValid()); - } - - if (pp->pair->face() != NULL) { - nvDebugCheck(pn->pair->face->isValid()); - } - - if (p0->face != NULL) { - nvDebugCheck(p0->face->isValid()); - } - - if (p1->face() != NULL) { - nvDebugCheck(p1->face()->isValid()); - } - - nvDebugCheck(isValid()); // Only for extreme debugging. - - // Link vertices. - edge->from()->setEdge(e0); - vertex->setEdge(p0); - - delete edge; - delete pair; -} -#endif - -bool Mesh::isValid() const -{ - // Make sure all edges are valid. - const uint edgeCount = m_edgeArray.count(); - for (uint e = 0; e < edgeCount; e++) { - Edge * edge = m_edgeArray[e]; - if (edge != NULL) { - if (edge->id != 2*e) { - return false; - } - if (!edge->isValid()) { - return false; - } - - if (edge->pair->id != 2*e+1) { - return false; - } - if (!edge->pair->isValid()) { - return false; - } - } - } - - // @@ Make sure all faces are valid. - - // @@ Make sure all vertices are valid. - - return true; -} diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h deleted file mode 100644 index c202c2ef9a..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Mesh.h +++ /dev/null @@ -1,274 +0,0 @@ -// This code is in the public domain -- castanyo@yahoo.es - -#pragma once -#ifndef NV_MESH_HALFEDGE_MESH_H -#define NV_MESH_HALFEDGE_MESH_H - -#include "nvmesh/nvmesh.h" -#include "nvcore/Array.h" -#include "nvcore/HashMap.h" - -/* -If I were to redo this again, there are a number of things that I would do differently. -- Edge map is only useful when importing a mesh to guarantee the result is two-manifold. However, when manipulating the mesh - it's a pain to maintain the map up to date. -- Edge array only points to the even vertices. There's no good reason for that. The map becomes required to traverse all edges - or you have to make sure edges are properly paired. -- Linked boundaries. It's cleaner to assume a NULL pair means a boundary edge. Makes easier to seal boundaries. The only reason - why we link boundaries is to simplify traversal, but that could be done with two helper functions (nextBoundary, prevBoundary). -- Minimize the amount of state that needs to be set in a certain way: - - boundary vertices point to boundary edge. -- Remove parenthesis! Make some members public. -- Remove member functions with side effects: - - e->setNext(n) modifies e->next and n->prev, instead use "link(e, n)", or "e->next = n, n->prev = e" -*/ - - -namespace nv -{ - class Vector3; - class TriMesh; - class QuadTriMesh; - //template <typename T> struct Hash<Mesh::Key>; - - namespace HalfEdge - { - class Edge; - class Face; - class Vertex; - - /// Simple half edge mesh designed for dynamic mesh manipulation. - class Mesh - { - public: - - Mesh(); - Mesh(const Mesh * mesh); - ~Mesh(); - - void clear(); - - Vertex * addVertex(const Vector3 & pos); - //Vertex * addVertex(uint id, const Vector3 & pos); - //void addVertices(const Mesh * mesh); - - void linkColocals(); - void linkColocalsWithCanonicalMap(const Array<uint> & canonicalMap); - void resetColocalLinks(); - - Face * addFace(); - Face * addFace(uint v0, uint v1, uint v2); - Face * addFace(uint v0, uint v1, uint v2, uint v3); - Face * addFace(const Array<uint> & indexArray); - Face * addFace(const Array<uint> & indexArray, uint first, uint num); - //void addFaces(const Mesh * mesh); - - // These functions disconnect the given element from the mesh and delete it. - void disconnect(Edge * edge); - void disconnectPair(Edge * edge); - void disconnect(Vertex * vertex); - void disconnect(Face * face); - - void remove(Edge * edge); - void remove(Vertex * vertex); - void remove(Face * face); - - // Remove holes from arrays and reassign indices. - void compactEdges(); - void compactVertices(); - void compactFaces(); - - void triangulate(); - - void linkBoundary(); - - bool splitBoundaryEdges(); // Returns true if any split was made. - - // Sew the boundary that starts at the given edge, returns one edge that still belongs to boundary, or NULL if boundary closed. - HalfEdge::Edge * sewBoundary(Edge * startEdge); - - - // Vertices - uint vertexCount() const { return m_vertexArray.count(); } - const Vertex * vertexAt(int i) const { return m_vertexArray[i]; } - Vertex * vertexAt(int i) { return m_vertexArray[i]; } - - uint colocalVertexCount() const { return m_colocalVertexCount; } - - // Faces - uint faceCount() const { return m_faceArray.count(); } - const Face * faceAt(int i) const { return m_faceArray[i]; } - Face * faceAt(int i) { return m_faceArray[i]; } - - // Edges - uint edgeCount() const { return m_edgeArray.count(); } - const Edge * edgeAt(int i) const { return m_edgeArray[i]; } - Edge * edgeAt(int i) { return m_edgeArray[i]; } - - class ConstVertexIterator; - - class VertexIterator - { - friend class ConstVertexIterator; - public: - VertexIterator(Mesh * mesh) : m_mesh(mesh), m_current(0) { } - - virtual void advance() { m_current++; } - virtual bool isDone() const { return m_current == m_mesh->vertexCount(); } - virtual Vertex * current() const { return m_mesh->vertexAt(m_current); } - - private: - HalfEdge::Mesh * m_mesh; - uint m_current; - }; - VertexIterator vertices() { return VertexIterator(this); } - - class ConstVertexIterator - { - public: - ConstVertexIterator(const Mesh * mesh) : m_mesh(mesh), m_current(0) { } - ConstVertexIterator(class VertexIterator & it) : m_mesh(it.m_mesh), m_current(it.m_current) { } - - virtual void advance() { m_current++; } - virtual bool isDone() const { return m_current == m_mesh->vertexCount(); } - virtual const Vertex * current() const { return m_mesh->vertexAt(m_current); } - - private: - const HalfEdge::Mesh * m_mesh; - uint m_current; - }; - ConstVertexIterator vertices() const { return ConstVertexIterator(this); } - - class ConstFaceIterator; - - class FaceIterator - { - friend class ConstFaceIterator; - public: - FaceIterator(Mesh * mesh) : m_mesh(mesh), m_current(0) { } - - virtual void advance() { m_current++; } - virtual bool isDone() const { return m_current == m_mesh->faceCount(); } - virtual Face * current() const { return m_mesh->faceAt(m_current); } - - private: - HalfEdge::Mesh * m_mesh; - uint m_current; - }; - FaceIterator faces() { return FaceIterator(this); } - - class ConstFaceIterator - { - public: - ConstFaceIterator(const Mesh * mesh) : m_mesh(mesh), m_current(0) { } - ConstFaceIterator(const FaceIterator & it) : m_mesh(it.m_mesh), m_current(it.m_current) { } - - virtual void advance() { m_current++; } - virtual bool isDone() const { return m_current == m_mesh->faceCount(); } - virtual const Face * current() const { return m_mesh->faceAt(m_current); } - - private: - const HalfEdge::Mesh * m_mesh; - uint m_current; - }; - ConstFaceIterator faces() const { return ConstFaceIterator(this); } - - class ConstEdgeIterator; - - class EdgeIterator - { - friend class ConstEdgeIterator; - public: - EdgeIterator(Mesh * mesh) : m_mesh(mesh), m_current(0) { } - - virtual void advance() { m_current++; } - virtual bool isDone() const { return m_current == m_mesh->edgeCount(); } - virtual Edge * current() const { return m_mesh->edgeAt(m_current); } - - private: - HalfEdge::Mesh * m_mesh; - uint m_current; - }; - EdgeIterator edges() { return EdgeIterator(this); } - - class ConstEdgeIterator - { - public: - ConstEdgeIterator(const Mesh * mesh) : m_mesh(mesh), m_current(0) { } - ConstEdgeIterator(const EdgeIterator & it) : m_mesh(it.m_mesh), m_current(it.m_current) { } - - virtual void advance() { m_current++; } - virtual bool isDone() const { return m_current == m_mesh->edgeCount(); } - virtual const Edge * current() const { return m_mesh->edgeAt(m_current); } - - private: - const HalfEdge::Mesh * m_mesh; - uint m_current; - }; - ConstEdgeIterator edges() const { return ConstEdgeIterator(this); } - - // @@ Add half-edge iterator. - - - - // Convert to tri mesh. - TriMesh * toTriMesh() const; - QuadTriMesh * toQuadTriMesh() const; - - bool isValid() const; - - public: - - // Error status: - mutable uint errorCount; - mutable uint errorIndex0; - mutable uint errorIndex1; - - private: - - bool canAddFace(const Array<uint> & indexArray, uint first, uint num) const; - bool canAddEdge(uint i, uint j) const; - Edge * addEdge(uint i, uint j); - - Edge * findEdge(uint i, uint j) const; - - void linkBoundaryEdge(Edge * edge); - Vertex * splitBoundaryEdge(Edge * edge, float t, const Vector3 & pos); - void splitBoundaryEdge(Edge * edge, Vertex * vertex); - - private: - - Array<Vertex *> m_vertexArray; - Array<Edge *> m_edgeArray; - Array<Face *> m_faceArray; - - struct Key { - Key() {} - Key(const Key & k) : p0(k.p0), p1(k.p1) {} - Key(uint v0, uint v1) : p0(v0), p1(v1) {} - void operator=(const Key & k) { p0 = k.p0; p1 = k.p1; } - bool operator==(const Key & k) const { return p0 == k.p0 && p1 == k.p1; } - - uint p0; - uint p1; - }; - friend struct Hash<Mesh::Key>; - - HashMap<Key, Edge *> m_edgeMap; - - uint m_colocalVertexCount; - - }; - /* - // This is a much better hash than the default and greatly improves performance! - template <> struct hash<Mesh::Key> - { - uint operator()(const Mesh::Key & k) const { return k.p0 + k.p1; } - }; - */ - - } // HalfEdge namespace - -} // nv namespace - -#endif // NV_MESH_HALFEDGE_MESH_H diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp b/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp deleted file mode 100644 index 66dad69f8a..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// This code is in the public domain -- castano@gmail.com - -#include "nvmesh.h" // pch - -#include "Vertex.h" - -#include "nvmath/Vector.inl" - -using namespace nv; -using namespace HalfEdge; - - -// Set first edge of all colocals. -void Vertex::setEdge(Edge * e) -{ - for (VertexIterator it(colocals()); !it.isDone(); it.advance()) { - it.current()->edge = e; - } -} - -// Update position of all colocals. -void Vertex::setPos(const Vector3 & p) -{ - for (VertexIterator it(colocals()); !it.isDone(); it.advance()) { - it.current()->pos = p; - } -} - - -uint HalfEdge::Vertex::colocalCount() const -{ - uint count = 0; - for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) { ++count; } - return count; -} - -uint HalfEdge::Vertex::valence() const -{ - uint count = 0; - for (ConstEdgeIterator it(edges()); !it.isDone(); it.advance()) { ++count; } - return count; -} - -const HalfEdge::Vertex * HalfEdge::Vertex::firstColocal() const -{ - uint firstId = id; - const Vertex * vertex = this; - - for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) - { - if (it.current()->id < firstId) { - firstId = vertex->id; - vertex = it.current(); - } - } - - return vertex; -} - -HalfEdge::Vertex * HalfEdge::Vertex::firstColocal() -{ - Vertex * vertex = this; - uint firstId = id; - - for (VertexIterator it(colocals()); !it.isDone(); it.advance()) - { - if (it.current()->id < firstId) { - firstId = vertex->id; - vertex = it.current(); - } - } - - return vertex; -} - -bool HalfEdge::Vertex::isFirstColocal() const -{ - return firstColocal() == this; -} - -bool HalfEdge::Vertex::isColocal(const Vertex * v) const { - if (this == v) return true; - if (pos != v->pos) return false; - - for (ConstVertexIterator it(colocals()); !it.isDone(); it.advance()) - { - if (v == it.current()) { - return true; - } - } - - return false; -} - diff --git a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h b/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h deleted file mode 100644 index 1c5c8d7141..0000000000 --- a/thirdparty/thekla_atlas/nvmesh/halfedge/Vertex.h +++ /dev/null @@ -1,221 +0,0 @@ -// This code is in the public domain -- castanyo@yahoo.es - -#pragma once -#ifndef NV_MESH_HALFEDGE_VERTEX_H -#define NV_MESH_HALFEDGE_VERTEX_H - -#include "nvmesh/halfedge/Edge.h" - -namespace nv -{ - namespace HalfEdge { class Vertex; class Face; class Edge; } - - // Half edge vertex. - class HalfEdge::Vertex - { - NV_FORBID_COPY(Vertex); - public: - - uint id; - - Edge * edge; - Vertex * next; - Vertex * prev; - - Vector3 pos; - Vector3 nor; - Vector2 tex; - Vector4 col; - - - Vertex(uint id) : id(id), edge(NULL), pos(0.0f), nor(0.0f), tex(0.0f), col(0.0f) { - next = this; - prev = this; - } - - - void setEdge(Edge * e); - void setPos(const Vector3 & p); - - uint colocalCount() const; - uint valence() const; - bool isFirstColocal() const; - const Vertex * firstColocal() const; - Vertex * firstColocal(); - - bool isColocal(const Vertex * v) const; - - - void linkColocal(Vertex * v) { - next->prev = v; - v->next = next; - next = v; - v->prev = this; - } - void unlinkColocal() { - next->prev = prev; - prev->next = next; - next = this; - prev = this; - } - - - // @@ Note: This only works if linkBoundary has been called. - bool isBoundary() const { - return (edge && !edge->face); - } - - - // for(EdgeIterator it(iterator()); !it.isDone(); it.advance()) { ... } - // - // EdgeIterator it(iterator()); - // while(!it.isDone()) { - // ... - // id.advance(); - // } - - // Iterator that visits the edges around this vertex in counterclockwise order. - class EdgeIterator //: public Iterator<Edge *> - { - public: - EdgeIterator(Edge * e) : m_end(NULL), m_current(e) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->pair->next; - //m_current = m_current->prev->pair; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual Edge * current() const { return m_current; } - Vertex * vertex() const { return m_current->vertex; } - - private: - Edge * m_end; - Edge * m_current; - }; - - EdgeIterator edges() { return EdgeIterator(edge); } - EdgeIterator edges(Edge * e) { return EdgeIterator(e); } - - // Iterator that visits the edges around this vertex in counterclockwise order. - class ConstEdgeIterator //: public Iterator<Edge *> - { - public: - ConstEdgeIterator(const Edge * e) : m_end(NULL), m_current(e) { } - ConstEdgeIterator(EdgeIterator it) : m_end(NULL), m_current(it.current()) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->pair->next; - //m_current = m_current->prev->pair; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual const Edge * current() const { return m_current; } - const Vertex * vertex() const { return m_current->to(); } - - private: - const Edge * m_end; - const Edge * m_current; - }; - - ConstEdgeIterator edges() const { return ConstEdgeIterator(edge); } - ConstEdgeIterator edges(const Edge * e) const { return ConstEdgeIterator(e); } - - - // Iterator that visits the edges around this vertex in counterclockwise order. - class ReverseEdgeIterator //: public Iterator<Edge *> - { - public: - ReverseEdgeIterator(Edge * e) : m_end(NULL), m_current(e) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->prev->pair; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual Edge * current() const { return m_current; } - Vertex * vertex() const { return m_current->vertex; } - - private: - Edge * m_end; - Edge * m_current; - }; - - // Iterator that visits the edges around this vertex in counterclockwise order. - class ReverseConstEdgeIterator //: public Iterator<Edge *> - { - public: - ReverseConstEdgeIterator(const Edge * e) : m_end(NULL), m_current(e) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->prev->pair; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual const Edge * current() const { return m_current; } - const Vertex * vertex() const { return m_current->to(); } - - private: - const Edge * m_end; - const Edge * m_current; - }; - - - - // Iterator that visits all the colocal vertices. - class VertexIterator //: public Iterator<Edge *> - { - public: - VertexIterator(Vertex * v) : m_end(NULL), m_current(v) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->next; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual Vertex * current() const { return m_current; } - - private: - Vertex * m_end; - Vertex * m_current; - }; - - VertexIterator colocals() { return VertexIterator(this); } - - // Iterator that visits all the colocal vertices. - class ConstVertexIterator //: public Iterator<Edge *> - { - public: - ConstVertexIterator(const Vertex * v) : m_end(NULL), m_current(v) { } - - virtual void advance() - { - if (m_end == NULL) m_end = m_current; - m_current = m_current->next; - } - - virtual bool isDone() const { return m_end == m_current; } - virtual const Vertex * current() const { return m_current; } - - private: - const Vertex * m_end; - const Vertex * m_current; - }; - - ConstVertexIterator colocals() const { return ConstVertexIterator(this); } - - }; - -} // nv namespace - -#endif // NV_MESH_HALFEDGE_VERTEX_H |