/** * Removes faces from facesB that are overlapped with anyone from facesA. * @param mesh mesh that contains the faces, edges and vertices * @param facesA set of faces from object A * @param facesB set of faces from object B */ void BOP_removeOverlappedFaces(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB) { for(unsigned int i=0;i<facesA->size();i++) { BOP_Face *faceI = (*facesA)[i]; if (faceI->getTAG()==BROKEN) continue; bool overlapped = false; MT_Point3 p1 = mesh->getVertex(faceI->getVertex(0))->getPoint(); MT_Point3 p2 = mesh->getVertex(faceI->getVertex(1))->getPoint(); MT_Point3 p3 = mesh->getVertex(faceI->getVertex(2))->getPoint(); for(unsigned int j=0;j<facesB->size();) { BOP_Face *faceJ = (*facesB)[j]; if (faceJ->getTAG()!=BROKEN) { MT_Plane3 planeJ = faceJ->getPlane(); if (BOP_containsPoint(planeJ,p1) && BOP_containsPoint(planeJ,p2) && BOP_containsPoint(planeJ,p3)) { MT_Point3 q1 = mesh->getVertex(faceJ->getVertex(0))->getPoint(); MT_Point3 q2 = mesh->getVertex(faceJ->getVertex(1))->getPoint(); MT_Point3 q3 = mesh->getVertex(faceJ->getVertex(2))->getPoint(); if (BOP_overlap(MT_Vector3(planeJ.x(),planeJ.y(),planeJ.z()), p1,p2,p3,q1,q2,q3)) { facesB->erase(facesB->begin()+j,facesB->begin()+(j+1)); faceJ->setTAG(BROKEN); overlapped = true; } else j++; } else j++; }else j++; } if (overlapped) faceI->setTAG(OVERLAPPED); } }
/** * Returns a new quad (convex) from the merge of two triangles that share the * vertex index v. * @param faceI mesh triangle * @param faceJ mesh triangle * @param v vertex index shared by both triangles * @return a new convex quad if the merge is possible */ BOP_Face* BOP_Merge::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v) { BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, prevJ, nextJ; faceI->getNeighbours(v,prevI,nextI); faceJ->getNeighbours(v,prevJ,nextJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); // Quad test if (prevI == nextJ) { if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) && BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) { faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } } else if (nextI == prevJ) { if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) && BOP_convex(vertex,vNextJ,vNextI,vPrevI)) { faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } } return faceK; }
/** * Returns a new triangle from the merge of two triangles that share the vertex * v and come from the same original face. * @param faceI mesh triangle * @param faceJ mesh triangle * @param v vertex index shared by both triangles * @return If the merge is possible, a new triangle without v */ BOP_Face* BOP_Merge::mergeFaces(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v) { BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, prevJ, nextJ; faceI->getNeighbours(v,prevI,nextI); faceJ->getNeighbours(v,prevJ,nextJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); // Merge test if (prevI == nextJ) { // Both faces share the edge (prevI,v) == (v,nextJ) if (BOP_between(vertex,vNextI,vPrevJ)) { faceK = new BOP_Face3(prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } } else if (nextI == prevJ) { // Both faces share the edge (v,nextI) == (prevJ,v) if (BOP_between(vertex,vPrevI,vNextJ)) { faceK = new BOP_Face3(prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } } return faceK; }
/** * Returns a new quad (convex) from the merge of two triangles that share the * vertex index v. * @param faceI mesh triangle * @param faceJ mesh triangle * @param v vertex index shared by both triangles * @return a new convex quad if the merge is possible */ BOP_Face* BOP_Merge2::createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ) { BOP_Face *faceK = NULL; // // Test if both quads share a vertex index // BOP_Index v; unsigned int i; for(i=0;i<4 ;i++) { v = faceI->getVertex(i); if( faceJ->containsVertex(v) ) break; } if (i == 3) return NULL; // Get faces data BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ; faceI->getNeighbours(v,prevI,nextI,oppI); faceJ->getNeighbours(v,prevJ,nextJ,oppJ); // Quad test BOP_Index edge; if (nextI == prevJ) { if (prevI == nextJ) { // v is in center faceK = new BOP_Face4(nextI,oppI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); m_mesh->getIndexEdge(v,prevI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(prevI)->removeEdge(edge); m_mesh->getIndexEdge(v,nextI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(nextI)->removeEdge(edge); freeVerts(v, m_mesh->getVertex(v)); } else if (oppI == oppJ) { // nextI is in center faceK = new BOP_Face4(v,nextJ,oppJ,prevI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); m_mesh->getIndexEdge(v,nextI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(nextI)->removeEdge(edge); m_mesh->getIndexEdge(prevI,nextI,edge); m_mesh->getVertex(prevI)->removeEdge(edge); m_mesh->getVertex(nextI)->removeEdge(edge); freeVerts(nextI, m_mesh->getVertex(nextI)); } } else if (prevI == nextJ && oppI == oppJ) { // prevI is in center faceK = new BOP_Face4(v,nextI,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); m_mesh->getIndexEdge(v,prevI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(prevI)->removeEdge(edge); m_mesh->getIndexEdge(nextI,prevI,edge); m_mesh->getVertex(nextI)->removeEdge(edge); m_mesh->getVertex(prevI)->removeEdge(edge); freeVerts(prevI, m_mesh->getVertex(prevI)); } return faceK; }
/** * Returns a new face (quad or triangle) from the merge of one quad and one * triangle that share the vertex v and come from the same original face. * @param faceI mesh quad * @param faceJ mesh triangle * @param pending vector with pending vertices (required to merge one quad * and one triangle into a new triangle; it supposes to remove two vertexs, * v and its neighbour, that will be a new pending vertex if it wasn't) * @param v vertex index shared by both faces * @return If the merge is possible, a new face without v */ BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v) { BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, opp, prevJ, nextJ; faceI->getNeighbours(v,prevI,nextI,opp); faceJ->getNeighbours(v,prevJ,nextJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vOpp = m_mesh->getVertex(opp)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); // Merge test if (prevI == nextJ) { if (BOP_between(vertex,vNextI,vPrevJ)) { if (!BOP_collinear(vPrevJ,vPrevI,vOpp) && BOP_convex(vOpp,vPrevI,vPrevJ,vNextI)) { // The result is a new quad faceK = new BOP_Face4(opp,prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } else if (BOP_between(vPrevI,vPrevJ,vOpp)) { // The result is a triangle (only if prevI can be merged) if (prevI < m_firstVertex) return NULL; // It can't be merged faceK = new BOP_Face3(nextI,opp,prevJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); if (!containsIndex(pending, prevI)) pending.push_back(prevI); } } } else if (nextI == prevJ) { if (BOP_between(vertex,vPrevI,vNextJ)) { if (!BOP_collinear(vNextJ,vNextI,vOpp) && BOP_convex(vOpp,vPrevI,vNextJ,vNextI)) { // The result is a new quad faceK = new BOP_Face4(opp,prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } else if (BOP_between(vNextI,vOpp,vNextJ)) { // The result is a triangle (only if nextI can be merged) if (nextI < m_firstVertex) return NULL; faceK = new BOP_Face3(prevI,nextJ,opp,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); if (!containsIndex(pending, nextI)) pending.push_back(nextI); } } } return faceK; }
/** * Returns a new quad (convex) from the merge of two triangles that share the * vertex index v. * @param faceI mesh triangle * @param faceJ mesh triangle * @param v vertex index shared by both triangles * @return a new convex quad if the merge is possible */ BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ) { // Test if both triangles share a vertex index BOP_Index v; unsigned int i; for(i=0;i<3 ;i++) { v = faceI->getVertex(i); if( faceJ->containsVertex(v) ) break; } if (i == 3) return NULL; BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, prevJ, nextJ; faceI->getNeighbours(v,prevI,nextI); faceJ->getNeighbours(v,prevJ,nextJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); // Quad test if (prevI == nextJ) { if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) && BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) { faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); BOP_Index edge; m_mesh->getIndexEdge(v,prevI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(prevI)->removeEdge(edge); } } else if (nextI == prevJ) { if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) && BOP_convex(vertex,vNextJ,vNextI,vPrevI)) { faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); BOP_Index edge; m_mesh->getIndexEdge(v,nextI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(nextI)->removeEdge(edge); } } return faceK; }
/** * Returns a new quad from the merge of two quads that share * the vertex v and come from the same original face. * @param faceI mesh quad * @param faceJ mesh quad * @param pending vector with pending vertices (required to merge the two * quads supposes to remove two vertexs, v and its neighbour, * that will be a new pending vertex if it wasn't) * @param v vertex index shared by both quads * @return If the merge is possible, a new quad without v */ BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face4 *faceJ, BOP_Indexs &pending, BOP_Index v) { BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ; faceI->getNeighbours(v,prevI,nextI,oppI); faceJ->getNeighbours(v,prevJ,nextJ,oppJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vOppI = m_mesh->getVertex(oppI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); MT_Point3 vOppJ = m_mesh->getVertex(oppJ)->getPoint(); // Merge test if (prevI == nextJ) { // prevI/nextJ will be a new vertex required to merge if (prevI < m_firstVertex) return NULL; // It can't be merged if (BOP_between(vertex,vPrevJ,vNextI) && BOP_between(vNextJ,vOppJ,vOppI)) { faceK = new BOP_Face4(oppJ,prevJ,nextI,oppI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); // We add prevI to the pending list if it wasn't yet if (!containsIndex(pending, prevI)) pending.push_back(prevI); } } else if (nextI == prevJ) { // nextI/prevJ will be a new vertex required to merge if (nextI < m_firstVertex) return NULL; // It can't be merged if (BOP_between(vertex,vPrevI,vNextJ) && BOP_between(vNextI,vOppI,vOppJ)) { faceK = new BOP_Face4(oppI,prevI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); // Add nextI to the pending list if it wasn't yet if (!containsIndex(pending, nextI)) pending.push_back(nextI); } } return faceK; }
/** * Tests if faces since firstFace have all vertexs non-coincident of colinear, otherwise repairs the mesh. * @param mesh mesh that contains the faces, edges and vertices * @param firstFace first face index to be tested */ void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace) { unsigned int numFaces = mesh->getNumFaces(); for(unsigned int idxFace = firstFace; idxFace < numFaces; idxFace++) { BOP_Face *face = mesh->getFace(idxFace); if ((face->getTAG() != BROKEN) && (face->getTAG() != PHANTOM)) { MT_Point3 vertex1 = mesh->getVertex(face->getVertex(0))->getPoint(); MT_Point3 vertex2 = mesh->getVertex(face->getVertex(1))->getPoint(); MT_Point3 vertex3 = mesh->getVertex(face->getVertex(2))->getPoint(); if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle face->setTAG(PHANTOM); } } }
/** * Pre-process to filter no collisioned faces. * @param meshC Input & Output mesh data * @param faces Faces list to test * @param bsp BSP tree used to filter * @param inverted determines if the object is inverted */ void BOP_simplifiedMeshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp, bool inverted) { BOP_IT_Faces it; it = faces->begin(); while (it!=faces->end()) { BOP_Face *face = *it; MT_Point3 p1 = meshC->getVertex(face->getVertex(0))->getPoint(); MT_Point3 p2 = meshC->getVertex(face->getVertex(1))->getPoint(); MT_Point3 p3 = meshC->getVertex(face->getVertex(2))->getPoint(); if (bsp->filterFace(p1,p2,p3,face)==OUT) { if (!inverted) face->setTAG(BROKEN); it = faces->erase(it); } else { it++; } } }
/** * Preprocess to filter no collisioned faces. * @param meshC Input & Output mesh data * @param faces Faces list to test * @param bsp BSP tree used to filter */ void BOP_meshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp) { BOP_IT_Faces it; BOP_TAG tag; it = faces->begin(); while (it!=faces->end()) { BOP_Face *face = *it; MT_Point3 p1 = meshC->getVertex(face->getVertex(0))->getPoint(); MT_Point3 p2 = meshC->getVertex(face->getVertex(1))->getPoint(); MT_Point3 p3 = meshC->getVertex(face->getVertex(2))->getPoint(); if ((tag = bsp->classifyFace(p1,p2,p3,face->getPlane()))==OUT||tag==OUTON) { face->setTAG(BROKEN); it = faces->erase(it); } else if (tag == IN) { it = faces->erase(it); }else{ it++; } } }