cVECTOR3 tFACET<_Mesh_Entities>::Normal() const { /* BB * I don't see any division by zero. */ cVECTOR3 planeNormal(0.0, 0.0, 0.0); const cHALF_EDGE* heInit = HalfEdge(); const cHALF_EDGE* heCurr = heInit; const cHALF_EDGE* heNext = heCurr->Next(); do { const cPOINT3& point0 = heCurr->Vertex()->Point(); const cPOINT3& point1 = heNext->Vertex()->Point(); for (INT i = 0 ; i < 3; i++){ INT i1 = i + 1; if (i1 > 2) i1 -= 3; INT i2 = i + 2; if (i2 > 2) i2 -= 3; planeNormal[i] += (point0[i1]-point1[i1])*(point0[i2]+point1[i2]); } heCurr = heNext; heNext = heNext->Next(); } while(heCurr != heInit); return planeNormal; }
cBOX3 tFACET<_Mesh_Entities>::BoundingBox() const { cBOX3 boundingBox; const cHALF_EDGE* currHe = HalfEdge(); const cHALF_EDGE* facetHe = currHe; do { boundingBox += currHe->Vertex()->Point(); currHe = currHe->Next(); } while(currHe != facetHe); return boundingBox; }
bool MeshBuilder::buildMesh(const MeshData& data, Mesh& mesh) { std::map<std::pair<int, int>, int> edgeCount; std::map<std::pair<int, int>, HalfEdgeIter> existingHalfEdges; std::map<int, VertexIter> indexToVertex; std::map<HalfEdgeIter, bool> hasFlipEdge; preallocateMeshElements(data, mesh); // insert vertices into mesh and map vertex indices to vertex pointers for (unsigned int i = 0; i < data.positions.size(); i++) { VertexIter vertex = mesh.vertices.insert(mesh.vertices.end(), Vertex()); vertex->position = data.positions[i]; vertex->he = isolated.begin(); indexToVertex[i] = vertex; } // insert uvs into mesh for (unsigned int i = 0; i < data.uvs.size(); i++) { VectorIter uv = mesh.uvs.insert(mesh.uvs.end(), Eigen::Vector3d()); *uv = data.uvs[i]; } // insert normals into mesh for (unsigned int i = 0; i < data.normals.size(); i++) { VectorIter normal = mesh.normals.insert(mesh.normals.end(), Eigen::Vector3d()); *normal = data.normals[i]; } // insert faces into mesh int faceIndex = 0; bool degenerateFaces = false; for (std::vector<std::vector<Index>>::const_iterator f = data.indices.begin(); f != data.indices.end(); f ++) { int n = (int)f->size(); // check if face is degenerate if (n < 3) { std::cerr << "Error: face " << faceIndex << " is degenerate" << std::endl; degenerateFaces = true; continue; } // create face FaceIter newFace = mesh.faces.insert(mesh.faces.end(), Face()); // create a halfedge for each edge of the face std::vector<HalfEdgeIter> halfEdges(n); for (int i = 0; i < n; i++) { halfEdges[i] = mesh.halfEdges.insert(mesh.halfEdges.end(), HalfEdge()); } // initialize the halfedges for (int i = 0; i < n; i++) { // vertex indices int a = (*f)[i].position; int b = (*f)[(i+1)%n].position; // set halfedge attributes halfEdges[i]->next = halfEdges[(i+1)%n]; halfEdges[i]->vertex = indexToVertex[a]; int uv = (*f)[i].uv; if (uv >= 0) halfEdges[i]->uv = data.uvs[uv]; else halfEdges[i]->uv.setZero(); int normal = (*f)[i].normal; if (normal >= 0) halfEdges[i]->normal = data.normals[normal]; else halfEdges[i]->normal.setZero(); halfEdges[i]->onBoundary = false; // keep track of which halfedges have flip edges defined (for deteting boundaries) hasFlipEdge[halfEdges[i]] = false; // point vertex a at the current halfedge indexToVertex[a]->he = halfEdges[i]; // point new face and halfedge to each other halfEdges[i]->face = newFace; newFace->he = halfEdges[i]; // if an edge between a and b has been created in the past, it is the flip edge of the current halfedge if (a > b) std::swap(a, b); if (existingHalfEdges.find(std::pair<int, int>(a, b)) != existingHalfEdges.end()) { halfEdges[i]->flip = existingHalfEdges[std::pair<int, int>(a, b)]; halfEdges[i]->flip->flip = halfEdges[i]; halfEdges[i]->edge = halfEdges[i]->flip->edge; hasFlipEdge[halfEdges[i]] = true; hasFlipEdge[halfEdges[i]->flip] = true; } else { // create an edge and set its halfedge halfEdges[i]->edge = mesh.edges.insert(mesh.edges.end(), Edge()); halfEdges[i]->edge->he = halfEdges[i]; edgeCount[std::pair<int, int>(a, b)] = 0; } // record that halfedge has been created from a to b existingHalfEdges[std::pair<int, int>(a, b)] = halfEdges[i]; // check for nonmanifold edges edgeCount[std::pair<int, int>(a, b)] ++; if (edgeCount[std::pair<int, int>(a, b)] > 2) { std::cerr << "Error: edge " << a << ", " << b << " is non manifold" << std::endl; return false; } } faceIndex++; } if (degenerateFaces) { return false; } // insert extra faces for boundary cycle for (HalfEdgeIter currHe = mesh.halfEdges.begin(); currHe != mesh.halfEdges.end(); currHe++) { // if a halfedge with no flip edge is found, create a new face and link it the corresponding boundary cycle if (!hasFlipEdge[currHe]) { // create face FaceIter newFace = mesh.faces.insert(mesh.faces.end(), Face()); // walk along boundary cycle std::vector<HalfEdgeIter> boundaryCycle; HalfEdgeIter he = currHe; do { // create a new halfedge on the boundary face HalfEdgeIter newHe = mesh.halfEdges.insert(mesh.halfEdges.end(), HalfEdge()); newHe->onBoundary = true; // link the current halfedge in the cycle to its new flip edge he->flip = newHe; // grab the next halfedge along the boundary by finding // the next halfedge around the current vertex that doesn't // have a flip edge defined HalfEdgeIter nextHe = he->next; while (hasFlipEdge[nextHe]) { nextHe = nextHe->flip->next; } // set attritubes for new halfedge newHe->flip = he; newHe->vertex = nextHe->vertex; newHe->edge = he->edge; newHe->face = newFace; newHe->uv = nextHe->uv; // set face's halfedge to boundary halfedge newFace->he = newHe; boundaryCycle.push_back(newHe); // continue walk along cycle he = nextHe; } while (he != currHe); // link the cycle of boundary halfedges together int n = (int)boundaryCycle.size(); for (int i = 0; i < n; i++) { boundaryCycle[i]->next = boundaryCycle[(i+n-1)%n]; hasFlipEdge[boundaryCycle[i]] = true; hasFlipEdge[boundaryCycle[i]->flip] = true; } mesh.boundaries.insert(mesh.boundaries.end(), boundaryCycle[0]); } } indexVertices(mesh); checkIsolatedVertices(mesh); checkNonManifoldVertices(mesh); return true; }