/** * Exports a BOP_Mesh to a BSP_CSGMesh. * @param mesh Input mesh * @param invert if TRUE export with inverted faces, no inverted otherwise * @return the corresponding new BSP_CSGMesh */ BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* mesh, bool invert) { BSP_CSGMesh* outputMesh = BOP_newEmptyMesh(); if (outputMesh == NULL) return NULL; // vtx index dictionary, to translate indeces from input to output. map<int,unsigned int> dic; map<int,unsigned int>::iterator itDic; unsigned int count = 0; // Add a new face for each face in the input list BOP_Faces faces = mesh->getFaces(); BOP_Vertexs vertexs = mesh->getVertexs(); for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) { if ((*face)->getTAG()!=BROKEN){ // Add output face outputMesh->FaceSet().push_back(BSP_MFace()); BSP_MFace& outFace = outputMesh->FaceSet().back(); // Copy face outFace.m_verts.clear(); outFace.m_plane = (*face)->getPlane(); outFace.m_orig_face = (*face)->getOriginalFace(); // invert face if is required if (invert) (*face)->invert(); // Add the face vertex if not added yet for (unsigned int pos=0;pos<(*face)->size();pos++) { BSP_VertexInd outVtxId; BOP_Index idVertex = (*face)->getVertex(pos); itDic = dic.find(idVertex); if (itDic == dic.end()) { // The vertex isn't added yet outVtxId = BSP_VertexInd(outputMesh->VertexSet().size()); BSP_MVertex outVtx((mesh->getVertex(idVertex))->getPoint()); outVtx.m_edges.clear(); outputMesh->VertexSet().push_back(outVtx); dic[idVertex] = outVtxId; count++; } else { // The vertex is added outVtxId = BSP_VertexInd(itDic->second); } outFace.m_verts.push_back(outVtxId); } } } // Build the mesh edges using topological informtion outputMesh->BuildEdges(); return outputMesh; }
/** * Simplifies the mesh, merging the pairs of triangles that come frome the * same original face and define a quad. * @return true if a quad was added, false otherwise */ bool BOP_Merge::createQuads() { BOP_Faces quads; // Get mesh faces BOP_Faces faces = m_mesh->getFaces(); // Merge mesh triangles const BOP_IT_Faces facesIEnd = (faces.end()-1); const BOP_IT_Faces facesJEnd = faces.end(); for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) { if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; // Test if both triangles share a vertex index BOP_Index v; bool found = false; for(unsigned int i=0;i<3 && !found;i++) { v = (*faceI)->getVertex(i); found = (*faceJ)->containsVertex(v); } if (!found) continue; BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ,v); if (faceK != NULL) { // Set triangles to BROKEN (*faceI)->setTAG(BROKEN); (*faceJ)->setTAG(BROKEN); quads.push_back(faceK); break; } } } // Add quads to mesh const BOP_IT_Faces quadsEnd = quads.end(); for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad); return (quads.size() > 0); }
void BOP_Merge2::mergeVertex(BOP_Faces &faces, BOP_Index v1, BOP_Index v2) { for(BOP_IT_Faces face=faces.begin();face!=faces.end();face++) { if( (*face)->size() == 3) mergeVertex((BOP_Face3 *) *face, v1, v2); else mergeVertex((BOP_Face4 *) *face, v1, v2); (*face)->setTAG(BROKEN); #ifdef BOP_DEBUG cout << " breaking " << (*face) << endl; #endif } }
/** * Simplifies the mesh, merging the pairs of triangles that come frome the * same original face and define a quad. * @return true if a quad was added, false otherwise */ bool BOP_Merge2::createQuads() { BOP_Faces quads; // Get mesh faces BOP_Faces faces = m_mesh->getFaces(); // Merge mesh triangles const BOP_IT_Faces facesIEnd = (faces.end()-1); const BOP_IT_Faces facesJEnd = faces.end(); for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) { #ifdef OLD_QUAD if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); if (faceK != NULL) { // Set triangles to BROKEN deleteFace(m_mesh, *faceI); deleteFace(m_mesh, *faceJ); #ifdef BOP_DEBUG cout << "createQuad: del " << *faceI << endl; cout << "createQuad: del " << *faceJ << endl; cout << "createQuad: add " << faceK << endl; #endif quads.push_back(faceK); break; } } #else if ((*faceI)->getTAG() == BROKEN ) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; BOP_Face *faceK = NULL; if((*faceI)->size() == 3) { if((*faceJ)->size() == 3) faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); else faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face4*)*faceJ); } else { if((*faceJ)->size() == 3) faceK = createQuad((BOP_Face3*)*faceJ,(BOP_Face4*)*faceI); else faceK = createQuad((BOP_Face4*)*faceI,(BOP_Face4*)*faceJ); } if (faceK != NULL) { // Set triangles to BROKEN deleteFace(m_mesh, *faceI); deleteFace(m_mesh, *faceJ); #ifdef BOP_DEBUG cout << "createQuad: del " << *faceI << endl; cout << "createQuad: del " << *faceJ << endl; cout << "createQuad: add " << faceK << endl; #endif quads.push_back(faceK); break; } } #endif } // Add quads to mesh const BOP_IT_Faces quadsEnd = quads.end(); for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad); return (quads.size() > 0); }
void dumpmesh ( BOP_Mesh *m, bool force ) { unsigned int nonmanifold = 0; { BOP_Edges edges = m->getEdges(); int count = 0; for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); ++count, ++edge) { if (!(*edge)->getUsed() && (*edge)->getFaces().size() == 0 ) continue; BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1()); BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2()); if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) { int fcount = 0; BOP_Indexs faces = (*edge)->getFaces(); for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) { BOP_Face *f = m->getFace(*face); if(f->getTAG()== UNCLASSIFIED) ++fcount; } if(fcount !=0 && fcount !=2 ) { ++nonmanifold; } } } if (!force && nonmanifold == 0) return; } if( nonmanifold ) cout << nonmanifold << " edges detected" << endl; #ifdef BOP_DEBUG cout << "---------------------------" << endl; BOP_Edges edges = m->getEdges(); int count = 0; for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); ++count, ++edge) { BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1()); BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2()); if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) { int fcount = 0; BOP_Indexs faces = (*edge)->getFaces(); cout << count << ", " << (*edge) << ", " << faces.size() << endl; for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) { BOP_Face *f = m->getFace(*face); if(f->getTAG()== UNCLASSIFIED) ++fcount; cout << " face " << f << endl; } if(fcount !=0 && fcount !=2 ) cout << " NON-MANIFOLD" << endl; } } BOP_Faces faces = m->getFaces(); count = 0; for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) { if( count < 12*2 || (*face)->getTAG() != BROKEN ) { cout << count << ", " << *face << endl; } ++count; } BOP_Vertexs verts = m->getVertexs(); count = 0; for (BOP_IT_Vertexs vert = verts.begin(); vert != verts.end(); vert++) { cout << count++ << ", " << *vert << " " << (*vert)->getNumEdges() << endl; BOP_Indexs edges = (*vert)->getEdges(); for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) { BOP_Edge *edge = m->getEdge(*it); cout << " " << edge << endl; } } cout << "===========================" << endl; #endif }
/** * Simplifies a mesh, merging the faces with the specified vertices. * @param mergeVertices vertices to test * @return true if a face merge was performed */ bool BOP_Merge::mergeFaces(BOP_Indexs &mergeVertices) { // Check size > 0! if (mergeVertices.size() == 0) return false; // New faces added by merge BOP_Faces newFaces; // Old faces removed by merge BOP_Faces oldFaces; // Get the first vertex index and add it to // the current pending vertices to merge BOP_Index v = mergeVertices[0]; BOP_Indexs pendingVertices; pendingVertices.push_back(v); // Get faces with index v that come from the same original face BOP_LFaces facesByOriginalFace; getFaces(facesByOriginalFace,v); bool merged = true; // Check it has any unbroken face if (facesByOriginalFace.size()==0) { // v has not any unbroken face (so it's a new BROKEN vertex) (m_mesh->getVertex(v))->setTAG(BROKEN); merged = false; } // Merge vertex faces const BOP_IT_LFaces facesEnd = facesByOriginalFace.end(); for(BOP_IT_LFaces facesByOriginalFaceX = facesByOriginalFace.begin(); (facesByOriginalFaceX != facesEnd)&&merged; facesByOriginalFaceX++) { merged = mergeFaces((*facesByOriginalFaceX),oldFaces,newFaces,pendingVertices,v); } // Check if the are some pendingVertices to merge if (pendingVertices.size() > 1 && merged) { // There are pending vertices that we need to merge in order to merge v ... for(unsigned int i=1;i<pendingVertices.size() && merged;i++) merged = mergeFaces(oldFaces,newFaces,pendingVertices,pendingVertices[i]); } // If merge was succesful ... if (merged) { // Set old faces to BROKEN... const BOP_IT_Faces oldFacesEnd = oldFaces.end(); for(BOP_IT_Faces face=oldFaces.begin();face!=oldFacesEnd;face++) (*face)->setTAG(BROKEN); // ... and add merged faces (that are the new merged faces without pending vertices) const BOP_IT_Faces newFacesEnd = newFaces.end(); for(BOP_IT_Faces newFace=newFaces.begin();newFace!=newFacesEnd;newFace++) { m_mesh->addFace(*newFace); // Also, add new face vertices to the queue of vertices to merge if they weren't for(BOP_Index i = 0;i<(*newFace)->size();i++) { BOP_Index vertexIndex = (*newFace)->getVertex(i); if (vertexIndex >= m_firstVertex && !containsIndex(mergeVertices,vertexIndex)) mergeVertices.push_back(vertexIndex); } } // Set the merged vertices to BROKEN ... const BOP_IT_Indexs pendingEnd = pendingVertices.end(); for(BOP_IT_Indexs pendingVertex = pendingVertices.begin(); pendingVertex != pendingEnd;pendingVertex++) { BOP_Index pV = *pendingVertex; m_mesh->getVertex(pV)->setTAG(BROKEN); // ... and remove them from mergeVertices queue const BOP_IT_Indexs mergeEnd = mergeVertices.end(); for(BOP_IT_Indexs mergeVertex = mergeVertices.begin(); mergeVertex != mergeEnd;mergeVertex++) { BOP_Index mV = *mergeVertex; if (mV == pV) { mergeVertices.erase(mergeVertex); break; } } } } else { // The merge was not succesful, remove the vertex frome merge vertices queue mergeVertices.erase(mergeVertices.begin()); // free the not used newfaces const BOP_IT_Faces newFacesEnd = newFaces.end(); for(BOP_IT_Faces newFace=newFaces.begin();newFace!=newFacesEnd;newFace++) { delete (*newFace); } } // Invoke mergeFaces and return the merge result return (mergeFaces(mergeVertices) || merged); }