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) Blender Foundation 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 * CSG operations. 00027 */ 00028 00034 #include "DNA_material_types.h" 00035 #include "DNA_mesh_types.h" 00036 #include "DNA_meshdata_types.h" 00037 #include "DNA_object_types.h" 00038 #include "DNA_scene_types.h" 00039 00040 #include "MEM_guardedalloc.h" 00041 00042 #include "BLI_math.h" 00043 #include "BLI_utildefines.h" 00044 #include "BLI_listbase.h" 00045 #include "BLI_ghash.h" 00046 00047 #include "BKE_cdderivedmesh.h" 00048 #include "BKE_depsgraph.h" 00049 #include "BKE_material.h" 00050 #include "BKE_mesh.h" 00051 #include "BKE_object.h" 00052 00053 #include "CSG_BooleanOps.h" 00054 00055 #include "MOD_boolean_util.h" 00056 00062 typedef struct { 00063 DerivedMesh *dm; 00064 Object *ob; 00065 int pos; 00066 } VertexIt; 00067 00073 static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator) 00074 { 00075 if (iterator->it) { 00076 // deallocate memory for iterator 00077 MEM_freeN(iterator->it); 00078 iterator->it = 0; 00079 } 00080 iterator->Done = NULL; 00081 iterator->Fill = NULL; 00082 iterator->Reset = NULL; 00083 iterator->Step = NULL; 00084 iterator->num_elements = 0; 00085 00086 } 00087 00088 static int VertexIt_Done(CSG_IteratorPtr it) 00089 { 00090 VertexIt * iterator = (VertexIt *)it; 00091 return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm)); 00092 } 00093 00094 static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert) 00095 { 00096 VertexIt * iterator = (VertexIt *)it; 00097 MVert *verts = iterator->dm->getVertArray(iterator->dm); 00098 00099 float global_pos[3]; 00100 00101 /* boolean happens in global space, transform both with obmat */ 00102 mul_v3_m4v3( 00103 global_pos, 00104 iterator->ob->obmat, 00105 verts[iterator->pos].co 00106 ); 00107 00108 vert->position[0] = global_pos[0]; 00109 vert->position[1] = global_pos[1]; 00110 vert->position[2] = global_pos[2]; 00111 } 00112 00113 static void VertexIt_Step(CSG_IteratorPtr it) 00114 { 00115 VertexIt * iterator = (VertexIt *)it; 00116 iterator->pos ++; 00117 } 00118 00119 static void VertexIt_Reset(CSG_IteratorPtr it) 00120 { 00121 VertexIt * iterator = (VertexIt *)it; 00122 iterator->pos = 0; 00123 } 00124 00125 static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob) 00126 { 00127 00128 VertexIt *it; 00129 if (output == 0) return; 00130 00131 // allocate some memory for blender iterator 00132 it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt")); 00133 if (it == 0) { 00134 return; 00135 } 00136 // assign blender specific variables 00137 it->dm = dm; 00138 it->ob = ob; // needed for obmat transformations 00139 00140 it->pos = 0; 00141 00142 // assign iterator function pointers. 00143 output->Step = VertexIt_Step; 00144 output->Fill = VertexIt_Fill; 00145 output->Done = VertexIt_Done; 00146 output->Reset = VertexIt_Reset; 00147 output->num_elements = it->dm->getNumVerts(it->dm); 00148 output->it = it; 00149 } 00150 00155 typedef struct { 00156 DerivedMesh *dm; 00157 int pos; 00158 int offset; 00159 int flip; 00160 } FaceIt; 00161 00162 static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator) 00163 { 00164 MEM_freeN(iterator->it); 00165 iterator->Done = NULL; 00166 iterator->Fill = NULL; 00167 iterator->Reset = NULL; 00168 iterator->Step = NULL; 00169 iterator->num_elements = 0; 00170 } 00171 00172 static int FaceIt_Done(CSG_IteratorPtr it) 00173 { 00174 // assume CSG_IteratorPtr is of the correct type. 00175 FaceIt * iterator = (FaceIt *)it; 00176 return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm)); 00177 } 00178 00179 static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face) 00180 { 00181 // assume CSG_IteratorPtr is of the correct type. 00182 FaceIt *face_it = (FaceIt *)it; 00183 MFace *mfaces = face_it->dm->getFaceArray(face_it->dm); 00184 MFace *mface = &mfaces[face_it->pos]; 00185 00186 /* reverse face vertices if necessary */ 00187 face->vertex_index[1] = mface->v2; 00188 if( face_it->flip == 0 ) { 00189 face->vertex_index[0] = mface->v1; 00190 face->vertex_index[2] = mface->v3; 00191 } else { 00192 face->vertex_index[2] = mface->v1; 00193 face->vertex_index[0] = mface->v3; 00194 } 00195 if (mface->v4) { 00196 face->vertex_index[3] = mface->v4; 00197 face->vertex_number = 4; 00198 } else { 00199 face->vertex_number = 3; 00200 } 00201 00202 face->orig_face = face_it->offset + face_it->pos; 00203 } 00204 00205 static void FaceIt_Step(CSG_IteratorPtr it) 00206 { 00207 FaceIt * face_it = (FaceIt *)it; 00208 face_it->pos ++; 00209 } 00210 00211 static void FaceIt_Reset(CSG_IteratorPtr it) 00212 { 00213 FaceIt * face_it = (FaceIt *)it; 00214 face_it->pos = 0; 00215 } 00216 00217 static void FaceIt_Construct( 00218 CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset, Object *ob) 00219 { 00220 FaceIt *it; 00221 if (output == 0) return; 00222 00223 // allocate some memory for blender iterator 00224 it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt")); 00225 if (it == 0) { 00226 return ; 00227 } 00228 // assign blender specific variables 00229 it->dm = dm; 00230 it->offset = offset; 00231 it->pos = 0; 00232 00233 /* determine if we will need to reverse order of face vertices */ 00234 if (ob->size[0] < 0.0f) { 00235 if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) { 00236 it->flip = 1; 00237 } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) { 00238 it->flip = 1; 00239 } else { 00240 it->flip = 0; 00241 } 00242 } else { 00243 if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) { 00244 it->flip = 0; 00245 } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) { 00246 it->flip = 0; 00247 } else { 00248 it->flip = 1; 00249 } 00250 } 00251 00252 // assign iterator function pointers. 00253 output->Step = FaceIt_Step; 00254 output->Fill = FaceIt_Fill; 00255 output->Done = FaceIt_Done; 00256 output->Reset = FaceIt_Reset; 00257 output->num_elements = it->dm->getNumFaces(it->dm); 00258 output->it = it; 00259 } 00260 00261 static Object *AddNewBlenderMesh(Scene *scene, Base *base) 00262 { 00263 // This little function adds a new mesh object to the blender object list 00264 // It uses ob to duplicate data as this seems to be easier than creating 00265 // a new one. This new oject contains no faces nor vertices. 00266 Mesh *old_me; 00267 Base *basen; 00268 Object *ob_new; 00269 00270 // now create a new blender object. 00271 // duplicating all the settings from the previous object 00272 // to the new one. 00273 ob_new= copy_object(base->object); 00274 00275 // Ok we don't want to use the actual data from the 00276 // last object, the above function incremented the 00277 // number of users, so decrement it here. 00278 old_me= ob_new->data; 00279 old_me->id.us--; 00280 00281 // Now create a new base to add into the linked list of 00282 // vase objects. 00283 00284 basen= MEM_mallocN(sizeof(Base), "duplibase"); 00285 *basen= *base; 00286 BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */ 00287 basen->object= ob_new; 00288 basen->flag &= ~SELECT; 00289 00290 // Initialize the mesh data associated with this object. 00291 ob_new->data= add_mesh("Mesh"); 00292 00293 // Finally assign the object type. 00294 ob_new->type= OB_MESH; 00295 00296 return ob_new; 00297 } 00298 00299 static void InterpCSGFace( 00300 DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr, 00301 float mapmat[][4]) 00302 { 00303 float obco[3], *co[4], *orig_co[4], w[4][4]; 00304 MFace *mface, *orig_mface; 00305 int j; 00306 00307 mface = CDDM_get_face(dm, index); 00308 orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index; 00309 00310 // get the vertex coordinates from the original mesh 00311 orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co; 00312 orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co; 00313 orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co; 00314 orig_co[3] = (orig_mface->v4)? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co: NULL; 00315 00316 // get the vertex coordinates from the new derivedmesh 00317 co[0] = CDDM_get_vert(dm, mface->v1)->co; 00318 co[1] = CDDM_get_vert(dm, mface->v2)->co; 00319 co[2] = CDDM_get_vert(dm, mface->v3)->co; 00320 co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL; 00321 00322 for (j = 0; j < nr; j++) { 00323 // get coordinate into the space of the original mesh 00324 if (mapmat) 00325 mul_v3_m4v3(obco, mapmat, co[j]); 00326 else 00327 copy_v3_v3(obco, co[j]); 00328 00329 interp_weights_face_v3( w[j],orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco); 00330 } 00331 00332 CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float*)w, 1, index); 00333 } 00334 00335 /* Iterate over the CSG Output Descriptors and create a new DerivedMesh 00336 from them */ 00337 static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( 00338 CSG_FaceIteratorDescriptor *face_it, 00339 CSG_VertexIteratorDescriptor *vertex_it, 00340 float parinv[][4], 00341 float mapmat[][4], 00342 Material **mat, 00343 int *totmat, 00344 DerivedMesh *dm1, 00345 Object *ob1, 00346 DerivedMesh *dm2, 00347 Object *ob2) 00348 { 00349 DerivedMesh *result, *orig_dm; 00350 GHash *material_hash = NULL; 00351 Mesh *me1= (Mesh*)ob1->data; 00352 Mesh *me2= (Mesh*)ob2->data; 00353 int i; 00354 00355 // create a new DerivedMesh 00356 result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements); 00357 CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH, 00358 CD_DEFAULT, face_it->num_elements); 00359 CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH, 00360 CD_DEFAULT, face_it->num_elements); 00361 00362 // step through the vertex iterators: 00363 for (i = 0; !vertex_it->Done(vertex_it->it); i++) { 00364 CSG_IVertex csgvert; 00365 MVert *mvert = CDDM_get_vert(result, i); 00366 00367 // retrieve a csg vertex from the boolean module 00368 vertex_it->Fill(vertex_it->it, &csgvert); 00369 vertex_it->Step(vertex_it->it); 00370 00371 // we have to map the vertex coordinates back in the coordinate frame 00372 // of the resulting object, since it was computed in world space 00373 mul_v3_m4v3(mvert->co, parinv, csgvert.position); 00374 } 00375 00376 // a hash table to remap materials to indices 00377 if (mat) { 00378 material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "CSG_mat gh"); 00379 *totmat = 0; 00380 } 00381 00382 // step through the face iterators 00383 for(i = 0; !face_it->Done(face_it->it); i++) { 00384 Mesh *orig_me; 00385 Object *orig_ob; 00386 Material *orig_mat; 00387 CSG_IFace csgface; 00388 MFace *mface; 00389 int orig_index, mat_nr; 00390 00391 // retrieve a csg face from the boolean module 00392 face_it->Fill(face_it->it, &csgface); 00393 face_it->Step(face_it->it); 00394 00395 // find the original mesh and data 00396 orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2; 00397 orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2; 00398 orig_me = (orig_ob == ob1)? me1: me2; 00399 orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1); 00400 00401 // copy all face layers, including mface 00402 CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1); 00403 00404 // set mface 00405 mface = CDDM_get_face(result, i); 00406 mface->v1 = csgface.vertex_index[0]; 00407 mface->v2 = csgface.vertex_index[1]; 00408 mface->v3 = csgface.vertex_index[2]; 00409 mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0; 00410 00411 // set material, based on lookup in hash table 00412 orig_mat= give_current_material(orig_ob, mface->mat_nr+1); 00413 00414 if (mat && orig_mat) { 00415 if (!BLI_ghash_haskey(material_hash, orig_mat)) { 00416 mat[*totmat] = orig_mat; 00417 mat_nr = mface->mat_nr = (*totmat)++; 00418 BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr)); 00419 } 00420 else 00421 mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat)); 00422 } 00423 else 00424 mface->mat_nr = 0; 00425 00426 InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number, 00427 (orig_me == me2)? mapmat: NULL); 00428 00429 test_index_face(mface, &result->faceData, i, csgface.vertex_number); 00430 } 00431 00432 if (material_hash) 00433 BLI_ghash_free(material_hash, NULL, NULL); 00434 00435 CDDM_calc_edges(result); 00436 CDDM_calc_normals(result); 00437 00438 return result; 00439 } 00440 00441 static void BuildMeshDescriptors( 00442 struct DerivedMesh *dm, 00443 struct Object *ob, 00444 int face_offset, 00445 struct CSG_FaceIteratorDescriptor * face_it, 00446 struct CSG_VertexIteratorDescriptor * vertex_it) 00447 { 00448 VertexIt_Construct(vertex_it,dm, ob); 00449 FaceIt_Construct(face_it,dm,face_offset,ob); 00450 } 00451 00452 static void FreeMeshDescriptors( 00453 struct CSG_FaceIteratorDescriptor *face_it, 00454 struct CSG_VertexIteratorDescriptor *vertex_it) 00455 { 00456 VertexIt_Destruct(vertex_it); 00457 FaceIt_Destruct(face_it); 00458 } 00459 00460 static DerivedMesh *NewBooleanDerivedMesh_intern( 00461 DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, 00462 int int_op_type, Material **mat, int *totmat) 00463 { 00464 00465 float inv_mat[4][4]; 00466 float map_mat[4][4]; 00467 00468 DerivedMesh *result = NULL; 00469 00470 if (dm == NULL || dm_select == NULL) return 0; 00471 if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0; 00472 00473 // we map the final object back into ob's local coordinate space. For this 00474 // we need to compute the inverse transform from global to ob (inv_mat), 00475 // and the transform from ob to ob_select for use in interpolation (map_mat) 00476 invert_m4_m4(inv_mat, ob->obmat); 00477 mult_m4_m4m4(map_mat, inv_mat, ob_select->obmat); 00478 invert_m4_m4(inv_mat, ob_select->obmat); 00479 00480 { 00481 // interface with the boolean module: 00482 // 00483 // the idea is, we pass the boolean module verts and faces using the 00484 // provided descriptors. once the boolean operation is performed, we 00485 // get back output descriptors, from which we then build a DerivedMesh 00486 00487 CSG_VertexIteratorDescriptor vd_1, vd_2; 00488 CSG_FaceIteratorDescriptor fd_1, fd_2; 00489 CSG_OperationType op_type; 00490 CSG_BooleanOperation *bool_op; 00491 00492 // work out the operation they chose and pick the appropriate 00493 // enum from the csg module. 00494 switch (int_op_type) { 00495 case 1 : op_type = e_csg_intersection; break; 00496 case 2 : op_type = e_csg_union; break; 00497 case 3 : op_type = e_csg_difference; break; 00498 case 4 : op_type = e_csg_classify; break; 00499 default : op_type = e_csg_intersection; 00500 } 00501 00502 BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1); 00503 BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2); 00504 00505 bool_op = CSG_NewBooleanFunction(); 00506 00507 // perform the operation 00508 if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) { 00509 CSG_VertexIteratorDescriptor vd_o; 00510 CSG_FaceIteratorDescriptor fd_o; 00511 00512 CSG_OutputFaceDescriptor(bool_op, &fd_o); 00513 CSG_OutputVertexDescriptor(bool_op, &vd_o); 00514 00515 // iterate through results of operation and insert 00516 // into new object 00517 result = ConvertCSGDescriptorsToDerivedMesh( 00518 &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob); 00519 00520 // free up the memory 00521 CSG_FreeVertexDescriptor(&vd_o); 00522 CSG_FreeFaceDescriptor(&fd_o); 00523 } 00524 else 00525 printf("Unknown internal error in boolean"); 00526 00527 CSG_FreeBooleanOperation(bool_op); 00528 00529 FreeMeshDescriptors(&fd_1, &vd_1); 00530 FreeMeshDescriptors(&fd_2, &vd_2); 00531 } 00532 00533 return result; 00534 } 00535 00536 int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type) 00537 { 00538 Mesh *me_new; 00539 int a, maxmat, totmat= 0; 00540 Object *ob_new, *ob, *ob_select; 00541 Material **mat; 00542 DerivedMesh *result; 00543 DerivedMesh *dm_select; 00544 DerivedMesh *dm; 00545 00546 ob= base->object; 00547 ob_select= base_select->object; 00548 00549 dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); 00550 dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ?? 00551 00552 maxmat= ob->totcol + ob_select->totcol; 00553 mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat"); 00554 00555 /* put some checks in for nice user feedback */ 00556 if (dm == NULL || dm_select == NULL) return 0; 00557 if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) 00558 { 00559 MEM_freeN(mat); 00560 return -1; 00561 } 00562 00563 result= NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat); 00564 00565 if (result == NULL) { 00566 MEM_freeN(mat); 00567 return 0; 00568 } 00569 00570 /* create a new blender mesh object - using 'base' as a template */ 00571 ob_new= AddNewBlenderMesh(scene, base_select); 00572 me_new= ob_new->data; 00573 00574 DM_to_mesh(result, me_new); 00575 result->release(result); 00576 00577 dm->release(dm); 00578 dm_select->release(dm_select); 00579 00580 /* add materials to object */ 00581 for (a = 0; a < totmat; a++) 00582 assign_material(ob_new, mat[a], a+1); 00583 00584 MEM_freeN(mat); 00585 00586 /* update dag */ 00587 DAG_id_tag_update(&ob_new->id, OB_RECALC_DATA); 00588 00589 return 1; 00590 } 00591 00592 DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, 00593 int int_op_type) 00594 { 00595 return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL); 00596 }