Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <iostream> 00034 #include <map> 00035 #include "../extern/BOP_Interface.h" 00036 #include "../../bsp/intern/BSP_CSGMesh_CFIterator.h" 00037 #include "BOP_BSPTree.h" 00038 #include "BOP_Mesh.h" 00039 #include "BOP_Face2Face.h" 00040 #include "BOP_Merge.h" 00041 #include "BOP_Merge2.h" 00042 #include "BOP_Chrono.h" 00043 00044 #if defined(BOP_ORIG_MERGE) && defined(BOP_NEW_MERGE) 00045 #include "../../../source/blender/blenkernel/BKE_global.h" 00046 #endif 00047 00048 BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC, 00049 BOP_Faces* facesA, 00050 BOP_Faces* facesB, 00051 bool invertMeshA, 00052 bool invertMeshB); 00053 BOP_Face3* BOP_createFace(BOP_Mesh* mesh, 00054 BOP_Index vertex1, 00055 BOP_Index vertex2, 00056 BOP_Index vertex3, 00057 BOP_Index origFace); 00058 void BOP_addMesh(BOP_Mesh* mesh, 00059 BOP_Faces* meshFacesId, 00060 CSG_FaceIteratorDescriptor& face_it, 00061 CSG_VertexIteratorDescriptor& vertex_it, 00062 bool invert); 00063 BSP_CSGMesh* BOP_newEmptyMesh(); 00064 BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* inputMesh, 00065 bool invert); 00066 void BOP_meshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp); 00067 void BOP_simplifiedMeshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp, bool inverted); 00068 void BOP_meshClassify(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp); 00069 00081 BoolOpState BOP_performBooleanOperation(BoolOpType opType, 00082 BSP_CSGMesh** outputMesh, 00083 CSG_FaceIteratorDescriptor obAFaces, 00084 CSG_VertexIteratorDescriptor obAVertices, 00085 CSG_FaceIteratorDescriptor obBFaces, 00086 CSG_VertexIteratorDescriptor obBVertices) 00087 { 00088 #ifdef BOP_DEBUG 00089 std::cout << "BEGIN BOP_performBooleanOperation" << std::endl; 00090 #endif 00091 00092 // Set invert flags depending on boolean operation type: 00093 // INTERSECTION: A^B = and(A,B) 00094 // UNION: A|B = not(and(not(A),not(B))) 00095 // DIFFERENCE: A-B = and(A,not(B)) 00096 bool invertMeshA = (opType == BOP_UNION); 00097 bool invertMeshB = (opType != BOP_INTERSECTION); 00098 bool invertMeshC = (opType == BOP_UNION); 00099 00100 // Faces list for both objects, used by boolean op. 00101 BOP_Faces meshAFacesId; 00102 BOP_Faces meshBFacesId; 00103 00104 // Build C-mesh, the output mesh 00105 BOP_Mesh meshC; 00106 00107 // Add A-mesh into C-mesh 00108 BOP_addMesh(&meshC, &meshAFacesId, obAFaces, obAVertices, invertMeshA); 00109 00110 // Add B-mesh into C-mesh 00111 BOP_addMesh(&meshC, &meshBFacesId, obBFaces, obBVertices, invertMeshB); 00112 00113 // for now, allow operations on non-manifold (non-solid) meshes 00114 #if 0 00115 if (!meshC.isClosedMesh()) 00116 return BOP_NO_SOLID; 00117 #endif 00118 00119 // Perform the intersection boolean operation. 00120 BoolOpState result = BOP_intersectionBoolOp(&meshC, &meshAFacesId, &meshBFacesId, 00121 invertMeshA, invertMeshB); 00122 00123 // Invert the output mesh if is required 00124 *outputMesh = BOP_exportMesh(&meshC, invertMeshC); 00125 00126 #ifdef BOP_DEBUG 00127 std::cout << "END BOP_performBooleanOperation" << std::endl; 00128 #endif 00129 00130 return result; 00131 } 00132 00143 BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC, 00144 BOP_Faces* facesA, 00145 BOP_Faces* facesB, 00146 bool invertMeshA, 00147 bool invertMeshB) 00148 { 00149 #ifdef BOP_DEBUG 00150 BOP_Chrono chrono; 00151 float t = 0.0f; 00152 float c = 0.0f; 00153 chrono.start(); 00154 std::cout << "---" << std::endl; 00155 #endif 00156 00157 // Create BSPs trees for mesh A & B 00158 BOP_BSPTree bspA; 00159 bspA.addMesh(meshC, *facesA); 00160 00161 BOP_BSPTree bspB; 00162 bspB.addMesh(meshC, *facesB); 00163 00164 #ifdef BOP_DEBUG 00165 c = chrono.stamp(); t += c; 00166 std::cout << "Create BSP " << c << std::endl; 00167 #endif 00168 00169 unsigned int numVertices = meshC->getNumVertexs(); 00170 00171 // mesh pre-filter 00172 BOP_simplifiedMeshFilter(meshC, facesA, &bspB, invertMeshB); 00173 if ((0.25*facesA->size()) > bspB.getDeep()) 00174 BOP_meshFilter(meshC, facesA, &bspB); 00175 00176 BOP_simplifiedMeshFilter(meshC, facesB, &bspA, invertMeshA); 00177 if ((0.25*facesB->size()) > bspA.getDeep()) 00178 BOP_meshFilter(meshC, facesB, &bspA); 00179 00180 #ifdef BOP_DEBUG 00181 c = chrono.stamp(); t += c; 00182 std::cout << "mesh Filter " << c << std::endl; 00183 #endif 00184 00185 // Face 2 Face 00186 BOP_Face2Face(meshC,facesA,facesB); 00187 00188 #ifdef BOP_DEBUG 00189 c = chrono.stamp(); t += c; 00190 std::cout << "Face2Face " << c << std::endl; 00191 #endif 00192 00193 // BSP classification 00194 BOP_meshClassify(meshC,facesA,&bspB); 00195 BOP_meshClassify(meshC,facesB,&bspA); 00196 00197 #ifdef BOP_DEBUG 00198 c = chrono.stamp(); t += c; 00199 std::cout << "Classification " << c << std::endl; 00200 #endif 00201 00202 // Process overlapped faces 00203 BOP_removeOverlappedFaces(meshC,facesA,facesB); 00204 00205 #ifdef BOP_DEBUG 00206 c = chrono.stamp(); t += c; 00207 std::cout << "Remove overlap " << c << std::endl; 00208 #endif 00209 00210 // Sew two meshes 00211 BOP_sew(meshC,facesA,facesB); 00212 00213 #ifdef BOP_DEBUG 00214 c = chrono.stamp(); t += c; 00215 std::cout << "Sew " << c << std::endl; 00216 #endif 00217 00218 // Merge faces 00219 #ifdef BOP_ORIG_MERGE 00220 #ifndef BOP_NEW_MERGE 00221 BOP_Merge::getInstance().mergeFaces(meshC,numVertices); 00222 #endif 00223 #endif 00224 00225 #ifdef BOP_NEW_MERGE 00226 #ifndef BOP_ORIG_MERGE 00227 BOP_Merge2::getInstance().mergeFaces(meshC,numVertices); 00228 #else 00229 static int state = -1; 00230 if (G.rt == 100) { 00231 if( state != 1 ) { 00232 std::cout << "Boolean code using old merge technique." << std::endl; 00233 state = 1; 00234 } 00235 BOP_Merge::getInstance().mergeFaces(meshC,numVertices); 00236 } else { 00237 if( state != 0 ) { 00238 std::cout << "Boolean code using new merge technique." << std::endl; 00239 state = 0; 00240 } 00241 BOP_Merge2::getInstance().mergeFaces(meshC,numVertices); 00242 } 00243 #endif 00244 #endif 00245 00246 #ifdef BOP_DEBUG 00247 c = chrono.stamp(); t += c; 00248 std::cout << "Merge faces " << c << std::endl; 00249 std::cout << "Total " << t << std::endl; 00250 // Test integrity 00251 meshC->testMesh(); 00252 #endif 00253 00254 return BOP_OK; 00255 } 00256 00263 void BOP_meshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp) 00264 { 00265 BOP_IT_Faces it; 00266 BOP_TAG tag; 00267 00268 it = faces->begin(); 00269 while (it!=faces->end()) { 00270 BOP_Face *face = *it; 00271 MT_Point3 p1 = meshC->getVertex(face->getVertex(0))->getPoint(); 00272 MT_Point3 p2 = meshC->getVertex(face->getVertex(1))->getPoint(); 00273 MT_Point3 p3 = meshC->getVertex(face->getVertex(2))->getPoint(); 00274 if ((tag = bsp->classifyFace(p1,p2,p3,face->getPlane()))==OUT||tag==OUTON) { 00275 face->setTAG(BROKEN); 00276 it = faces->erase(it); 00277 } 00278 else if (tag == IN) { 00279 it = faces->erase(it); 00280 }else{ 00281 it++; 00282 } 00283 } 00284 } 00285 00293 void BOP_simplifiedMeshFilter(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp, bool inverted) 00294 { 00295 BOP_IT_Faces it; 00296 00297 it = faces->begin(); 00298 while (it!=faces->end()) { 00299 BOP_Face *face = *it; 00300 MT_Point3 p1 = meshC->getVertex(face->getVertex(0))->getPoint(); 00301 MT_Point3 p2 = meshC->getVertex(face->getVertex(1))->getPoint(); 00302 MT_Point3 p3 = meshC->getVertex(face->getVertex(2))->getPoint(); 00303 if (bsp->filterFace(p1,p2,p3,face)==OUT) { 00304 if (!inverted) face->setTAG(BROKEN); 00305 it = faces->erase(it); 00306 } 00307 else { 00308 it++; 00309 } 00310 } 00311 } 00312 00319 void BOP_meshClassify(BOP_Mesh* meshC, BOP_Faces* faces, BOP_BSPTree* bsp) 00320 { 00321 for(BOP_IT_Faces face=faces->begin();face!=faces->end();face++) { 00322 if ((*face)->getTAG()!=BROKEN) { 00323 MT_Point3 p1 = meshC->getVertex((*face)->getVertex(0))->getPoint(); 00324 MT_Point3 p2 = meshC->getVertex((*face)->getVertex(1))->getPoint(); 00325 MT_Point3 p3 = meshC->getVertex((*face)->getVertex(2))->getPoint(); 00326 if (bsp->simplifiedClassifyFace(p1,p2,p3,(*face)->getPlane())!=IN) { 00327 (*face)->setTAG(BROKEN); 00328 } 00329 } 00330 } 00331 } 00332 00342 BOP_Face3 *BOP_createFace3(BOP_Mesh* mesh, 00343 BOP_Index vertex1, 00344 BOP_Index vertex2, 00345 BOP_Index vertex3, 00346 BOP_Index origFace) 00347 { 00348 MT_Point3 p1 = mesh->getVertex(vertex1)->getPoint(); 00349 MT_Point3 p2 = mesh->getVertex(vertex2)->getPoint(); 00350 MT_Point3 p3 = mesh->getVertex(vertex3)->getPoint(); 00351 MT_Plane3 plane(p1,p2,p3); 00352 00353 return new BOP_Face3(vertex1, vertex2, vertex3, plane, origFace); 00354 } 00355 00364 void BOP_addMesh(BOP_Mesh* mesh, 00365 BOP_Faces* meshFacesId, 00366 CSG_FaceIteratorDescriptor& face_it, 00367 CSG_VertexIteratorDescriptor& vertex_it, 00368 bool invert) 00369 { 00370 unsigned int vtxIndexOffset = mesh->getNumVertexs(); 00371 00372 // The size of the vertex data array will be at least the number of faces. 00373 CSG_IVertex vertex; 00374 while (!vertex_it.Done(vertex_it.it)) { 00375 vertex_it.Fill(vertex_it.it,&vertex); 00376 MT_Point3 pos(vertex.position); 00377 mesh->addVertex(pos); 00378 vertex_it.Step(vertex_it.it); 00379 } 00380 00381 CSG_IFace face; 00382 00383 // now for the polygons. 00384 // we may need to decalare some memory for user defined face properties. 00385 00386 BOP_Face3 *newface; 00387 00388 while (!face_it.Done(face_it.it)) { 00389 face_it.Fill(face_it.it,&face); 00390 00391 // Let's not rely on quads being coplanar - especially if they 00392 // are coming out of that soup of code from blender... 00393 if (face.vertex_number == 4){ 00394 // QUAD 00395 if (invert) { 00396 newface = BOP_createFace3(mesh, 00397 face.vertex_index[2] + vtxIndexOffset, 00398 face.vertex_index[0] + vtxIndexOffset, 00399 face.vertex_index[3] + vtxIndexOffset, 00400 face.orig_face); 00401 meshFacesId->push_back(newface); 00402 mesh->addFace(newface); 00403 newface = BOP_createFace3(mesh, 00404 face.vertex_index[2] + vtxIndexOffset, 00405 face.vertex_index[1] + vtxIndexOffset, 00406 face.vertex_index[0] + vtxIndexOffset, 00407 face.orig_face); 00408 meshFacesId->push_back(newface); 00409 mesh->addFace(newface); 00410 } 00411 else { 00412 newface = BOP_createFace3(mesh, 00413 face.vertex_index[0] + vtxIndexOffset, 00414 face.vertex_index[2] + vtxIndexOffset, 00415 face.vertex_index[3] + vtxIndexOffset, 00416 face.orig_face); 00417 meshFacesId->push_back(newface); 00418 mesh->addFace(newface); 00419 newface = BOP_createFace3(mesh, 00420 face.vertex_index[0] + vtxIndexOffset, 00421 face.vertex_index[1] + vtxIndexOffset, 00422 face.vertex_index[2] + vtxIndexOffset, 00423 face.orig_face); 00424 meshFacesId->push_back(newface); 00425 mesh->addFace(newface); 00426 } 00427 } 00428 else { 00429 // TRIANGLES 00430 if (invert) { 00431 newface = BOP_createFace3(mesh, 00432 face.vertex_index[2] + vtxIndexOffset, 00433 face.vertex_index[1] + vtxIndexOffset, 00434 face.vertex_index[0] + vtxIndexOffset, 00435 face.orig_face); 00436 meshFacesId->push_back(newface); 00437 mesh->addFace(newface); 00438 } 00439 else { 00440 newface = BOP_createFace3(mesh, 00441 face.vertex_index[0] + vtxIndexOffset, 00442 face.vertex_index[1] + vtxIndexOffset, 00443 face.vertex_index[2] + vtxIndexOffset, 00444 face.orig_face); 00445 meshFacesId->push_back(newface); 00446 mesh->addFace(newface); 00447 } 00448 } 00449 00450 face_it.Step(face_it.it); 00451 } 00452 } 00453 00458 BSP_CSGMesh* BOP_newEmptyMesh() 00459 { 00460 BSP_CSGMesh* mesh = BSP_CSGMesh::New(); 00461 if (mesh == NULL) return mesh; 00462 00463 std::vector<BSP_MVertex>* vertices = new std::vector<BSP_MVertex>; 00464 00465 mesh->SetVertices(vertices); 00466 00467 return mesh; 00468 } 00469 00476 BSP_CSGMesh* BOP_exportMesh(BOP_Mesh* mesh, 00477 bool invert) 00478 { 00479 BSP_CSGMesh* outputMesh = BOP_newEmptyMesh(); 00480 00481 if (outputMesh == NULL) return NULL; 00482 00483 // vtx index dictionary, to translate indeces from input to output. 00484 std::map<int,unsigned int> dic; 00485 std::map<int,unsigned int>::iterator itDic; 00486 00487 unsigned int count = 0; 00488 00489 // Add a new face for each face in the input list 00490 BOP_Faces faces = mesh->getFaces(); 00491 BOP_Vertexs vertexs = mesh->getVertexs(); 00492 00493 for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) { 00494 if ((*face)->getTAG()!=BROKEN){ 00495 // Add output face 00496 outputMesh->FaceSet().push_back(BSP_MFace()); 00497 BSP_MFace& outFace = outputMesh->FaceSet().back(); 00498 00499 // Copy face 00500 outFace.m_verts.clear(); 00501 outFace.m_plane = (*face)->getPlane(); 00502 outFace.m_orig_face = (*face)->getOriginalFace(); 00503 00504 // invert face if is required 00505 if (invert) (*face)->invert(); 00506 00507 // Add the face vertex if not added yet 00508 for (unsigned int pos=0;pos<(*face)->size();pos++) { 00509 BSP_VertexInd outVtxId; 00510 BOP_Index idVertex = (*face)->getVertex(pos); 00511 itDic = dic.find(idVertex); 00512 if (itDic == dic.end()) { 00513 // The vertex isn't added yet 00514 outVtxId = BSP_VertexInd(outputMesh->VertexSet().size()); 00515 BSP_MVertex outVtx((mesh->getVertex(idVertex))->getPoint()); 00516 outVtx.m_edges.clear(); 00517 outputMesh->VertexSet().push_back(outVtx); 00518 dic[idVertex] = outVtxId; 00519 count++; 00520 } 00521 else { 00522 // The vertex is added 00523 outVtxId = BSP_VertexInd(itDic->second); 00524 } 00525 00526 outFace.m_verts.push_back(outVtxId); 00527 } 00528 } 00529 } 00530 00531 // Build the mesh edges using topological informtion 00532 outputMesh->BuildEdges(); 00533 00534 return outputMesh; 00535 }