|
Blender
V2.59
|
00001 /* 00002 * $Id: editmesh.c 36296 2011-04-23 09:25:34Z nazgul $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * Contributor(s): Blender Foundation, full recode 2002-2008 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00034 #include <stdlib.h> 00035 #include <string.h> 00036 #include <math.h> 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "DNA_scene_types.h" 00041 #include "DNA_object_types.h" 00042 #include "DNA_key_types.h" 00043 #include "DNA_meshdata_types.h" 00044 #include "DNA_modifier_types.h" 00045 00046 #include "BLI_blenlib.h" 00047 #include "BLI_math.h" 00048 #include "BLI_editVert.h" 00049 #include "BLI_dynstr.h" 00050 #include "BLI_rand.h" 00051 #include "BLI_utildefines.h" 00052 00053 #include "BKE_DerivedMesh.h" 00054 #include "BKE_context.h" 00055 #include "BKE_depsgraph.h" 00056 #include "BKE_global.h" 00057 #include "BKE_key.h" 00058 #include "BKE_main.h" 00059 #include "BKE_material.h" 00060 #include "BKE_mesh.h" 00061 #include "BKE_paint.h" 00062 #include "BKE_report.h" 00063 #include "BKE_multires.h" 00064 00065 #include "ED_mesh.h" 00066 #include "ED_object.h" 00067 #include "ED_screen.h" 00068 #include "ED_util.h" 00069 #include "ED_view3d.h" 00070 00071 #include "RNA_access.h" 00072 #include "RNA_define.h" 00073 00074 #include "WM_api.h" 00075 #include "WM_types.h" 00076 00077 /* own include */ 00078 #include "mesh_intern.h" 00079 00080 /* 00081 editmesh.c: 00082 - add/alloc/free data 00083 - hashtables 00084 - enter/exit editmode 00085 */ 00086 00087 /* XXX */ 00088 static void BIF_undo_push(const char *UNUSED(arg)) {} 00089 static void error(const char *UNUSED(arg)) {} 00090 00091 00092 /* ***************** HASH ********************* */ 00093 00094 00095 #define EDHASHSIZE (512*512) 00096 #define EDHASH(a, b) (a % EDHASHSIZE) 00097 00098 00099 /* ************ ADD / REMOVE / FIND ****************** */ 00100 00101 static void *calloc_em(EditMesh *UNUSED(em), size_t size, size_t nr) 00102 { 00103 return calloc(size, nr); 00104 } 00105 00106 /* used to bypass normal calloc with fast one */ 00107 static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em; 00108 static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em; 00109 static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em; 00110 00111 EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example) 00112 { 00113 EditVert *eve; 00114 static int hashnr= 0; 00115 00116 eve= callocvert(em, sizeof(EditVert), 1); 00117 BLI_addtail(&em->verts, eve); 00118 em->totvert++; 00119 00120 if(vec) VECCOPY(eve->co, vec); 00121 00122 eve->hash= hashnr++; 00123 if( hashnr>=EDHASHSIZE) hashnr= 0; 00124 00125 /* new verts get keyindex of -1 since they did not 00126 * have a pre-editmode vertex order 00127 */ 00128 eve->keyindex = -1; 00129 00130 if(example) { 00131 CustomData_em_copy_data(&em->vdata, &em->vdata, example->data, &eve->data); 00132 eve->bweight = example->bweight; 00133 } 00134 else { 00135 CustomData_em_set_default(&em->vdata, &eve->data); 00136 } 00137 00138 return eve; 00139 } 00140 00141 void free_editvert (EditMesh *em, EditVert *eve) 00142 { 00143 00144 EM_remove_selection(em, eve, EDITVERT); 00145 CustomData_em_free_block(&em->vdata, &eve->data); 00146 if(eve->fast==0) 00147 free(eve); 00148 00149 em->totvert--; 00150 } 00151 00152 00153 EditEdge *findedgelist(EditMesh *em, EditVert *v1, EditVert *v2) 00154 { 00155 EditVert *v3; 00156 struct HashEdge *he; 00157 00158 /* swap ? */ 00159 if( v1 > v2) { 00160 v3= v2; 00161 v2= v1; 00162 v1= v3; 00163 } 00164 00165 if(em->hashedgetab==NULL) 00166 em->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab"); 00167 00168 he= em->hashedgetab + EDHASH(v1->hash, v2->hash); 00169 00170 while(he) { 00171 00172 if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed; 00173 00174 he= he->next; 00175 } 00176 return 0; 00177 } 00178 00179 static void insert_hashedge(EditMesh *em, EditEdge *eed) 00180 { 00181 /* assuming that eed is not in the list yet, and that a find has been done before */ 00182 00183 struct HashEdge *first, *he; 00184 00185 first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); 00186 00187 if( first->eed==0 ) { 00188 first->eed= eed; 00189 } 00190 else { 00191 he= &eed->hash; 00192 he->eed= eed; 00193 he->next= first->next; 00194 first->next= he; 00195 } 00196 } 00197 00198 static void remove_hashedge(EditMesh *em, EditEdge *eed) 00199 { 00200 /* assuming eed is in the list */ 00201 00202 struct HashEdge *first, *he, *prev=NULL; 00203 00204 he=first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); 00205 00206 while(he) { 00207 if(he->eed == eed) { 00208 /* remove from list */ 00209 if(he==first) { 00210 if(first->next) { 00211 he= first->next; 00212 first->eed= he->eed; 00213 first->next= he->next; 00214 } 00215 else he->eed= 0; 00216 } 00217 else { 00218 prev->next= he->next; 00219 } 00220 return; 00221 } 00222 prev= he; 00223 he= he->next; 00224 } 00225 } 00226 00227 EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *example) 00228 { 00229 EditVert *v3; 00230 EditEdge *eed; 00231 int swap= 0; 00232 00233 if(v1==v2) return NULL; 00234 if(v1==NULL || v2==NULL) return NULL; 00235 00236 /* swap ? */ 00237 if(v1>v2) { 00238 v3= v2; 00239 v2= v1; 00240 v1= v3; 00241 swap= 1; 00242 } 00243 00244 /* find in hashlist */ 00245 eed= findedgelist(em, v1, v2); 00246 00247 if(eed==NULL) { 00248 00249 eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1); 00250 eed->v1= v1; 00251 eed->v2= v2; 00252 BLI_addtail(&em->edges, eed); 00253 eed->dir= swap; 00254 insert_hashedge(em, eed); 00255 em->totedge++; 00256 00257 /* copy edge data: 00258 rule is to do this with addedgelist call, before addfacelist */ 00259 if(example) { 00260 eed->crease= example->crease; 00261 eed->bweight= example->bweight; 00262 eed->sharp = example->sharp; 00263 eed->seam = example->seam; 00264 eed->h |= (example->h & EM_FGON); 00265 } 00266 } 00267 00268 return eed; 00269 } 00270 00271 void remedge(EditMesh *em, EditEdge *eed) 00272 { 00273 BLI_remlink(&em->edges, eed); 00274 remove_hashedge(em, eed); 00275 00276 em->totedge--; 00277 } 00278 00279 void free_editedge(EditMesh *em, EditEdge *eed) 00280 { 00281 EM_remove_selection(em, eed, EDITEDGE); 00282 if(eed->fast==0){ 00283 free(eed); 00284 } 00285 } 00286 00287 void free_editface(EditMesh *em, EditFace *efa) 00288 { 00289 EM_remove_selection(em, efa, EDITFACE); 00290 00291 if (em->act_face==efa) { 00292 EM_set_actFace(em, em->faces.first == efa ? NULL : em->faces.first); 00293 } 00294 00295 CustomData_em_free_block(&em->fdata, &efa->data); 00296 if(efa->fast==0) 00297 free(efa); 00298 00299 em->totface--; 00300 } 00301 00302 void free_vertlist(EditMesh *em, ListBase *edve) 00303 { 00304 EditVert *eve, *next; 00305 00306 if (!edve) return; 00307 00308 eve= edve->first; 00309 while(eve) { 00310 next= eve->next; 00311 free_editvert(em, eve); 00312 eve= next; 00313 } 00314 edve->first= edve->last= NULL; 00315 em->totvert= em->totvertsel= 0; 00316 } 00317 00318 void free_edgelist(EditMesh *em, ListBase *lb) 00319 { 00320 EditEdge *eed, *next; 00321 00322 eed= lb->first; 00323 while(eed) { 00324 next= eed->next; 00325 free_editedge(em, eed); 00326 eed= next; 00327 } 00328 lb->first= lb->last= NULL; 00329 em->totedge= em->totedgesel= 0; 00330 } 00331 00332 void free_facelist(EditMesh *em, ListBase *lb) 00333 { 00334 EditFace *efa, *next; 00335 00336 efa= lb->first; 00337 while(efa) { 00338 next= efa->next; 00339 free_editface(em, efa); 00340 efa= next; 00341 } 00342 lb->first= lb->last= NULL; 00343 em->totface= em->totfacesel= 0; 00344 } 00345 00346 EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges) 00347 { 00348 EditFace *efa; 00349 EditEdge *e1, *e2=0, *e3=0, *e4=0; 00350 00351 /* added sanity check... seems to happen for some tools, or for enter editmode for corrupted meshes */ 00352 if(v1==v4 || v2==v4 || v3==v4) v4= NULL; 00353 00354 /* add face to list and do the edges */ 00355 if(exampleEdges) { 00356 e1= addedgelist(em, v1, v2, exampleEdges->e1); 00357 e2= addedgelist(em, v2, v3, exampleEdges->e2); 00358 if(v4) e3= addedgelist(em, v3, v4, exampleEdges->e3); 00359 else e3= addedgelist(em, v3, v1, exampleEdges->e3); 00360 if(v4) e4= addedgelist(em, v4, v1, exampleEdges->e4); 00361 } 00362 else { 00363 e1= addedgelist(em, v1, v2, NULL); 00364 e2= addedgelist(em, v2, v3, NULL); 00365 if(v4) e3= addedgelist(em, v3, v4, NULL); 00366 else e3= addedgelist(em, v3, v1, NULL); 00367 if(v4) e4= addedgelist(em, v4, v1, NULL); 00368 } 00369 00370 if(v1==v2 || v2==v3 || v1==v3) return NULL; 00371 if(e2==0) return NULL; 00372 00373 efa= (EditFace *)callocface(em, sizeof(EditFace), 1); 00374 efa->v1= v1; 00375 efa->v2= v2; 00376 efa->v3= v3; 00377 efa->v4= v4; 00378 00379 efa->e1= e1; 00380 efa->e2= e2; 00381 efa->e3= e3; 00382 efa->e4= e4; 00383 00384 if(example) { 00385 efa->mat_nr= example->mat_nr; 00386 efa->flag= example->flag; 00387 CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data); 00388 CustomData_em_validate_data(&em->fdata, efa->data, efa->v4 ? 4 : 3); 00389 } 00390 else { 00391 efa->mat_nr= em->mat_nr; 00392 00393 CustomData_em_set_default(&em->fdata, &efa->data); 00394 } 00395 00396 BLI_addtail(&em->faces, efa); 00397 em->totface++; 00398 00399 if(efa->v4) { 00400 normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); 00401 cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); 00402 } 00403 else { 00404 normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co); 00405 cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co); 00406 } 00407 00408 return efa; 00409 } 00410 00411 /* ************************ end add/new/find ************ */ 00412 00413 /* ************************ Edit{Vert,Edge,Face} utilss ***************************** */ 00414 00415 /* some nice utility functions */ 00416 00417 EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve) 00418 { 00419 if (eve==eed->v1) { 00420 return eed->v2; 00421 } else if (eve==eed->v2) { 00422 return eed->v1; 00423 } else { 00424 return NULL; 00425 } 00426 } 00427 00428 EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2) 00429 { 00430 if (eed->v1==eed2->v1 || eed->v1==eed2->v2) { 00431 return eed->v1; 00432 } else if (eed->v2==eed2->v1 || eed->v2==eed2->v2) { 00433 return eed->v2; 00434 } else { 00435 return NULL; 00436 } 00437 } 00438 00439 int editedge_containsVert(EditEdge *eed, EditVert *eve) 00440 { 00441 return (eed->v1==eve || eed->v2==eve); 00442 } 00443 00444 int editface_containsVert(EditFace *efa, EditVert *eve) 00445 { 00446 return (efa->v1==eve || efa->v2==eve || efa->v3==eve || (efa->v4 && efa->v4==eve)); 00447 } 00448 00449 int editface_containsEdge(EditFace *efa, EditEdge *eed) 00450 { 00451 return (efa->e1==eed || efa->e2==eed || efa->e3==eed || (efa->e4 && efa->e4==eed)); 00452 } 00453 00454 00455 /* ************************ stuct EditMesh manipulation ***************************** */ 00456 00457 /* fake callocs for fastmalloc below */ 00458 static void *calloc_fastvert(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr)) 00459 { 00460 EditVert *eve= em->curvert++; 00461 eve->fast= 1; 00462 return eve; 00463 } 00464 static void *calloc_fastedge(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr)) 00465 { 00466 EditEdge *eed= em->curedge++; 00467 eed->fast= 1; 00468 return eed; 00469 } 00470 static void *calloc_fastface(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr)) 00471 { 00472 EditFace *efa= em->curface++; 00473 efa->fast= 1; 00474 return efa; 00475 } 00476 00477 /* allocate 1 chunk for all vertices, edges, faces. These get tagged to 00478 prevent it from being freed 00479 */ 00480 static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface) 00481 { 00482 if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts"); 00483 else em->allverts= NULL; 00484 em->curvert= em->allverts; 00485 00486 if(totedge==0) totedge= 4*totface; // max possible 00487 00488 if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges"); 00489 else em->alledges= NULL; 00490 em->curedge= em->alledges; 00491 00492 if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces"); 00493 else em->allfaces= NULL; 00494 em->curface= em->allfaces; 00495 00496 callocvert= calloc_fastvert; 00497 callocedge= calloc_fastedge; 00498 callocface= calloc_fastface; 00499 } 00500 00501 static void end_editmesh_fastmalloc(void) 00502 { 00503 callocvert= calloc_em; 00504 callocedge= calloc_em; 00505 callocface= calloc_em; 00506 } 00507 00508 /* do not free editmesh itself here */ 00509 void free_editMesh(EditMesh *em) 00510 { 00511 if(em==NULL) return; 00512 00513 if(em->verts.first) free_vertlist(em, &em->verts); 00514 if(em->edges.first) free_edgelist(em, &em->edges); 00515 if(em->faces.first) free_facelist(em, &em->faces); 00516 if(em->selected.first) BLI_freelistN(&(em->selected)); 00517 00518 CustomData_free(&em->vdata, 0); 00519 CustomData_free(&em->fdata, 0); 00520 00521 if(em->derivedFinal) { 00522 if (em->derivedFinal!=em->derivedCage) { 00523 em->derivedFinal->needsFree= 1; 00524 em->derivedFinal->release(em->derivedFinal); 00525 } 00526 em->derivedFinal= NULL; 00527 } 00528 if(em->derivedCage) { 00529 em->derivedCage->needsFree= 1; 00530 em->derivedCage->release(em->derivedCage); 00531 em->derivedCage= NULL; 00532 } 00533 00534 /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */ 00535 #if 0 00536 if(em->hashedgetab) { 00537 HashEdge *he, *hen; 00538 int a, used=0, max=0, nr; 00539 he= em->hashedgetab; 00540 for(a=0; a<EDHASHSIZE; a++, he++) { 00541 if(he->eed) used++; 00542 hen= he->next; 00543 nr= 0; 00544 while(hen) { 00545 nr++; 00546 hen= hen->next; 00547 } 00548 if(max<nr) max= nr; 00549 } 00550 printf("hastab used %d max %d\n", used, max); 00551 } 00552 #endif 00553 if(em->hashedgetab) MEM_freeN(em->hashedgetab); 00554 em->hashedgetab= NULL; 00555 00556 if(em->allverts) MEM_freeN(em->allverts); 00557 if(em->alledges) MEM_freeN(em->alledges); 00558 if(em->allfaces) MEM_freeN(em->allfaces); 00559 00560 em->allverts= em->curvert= NULL; 00561 em->alledges= em->curedge= NULL; 00562 em->allfaces= em->curface= NULL; 00563 00564 mesh_octree_table(NULL, NULL, NULL, 'e'); 00565 mesh_mirrtopo_table(NULL, 'e'); 00566 00567 em->totvert= em->totedge= em->totface= 0; 00568 00569 // XXX if(em->retopo_paint_data) retopo_free_paint_data(em->retopo_paint_data); 00570 em->retopo_paint_data= NULL; 00571 em->act_face = NULL; 00572 } 00573 00574 static void editMesh_set_hash(EditMesh *em) 00575 { 00576 EditEdge *eed; 00577 00578 if(em->hashedgetab) MEM_freeN(em->hashedgetab); 00579 em->hashedgetab= NULL; 00580 00581 for(eed=em->edges.first; eed; eed= eed->next) { 00582 if( findedgelist(em, eed->v1, eed->v2)==NULL ) 00583 insert_hashedge(em, eed); 00584 } 00585 00586 } 00587 00588 00589 /* ************************ IN & OUT EDITMODE ***************************** */ 00590 00591 00592 static void edge_normal_compare(EditEdge *eed, EditFace *efa1) 00593 { 00594 EditFace *efa2; 00595 float cent1[3], cent2[3]; 00596 float inp; 00597 00598 efa2 = eed->tmp.f; 00599 if(efa1==efa2) return; 00600 00601 inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2]; 00602 if(inp<0.999f && inp >-0.999f) eed->f2= 1; 00603 00604 if(efa1->v4) cent_quad_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co); 00605 else cent_tri_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co); 00606 if(efa2->v4) cent_quad_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co); 00607 else cent_tri_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co); 00608 00609 sub_v3_v3v3(cent1, cent2, cent1); 00610 normalize_v3(cent1); 00611 inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2]; 00612 00613 if(inp < -0.001f) eed->f1= 1; 00614 } 00615 00616 #if 0 00617 typedef struct { 00618 EditEdge *eed; 00619 float noLen,no[3]; 00620 int adjCount; 00621 } EdgeDrawFlagInfo; 00622 00623 static int edgeDrawFlagInfo_cmp(const void *av, const void *bv) 00624 { 00625 const EdgeDrawFlagInfo *a = av; 00626 const EdgeDrawFlagInfo *b = bv; 00627 00628 if (a->noLen<b->noLen) return -1; 00629 else if (a->noLen>b->noLen) return 1; 00630 else return 0; 00631 } 00632 #endif 00633 00634 static void edge_drawflags(Mesh *me, EditMesh *em) 00635 { 00636 EditVert *eve; 00637 EditEdge *eed, *e1, *e2, *e3, *e4; 00638 EditFace *efa; 00639 00640 /* - count number of times edges are used in faces: 0 en 1 time means draw edge 00641 * - edges more than 1 time used: in *tmp.f is pointer to first face 00642 * - check all faces, when normal differs to much: draw (flag becomes 1) 00643 */ 00644 00645 /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old 00646 game engine (2.04) 00647 */ 00648 00649 recalc_editnormals(em); 00650 00651 /* init */ 00652 eve= em->verts.first; 00653 while(eve) { 00654 eve->f1= 1; /* during test it's set at zero */ 00655 eve= eve->next; 00656 } 00657 eed= em->edges.first; 00658 while(eed) { 00659 eed->f2= eed->f1= 0; 00660 eed->tmp.f = 0; 00661 eed= eed->next; 00662 } 00663 00664 efa= em->faces.first; 00665 while(efa) { 00666 e1= efa->e1; 00667 e2= efa->e2; 00668 e3= efa->e3; 00669 e4= efa->e4; 00670 if(e1->f2<4) e1->f2+= 1; 00671 if(e2->f2<4) e2->f2+= 1; 00672 if(e3->f2<4) e3->f2+= 1; 00673 if(e4 && e4->f2<4) e4->f2+= 1; 00674 00675 if(e1->tmp.f == 0) e1->tmp.f = (void *) efa; 00676 if(e2->tmp.f == 0) e2->tmp.f = (void *) efa; 00677 if(e3->tmp.f ==0) e3->tmp.f = (void *) efa; 00678 if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa; 00679 00680 efa= efa->next; 00681 } 00682 00683 if(me->drawflag & ME_ALLEDGES) { 00684 efa= em->faces.first; 00685 while(efa) { 00686 if(efa->e1->f2>=2) efa->e1->f2= 1; 00687 if(efa->e2->f2>=2) efa->e2->f2= 1; 00688 if(efa->e3->f2>=2) efa->e3->f2= 1; 00689 if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1; 00690 00691 efa= efa->next; 00692 } 00693 } 00694 else { 00695 00696 /* handle single-edges for 'test cylinder flag' (old engine) */ 00697 00698 eed= em->edges.first; 00699 while(eed) { 00700 if(eed->f2==1) eed->f1= 1; 00701 eed= eed->next; 00702 } 00703 00704 /* all faces, all edges with flag==2: compare normal */ 00705 efa= em->faces.first; 00706 while(efa) { 00707 if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa); 00708 else efa->e1->f2= 1; 00709 if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa); 00710 else efa->e2->f2= 1; 00711 if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa); 00712 else efa->e3->f2= 1; 00713 if(efa->e4) { 00714 if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa); 00715 else efa->e4->f2= 1; 00716 } 00717 efa= efa->next; 00718 } 00719 00720 /* sphere collision flag */ 00721 00722 eed= em->edges.first; 00723 while(eed) { 00724 if(eed->f1!=1) { 00725 eed->v1->f1= eed->v2->f1= 0; 00726 } 00727 eed= eed->next; 00728 } 00729 00730 } 00731 } 00732 00733 /* turns Mesh into editmesh */ 00734 void make_editMesh(Scene *scene, Object *ob) 00735 { 00736 Mesh *me= ob->data; 00737 MFace *mface; 00738 MVert *mvert; 00739 MSelect *mselect; 00740 KeyBlock *actkey; 00741 EditMesh *em; 00742 EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4; 00743 EditFace *efa, *efa_last_sel= NULL; 00744 EditEdge *eed; 00745 EditSelection *ese; 00746 float *co, (*keyco)[3]= NULL; 00747 int tot, a, eekadoodle= 0; 00748 const short is_paint_sel= paint_facesel_test(ob); 00749 00750 if(me->edit_mesh==NULL) 00751 me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh"); 00752 else 00753 /* because of reload */ 00754 free_editMesh(me->edit_mesh); 00755 00756 em= me->edit_mesh; 00757 00758 em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced 00759 em->act_face = NULL; 00760 em->totvert= tot= me->totvert; 00761 em->totedge= me->totedge; 00762 em->totface= me->totface; 00763 00764 if(tot==0) { 00765 return; 00766 } 00767 00768 if(ob->actcol > 0) 00769 em->mat_nr= ob->actcol-1; 00770 00771 /* initialize fastmalloc for editmesh */ 00772 init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface); 00773 00774 actkey = ob_get_keyblock(ob); 00775 if(actkey) { 00776 /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */ 00777 undo_editmode_clear(); 00778 keyco= actkey->data; 00779 em->shapenr= ob->shapenr; 00780 } 00781 00782 /* make editverts */ 00783 CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); 00784 mvert= me->mvert; 00785 00786 evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist"); 00787 for(a=0; a<tot; a++, mvert++) { 00788 00789 co= mvert->co; 00790 00791 /* edit the shape key coordinate if available */ 00792 if(keyco && a < actkey->totelem) 00793 co= keyco[a]; 00794 00795 eve= addvertlist(em, co, NULL); 00796 evlist[a]= eve; 00797 00798 /* face select sets selection in next loop */ 00799 if(!is_paint_sel) 00800 eve->f |= (mvert->flag & 1); 00801 00802 if (mvert->flag & ME_HIDE) eve->h= 1; 00803 normal_short_to_float_v3(eve->no, mvert->no); 00804 00805 eve->bweight= ((float)mvert->bweight)/255.0f; 00806 00807 /* lets overwrite the keyindex of the editvert 00808 * with the order it used to be in before 00809 * editmode 00810 */ 00811 eve->keyindex = a; 00812 00813 CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data); 00814 } 00815 00816 if(actkey && actkey->totelem!=me->totvert); 00817 else { 00818 MEdge *medge= me->medge; 00819 00820 CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0); 00821 /* make edges */ 00822 for(a=0; a<me->totedge; a++, medge++) { 00823 eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL); 00824 /* eed can be zero when v1 and v2 are identical, dxf import does this... */ 00825 if(eed) { 00826 eed->crease= ((float)medge->crease)/255.0f; 00827 eed->bweight= ((float)medge->bweight)/255.0f; 00828 00829 if(medge->flag & ME_SEAM) eed->seam= 1; 00830 if(medge->flag & ME_SHARP) eed->sharp = 1; 00831 if(medge->flag & SELECT) eed->f |= SELECT; 00832 if(medge->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! 00833 if(medge->flag & ME_HIDE) eed->h |= 1; 00834 if(em->selectmode==SCE_SELECT_EDGE) 00835 EM_select_edge(eed, eed->f & SELECT); // force edge selection to vertices, seems to be needed ... 00836 CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data); 00837 } 00838 } 00839 00840 CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); 00841 00842 /* make faces */ 00843 mface= me->mface; 00844 00845 for(a=0; a<me->totface; a++, mface++) { 00846 eve1= evlist[mface->v1]; 00847 eve2= evlist[mface->v2]; 00848 if(!mface->v3) eekadoodle= 1; 00849 eve3= evlist[mface->v3]; 00850 if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL; 00851 00852 efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL); 00853 00854 if(efa) { 00855 CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data); 00856 00857 efa->mat_nr= mface->mat_nr; 00858 efa->flag= mface->flag & ~ME_HIDE; 00859 00860 /* select and hide face flag */ 00861 if(mface->flag & ME_HIDE) { 00862 efa->h= 1; 00863 } else { 00864 if (a==me->act_face) { 00865 EM_set_actFace(em, efa); 00866 } 00867 00868 /* dont allow hidden and selected */ 00869 if(mface->flag & ME_FACE_SEL) { 00870 efa->f |= SELECT; 00871 00872 if(is_paint_sel) { 00873 EM_select_face(efa, 1); /* flush down */ 00874 } 00875 00876 efa_last_sel= efa; 00877 } 00878 } 00879 } 00880 } 00881 } 00882 00883 if(EM_get_actFace(em, 0)==NULL && efa_last_sel) { 00884 EM_set_actFace(em, efa_last_sel); 00885 } 00886 00887 if(eekadoodle) 00888 error("This Mesh has old style edgecodes, please put it in the bugtracker!"); 00889 00890 MEM_freeN(evlist); 00891 00892 end_editmesh_fastmalloc(); // resets global function pointers 00893 00894 if(me->mselect){ 00895 //restore editselections 00896 EM_init_index_arrays(em, 1,1,1); 00897 mselect = me->mselect; 00898 00899 for(a=0; a<me->totselect; a++, mselect++){ 00900 /*check if recorded selection is still valid, if so copy into editmesh*/ 00901 if( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ){ 00902 ese = MEM_callocN(sizeof(EditSelection), "Edit Selection"); 00903 ese->type = mselect->type; 00904 if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else 00905 if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else 00906 if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index); 00907 BLI_addtail(&(em->selected),ese); 00908 } 00909 } 00910 EM_free_index_arrays(); 00911 } 00912 /* this creates coherent selections. also needed for older files */ 00913 EM_selectmode_set(em); 00914 /* paranoia check to enforce hide rules */ 00915 EM_hide_reset(em); 00916 /* sets helper flags which arent saved */ 00917 EM_fgon_flags(em); 00918 00919 if (EM_get_actFace(em, 0)==NULL) { 00920 EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */ 00921 } 00922 } 00923 00924 /* makes Mesh out of editmesh */ 00925 void load_editMesh(Scene *scene, Object *obedit) 00926 { 00927 Mesh *me= obedit->data; 00928 MVert *mvert, *oldverts; 00929 MEdge *medge; 00930 MFace *mface; 00931 MSelect *mselect; 00932 EditMesh *em= me->edit_mesh; 00933 EditVert *eve; 00934 EditFace *efa, *efa_act; 00935 EditEdge *eed; 00936 EditSelection *ese; 00937 float *fp, *newkey, *oldkey; 00938 int i, a, ototvert; 00939 00940 /* this one also tests of edges are not in faces: */ 00941 /* eed->f2==0: not in face, f2==1: draw it */ 00942 /* eed->f1 : flag for dynaface (cylindertest, old engine) */ 00943 /* eve->f1 : flag for dynaface (sphere test, old engine) */ 00944 /* eve->f2 : being used in vertexnormals */ 00945 edge_drawflags(me, em); 00946 00947 EM_stats_update(em); 00948 00949 /* new Vertex block */ 00950 if(em->totvert==0) mvert= NULL; 00951 else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert"); 00952 00953 /* new Edge block */ 00954 if(em->totedge==0) medge= NULL; 00955 else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge"); 00956 00957 /* new Face block */ 00958 if(em->totface==0) mface= NULL; 00959 else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face"); 00960 00961 /* lets save the old verts just in case we are actually working on 00962 * a key ... we now do processing of the keys at the end */ 00963 oldverts= me->mvert; 00964 ototvert= me->totvert; 00965 00966 /* don't free this yet */ 00967 CustomData_set_layer(&me->vdata, CD_MVERT, NULL); 00968 00969 /* free custom data */ 00970 CustomData_free(&me->vdata, me->totvert); 00971 CustomData_free(&me->edata, me->totedge); 00972 CustomData_free(&me->fdata, me->totface); 00973 00974 /* add new custom data */ 00975 me->totvert= em->totvert; 00976 me->totedge= em->totedge; 00977 me->totface= em->totface; 00978 00979 CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert); 00980 CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge); 00981 CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface); 00982 00983 CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); 00984 CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); 00985 CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface); 00986 mesh_update_customdata_pointers(me); 00987 00988 /* the vertices, use ->tmp.l as counter */ 00989 eve= em->verts.first; 00990 a= 0; 00991 00992 while(eve) { 00993 VECCOPY(mvert->co, eve->co); 00994 00995 /* vertex normal */ 00996 normal_float_to_short_v3(mvert->no, eve->no); 00997 00998 /* note: it used to remove me->dvert when it was not in use, cancelled 00999 that... annoying when you have a fresh vgroup */ 01000 CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a); 01001 01002 eve->tmp.l = a++; /* counter */ 01003 01004 mvert->flag= 0; 01005 mvert->flag |= (eve->f & SELECT); 01006 if (eve->h) mvert->flag |= ME_HIDE; 01007 01008 mvert->bweight= (char)(255.0f*eve->bweight); 01009 01010 eve= eve->next; 01011 mvert++; 01012 } 01013 01014 /* the edges */ 01015 a= 0; 01016 eed= em->edges.first; 01017 while(eed) { 01018 medge->v1= (unsigned int) eed->v1->tmp.l; 01019 medge->v2= (unsigned int) eed->v2->tmp.l; 01020 01021 medge->flag= (eed->f & SELECT) | ME_EDGERENDER; 01022 if(eed->f2<2) medge->flag |= ME_EDGEDRAW; 01023 if(eed->f2==0) medge->flag |= ME_LOOSEEDGE; 01024 if(eed->sharp) medge->flag |= ME_SHARP; 01025 if(eed->seam) medge->flag |= ME_SEAM; 01026 if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes 01027 if(eed->h & 1) medge->flag |= ME_HIDE; 01028 01029 medge->crease= (char)(255.0f*eed->crease); 01030 medge->bweight= (char)(255.0f*eed->bweight); 01031 CustomData_from_em_block(&em->edata, &me->edata, eed->data, a); 01032 01033 eed->tmp.l = a++; 01034 01035 medge++; 01036 eed= eed->next; 01037 } 01038 01039 /* the faces */ 01040 a = 0; 01041 efa= em->faces.first; 01042 efa_act= EM_get_actFace(em, 0); 01043 i = 0; 01044 me->act_face = -1; 01045 while(efa) { 01046 mface= &((MFace *) me->mface)[i]; 01047 01048 mface->v1= (unsigned int) efa->v1->tmp.l; 01049 mface->v2= (unsigned int) efa->v2->tmp.l; 01050 mface->v3= (unsigned int) efa->v3->tmp.l; 01051 if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l; 01052 01053 mface->mat_nr= efa->mat_nr; 01054 01055 mface->flag= efa->flag; 01056 /* bit 0 of flag is already taken for smooth... */ 01057 01058 if(efa->h) { 01059 mface->flag |= ME_HIDE; 01060 mface->flag &= ~ME_FACE_SEL; 01061 } else { 01062 if(efa->f & 1) mface->flag |= ME_FACE_SEL; 01063 else mface->flag &= ~ME_FACE_SEL; 01064 } 01065 01066 /* watch: efa->e1->f2==0 means loose edge */ 01067 01068 if(efa->e1->f2==1) { 01069 efa->e1->f2= 2; 01070 } 01071 if(efa->e2->f2==1) { 01072 efa->e2->f2= 2; 01073 } 01074 if(efa->e3->f2==1) { 01075 efa->e3->f2= 2; 01076 } 01077 if(efa->e4 && efa->e4->f2==1) { 01078 efa->e4->f2= 2; 01079 } 01080 01081 CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i); 01082 01083 /* no index '0' at location 3 or 4 */ 01084 test_index_face(mface, &me->fdata, i, efa->v4?4:3); 01085 01086 if (efa_act == efa) 01087 me->act_face = a; 01088 01089 efa->tmp.l = a++; 01090 i++; 01091 efa= efa->next; 01092 } 01093 01094 /* patch hook indices and vertex parents */ 01095 { 01096 Object *ob; 01097 ModifierData *md; 01098 EditVert **vertMap = NULL; 01099 int j; 01100 01101 for (ob=G.main->object.first; ob; ob=ob->id.next) { 01102 if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) { 01103 01104 /* duplicate code from below, make it function later...? */ 01105 if (!vertMap) { 01106 vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); 01107 01108 for (eve=em->verts.first; eve; eve=eve->next) { 01109 if (eve->keyindex!=-1) 01110 vertMap[eve->keyindex] = eve; 01111 } 01112 } 01113 if(ob->par1 < ototvert) { 01114 eve = vertMap[ob->par1]; 01115 if(eve) ob->par1= eve->tmp.l; 01116 } 01117 if(ob->par2 < ototvert) { 01118 eve = vertMap[ob->par2]; 01119 if(eve) ob->par2= eve->tmp.l; 01120 } 01121 if(ob->par3 < ototvert) { 01122 eve = vertMap[ob->par3]; 01123 if(eve) ob->par3= eve->tmp.l; 01124 } 01125 01126 } 01127 if (ob->data==me) { 01128 for (md=ob->modifiers.first; md; md=md->next) { 01129 if (md->type==eModifierType_Hook) { 01130 HookModifierData *hmd = (HookModifierData*) md; 01131 01132 if (!vertMap) { 01133 vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); 01134 01135 for (eve=em->verts.first; eve; eve=eve->next) { 01136 if (eve->keyindex!=-1) 01137 vertMap[eve->keyindex] = eve; 01138 } 01139 } 01140 01141 for (i=j=0; i<hmd->totindex; i++) { 01142 if(hmd->indexar[i] < ototvert) { 01143 eve = vertMap[hmd->indexar[i]]; 01144 01145 if (eve) { 01146 hmd->indexar[j++] = eve->tmp.l; 01147 } 01148 } 01149 else j++; 01150 } 01151 01152 hmd->totindex = j; 01153 } 01154 } 01155 } 01156 } 01157 01158 if (vertMap) MEM_freeN(vertMap); 01159 } 01160 01161 /* are there keys? */ 01162 if(me->key) { 01163 KeyBlock *currkey; 01164 KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1); 01165 01166 float (*ofs)[3] = NULL; 01167 01168 /* editing the base key should update others */ 01169 if(me->key->type==KEY_RELATIVE && oldverts) { 01170 int act_is_basis = 0; 01171 /* find if this key is a basis for any others */ 01172 for(currkey = me->key->block.first; currkey; currkey= currkey->next) { 01173 if(em->shapenr-1 == currkey->relative) { 01174 act_is_basis = 1; 01175 break; 01176 } 01177 } 01178 01179 if(act_is_basis) { /* active key is a base */ 01180 float (*fp)[3]= actkey->data; 01181 i=0; 01182 ofs= MEM_callocN(sizeof(float) * 3 * em->totvert, "currkey->data"); 01183 eve= em->verts.first; 01184 mvert = me->mvert; 01185 while(eve) { 01186 if(eve->keyindex>=0) 01187 VECSUB(ofs[i], mvert->co, fp[eve->keyindex]); 01188 01189 eve= eve->next; 01190 i++; 01191 mvert++; 01192 } 01193 } 01194 } 01195 01196 01197 /* Lets reorder the key data so that things line up roughly 01198 * with the way things were before editmode */ 01199 currkey = me->key->block.first; 01200 while(currkey) { 01201 int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative)); 01202 01203 fp= newkey= MEM_callocN(me->key->elemsize*em->totvert, "currkey->data"); 01204 oldkey = currkey->data; 01205 01206 eve= em->verts.first; 01207 01208 i = 0; 01209 mvert = me->mvert; 01210 while(eve) { 01211 if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex 01212 if(currkey == actkey) { 01213 if(actkey == me->key->refkey) { 01214 VECCOPY(fp, mvert->co); 01215 } 01216 else { 01217 VECCOPY(fp, mvert->co); 01218 if(oldverts) { 01219 VECCOPY(mvert->co, oldverts[eve->keyindex].co); 01220 } 01221 } 01222 } 01223 else { 01224 if(oldkey) { 01225 VECCOPY(fp, oldkey + 3 * eve->keyindex); 01226 } 01227 } 01228 } 01229 else { 01230 VECCOPY(fp, mvert->co); 01231 } 01232 01233 /* propagate edited basis offsets to other shapes */ 01234 if(apply_offset) { 01235 VECADD(fp, fp, ofs[i]); 01236 } 01237 01238 fp+= 3; 01239 ++i; 01240 ++mvert; 01241 eve= eve->next; 01242 } 01243 currkey->totelem= em->totvert; 01244 if(currkey->data) MEM_freeN(currkey->data); 01245 currkey->data = newkey; 01246 01247 currkey= currkey->next; 01248 } 01249 01250 if(ofs) MEM_freeN(ofs); 01251 } 01252 01253 if(oldverts) MEM_freeN(oldverts); 01254 01255 i = 0; 01256 for(ese=em->selected.first; ese; ese=ese->next) i++; 01257 me->totselect = i; 01258 if(i==0) mselect= NULL; 01259 else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections"); 01260 01261 if(me->mselect) MEM_freeN(me->mselect); 01262 me->mselect= mselect; 01263 01264 for(ese=em->selected.first; ese; ese=ese->next){ 01265 mselect->type = ese->type; 01266 if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l; 01267 else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l; 01268 else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l; 01269 mselect++; 01270 } 01271 01272 /* to be sure: clear ->tmp.l pointers */ 01273 eve= em->verts.first; 01274 while(eve) { 01275 eve->tmp.l = 0; 01276 eve= eve->next; 01277 } 01278 01279 eed= em->edges.first; 01280 while(eed) { 01281 eed->tmp.l = 0; 01282 eed= eed->next; 01283 } 01284 01285 efa= em->faces.first; 01286 while(efa) { 01287 efa->tmp.l = 0; 01288 efa= efa->next; 01289 } 01290 01291 /* remake softbody of all users */ 01292 if(me->id.us>1) { 01293 Base *base; 01294 for(base= scene->base.first; base; base= base->next) 01295 if(base->object->data==me) 01296 base->object->recalc |= OB_RECALC_DATA; 01297 } 01298 01299 mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); 01300 01301 /* topology could be changed, ensure mdisps are ok */ 01302 multires_topology_changed(scene, obedit); 01303 } 01304 01305 void remake_editMesh(Scene *scene, Object *ob) 01306 { 01307 make_editMesh(scene, ob); 01308 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01309 BIF_undo_push("Undo all changes"); 01310 } 01311 01312 /* *************** Operator: separate parts *************/ 01313 01314 static EnumPropertyItem prop_separate_types[] = { 01315 {0, "SELECTED", 0, "Selection", ""}, 01316 {1, "MATERIAL", 0, "By Material", ""}, 01317 {2, "LOOSE", 0, "By loose parts", ""}, 01318 {0, NULL, 0, NULL, NULL} 01319 }; 01320 01321 /* return 1: success */ 01322 static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) 01323 { 01324 EditMesh *em, *emnew; 01325 EditVert *eve, *v1; 01326 EditEdge *eed, *e1; 01327 EditFace *efa, *f1; 01328 Object *obedit; 01329 Mesh *me, *menew; 01330 Base *basenew; 01331 01332 if(editbase==NULL) return 0; 01333 01334 obedit= editbase->object; 01335 me= obedit->data; 01336 em= BKE_mesh_get_editmesh(me); 01337 if(me->key) { 01338 BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys."); 01339 BKE_mesh_end_editmesh(me, em); 01340 return 0; 01341 } 01342 01343 if(em->selected.first) 01344 BLI_freelistN(&(em->selected)); /* clear the selection order */ 01345 01346 EM_selectmode_set(em); // enforce full consistent selection flags 01347 01348 EM_stats_update(em); 01349 01350 if(em->totvertsel==0) { 01351 BKE_mesh_end_editmesh(me, em); 01352 return 0; 01353 } 01354 01355 /* we are going to work as follows: 01356 * 1. add a linked duplicate object: this will be the new one, we remember old pointer 01357 * 2. give new object empty mesh and put in editmode 01358 * 3: do a split if needed on current editmesh. 01359 * 4. copy over: all NOT selected verts, edges, faces 01360 * 5. call load_editMesh() on the new object 01361 */ 01362 01363 /* 1 */ 01364 basenew= ED_object_add_duplicate(bmain, scene, editbase, 0); /* 0 = fully linked */ 01365 ED_base_object_select(basenew, BA_DESELECT); 01366 01367 /* 2 */ 01368 basenew->object->data= menew= add_mesh(me->id.name+2); /* empty */ 01369 assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ 01370 me->id.us--; 01371 make_editMesh(scene, basenew->object); 01372 emnew= menew->edit_mesh; 01373 CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); 01374 CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0); 01375 CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); 01376 01377 /* 3 */ 01378 /* SPLIT: first make duplicate */ 01379 adduplicateflag(em, SELECT); 01380 /* SPLIT: old faces have 3x flag 128 set, delete these ones */ 01381 delfaceflag(em, 128); 01382 /* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */ 01383 EM_selectmode_set(em); 01384 01385 /* 4 */ 01386 /* move over: everything that is selected */ 01387 for(eve= em->verts.first; eve; eve= v1) { 01388 v1= eve->next; 01389 if(eve->f & SELECT) { 01390 BLI_remlink(&em->verts, eve); 01391 BLI_addtail(&emnew->verts, eve); 01392 } 01393 } 01394 01395 for(eed= em->edges.first; eed; eed= e1) { 01396 e1= eed->next; 01397 if(eed->f & SELECT) { 01398 BLI_remlink(&em->edges, eed); 01399 BLI_addtail(&emnew->edges, eed); 01400 } 01401 } 01402 01403 for(efa= em->faces.first; efa; efa= f1) { 01404 f1= efa->next; 01405 if (efa == em->act_face && (efa->f & SELECT)) { 01406 EM_set_actFace(em, NULL); 01407 } 01408 01409 if(efa->f & SELECT) { 01410 BLI_remlink(&em->faces, efa); 01411 BLI_addtail(&emnew->faces, efa); 01412 } 01413 } 01414 01415 /* 5 */ 01416 load_editMesh(scene, basenew->object); 01417 free_editMesh(emnew); 01418 MEM_freeN(menew->edit_mesh); 01419 menew->edit_mesh= NULL; 01420 01421 /* copy settings */ 01422 menew->texflag= me->texflag; 01423 menew->drawflag= me->drawflag; 01424 menew->flag= me->flag; 01425 menew->editflag= me->editflag; 01426 menew->smoothresh= me->smoothresh; 01427 01428 /* hashedges are invalid now, make new! */ 01429 editMesh_set_hash(em); 01430 01431 DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 01432 DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA); 01433 01434 BKE_mesh_end_editmesh(me, em); 01435 01436 return 1; 01437 } 01438 01439 /* return 1: success */ 01440 static int mesh_separate_material(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) 01441 { 01442 Mesh *me= editbase->object->data; 01443 EditMesh *em= BKE_mesh_get_editmesh(me); 01444 unsigned char curr_mat; 01445 01446 for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) { 01447 /* clear selection, we're going to use that to select material group */ 01448 EM_clear_flag_all(em, SELECT); 01449 /* select the material */ 01450 EM_select_by_material(em, curr_mat); 01451 /* and now separate */ 01452 if(0==mesh_separate_selected(op, bmain, scene, editbase)) { 01453 BKE_mesh_end_editmesh(me, em); 01454 return 0; 01455 } 01456 } 01457 01458 BKE_mesh_end_editmesh(me, em); 01459 return 1; 01460 } 01461 01462 /* return 1: success */ 01463 static int mesh_separate_loose(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) 01464 { 01465 Mesh *me; 01466 EditMesh *em; 01467 int doit= 1; 01468 01469 me= editbase->object->data; 01470 em= BKE_mesh_get_editmesh(me); 01471 01472 if(me->key) { 01473 error("Can't separate with vertex keys"); 01474 BKE_mesh_end_editmesh(me, em); 01475 return 0; 01476 } 01477 01478 EM_clear_flag_all(em, SELECT); 01479 01480 while(doit) { 01481 /* Select a random vert to start with */ 01482 EditVert *eve; 01483 int tot; 01484 01485 /* check if all verts that are visible have been done */ 01486 for(eve=em->verts.first; eve; eve= eve->next) 01487 if(!eve->h) break; 01488 if(eve==NULL) break; /* only hidden verts left, quit early */ 01489 01490 /* first non hidden vert */ 01491 eve->f |= SELECT; 01492 01493 selectconnected_mesh_all(em); 01494 01495 /* don't separate the very last part */ 01496 for(eve=em->verts.first; eve; eve= eve->next) 01497 if((eve->f & SELECT)==0) break; 01498 if(eve==NULL) break; 01499 01500 tot= BLI_countlist(&em->verts); 01501 01502 /* and now separate */ 01503 doit= mesh_separate_selected(op, bmain, scene, editbase); 01504 01505 /* with hidden verts this can happen */ 01506 if(tot == BLI_countlist(&em->verts)) 01507 break; 01508 } 01509 01510 BKE_mesh_end_editmesh(me, em); 01511 return 1; 01512 } 01513 01514 01515 static int mesh_separate_exec(bContext *C, wmOperator *op) 01516 { 01517 Main *bmain= CTX_data_main(C); 01518 Scene *scene= CTX_data_scene(C); 01519 Base *base= CTX_data_active_base(C); 01520 int retval= 0, type= RNA_enum_get(op->ptr, "type"); 01521 01522 if(type == 0) 01523 retval= mesh_separate_selected(op, bmain, scene, base); 01524 else if(type == 1) 01525 retval= mesh_separate_material(op, bmain, scene, base); 01526 else if(type == 2) 01527 retval= mesh_separate_loose(op, bmain, scene, base); 01528 01529 if(retval) { 01530 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data); 01531 01532 // XXX: new object was created, but selection wasn't actually changed 01533 // need this for outliner update without adding new ND. nazgul. 01534 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); 01535 01536 return OPERATOR_FINISHED; 01537 } 01538 return OPERATOR_CANCELLED; 01539 } 01540 01541 void MESH_OT_separate(wmOperatorType *ot) 01542 { 01543 /* identifiers */ 01544 ot->name= "Separate"; 01545 ot->description= "Separate selected geometry into a new mesh"; 01546 ot->idname= "MESH_OT_separate"; 01547 01548 /* api callbacks */ 01549 ot->invoke= WM_menu_invoke; 01550 ot->exec= mesh_separate_exec; 01551 ot->poll= ED_operator_editmesh; 01552 01553 /* flags */ 01554 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01555 01556 ot->prop= RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", ""); 01557 } 01558 01559 01560 /* ******************************************** */ 01561 01562 /* *************** UNDO ***************************** */ 01563 /* new mesh undo, based on pushing editmesh data itself */ 01564 /* reuses same code as for global and curve undo... unify that (ton) */ 01565 01566 /* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */ 01567 01568 /* a compressed version of editmesh data */ 01569 01570 typedef struct EditVertC 01571 { 01572 float no[3]; 01573 float co[3]; 01574 unsigned char f, h; 01575 short bweight; 01576 int keyindex; 01577 } EditVertC; 01578 01579 typedef struct EditEdgeC 01580 { 01581 int v1, v2; 01582 unsigned char f, h, seam, sharp, pad; 01583 short crease, bweight, fgoni; 01584 } EditEdgeC; 01585 01586 typedef struct EditFaceC 01587 { 01588 int v1, v2, v3, v4; 01589 unsigned char flag, f, h, fgonf, pad1; 01590 short mat_nr; 01591 } EditFaceC; 01592 01593 typedef struct EditSelectionC{ 01594 short type; 01595 int index; 01596 }EditSelectionC; 01597 01598 typedef struct UndoMesh { 01599 EditVertC *verts; 01600 EditEdgeC *edges; 01601 EditFaceC *faces; 01602 EditSelectionC *selected; 01603 int totvert, totedge, totface, totsel; 01604 int selectmode, shapenr; 01605 char retopo_mode; 01606 CustomData vdata, edata, fdata; 01607 } UndoMesh; 01608 01609 /* for callbacks */ 01610 01611 static void free_undoMesh(void *umv) 01612 { 01613 UndoMesh *um= umv; 01614 01615 if(um->verts) MEM_freeN(um->verts); 01616 if(um->edges) MEM_freeN(um->edges); 01617 if(um->faces) MEM_freeN(um->faces); 01618 if(um->selected) MEM_freeN(um->selected); 01619 // XXX if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data); 01620 CustomData_free(&um->vdata, um->totvert); 01621 CustomData_free(&um->edata, um->totedge); 01622 CustomData_free(&um->fdata, um->totface); 01623 MEM_freeN(um); 01624 } 01625 01626 static void *editMesh_to_undoMesh(void *emv) 01627 { 01628 EditMesh *em= (EditMesh *)emv; 01629 UndoMesh *um; 01630 EditVert *eve; 01631 EditEdge *eed; 01632 EditFace *efa; 01633 EditSelection *ese; 01634 EditVertC *evec=NULL; 01635 EditEdgeC *eedc=NULL; 01636 EditFaceC *efac=NULL; 01637 EditSelectionC *esec=NULL; 01638 int a; 01639 01640 um= MEM_callocN(sizeof(UndoMesh), "undomesh"); 01641 01642 um->selectmode = em->selectmode; 01643 um->shapenr = em->shapenr; 01644 01645 for(eve=em->verts.first; eve; eve= eve->next) um->totvert++; 01646 for(eed=em->edges.first; eed; eed= eed->next) um->totedge++; 01647 for(efa=em->faces.first; efa; efa= efa->next) um->totface++; 01648 for(ese=em->selected.first; ese; ese=ese->next) um->totsel++; 01649 /* malloc blocks */ 01650 01651 if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC"); 01652 if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC"); 01653 if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC"); 01654 if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections"); 01655 01656 if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert); 01657 if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge); 01658 if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface); 01659 01660 /* now copy vertices */ 01661 a = 0; 01662 for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) { 01663 VECCOPY(evec->co, eve->co); 01664 VECCOPY(evec->no, eve->no); 01665 01666 evec->f= eve->f; 01667 evec->h= eve->h; 01668 evec->keyindex= eve->keyindex; 01669 eve->tmp.l = a; /*store index*/ 01670 evec->bweight= (short)(eve->bweight*255.0f); 01671 01672 CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a); 01673 } 01674 01675 /* copy edges */ 01676 a = 0; 01677 for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++) { 01678 eedc->v1= (int)eed->v1->tmp.l; 01679 eedc->v2= (int)eed->v2->tmp.l; 01680 eedc->f= eed->f; 01681 eedc->h= eed->h; 01682 eedc->seam= eed->seam; 01683 eedc->sharp= eed->sharp; 01684 eedc->crease= (short)(eed->crease*255.0f); 01685 eedc->bweight= (short)(eed->bweight*255.0f); 01686 eedc->fgoni= eed->fgoni; 01687 eed->tmp.l = a; /*store index*/ 01688 CustomData_from_em_block(&em->edata, &um->edata, eed->data, a); 01689 01690 } 01691 01692 /* copy faces */ 01693 a = 0; 01694 for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) { 01695 efac->v1= (int)efa->v1->tmp.l; 01696 efac->v2= (int)efa->v2->tmp.l; 01697 efac->v3= (int)efa->v3->tmp.l; 01698 if(efa->v4) efac->v4= (int)efa->v4->tmp.l; 01699 else efac->v4= -1; 01700 01701 efac->mat_nr= efa->mat_nr; 01702 efac->flag= efa->flag; 01703 efac->f= efa->f; 01704 efac->h= efa->h; 01705 efac->fgonf= efa->fgonf; 01706 01707 efa->tmp.l = a; /*store index*/ 01708 01709 CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a); 01710 } 01711 01712 a = 0; 01713 for(ese=em->selected.first; ese; ese=ese->next, esec++){ 01714 esec->type = ese->type; 01715 if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l; 01716 else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l; 01717 else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l; 01718 } 01719 01720 // XXX um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data); 01721 // um->retopo_mode= scene->toolsettings->retopo_mode; 01722 01723 return um; 01724 } 01725 01726 static void undoMesh_to_editMesh(void *umv, void *emv) 01727 { 01728 EditMesh *em= (EditMesh *)emv; 01729 UndoMesh *um= (UndoMesh *)umv; 01730 EditVert *eve, **evar=NULL; 01731 EditEdge *eed; 01732 EditFace *efa; 01733 EditSelection *ese; 01734 EditVertC *evec; 01735 EditEdgeC *eedc; 01736 EditFaceC *efac; 01737 EditSelectionC *esec; 01738 int a=0; 01739 01740 free_editMesh(em); 01741 01742 /* malloc blocks */ 01743 memset(em, 0, sizeof(EditMesh)); 01744 01745 em->selectmode = um->selectmode; 01746 em->shapenr = um->shapenr; 01747 01748 init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface); 01749 01750 CustomData_free(&em->vdata, 0); 01751 CustomData_free(&em->edata, 0); 01752 CustomData_free(&em->fdata, 0); 01753 01754 CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); 01755 CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0); 01756 CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); 01757 01758 /* now copy vertices */ 01759 01760 if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar"); 01761 for(a=0, evec= um->verts; a<um->totvert; a++, evec++) { 01762 eve= addvertlist(em, evec->co, NULL); 01763 evar[a]= eve; 01764 01765 VECCOPY(eve->no, evec->no); 01766 eve->f= evec->f; 01767 eve->h= evec->h; 01768 eve->keyindex= evec->keyindex; 01769 eve->bweight= ((float)evec->bweight)/255.0f; 01770 01771 CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data); 01772 } 01773 01774 /* copy edges */ 01775 for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) { 01776 eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL); 01777 01778 eed->f= eedc->f; 01779 eed->h= eedc->h; 01780 eed->seam= eedc->seam; 01781 eed->sharp= eedc->sharp; 01782 eed->fgoni= eedc->fgoni; 01783 eed->crease= ((float)eedc->crease)/255.0f; 01784 eed->bweight= ((float)eedc->bweight)/255.0f; 01785 CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data); 01786 } 01787 01788 /* copy faces */ 01789 for(a=0, efac= um->faces; a<um->totface; a++, efac++) { 01790 if(efac->v4 != -1) 01791 efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL); 01792 else 01793 efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL); 01794 01795 efa->mat_nr= efac->mat_nr; 01796 efa->flag= efac->flag; 01797 efa->f= efac->f; 01798 efa->h= efac->h; 01799 efa->fgonf= efac->fgonf; 01800 01801 CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data); 01802 } 01803 01804 end_editmesh_fastmalloc(); 01805 if(evar) MEM_freeN(evar); 01806 01807 em->totvert = um->totvert; 01808 em->totedge = um->totedge; 01809 em->totface = um->totface; 01810 /*restore stored editselections*/ 01811 if(um->totsel){ 01812 EM_init_index_arrays(em, 1,1,1); 01813 for(a=0, esec= um->selected; a<um->totsel; a++, esec++){ 01814 ese = MEM_callocN(sizeof(EditSelection), "Edit Selection"); 01815 ese->type = esec->type; 01816 if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else 01817 if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else 01818 if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index); 01819 BLI_addtail(&(em->selected),ese); 01820 } 01821 EM_free_index_arrays(); 01822 } 01823 01824 /* restore total selections */ 01825 EM_nvertices_selected(em); 01826 EM_nedges_selected(em); 01827 EM_nfaces_selected(em); 01828 01829 // XXX retopo_free_paint(); 01830 // em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data); 01831 // scene->toolsettings->retopo_mode= um->retopo_mode; 01832 // if(scene->toolsettings->retopo_mode) { 01833 // XXX if(G.vd->depths) G.vd->depths->damaged= 1; 01834 // retopo_queue_updates(G.vd); 01835 // retopo_paint_view_update(G.vd); 01836 // } 01837 01838 } 01839 01840 static void *getEditMesh(bContext *C) 01841 { 01842 Object *obedit= CTX_data_edit_object(C); 01843 if(obedit && obedit->type==OB_MESH) { 01844 Mesh *me= obedit->data; 01845 return me->edit_mesh; 01846 } 01847 return NULL; 01848 } 01849 01850 /* and this is all the undo system needs to know */ 01851 void undo_push_mesh(bContext *C, const char *name) 01852 { 01853 undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL); 01854 } 01855 01856 01857 01858 /* *************** END UNDO *************/ 01859 01860 static EditVert **g_em_vert_array = NULL; 01861 static EditEdge **g_em_edge_array = NULL; 01862 static EditFace **g_em_face_array = NULL; 01863 01864 void EM_init_index_arrays(EditMesh *em, int forVert, int forEdge, int forFace) 01865 { 01866 EditVert *eve; 01867 EditEdge *eed; 01868 EditFace *efa; 01869 int i; 01870 01871 if (forVert) { 01872 em->totvert= BLI_countlist(&em->verts); 01873 01874 if(em->totvert) { 01875 g_em_vert_array = MEM_mallocN(sizeof(*g_em_vert_array)*em->totvert, "em_v_arr"); 01876 01877 for (i=0,eve=em->verts.first; eve; i++,eve=eve->next) 01878 g_em_vert_array[i] = eve; 01879 } 01880 } 01881 01882 if (forEdge) { 01883 em->totedge= BLI_countlist(&em->edges); 01884 01885 if(em->totedge) { 01886 g_em_edge_array = MEM_mallocN(sizeof(*g_em_edge_array)*em->totedge, "em_e_arr"); 01887 01888 for (i=0,eed=em->edges.first; eed; i++,eed=eed->next) 01889 g_em_edge_array[i] = eed; 01890 } 01891 } 01892 01893 if (forFace) { 01894 em->totface= BLI_countlist(&em->faces); 01895 01896 if(em->totface) { 01897 g_em_face_array = MEM_mallocN(sizeof(*g_em_face_array)*em->totface, "em_f_arr"); 01898 01899 for (i=0,efa=em->faces.first; efa; i++,efa=efa->next) 01900 g_em_face_array[i] = efa; 01901 } 01902 } 01903 } 01904 01905 void EM_free_index_arrays(void) 01906 { 01907 if (g_em_vert_array) MEM_freeN(g_em_vert_array); 01908 if (g_em_edge_array) MEM_freeN(g_em_edge_array); 01909 if (g_em_face_array) MEM_freeN(g_em_face_array); 01910 g_em_vert_array = NULL; 01911 g_em_edge_array = NULL; 01912 g_em_face_array = NULL; 01913 } 01914 01915 EditVert *EM_get_vert_for_index(int index) 01916 { 01917 return g_em_vert_array?g_em_vert_array[index]:NULL; 01918 } 01919 01920 EditEdge *EM_get_edge_for_index(int index) 01921 { 01922 return g_em_edge_array?g_em_edge_array[index]:NULL; 01923 } 01924 01925 EditFace *EM_get_face_for_index(int index) 01926 { 01927 return g_em_face_array?g_em_face_array[index]:NULL; 01928 } 01929 01930 /* can we edit UV's for this mesh?*/ 01931 int EM_texFaceCheck(EditMesh *em) 01932 { 01933 /* some of these checks could be a touch overkill */ 01934 if ( (em) && 01935 (em->faces.first) && 01936 (CustomData_has_layer(&em->fdata, CD_MTFACE))) 01937 return 1; 01938 return 0; 01939 } 01940 01941 /* can we edit colors for this mesh?*/ 01942 int EM_vertColorCheck(EditMesh *em) 01943 { 01944 /* some of these checks could be a touch overkill */ 01945 if ( (em) && 01946 (em->faces.first) && 01947 (CustomData_has_layer(&em->fdata, CD_MCOL))) 01948 return 1; 01949 return 0; 01950 } 01951 01952 01953 void em_setup_viewcontext(bContext *C, ViewContext *vc) 01954 { 01955 view3d_set_viewcontext(C, vc); 01956 01957 if(vc->obedit) { 01958 Mesh *me= vc->obedit->data; 01959 vc->em= me->edit_mesh; 01960 } 01961 }