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) 2004 by 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 */ 00027 00033 /* 00034 00035 editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data 00036 00037 */ 00038 00039 #include <stdlib.h> 00040 #include <string.h> 00041 #include <math.h> 00042 00043 #include "MEM_guardedalloc.h" 00044 00045 #include "DNA_meshdata_types.h" 00046 #include "DNA_modifier_types.h" 00047 #include "DNA_object_types.h" 00048 #include "DNA_scene_types.h" 00049 00050 #include "BLI_blenlib.h" 00051 #include "BLI_math.h" 00052 #include "BLI_editVert.h" 00053 #include "BLI_edgehash.h" 00054 #include "BLI_utildefines.h" 00055 00056 #include "BKE_customdata.h" 00057 #include "BKE_context.h" 00058 #include "BKE_global.h" 00059 #include "BKE_mesh.h" 00060 00061 00062 #include "ED_mesh.h" 00063 #include "ED_screen.h" 00064 #include "ED_view3d.h" 00065 #include "ED_transform.h" 00066 00067 #include "mesh_intern.h" 00068 00069 /* Helpers for EM_set_flag_all_selectmode */ 00070 #define SET_EVE_FLAG(eve, flag) \ 00071 if (eve->h==0) { \ 00072 if (flag & SELECT && !(eve->f & SELECT)) { \ 00073 ++selvert; \ 00074 } \ 00075 eve->f |= flag; \ 00076 } 00077 00078 #define SET_EED_FLAG(eed, flag) \ 00079 if (eed->h==0) { \ 00080 if (flag & SELECT && !(eed->f & SELECT)) { \ 00081 ++seledge; \ 00082 } \ 00083 eed->f |= flag; \ 00084 SET_EVE_FLAG(eed->v1, flag); \ 00085 SET_EVE_FLAG(eed->v2, flag); \ 00086 } 00087 00088 00089 /* ****************** stats *************** */ 00090 00091 int EM_nfaces_selected(EditMesh *em) 00092 { 00093 EditFace *efa; 00094 int count= 0; 00095 00096 for (efa= em->faces.first; efa; efa= efa->next) 00097 if (efa->f & SELECT) 00098 count++; 00099 00100 em->totfacesel= count; 00101 00102 return count; 00103 } 00104 00105 int EM_nedges_selected(EditMesh *em) 00106 { 00107 EditEdge *eed; 00108 int count= 0; 00109 00110 for (eed= em->edges.first; eed; eed= eed->next) 00111 if(eed->f & SELECT) 00112 count++; 00113 00114 em->totedgesel= count; 00115 00116 return count; 00117 } 00118 00119 int EM_nvertices_selected(EditMesh *em) 00120 { 00121 EditVert *eve; 00122 int count= 0; 00123 00124 for (eve= em->verts.first; eve; eve= eve->next) 00125 if (eve->f & SELECT) 00126 count++; 00127 00128 em->totvertsel= count; 00129 00130 return count; 00131 } 00132 00133 void EM_stats_update(EditMesh *em) 00134 { 00135 00136 em->totvert= BLI_countlist(&em->verts); 00137 em->totedge= BLI_countlist(&em->edges); 00138 em->totface= BLI_countlist(&em->faces); 00139 00140 EM_nvertices_selected(em); 00141 EM_nedges_selected(em); 00142 EM_nfaces_selected(em); 00143 } 00144 00145 /* ************************************** */ 00146 00147 /* this replaces the active flag used in uv/face mode */ 00148 void EM_set_actFace(EditMesh *em, EditFace *efa) 00149 { 00150 em->act_face = efa; 00151 } 00152 00153 EditFace *EM_get_actFace(EditMesh *em, int sloppy) 00154 { 00155 if (em->act_face) { 00156 return em->act_face; 00157 } else if (sloppy) { 00158 EditFace *efa= NULL; 00159 EditSelection *ese; 00160 00161 ese = em->selected.last; 00162 for (; ese; ese=ese->prev){ 00163 if(ese->type == EDITFACE) { 00164 efa = (EditFace *)ese->data; 00165 00166 if (efa->h) efa= NULL; 00167 else break; 00168 } 00169 } 00170 if (efa==NULL) { 00171 for (efa= em->faces.first; efa; efa= efa->next) { 00172 if (efa->f & SELECT) 00173 break; 00174 } 00175 } 00176 return efa; /* can still be null */ 00177 } 00178 return NULL; 00179 } 00180 00181 int EM_get_actSelection(EditMesh *em, EditSelection *ese) 00182 { 00183 EditSelection *ese_last = em->selected.last; 00184 EditFace *efa = EM_get_actFace(em, 0); 00185 00186 ese->next = ese->prev = NULL; 00187 00188 if (ese_last) { 00189 if (ese_last->type == EDITFACE) { /* if there is an active face, use it over the last selected face */ 00190 if (efa) { 00191 ese->data = (void *)efa; 00192 } else { 00193 ese->data = ese_last->data; 00194 } 00195 ese->type = EDITFACE; 00196 } else { 00197 ese->data = ese_last->data; 00198 ese->type = ese_last->type; 00199 } 00200 } else if (efa) { /* no */ 00201 ese->data = (void *)efa; 00202 ese->type = EDITFACE; 00203 } else { 00204 ese->data = NULL; 00205 return 0; 00206 } 00207 return 1; 00208 } 00209 00210 /* ********* Selection History ************ */ 00211 static int EM_check_selection(EditMesh *em, void *data) 00212 { 00213 EditSelection *ese; 00214 00215 for(ese = em->selected.first; ese; ese = ese->next){ 00216 if(ese->data == data) return 1; 00217 } 00218 00219 return 0; 00220 } 00221 00222 void EM_remove_selection(EditMesh *em, void *data, int UNUSED(type)) 00223 { 00224 EditSelection *ese; 00225 for(ese=em->selected.first; ese; ese = ese->next){ 00226 if(ese->data == data){ 00227 BLI_freelinkN(&(em->selected),ese); 00228 break; 00229 } 00230 } 00231 } 00232 00233 void EM_store_selection(EditMesh *em, void *data, int type) 00234 { 00235 EditSelection *ese; 00236 if(!EM_check_selection(em, data)){ 00237 ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection"); 00238 ese->type = type; 00239 ese->data = data; 00240 BLI_addtail(&(em->selected),ese); 00241 } 00242 } 00243 00244 void EM_validate_selections(EditMesh *em) 00245 { 00246 EditSelection *ese, *nextese; 00247 00248 ese = em->selected.first; 00249 00250 while(ese){ 00251 nextese = ese->next; 00252 if(ese->type == EDITVERT && !(((EditVert*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); 00253 else if(ese->type == EDITEDGE && !(((EditEdge*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); 00254 else if(ese->type == EDITFACE && !(((EditFace*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); 00255 ese = nextese; 00256 } 00257 } 00258 00259 static void EM_strip_selections(EditMesh *em) 00260 { 00261 EditSelection *ese, *nextese; 00262 if(!(em->selectmode & SCE_SELECT_VERTEX)){ 00263 ese = em->selected.first; 00264 while(ese){ 00265 nextese = ese->next; 00266 if(ese->type == EDITVERT) BLI_freelinkN(&(em->selected),ese); 00267 ese = nextese; 00268 } 00269 } 00270 if(!(em->selectmode & SCE_SELECT_EDGE)){ 00271 ese=em->selected.first; 00272 while(ese){ 00273 nextese = ese->next; 00274 if(ese->type == EDITEDGE) BLI_freelinkN(&(em->selected), ese); 00275 ese = nextese; 00276 } 00277 } 00278 if(!(em->selectmode & SCE_SELECT_FACE)){ 00279 ese=em->selected.first; 00280 while(ese){ 00281 nextese = ese->next; 00282 if(ese->type == EDITFACE) BLI_freelinkN(&(em->selected), ese); 00283 ese = nextese; 00284 } 00285 } 00286 } 00287 00288 /* generic way to get data from an EditSelection type 00289 These functions were written to be used by the Modifier widget when in Rotate about active mode, 00290 but can be used anywhere. 00291 EM_editselection_center 00292 EM_editselection_normal 00293 EM_editselection_plane 00294 */ 00295 void EM_editselection_center(float *center, EditSelection *ese) 00296 { 00297 if (ese->type==EDITVERT) { 00298 EditVert *eve= ese->data; 00299 copy_v3_v3(center, eve->co); 00300 } else if (ese->type==EDITEDGE) { 00301 EditEdge *eed= ese->data; 00302 add_v3_v3v3(center, eed->v1->co, eed->v2->co); 00303 mul_v3_fl(center, 0.5); 00304 } else if (ese->type==EDITFACE) { 00305 EditFace *efa= ese->data; 00306 copy_v3_v3(center, efa->cent); 00307 } 00308 } 00309 00310 void EM_editselection_normal(float *normal, EditSelection *ese) 00311 { 00312 if (ese->type==EDITVERT) { 00313 EditVert *eve= ese->data; 00314 copy_v3_v3(normal, eve->no); 00315 } else if (ese->type==EDITEDGE) { 00316 EditEdge *eed= ese->data; 00317 float plane[3]; /* need a plane to correct the normal */ 00318 float vec[3]; /* temp vec storage */ 00319 00320 add_v3_v3v3(normal, eed->v1->no, eed->v2->no); 00321 sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); 00322 00323 /* the 2 vertex normals will be close but not at rightangles to the edge 00324 for rotate about edge we want them to be at right angles, so we need to 00325 do some extra colculation to correct the vert normals, 00326 we need the plane for this */ 00327 cross_v3_v3v3(vec, normal, plane); 00328 cross_v3_v3v3(normal, plane, vec); 00329 normalize_v3(normal); 00330 00331 } else if (ese->type==EDITFACE) { 00332 EditFace *efa= ese->data; 00333 copy_v3_v3(normal, efa->n); 00334 } 00335 } 00336 00337 /* Calculate a plane that is rightangles to the edge/vert/faces normal 00338 also make the plane run along an axis that is related to the geometry, 00339 because this is used for the manipulators Y axis.*/ 00340 void EM_editselection_plane(float *plane, EditSelection *ese) 00341 { 00342 if (ese->type==EDITVERT) { 00343 EditVert *eve= ese->data; 00344 float vec[3]={0,0,0}; 00345 00346 if (ese->prev) { /*use previously selected data to make a useful vertex plane */ 00347 EM_editselection_center(vec, ese->prev); 00348 sub_v3_v3v3(plane, vec, eve->co); 00349 } else { 00350 /* make a fake plane thats at rightangles to the normal 00351 we cant make a crossvec from a vec thats the same as the vec 00352 unlikely but possible, so make sure if the normal is (0,0,1) 00353 that vec isnt the same or in the same direction even.*/ 00354 if (eve->no[0]<0.5f) vec[0]=1; 00355 else if (eve->no[1]<0.5f) vec[1]=1; 00356 else vec[2]=1; 00357 cross_v3_v3v3(plane, eve->no, vec); 00358 } 00359 } else if (ese->type==EDITEDGE) { 00360 EditEdge *eed= ese->data; 00361 00362 /*the plane is simple, it runs along the edge 00363 however selecting different edges can swap the direction of the y axis. 00364 this makes it less likely for the y axis of the manipulator 00365 (running along the edge).. to flip less often. 00366 at least its more predictable */ 00367 if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */ 00368 sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); 00369 else 00370 sub_v3_v3v3(plane, eed->v1->co, eed->v2->co); 00371 00372 } else if (ese->type==EDITFACE) { 00373 EditFace *efa= ese->data; 00374 float vec[3]; 00375 if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/ 00376 float vecA[3], vecB[3]; 00377 sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co); 00378 sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co); 00379 add_v3_v3v3(plane, vecA, vecB); 00380 00381 sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co); 00382 sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co); 00383 add_v3_v3v3(vec, vecA, vecB); 00384 /*use the biggest edge length*/ 00385 if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) 00386 copy_v3_v3(plane, vec); 00387 } else { 00388 /*start with v1-2 */ 00389 sub_v3_v3v3(plane, efa->v1->co, efa->v2->co); 00390 00391 /*test the edge between v2-3, use if longer */ 00392 sub_v3_v3v3(vec, efa->v2->co, efa->v3->co); 00393 if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) 00394 copy_v3_v3(plane, vec); 00395 00396 /*test the edge between v1-3, use if longer */ 00397 sub_v3_v3v3(vec, efa->v3->co, efa->v1->co); 00398 if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) 00399 copy_v3_v3(plane, vec); 00400 } 00401 } 00402 normalize_v3(plane); 00403 } 00404 00405 00406 00407 void EM_select_face(EditFace *efa, int sel) 00408 { 00409 if(sel) { 00410 efa->f |= SELECT; 00411 efa->e1->f |= SELECT; 00412 efa->e2->f |= SELECT; 00413 efa->e3->f |= SELECT; 00414 if(efa->e4) efa->e4->f |= SELECT; 00415 efa->v1->f |= SELECT; 00416 efa->v2->f |= SELECT; 00417 efa->v3->f |= SELECT; 00418 if(efa->v4) efa->v4->f |= SELECT; 00419 } 00420 else { 00421 efa->f &= ~SELECT; 00422 efa->e1->f &= ~SELECT; 00423 efa->e2->f &= ~SELECT; 00424 efa->e3->f &= ~SELECT; 00425 if(efa->e4) efa->e4->f &= ~SELECT; 00426 efa->v1->f &= ~SELECT; 00427 efa->v2->f &= ~SELECT; 00428 efa->v3->f &= ~SELECT; 00429 if(efa->v4) efa->v4->f &= ~SELECT; 00430 } 00431 } 00432 00433 void EM_select_edge(EditEdge *eed, int sel) 00434 { 00435 if(sel) { 00436 eed->f |= SELECT; 00437 eed->v1->f |= SELECT; 00438 eed->v2->f |= SELECT; 00439 } 00440 else { 00441 eed->f &= ~SELECT; 00442 eed->v1->f &= ~SELECT; 00443 eed->v2->f &= ~SELECT; 00444 } 00445 } 00446 00447 void EM_select_face_fgon(EditMesh *em, EditFace *efa, int val) 00448 { 00449 short index=0; 00450 00451 if(efa->fgonf==0) EM_select_face(efa, val); 00452 else { 00453 if(efa->e1->fgoni) index= efa->e1->fgoni; 00454 if(efa->e2->fgoni) index= efa->e2->fgoni; 00455 if(efa->e3->fgoni) index= efa->e3->fgoni; 00456 if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni; 00457 00458 if((index==0) && (G.f & G_DEBUG))printf("wrong fgon select\n"); 00459 00460 // select all ngon faces with index 00461 for(efa= em->faces.first; efa; efa= efa->next) { 00462 if(efa->fgonf) { 00463 if(efa->e1->fgoni==index || efa->e2->fgoni==index || 00464 efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) { 00465 EM_select_face(efa, val); 00466 } 00467 } 00468 } 00469 } 00470 } 00471 00472 00473 /* only vertices */ 00474 int faceselectedOR(EditFace *efa, int flag) 00475 { 00476 if ((efa->v1->f | efa->v2->f | efa->v3->f | (efa->v4?efa->v4->f:0))&flag) { 00477 return 1; 00478 } else { 00479 return 0; 00480 } 00481 } 00482 00483 // replace with (efa->f & SELECT) 00484 int faceselectedAND(EditFace *efa, int flag) 00485 { 00486 if ((efa->v1->f & efa->v2->f & efa->v3->f & (efa->v4?efa->v4->f:flag))&flag) { 00487 return 1; 00488 } else { 00489 return 0; 00490 } 00491 } 00492 00493 void EM_clear_flag_all(EditMesh *em, int flag) 00494 { 00495 EditVert *eve; 00496 EditEdge *eed; 00497 EditFace *efa; 00498 00499 for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag; 00500 for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag; 00501 for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag; 00502 00503 if(flag & SELECT) { 00504 BLI_freelistN(&(em->selected)); 00505 em->totvertsel= em->totedgesel= em->totfacesel= 0; 00506 } 00507 } 00508 00509 void EM_set_flag_all(EditMesh *em, int flag) 00510 { 00511 EditVert *eve; 00512 EditEdge *eed; 00513 EditFace *efa; 00514 00515 for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag; 00516 for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag; 00517 for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag; 00518 00519 if(flag & SELECT) { 00520 em->totvertsel= em->totvert; 00521 em->totedgesel= em->totedge; 00522 em->totfacesel= em->totface; 00523 } 00524 } 00525 00526 void EM_set_flag_all_selectmode(EditMesh *em, int flag) 00527 { 00528 EditVert *eve; 00529 EditEdge *eed; 00530 EditFace *efa; 00531 00532 int selvert= 0, seledge= 0, selface= 0; 00533 00534 if (em->selectmode & SCE_SELECT_VERTEX) { 00535 /* If vertex select mode enabled all the data could be affected */ 00536 for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag; 00537 for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag; 00538 for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag; 00539 00540 if (flag & SELECT) { 00541 selvert= em->totvert; 00542 seledge= em->totedge; 00543 selface= em->totface; 00544 } 00545 } else if (em->selectmode & SCE_SELECT_EDGE) { 00546 /* If edge select mode is enabled we should affect on all edges, faces and */ 00547 /* vertices, connected to them */ 00548 00549 for (eed= em->edges.first; eed; eed= eed->next) { 00550 SET_EED_FLAG(eed, flag) 00551 } 00552 00553 for (efa= em->faces.first; efa; efa= efa->next) { 00554 if(efa->h==0) { 00555 efa->f |= flag; 00556 00557 if (flag & SELECT) { 00558 ++selface; 00559 } 00560 } 00561 } 00562 } else if (em->selectmode & SCE_SELECT_FACE) { 00563 /* No vertex and edge select mode, only face selection */ 00564 /* In face select mode only edges and vertices belongs to faces should be affected */ 00565 00566 for (efa= em->faces.first; efa; efa= efa->next) { 00567 if(efa->h==0) { 00568 efa->f |= flag; 00569 SET_EED_FLAG(efa->e1, flag); 00570 SET_EED_FLAG(efa->e2, flag); 00571 SET_EED_FLAG(efa->e3, flag); 00572 00573 if (efa->e4) { 00574 SET_EED_FLAG(efa->e4, flag); 00575 } 00576 00577 if (flag & SELECT) { 00578 ++selface; 00579 } 00580 } 00581 } 00582 } 00583 00584 if(flag & SELECT) { 00585 em->totvertsel= selvert; 00586 em->totedgesel= seledge; 00587 em->totfacesel= selface; 00588 } 00589 } 00590 /* flush for changes in vertices only */ 00591 void EM_deselect_flush(EditMesh *em) 00592 { 00593 EditEdge *eed; 00594 EditFace *efa; 00595 00596 for(eed= em->edges.first; eed; eed= eed->next) { 00597 if(eed->v1->f & eed->v2->f & SELECT); 00598 else eed->f &= ~SELECT; 00599 } 00600 for(efa= em->faces.first; efa; efa= efa->next) { 00601 if(efa->v4) { 00602 if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ); 00603 else efa->f &= ~SELECT; 00604 } 00605 else { 00606 if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ); 00607 else efa->f &= ~SELECT; 00608 } 00609 } 00610 EM_nedges_selected(em); 00611 EM_nfaces_selected(em); 00612 } 00613 00614 00615 /* flush selection to edges & faces */ 00616 00617 /* this only based on coherent selected vertices, for example when adding new 00618 objects. call clear_flag_all() before you select vertices to be sure it ends OK! 00619 00620 */ 00621 00622 void EM_select_flush(EditMesh *em) 00623 { 00624 EditEdge *eed; 00625 EditFace *efa; 00626 00627 for(eed= em->edges.first; eed; eed= eed->next) { 00628 if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT; 00629 } 00630 for(efa= em->faces.first; efa; efa= efa->next) { 00631 if(efa->v4) { 00632 if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT; 00633 } 00634 else { 00635 if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT; 00636 } 00637 } 00638 EM_nedges_selected(em); 00639 EM_nfaces_selected(em); 00640 } 00641 00642 /* when vertices or edges can be selected, also make fgon consistent */ 00643 static void check_fgons_selection(EditMesh *em) 00644 { 00645 EditFace *efa, *efan; 00646 EditEdge *eed; 00647 ListBase *lbar; 00648 int sel, desel, index, totfgon= 0; 00649 00650 /* count amount of fgons */ 00651 for(eed= em->edges.first; eed; eed= eed->next) 00652 if(eed->fgoni>totfgon) totfgon= eed->fgoni; 00653 00654 if(totfgon==0) return; 00655 00656 lbar= MEM_callocN((totfgon+1)*sizeof(ListBase), "listbase array"); 00657 00658 /* put all fgons in lbar */ 00659 for(efa= em->faces.first; efa; efa= efan) { 00660 efan= efa->next; 00661 index= efa->e1->fgoni; 00662 if(index==0) index= efa->e2->fgoni; 00663 if(index==0) index= efa->e3->fgoni; 00664 if(index==0 && efa->e4) index= efa->e4->fgoni; 00665 if(index) { 00666 BLI_remlink(&em->faces, efa); 00667 BLI_addtail(&lbar[index], efa); 00668 } 00669 } 00670 00671 /* now check the fgons */ 00672 for(index=1; index<=totfgon; index++) { 00673 /* we count on vertices/faces/edges being set OK, so we only have to set ngon itself */ 00674 sel= desel= 0; 00675 for(efa= lbar[index].first; efa; efa= efa->next) { 00676 if(efa->e1->fgoni==0) { 00677 if(efa->e1->f & SELECT) sel++; 00678 else desel++; 00679 } 00680 if(efa->e2->fgoni==0) { 00681 if(efa->e2->f & SELECT) sel++; 00682 else desel++; 00683 } 00684 if(efa->e3->fgoni==0) { 00685 if(efa->e3->f & SELECT) sel++; 00686 else desel++; 00687 } 00688 if(efa->e4 && efa->e4->fgoni==0) { 00689 if(efa->e4->f & SELECT) sel++; 00690 else desel++; 00691 } 00692 00693 if(sel && desel) break; 00694 } 00695 00696 if(sel && desel) sel= 0; 00697 else if(sel) sel= 1; 00698 else sel= 0; 00699 00700 /* select/deselect and put back */ 00701 for(efa= lbar[index].first; efa; efa= efa->next) { 00702 if(sel) efa->f |= SELECT; 00703 else efa->f &= ~SELECT; 00704 } 00705 BLI_movelisttolist(&em->faces, &lbar[index]); 00706 } 00707 00708 MEM_freeN(lbar); 00709 } 00710 00711 00712 /* flush to edges & faces */ 00713 00714 /* based on select mode it selects edges/faces 00715 assumed is that verts/edges/faces were properly selected themselves 00716 with the calls above 00717 */ 00718 00719 void EM_selectmode_flush(EditMesh *em) 00720 { 00721 EditEdge *eed; 00722 EditFace *efa; 00723 00724 // flush to edges & faces 00725 if(em->selectmode & SCE_SELECT_VERTEX) { 00726 for(eed= em->edges.first; eed; eed= eed->next) { 00727 if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT; 00728 else eed->f &= ~SELECT; 00729 } 00730 for(efa= em->faces.first; efa; efa= efa->next) { 00731 if(efa->v4) { 00732 if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT; 00733 else efa->f &= ~SELECT; 00734 } 00735 else { 00736 if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT; 00737 else efa->f &= ~SELECT; 00738 } 00739 } 00740 } 00741 // flush to faces 00742 else if(em->selectmode & SCE_SELECT_EDGE) { 00743 for(efa= em->faces.first; efa; efa= efa->next) { 00744 if(efa->e4) { 00745 if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT; 00746 else efa->f &= ~SELECT; 00747 } 00748 else { 00749 if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT; 00750 else efa->f &= ~SELECT; 00751 } 00752 } 00753 } 00754 // make sure selected faces have selected edges too, for extrude (hack?) 00755 else if(em->selectmode & SCE_SELECT_FACE) { 00756 for(efa= em->faces.first; efa; efa= efa->next) { 00757 if(efa->f & SELECT) EM_select_face(efa, 1); 00758 } 00759 } 00760 00761 if(!(em->selectmode & SCE_SELECT_FACE)) 00762 check_fgons_selection(em); 00763 00764 EM_nvertices_selected(em); 00765 EM_nedges_selected(em); 00766 EM_nfaces_selected(em); 00767 } 00768 00769 void EM_convertsel(EditMesh *em, short oldmode, short selectmode) 00770 { 00771 EditVert *eve; 00772 EditEdge *eed; 00773 EditFace *efa; 00774 /*clear flags*/ 00775 for(eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0; 00776 for(eed= em->edges.first; eed; eed= eed->next) eed->f1 = 0; 00777 for(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0; 00778 00779 /*have to find out what the selectionmode was previously*/ 00780 if(oldmode == SCE_SELECT_VERTEX) { 00781 if(selectmode == SCE_SELECT_EDGE){ 00782 /*select all edges associated with every selected vertex*/ 00783 for(eed= em->edges.first; eed; eed= eed->next){ 00784 if(eed->v1->f&SELECT) eed->f1 = 1; 00785 else if(eed->v2->f&SELECT) eed->f1 = 1; 00786 } 00787 00788 for(eed= em->edges.first; eed; eed= eed->next){ 00789 if(eed->f1 == 1) EM_select_edge(eed,1); 00790 } 00791 } 00792 else if(selectmode == SCE_SELECT_FACE){ 00793 /*select all faces associated with every selected vertex*/ 00794 for(efa= em->faces.first; efa; efa= efa->next){ 00795 if(efa->v1->f&SELECT) efa->f1 = 1; 00796 else if(efa->v2->f&SELECT) efa->f1 = 1; 00797 else if(efa->v3->f&SELECT) efa->f1 = 1; 00798 else{ 00799 if(efa->v4){ 00800 if(efa->v4->f&SELECT) efa->f1 =1; 00801 } 00802 } 00803 } 00804 for(efa= em->faces.first; efa; efa= efa->next){ 00805 if(efa->f1 == 1) EM_select_face(efa,1); 00806 } 00807 } 00808 } 00809 00810 if(oldmode == SCE_SELECT_EDGE){ 00811 if(selectmode == SCE_SELECT_FACE){ 00812 for(efa= em->faces.first; efa; efa= efa->next){ 00813 if(efa->e1->f&SELECT) efa->f1 = 1; 00814 else if(efa->e2->f&SELECT) efa->f1 = 1; 00815 else if(efa->e3->f&SELECT) efa->f1 = 1; 00816 else if(efa->e4){ 00817 if(efa->e4->f&SELECT) efa->f1 = 1; 00818 } 00819 } 00820 for(efa= em->faces.first; efa; efa= efa->next){ 00821 if(efa->f1 == 1) EM_select_face(efa,1); 00822 } 00823 } 00824 } 00825 00826 check_fgons_selection(em); 00827 00828 EM_nvertices_selected(em); 00829 EM_nedges_selected(em); 00830 EM_nfaces_selected(em); 00831 } 00832 00833 void EM_selectmode_to_scene(struct Scene *scene, struct Object *obedit) 00834 { 00835 scene->toolsettings->selectmode= get_mesh(obedit)->edit_mesh->selectmode; 00836 } 00837 00838 /* when switching select mode, makes sure selection is consistent for editing */ 00839 /* also for paranoia checks to make sure edge or face mode works */ 00840 void EM_selectmode_set(EditMesh *em) 00841 { 00842 EditVert *eve; 00843 EditEdge *eed; 00844 EditFace *efa; 00845 00846 EM_strip_selections(em); /*strip EditSelections from em->selected that are not relevant to new mode*/ 00847 00848 if(em->selectmode & SCE_SELECT_VERTEX) { 00849 /* vertices -> edges -> faces */ 00850 for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT; 00851 for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~SELECT; 00852 00853 EM_select_flush(em); 00854 } 00855 else if(em->selectmode & SCE_SELECT_EDGE) { 00856 /* deselect vertices, and select again based on edge select */ 00857 for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT; 00858 for(eed= em->edges.first; eed; eed= eed->next) 00859 if(eed->f & SELECT) EM_select_edge(eed, 1); 00860 /* selects faces based on edge status */ 00861 EM_selectmode_flush(em); 00862 } 00863 else if(em->selectmode & SCE_SELECT_FACE) { 00864 /* deselect eges, and select again based on face select */ 00865 for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0); 00866 00867 for(efa= em->faces.first; efa; efa= efa->next) 00868 if(efa->f & SELECT) EM_select_face(efa, 1); 00869 } 00870 00871 EM_nvertices_selected(em); 00872 EM_nedges_selected(em); 00873 EM_nfaces_selected(em); 00874 } 00875 00876 /* paranoia check, actually only for entering editmode. rule: 00877 - vertex hidden, always means edge is hidden too 00878 - edge hidden, always means face is hidden too 00879 - face hidden, dont change anything 00880 */ 00881 void EM_hide_reset(EditMesh *em) 00882 { 00883 EditEdge *eed; 00884 EditFace *efa; 00885 00886 for(eed= em->edges.first; eed; eed= eed->next) 00887 if(eed->v1->h || eed->v2->h) eed->h |= 1; 00888 00889 for(efa= em->faces.first; efa; efa= efa->next) 00890 if((efa->e1->h & 1) || (efa->e2->h & 1) || (efa->e3->h & 1) || (efa->e4 && (efa->e4->h & 1))) 00891 efa->h= 1; 00892 00893 } 00894 00895 void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *eve, float fac) 00896 { 00897 void *src[2]; 00898 float w[2]; 00899 00900 if (v1->data && v2->data) { 00901 src[0]= v1->data; 00902 src[1]= v2->data; 00903 w[0] = 1.0f-fac; 00904 w[1] = fac; 00905 00906 CustomData_em_interp(&em->vdata, src, w, NULL, 2, eve->data); 00907 } 00908 } 00909 00910 void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4) 00911 { 00912 float w[2][4][4]; 00913 void *src[2]; 00914 int count = (efa2)? 2: 1; 00915 00916 if (efa1->data) { 00917 /* set weights for copying from corners directly to other corners */ 00918 memset(w, 0, sizeof(w)); 00919 00920 w[i1/4][0][i1%4]= 1.0f; 00921 w[i2/4][1][i2%4]= 1.0f; 00922 w[i3/4][2][i3%4]= 1.0f; 00923 if (i4 != -1) 00924 w[i4/4][3][i4%4]= 1.0f; 00925 00926 src[0]= efa1->data; 00927 src[1]= (efa2)? efa2->data: NULL; 00928 00929 CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data); 00930 } 00931 } 00932 00933 EditFace *EM_face_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4) 00934 { 00935 EditFace *efan; 00936 EditVert **v[2]; 00937 00938 v[0]= &efa1->v1; 00939 v[1]= (efa2)? &efa2->v1: NULL; 00940 00941 efan= addfacelist(em, v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4], 00942 (i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL); 00943 00944 EM_data_interp_from_faces(em, efa1, efa2, efan, i1, i2, i3, i4); 00945 00946 return efan; 00947 } 00948 00949 static void update_data_blocks(EditMesh *em, CustomData *olddata, CustomData *data) 00950 { 00951 EditFace *efa; 00952 EditVert *eve; 00953 void *block; 00954 00955 if (data == &em->vdata) { 00956 for(eve= em->verts.first; eve; eve= eve->next) { 00957 block = NULL; 00958 CustomData_em_set_default(data, &block); 00959 CustomData_em_copy_data(olddata, data, eve->data, &block); 00960 CustomData_em_free_block(olddata, &eve->data); 00961 eve->data= block; 00962 } 00963 } 00964 else if (data == &em->fdata) { 00965 for(efa= em->faces.first; efa; efa= efa->next) { 00966 block = NULL; 00967 CustomData_em_set_default(data, &block); 00968 CustomData_em_copy_data(olddata, data, efa->data, &block); 00969 CustomData_em_free_block(olddata, &efa->data); 00970 efa->data= block; 00971 } 00972 } 00973 } 00974 00975 void EM_add_data_layer(EditMesh *em, CustomData *data, int type, const char *name) 00976 { 00977 CustomData olddata; 00978 00979 olddata= *data; 00980 olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL; 00981 CustomData_add_layer_named(data, type, CD_CALLOC, NULL, 0, name); 00982 00983 update_data_blocks(em, &olddata, data); 00984 if (olddata.layers) MEM_freeN(olddata.layers); 00985 } 00986 00987 void EM_free_data_layer(EditMesh *em, CustomData *data, int type) 00988 { 00989 CustomData olddata; 00990 00991 olddata= *data; 00992 olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL; 00993 CustomData_free_layer_active(data, type, 0); 00994 00995 update_data_blocks(em, &olddata, data); 00996 if (olddata.layers) MEM_freeN(olddata.layers); 00997 } 00998 00999 /* ******** EXTRUDE ********* */ 01000 01001 static void add_normal_aligned(float *nor, float *add) 01002 { 01003 if(dot_v3v3(nor, add) < -0.9999f) 01004 sub_v3_v3(nor, add); 01005 else 01006 add_v3_v3(nor, add); 01007 } 01008 01009 static void set_edge_directions_f2(EditMesh *em, int val) 01010 { 01011 EditFace *efa; 01012 int do_all= 1; 01013 01014 /* edge directions are used for extrude, to detect direction of edges that make new faces */ 01015 /* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */ 01016 /* the val argument differs... so we need it as arg */ 01017 01018 for(efa= em->faces.first; efa; efa= efa->next) { 01019 if(efa->f & SELECT) { 01020 do_all= 0; 01021 if(efa->e1->f2<val) { 01022 if(efa->e1->v1 == efa->v1) efa->e1->dir= 0; 01023 else efa->e1->dir= 1; 01024 } 01025 if(efa->e2->f2<val) { 01026 if(efa->e2->v1 == efa->v2) efa->e2->dir= 0; 01027 else efa->e2->dir= 1; 01028 } 01029 if(efa->e3->f2<val) { 01030 if(efa->e3->v1 == efa->v3) efa->e3->dir= 0; 01031 else efa->e3->dir= 1; 01032 } 01033 if(efa->e4 && efa->e4->f2<val) { 01034 if(efa->e4->v1 == efa->v4) efa->e4->dir= 0; 01035 else efa->e4->dir= 1; 01036 } 01037 } 01038 } 01039 /* ok, no faces done... then we at least set it for exterior edges */ 01040 if(do_all) { 01041 for(efa= em->faces.first; efa; efa= efa->next) { 01042 if(efa->e1->v1 == efa->v1) efa->e1->dir= 0; 01043 else efa->e1->dir= 1; 01044 if(efa->e2->v1 == efa->v2) efa->e2->dir= 0; 01045 else efa->e2->dir= 1; 01046 if(efa->e3->v1 == efa->v3) efa->e3->dir= 0; 01047 else efa->e3->dir= 1; 01048 if(efa->e4) { 01049 if(efa->e4->v1 == efa->v4) efa->e4->dir= 0; 01050 else efa->e4->dir= 1; 01051 } 01052 } 01053 } 01054 } 01055 01056 /* individual face extrude */ 01057 /* will use vertex normals for extrusion directions, so *nor is unaffected */ 01058 short extrudeflag_face_indiv(EditMesh *em, short UNUSED(flag), float *UNUSED(nor)) 01059 { 01060 EditVert *eve, *v1, *v2, *v3, *v4; 01061 EditEdge *eed; 01062 EditFace *efa, *nextfa; 01063 01064 if(em==NULL) return 0; 01065 01066 /* selected edges with 1 or more selected face become faces */ 01067 /* selected faces each makes new faces */ 01068 /* always remove old faces, keeps volumes manifold */ 01069 /* select the new extrusion, deselect old */ 01070 01071 /* step 1; init, count faces in edges */ 01072 recalc_editnormals(em); 01073 01074 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; // new select flag 01075 01076 for(eed= em->edges.first; eed; eed= eed->next) { 01077 eed->f2= 0; // amount of unselected faces 01078 } 01079 for(efa= em->faces.first; efa; efa= efa->next) { 01080 if(efa->f & SELECT); 01081 else { 01082 efa->e1->f2++; 01083 efa->e2->f2++; 01084 efa->e3->f2++; 01085 if(efa->e4) efa->e4->f2++; 01086 } 01087 } 01088 01089 /* step 2: make new faces from faces */ 01090 for(efa= em->faces.last; efa; efa= efa->prev) { 01091 if(efa->f & SELECT) { 01092 v1= addvertlist(em, efa->v1->co, efa->v1); 01093 v2= addvertlist(em, efa->v2->co, efa->v2); 01094 v3= addvertlist(em, efa->v3->co, efa->v3); 01095 01096 v1->f1= v2->f1= v3->f1= 1; 01097 copy_v3_v3(v1->no, efa->n); 01098 copy_v3_v3(v2->no, efa->n); 01099 copy_v3_v3(v3->no, efa->n); 01100 if(efa->v4) { 01101 v4= addvertlist(em, efa->v4->co, efa->v4); 01102 v4->f1= 1; 01103 copy_v3_v3(v4->no, efa->n); 01104 } 01105 else v4= NULL; 01106 01107 /* side faces, clockwise */ 01108 addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL); 01109 addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL); 01110 if(efa->v4) { 01111 addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL); 01112 addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL); 01113 } 01114 else { 01115 addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL); 01116 } 01117 /* top face */ 01118 addfacelist(em, v1, v2, v3, v4, efa, NULL); 01119 } 01120 } 01121 01122 /* step 3: remove old faces */ 01123 efa= em->faces.first; 01124 while(efa) { 01125 nextfa= efa->next; 01126 if(efa->f & SELECT) { 01127 BLI_remlink(&em->faces, efa); 01128 free_editface(em, efa); 01129 } 01130 efa= nextfa; 01131 } 01132 01133 /* step 4: redo selection */ 01134 EM_clear_flag_all(em, SELECT); 01135 01136 for(eve= em->verts.first; eve; eve= eve->next) { 01137 if(eve->f1) eve->f |= SELECT; 01138 } 01139 01140 EM_select_flush(em); 01141 01142 /* step 5; update normals after extrude */ 01143 recalc_editnormals(em); 01144 01145 return 'n'; 01146 } 01147 01148 01149 /* extrudes individual edges */ 01150 /* nor is filled with constraint vector */ 01151 short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor) 01152 { 01153 EditVert *eve; 01154 EditEdge *eed; 01155 EditFace *efa; 01156 01157 for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL; 01158 for(eed= em->edges.first; eed; eed= eed->next) { 01159 eed->tmp.f = NULL; 01160 eed->f2= ((eed->f & flag)!=0); 01161 } 01162 01163 set_edge_directions_f2(em, 2); 01164 01165 /* sample for next loop */ 01166 for(efa= em->faces.first; efa; efa= efa->next) { 01167 efa->e1->tmp.f = efa; 01168 efa->e2->tmp.f = efa; 01169 efa->e3->tmp.f = efa; 01170 if(efa->e4) efa->e4->tmp.f = efa; 01171 } 01172 /* make the faces */ 01173 for(eed= em->edges.first; eed; eed= eed->next) { 01174 if(eed->f & flag) { 01175 if(eed->v1->tmp.v == NULL) 01176 eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1); 01177 if(eed->v2->tmp.v == NULL) 01178 eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2); 01179 01180 if(eed->dir==1) 01181 addfacelist(em, eed->v1, eed->v2, 01182 eed->v2->tmp.v, eed->v1->tmp.v, 01183 eed->tmp.f, NULL); 01184 else 01185 addfacelist(em, eed->v2, eed->v1, 01186 eed->v1->tmp.v, eed->v2->tmp.v, 01187 eed->tmp.f, NULL); 01188 01189 /* for transform */ 01190 if(eed->tmp.f) { 01191 efa = eed->tmp.f; 01192 if (efa->f & SELECT) add_normal_aligned(nor, efa->n); 01193 } 01194 } 01195 } 01196 normalize_v3(nor); 01197 01198 /* set correct selection */ 01199 EM_clear_flag_all(em, SELECT); 01200 for(eve= em->verts.last; eve; eve= eve->prev) { 01201 if(eve->tmp.v) { 01202 eve->tmp.v->f |= flag; 01203 } 01204 } 01205 01206 for(eed= em->edges.first; eed; eed= eed->next) { 01207 if(eed->v1->f & eed->v2->f & flag) eed->f |= flag; 01208 } 01209 01210 /* update normals after extrude */ 01211 recalc_editnormals(em); 01212 01213 if(is_zero_v3(nor)) return 'g'; // g is grab 01214 return 'n'; // n is for normal constraint 01215 } 01216 01217 /* extrudes individual vertices */ 01218 short extrudeflag_verts_indiv(EditMesh *em, short flag, float *UNUSED(nor)) 01219 { 01220 EditVert *eve; 01221 01222 /* make the edges */ 01223 for(eve= em->verts.first; eve; eve= eve->next) { 01224 if(eve->f & flag) { 01225 eve->tmp.v = addvertlist(em, eve->co, eve); 01226 addedgelist(em, eve, eve->tmp.v, NULL); 01227 } 01228 else eve->tmp.v = NULL; 01229 } 01230 01231 /* set correct selection */ 01232 EM_clear_flag_all(em, SELECT); 01233 01234 for(eve= em->verts.last; eve; eve= eve->prev) 01235 if (eve->tmp.v) 01236 eve->tmp.v->f |= flag; 01237 01238 return 'g'; // g is grab 01239 } 01240 01241 01242 /* this is actually a recode of extrudeflag(), using proper edge/face select */ 01243 /* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */ 01244 static short extrudeflag_edge(Object *obedit, EditMesh *em, short UNUSED(flag), float *nor, int all) 01245 { 01246 /* all select edges/faces: extrude */ 01247 /* old select is cleared, in new ones it is set */ 01248 EditVert *eve, *nextve; 01249 EditEdge *eed, *nexted; 01250 EditFace *efa, *nextfa, *efan; 01251 short del_old= 0; 01252 ModifierData *md; 01253 01254 if(em==NULL) return 0; 01255 01256 md = obedit->modifiers.first; 01257 01258 /* selected edges with 0 or 1 selected face become faces */ 01259 /* selected faces generate new faces */ 01260 01261 /* if *one* selected face has edge with unselected face; remove old selected faces */ 01262 01263 /* if selected edge is not used anymore; remove */ 01264 /* if selected vertex is not used anymore: remove */ 01265 01266 /* select the new extrusion, deselect old */ 01267 01268 01269 /* step 1; init, count faces in edges */ 01270 recalc_editnormals(em); 01271 01272 for(eve= em->verts.first; eve; eve= eve->next) { 01273 eve->tmp.v = NULL; 01274 eve->f1= 0; 01275 } 01276 01277 for(eed= em->edges.first; eed; eed= eed->next) { 01278 eed->f1= 0; // amount of unselected faces 01279 eed->f2= 0; // amount of selected faces 01280 if(eed->f & SELECT) { 01281 eed->v1->f1= 1; // we call this 'selected vertex' now 01282 eed->v2->f1= 1; 01283 } 01284 eed->tmp.f = NULL; // here we tuck face pointer, as sample 01285 } 01286 for(efa= em->faces.first; efa; efa= efa->next) { 01287 if(efa->f & SELECT) { 01288 efa->e1->f2++; 01289 efa->e2->f2++; 01290 efa->e3->f2++; 01291 if(efa->e4) efa->e4->f2++; 01292 01293 // sample for next loop 01294 efa->e1->tmp.f = efa; 01295 efa->e2->tmp.f = efa; 01296 efa->e3->tmp.f = efa; 01297 if(efa->e4) efa->e4->tmp.f = efa; 01298 } 01299 else { 01300 efa->e1->f1++; 01301 efa->e2->f1++; 01302 efa->e3->f1++; 01303 if(efa->e4) efa->e4->f1++; 01304 } 01305 } 01306 01307 /* If a mirror modifier with clipping is on, we need to adjust some 01308 * of the cases above to handle edges on the line of symmetry. 01309 */ 01310 for (; md; md=md->next) { 01311 if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) { 01312 MirrorModifierData *mmd = (MirrorModifierData*) md; 01313 01314 if(mmd->flag & MOD_MIR_CLIPPING) { 01315 float mtx[4][4]; 01316 if (mmd->mirror_ob) { 01317 float imtx[4][4]; 01318 invert_m4_m4(imtx, mmd->mirror_ob->obmat); 01319 mult_m4_m4m4(mtx, imtx, obedit->obmat); 01320 } 01321 01322 for (eed= em->edges.first; eed; eed= eed->next) { 01323 if(eed->f2 == 1) { 01324 float co1[3], co2[3]; 01325 01326 copy_v3_v3(co1, eed->v1->co); 01327 copy_v3_v3(co2, eed->v2->co); 01328 01329 if (mmd->mirror_ob) { 01330 mul_m4_v3(mtx, co1); 01331 mul_m4_v3(mtx, co2); 01332 } 01333 01334 if (mmd->flag & MOD_MIR_AXIS_X) 01335 if ( (fabsf(co1[0]) < mmd->tolerance) && 01336 (fabsf(co2[0]) < mmd->tolerance) ) 01337 ++eed->f2; 01338 01339 if (mmd->flag & MOD_MIR_AXIS_Y) 01340 if ( (fabsf(co1[1]) < mmd->tolerance) && 01341 (fabsf(co2[1]) < mmd->tolerance) ) 01342 ++eed->f2; 01343 01344 if (mmd->flag & MOD_MIR_AXIS_Z) 01345 if ( (fabsf(co1[2]) < mmd->tolerance) && 01346 (fabsf(co2[2]) < mmd->tolerance) ) 01347 ++eed->f2; 01348 } 01349 } 01350 } 01351 } 01352 } 01353 01354 set_edge_directions_f2(em, 2); 01355 01356 /* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */ 01357 if(all == 0) { 01358 for(efa= em->faces.last; efa; efa= efa->prev) { 01359 if(efa->f & SELECT) { 01360 if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) { 01361 del_old= 1; 01362 break; 01363 } 01364 } 01365 } 01366 } 01367 01368 /* step 2: make new faces from edges */ 01369 for(eed= em->edges.last; eed; eed= eed->prev) { 01370 if(eed->f & SELECT) { 01371 if(eed->f2<2) { 01372 if(eed->v1->tmp.v == NULL) 01373 eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1); 01374 if(eed->v2->tmp.v == NULL) 01375 eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2); 01376 01377 /* if del_old, the preferred normal direction is exact 01378 * opposite as for keep old faces 01379 */ 01380 if(eed->dir!=del_old) 01381 addfacelist(em, eed->v1, eed->v2, 01382 eed->v2->tmp.v, eed->v1->tmp.v, 01383 eed->tmp.f, NULL); 01384 else 01385 addfacelist(em, eed->v2, eed->v1, 01386 eed->v1->tmp.v, eed->v2->tmp.v, 01387 eed->tmp.f, NULL); 01388 } 01389 } 01390 } 01391 01392 /* step 3: make new faces from faces */ 01393 for(efa= em->faces.last; efa; efa= efa->prev) { 01394 if(efa->f & SELECT) { 01395 if (efa->v1->tmp.v == NULL) 01396 efa->v1->tmp.v = addvertlist(em, efa->v1->co, efa->v1); 01397 if (efa->v2->tmp.v ==NULL) 01398 efa->v2->tmp.v = addvertlist(em, efa->v2->co, efa->v2); 01399 if (efa->v3->tmp.v ==NULL) 01400 efa->v3->tmp.v = addvertlist(em, efa->v3->co, efa->v3); 01401 if (efa->v4 && (efa->v4->tmp.v == NULL)) 01402 efa->v4->tmp.v = addvertlist(em, efa->v4->co, efa->v4); 01403 01404 if(efa->v4) 01405 efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v, 01406 efa->v3->tmp.v, efa->v4->tmp.v, efa, efa); 01407 else 01408 efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v, 01409 efa->v3->tmp.v, NULL, efa, efa); 01410 01411 /* keep old faces means flipping normal, reverse vertex order gives bad UV's & VCols etc - [#25260] */ 01412 if(del_old==0) { 01413 flipface(em, efan); 01414 } 01415 01416 if (em->act_face == efa) { 01417 em->act_face = efan; 01418 } 01419 01420 /* for transform */ 01421 add_normal_aligned(nor, efa->n); 01422 } 01423 } 01424 01425 if(del_old) { 01426 01427 /* step 4: remove old faces, if del_old */ 01428 efa= em->faces.first; 01429 while(efa) { 01430 nextfa= efa->next; 01431 if(efa->f & SELECT) { 01432 BLI_remlink(&em->faces, efa); 01433 free_editface(em, efa); 01434 } 01435 efa= nextfa; 01436 } 01437 01438 01439 /* step 5: remove selected unused edges */ 01440 /* start tagging again */ 01441 for(eed= em->edges.first; eed; eed= eed->next) eed->f1=0; 01442 for(efa= em->faces.first; efa; efa= efa->next) { 01443 efa->e1->f1= 1; 01444 efa->e2->f1= 1; 01445 efa->e3->f1= 1; 01446 if(efa->e4) efa->e4->f1= 1; 01447 } 01448 /* remove */ 01449 eed= em->edges.first; 01450 while(eed) { 01451 nexted= eed->next; 01452 if(eed->f & SELECT) { 01453 if(eed->f1==0) { 01454 remedge(em, eed); 01455 free_editedge(em, eed); 01456 } 01457 } 01458 eed= nexted; 01459 } 01460 01461 /* step 6: remove selected unused vertices */ 01462 for(eed= em->edges.first; eed; eed= eed->next) 01463 eed->v1->f1= eed->v2->f1= 0; 01464 01465 eve= em->verts.first; 01466 while(eve) { 01467 nextve= eve->next; 01468 if(eve->f1) { 01469 // hack... but we need it for step 7, redoing selection 01470 if(eve->tmp.v) eve->tmp.v->tmp.v= eve->tmp.v; 01471 01472 BLI_remlink(&em->verts, eve); 01473 free_editvert(em, eve); 01474 } 01475 eve= nextve; 01476 } 01477 } 01478 01479 normalize_v3(nor); // translation normal grab 01480 01481 /* step 7: redo selection */ 01482 EM_clear_flag_all(em, SELECT); 01483 01484 for(eve= em->verts.first; eve; eve= eve->next) { 01485 if(eve->tmp.v) { 01486 eve->tmp.v->f |= SELECT; 01487 } 01488 } 01489 01490 EM_select_flush(em); 01491 01492 /* step 8; update normals after extrude */ 01493 recalc_editnormals(em); 01494 01495 if(is_zero_v3(nor)) return 'g'; // grab 01496 return 'n'; // normal constraint 01497 } 01498 01499 short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor, int all) 01500 { 01501 /* all verts/edges/faces with (f & 'flag'): extrude */ 01502 /* from old verts, 'flag' is cleared, in new ones it is set */ 01503 EditVert *eve, *v1, *v2, *v3, *v4, *nextve; 01504 EditEdge *eed, *e1, *e2, *e3, *e4, *nexted; 01505 EditFace *efa, *efa2, *nextvl; 01506 short sel=0, del_old= 0, is_face_sel=0; 01507 ModifierData *md; 01508 01509 if(em==NULL) return 0; 01510 01511 md = obedit->modifiers.first; 01512 01513 /* clear vert flag f1, we use this to detect a loose selected vertice */ 01514 eve= em->verts.first; 01515 while(eve) { 01516 if(eve->f & flag) eve->f1= 1; 01517 else eve->f1= 0; 01518 eve= eve->next; 01519 } 01520 /* clear edges counter flag, if selected we set it at 1 */ 01521 eed= em->edges.first; 01522 while(eed) { 01523 if( (eed->v1->f & flag) && (eed->v2->f & flag) ) { 01524 eed->f2= 1; 01525 eed->v1->f1= 0; 01526 eed->v2->f1= 0; 01527 } 01528 else eed->f2= 0; 01529 01530 eed->f1= 1; /* this indicates it is an 'old' edge (in this routine we make new ones) */ 01531 eed->tmp.f = NULL; /* used as sample */ 01532 01533 eed= eed->next; 01534 } 01535 01536 /* we set a flag in all selected faces, and increase the associated edge counters */ 01537 01538 efa= em->faces.first; 01539 while(efa) { 01540 efa->f1= 0; 01541 01542 if(faceselectedAND(efa, flag)) { 01543 e1= efa->e1; 01544 e2= efa->e2; 01545 e3= efa->e3; 01546 e4= efa->e4; 01547 01548 if(e1->f2 < 3) e1->f2++; 01549 if(e2->f2 < 3) e2->f2++; 01550 if(e3->f2 < 3) e3->f2++; 01551 if(e4 && e4->f2 < 3) e4->f2++; 01552 01553 efa->f1= 1; 01554 is_face_sel= 1; // for del_old 01555 } 01556 else if(faceselectedOR(efa, flag)) { 01557 e1= efa->e1; 01558 e2= efa->e2; 01559 e3= efa->e3; 01560 e4= efa->e4; 01561 01562 if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2; 01563 if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2; 01564 if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2; 01565 if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2; 01566 } 01567 01568 // sample for next loop 01569 efa->e1->tmp.f = efa; 01570 efa->e2->tmp.f = efa; 01571 efa->e3->tmp.f = efa; 01572 if(efa->e4) efa->e4->tmp.f = efa; 01573 01574 efa= efa->next; 01575 } 01576 01577 set_edge_directions_f2(em, 3); 01578 01579 /* the current state now is: 01580 eve->f1==1: loose selected vertex 01581 01582 eed->f2==0 : edge is not selected, no extrude 01583 eed->f2==1 : edge selected, is not part of a face, extrude 01584 eed->f2==2 : edge selected, is part of 1 face, extrude 01585 eed->f2==3 : edge selected, is part of more faces, no extrude 01586 01587 eed->f1==0: new edge 01588 eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove 01589 eed->f1==2: edge selected, part of a partially selected face 01590 01591 efa->f1==1 : duplicate this face 01592 */ 01593 01594 /* If a mirror modifier with clipping is on, we need to adjust some 01595 * of the cases above to handle edges on the line of symmetry. 01596 */ 01597 for (; md; md=md->next) { 01598 if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) { 01599 MirrorModifierData *mmd = (MirrorModifierData*) md; 01600 01601 if(mmd->flag & MOD_MIR_CLIPPING) { 01602 float mtx[4][4]; 01603 if (mmd->mirror_ob) { 01604 float imtx[4][4]; 01605 invert_m4_m4(imtx, mmd->mirror_ob->obmat); 01606 mult_m4_m4m4(mtx, imtx, obedit->obmat); 01607 } 01608 01609 for (eed= em->edges.first; eed; eed= eed->next) { 01610 if(eed->f2 == 2) { 01611 float co1[3], co2[3]; 01612 01613 copy_v3_v3(co1, eed->v1->co); 01614 copy_v3_v3(co2, eed->v2->co); 01615 01616 if (mmd->mirror_ob) { 01617 mul_m4_v3(mtx, co1); 01618 mul_m4_v3(mtx, co2); 01619 } 01620 01621 if (mmd->flag & MOD_MIR_AXIS_X) 01622 if ( (fabsf(co1[0]) < mmd->tolerance) && 01623 (fabsf(co2[0]) < mmd->tolerance) ) 01624 ++eed->f2; 01625 01626 if (mmd->flag & MOD_MIR_AXIS_Y) 01627 if ( (fabsf(co1[1]) < mmd->tolerance) && 01628 (fabsf(co2[1]) < mmd->tolerance) ) 01629 ++eed->f2; 01630 if (mmd->flag & MOD_MIR_AXIS_Z) 01631 if ( (fabsf(co1[2]) < mmd->tolerance) && 01632 (fabsf(co2[2]) < mmd->tolerance) ) 01633 ++eed->f2; 01634 } 01635 } 01636 } 01637 } 01638 } 01639 01640 /* copy all selected vertices, */ 01641 /* write pointer to new vert in old struct at eve->tmp.v */ 01642 eve= em->verts.last; 01643 while(eve) { 01644 eve->f &= ~128; /* clear, for later test for loose verts */ 01645 if(eve->f & flag) { 01646 sel= 1; 01647 v1= addvertlist(em, 0, NULL); 01648 01649 copy_v3_v3(v1->co, eve->co); 01650 copy_v3_v3(v1->no, eve->no); 01651 v1->f= eve->f; 01652 eve->f &= ~flag; 01653 eve->tmp.v = v1; 01654 } 01655 else eve->tmp.v = NULL; 01656 eve= eve->prev; 01657 } 01658 01659 if(sel==0) return 0; 01660 01661 /* all edges with eed->f2==1 or eed->f2==2 become faces */ 01662 01663 /* if del_old==1 then extrude is in partial geometry, to keep it manifold. 01664 verts with f1==0 and (eve->f & 128)==0) are removed 01665 edges with eed->f2>2 are removed 01666 faces with efa->f1 are removed 01667 if del_old==0 the extrude creates a volume. 01668 */ 01669 01670 /* find if we delete old faces */ 01671 if(is_face_sel && all==0) { 01672 for(eed= em->edges.first; eed; eed= eed->next) { 01673 if( (eed->f2==1 || eed->f2==2) ) { 01674 if(eed->f1==2) { 01675 del_old= 1; 01676 break; 01677 } 01678 } 01679 } 01680 } 01681 01682 eed= em->edges.last; 01683 while(eed) { 01684 nexted= eed->prev; 01685 if( eed->f2<3) { 01686 eed->v1->f |= 128; /* = no loose vert! */ 01687 eed->v2->f |= 128; 01688 } 01689 if( (eed->f2==1 || eed->f2==2) ) { 01690 01691 /* if del_old, the preferred normal direction is exact opposite as for keep old faces */ 01692 if(eed->dir != del_old) 01693 efa2 = addfacelist(em, eed->v1, eed->v2, 01694 eed->v2->tmp.v, eed->v1->tmp.v, 01695 eed->tmp.f, NULL); 01696 else 01697 efa2 = addfacelist(em, eed->v2, eed->v1, 01698 eed->v1->tmp.v, eed->v2->tmp.v, 01699 eed->tmp.f, NULL); 01700 01701 /* Needs smarter adaption of existing creases. 01702 * If addedgelist is used, make sure seams are set to 0 on these 01703 * new edges, since we do not want to add any seams on extrusion. 01704 */ 01705 efa2->e1->crease= eed->crease; 01706 efa2->e2->crease= eed->crease; 01707 efa2->e3->crease= eed->crease; 01708 if(efa2->e4) efa2->e4->crease= eed->crease; 01709 } 01710 01711 eed= nexted; 01712 } 01713 01714 /* duplicate faces, if necessary remove old ones */ 01715 efa= em->faces.first; 01716 while(efa) { 01717 nextvl= efa->next; 01718 if(efa->f1 & 1) { 01719 01720 v1 = efa->v1->tmp.v; 01721 v2 = efa->v2->tmp.v; 01722 v3 = efa->v3->tmp.v; 01723 if(efa->v4) 01724 v4 = efa->v4->tmp.v; 01725 else 01726 v4= NULL; 01727 01728 /* hmm .. not sure about edges here */ 01729 if(del_old==0) // if we keep old, we flip normal 01730 efa2= addfacelist(em, v3, v2, v1, v4, efa, efa); 01731 else 01732 efa2= addfacelist(em, v1, v2, v3, v4, efa, efa); 01733 01734 /* for transform */ 01735 add_normal_aligned(nor, efa->n); 01736 01737 if(del_old) { 01738 BLI_remlink(&em->faces, efa); 01739 free_editface(em, efa); 01740 } 01741 } 01742 efa= nextvl; 01743 } 01744 /* delete edges after copying edges above! */ 01745 if(del_old) { 01746 eed= em->edges.first; 01747 while(eed) { 01748 nexted= eed->next; 01749 if(eed->f2==3 && eed->f1==1) { 01750 remedge(em, eed); 01751 free_editedge(em, eed); 01752 } 01753 eed= nexted; 01754 } 01755 } 01756 01757 normalize_v3(nor); // for grab 01758 01759 /* for all vertices with eve->tmp.v!=0 01760 if eve->f1==1: make edge 01761 if flag!=128 : if del_old==1: remove 01762 */ 01763 eve= em->verts.last; 01764 while(eve) { 01765 nextve= eve->prev; 01766 if(eve->tmp.v) { 01767 if(eve->f1==1) addedgelist(em, eve, eve->tmp.v, NULL); 01768 else if( (eve->f & 128)==0) { 01769 if(del_old) { 01770 BLI_remlink(&em->verts,eve); 01771 free_editvert(em, eve); 01772 eve= NULL; 01773 } 01774 } 01775 } 01776 if(eve) { 01777 eve->f &= ~128; 01778 } 01779 eve= nextve; 01780 } 01781 // since its vertex select mode now, it also deselects higher order 01782 EM_selectmode_flush(em); 01783 01784 if(is_zero_v3(nor)) return 'g'; // g is grab, for correct undo print 01785 return 'n'; 01786 } 01787 01788 /* generic extrude */ 01789 short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor, int all) 01790 { 01791 if(em->selectmode & SCE_SELECT_VERTEX) 01792 return extrudeflag_vert(obedit, em, flag, nor, all); 01793 else 01794 return extrudeflag_edge(obedit, em, flag, nor, all); 01795 01796 } 01797 01798 void rotateflag(EditMesh *em, short flag, float *cent, float rotmat[][3]) 01799 { 01800 /* all verts with (flag & 'flag') rotate */ 01801 EditVert *eve; 01802 01803 eve= em->verts.first; 01804 while(eve) { 01805 if(eve->f & flag) { 01806 eve->co[0]-=cent[0]; 01807 eve->co[1]-=cent[1]; 01808 eve->co[2]-=cent[2]; 01809 mul_m3_v3(rotmat,eve->co); 01810 eve->co[0]+=cent[0]; 01811 eve->co[1]+=cent[1]; 01812 eve->co[2]+=cent[2]; 01813 } 01814 eve= eve->next; 01815 } 01816 } 01817 01818 void translateflag(EditMesh *em, short flag, float *vec) 01819 { 01820 /* all verts with (flag & 'flag') translate */ 01821 EditVert *eve; 01822 01823 eve= em->verts.first; 01824 while(eve) { 01825 if(eve->f & flag) { 01826 eve->co[0]+=vec[0]; 01827 eve->co[1]+=vec[1]; 01828 eve->co[2]+=vec[2]; 01829 } 01830 eve= eve->next; 01831 } 01832 } 01833 01834 /* helper call for below */ 01835 static EditVert *adduplicate_vertex(EditMesh *em, EditVert *eve, int flag) 01836 { 01837 /* FIXME: copy deformation weight from eve ok here? */ 01838 EditVert *v1= addvertlist(em, eve->co, eve); 01839 01840 v1->f= eve->f; 01841 eve->f &= ~flag; 01842 eve->f|= 128; 01843 01844 eve->tmp.v = v1; 01845 01846 return v1; 01847 } 01848 01849 /* old selection has flag 128 set, and flag 'flag' cleared 01850 new selection has flag 'flag' set */ 01851 void adduplicateflag(EditMesh *em, int flag) 01852 { 01853 EditVert *eve, *v1, *v2, *v3, *v4; 01854 EditEdge *eed, *newed; 01855 EditFace *efa, *newfa, *act_efa = EM_get_actFace(em, 0); 01856 01857 EM_clear_flag_all(em, 128); 01858 EM_selectmode_set(em); // paranoia check, selection now is consistent 01859 01860 /* vertices first */ 01861 for(eve= em->verts.last; eve; eve= eve->prev) { 01862 01863 if(eve->f & flag) 01864 adduplicate_vertex(em, eve, flag); 01865 else 01866 eve->tmp.v = NULL; 01867 } 01868 01869 /* copy edges, note that vertex selection can be independent of edge */ 01870 for(eed= em->edges.last; eed; eed= eed->prev) { 01871 if( eed->f & flag ) { 01872 v1 = eed->v1->tmp.v; 01873 if(v1==NULL) v1= adduplicate_vertex(em, eed->v1, flag); 01874 v2 = eed->v2->tmp.v; 01875 if(v2==NULL) v2= adduplicate_vertex(em, eed->v2, flag); 01876 01877 newed= addedgelist(em, v1, v2, eed); 01878 01879 newed->f= eed->f; 01880 eed->f &= ~flag; 01881 eed->f |= 128; 01882 } 01883 } 01884 01885 /* then duplicate faces, again create new vertices if needed */ 01886 for(efa= em->faces.last; efa; efa= efa->prev) { 01887 if(efa->f & flag) { 01888 v1 = efa->v1->tmp.v; 01889 if(v1==NULL) v1= adduplicate_vertex(em, efa->v1, flag); 01890 v2 = efa->v2->tmp.v; 01891 if(v2==NULL) v2= adduplicate_vertex(em, efa->v2, flag); 01892 v3 = efa->v3->tmp.v; 01893 if(v3==NULL) v3= adduplicate_vertex(em, efa->v3, flag); 01894 if(efa->v4) { 01895 v4 = efa->v4->tmp.v; 01896 if(v4==NULL) v4= adduplicate_vertex(em, efa->v4, flag); 01897 } 01898 else v4= NULL; 01899 01900 newfa= addfacelist(em, v1, v2, v3, v4, efa, efa); 01901 01902 if (efa==act_efa) { 01903 EM_set_actFace(em, newfa); 01904 } 01905 01906 newfa->f= efa->f; 01907 efa->f &= ~flag; 01908 efa->f |= 128; 01909 } 01910 } 01911 01912 EM_fgon_flags(em); // redo flags and indices for fgons 01913 } 01914 01915 void delfaceflag(EditMesh *em, int flag) 01916 { 01917 /* delete all faces with 'flag', including loose edges and loose vertices */ 01918 /* this is maybe a bit weird, but this function is used for 'split' and 'separate' */ 01919 /* in remaining vertices/edges 'flag' is cleared */ 01920 EditVert *eve,*nextve; 01921 EditEdge *eed, *nexted; 01922 EditFace *efa,*nextvl; 01923 01924 /* to detect loose edges, we put f2 flag on 1 */ 01925 for(eed= em->edges.first; eed; eed= eed->next) { 01926 if(eed->f & flag) eed->f2= 1; 01927 else eed->f2= 0; 01928 } 01929 01930 /* delete faces */ 01931 efa= em->faces.first; 01932 while(efa) { 01933 nextvl= efa->next; 01934 if(efa->f & flag) { 01935 01936 efa->e1->f2= 1; 01937 efa->e2->f2= 1; 01938 efa->e3->f2= 1; 01939 if(efa->e4) { 01940 efa->e4->f2= 1; 01941 } 01942 01943 BLI_remlink(&em->faces, efa); 01944 free_editface(em, efa); 01945 } 01946 efa= nextvl; 01947 } 01948 01949 /* all remaining faces: make sure we keep the edges */ 01950 for(efa= em->faces.first; efa; efa= efa->next) { 01951 efa->e1->f2= 0; 01952 efa->e2->f2= 0; 01953 efa->e3->f2= 0; 01954 if(efa->e4) { 01955 efa->e4->f2= 0; 01956 } 01957 } 01958 01959 /* remove tagged edges, and clear remaining ones */ 01960 eed= em->edges.first; 01961 while(eed) { 01962 nexted= eed->next; 01963 01964 if(eed->f2==1) { 01965 remedge(em, eed); 01966 free_editedge(em, eed); 01967 } 01968 else { 01969 eed->f &= ~flag; 01970 eed->v1->f &= ~flag; 01971 eed->v2->f &= ~flag; 01972 } 01973 eed= nexted; 01974 } 01975 01976 /* vertices with 'flag' now are the loose ones, and will be removed */ 01977 eve= em->verts.first; 01978 while(eve) { 01979 nextve= eve->next; 01980 if(eve->f & flag) { 01981 BLI_remlink(&em->verts, eve); 01982 free_editvert(em, eve); 01983 } 01984 eve= nextve; 01985 } 01986 01987 } 01988 01989 /* ********************* */ 01990 #if 0 01991 static int check_vnormal_flip(float *n, float *vnorm) 01992 { 01993 float inp; 01994 01995 inp= n[0]*vnorm[0]+n[1]*vnorm[1]+n[2]*vnorm[2]; 01996 01997 /* angles 90 degrees: dont flip */ 01998 if(inp> -0.000001) return 0; 01999 02000 return 1; 02001 } 02002 #endif 02003 02004 02005 02006 /* does face centers too */ 02007 void recalc_editnormals(EditMesh *em) 02008 { 02009 EditFace *efa; 02010 EditVert *eve; 02011 02012 for(eve= em->verts.first; eve; eve=eve->next) 02013 zero_v3(eve->no); 02014 02015 for(efa= em->faces.first; efa; efa=efa->next) { 02016 float *n4= (efa->v4)? efa->v4->no: NULL; 02017 float *c4= (efa->v4)? efa->v4->co: NULL; 02018 02019 if(efa->v4) { 02020 normal_quad_v3(efa->n, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); 02021 cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); 02022 } 02023 else { 02024 normal_tri_v3(efa->n, efa->v1->co, efa->v2->co, efa->v3->co); 02025 cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co); 02026 } 02027 02028 accumulate_vertex_normals(efa->v1->no, efa->v2->no, efa->v3->no, n4, 02029 efa->n, efa->v1->co, efa->v2->co, efa->v3->co, c4); 02030 } 02031 02032 /* following Mesh convention; we use vertex coordinate itself for normal in this case */ 02033 for(eve= em->verts.first; eve; eve=eve->next) { 02034 if(normalize_v3(eve->no) == 0.0f) { 02035 copy_v3_v3(eve->no, eve->co); 02036 normalize_v3(eve->no); 02037 } 02038 } 02039 } 02040 02041 int compareface(EditFace *vl1, EditFace *vl2) 02042 { 02043 EditVert *v1, *v2, *v3, *v4; 02044 02045 if(vl1->v4 && vl2->v4) { 02046 v1= vl2->v1; 02047 v2= vl2->v2; 02048 v3= vl2->v3; 02049 v4= vl2->v4; 02050 02051 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) { 02052 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) { 02053 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) { 02054 if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) { 02055 return 1; 02056 } 02057 } 02058 } 02059 } 02060 } 02061 else if(vl1->v4==0 && vl2->v4==0) { 02062 v1= vl2->v1; 02063 v2= vl2->v2; 02064 v3= vl2->v3; 02065 02066 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) { 02067 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) { 02068 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) { 02069 return 1; 02070 } 02071 } 02072 } 02073 } 02074 02075 return 0; 02076 } 02077 02078 /* checks for existence, not tria overlapping inside quad */ 02079 EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4) 02080 { 02081 EditFace *efa, efatest; 02082 02083 efatest.v1= v1; 02084 efatest.v2= v2; 02085 efatest.v3= v3; 02086 efatest.v4= v4; 02087 02088 efa= em->faces.first; 02089 while(efa) { 02090 if(compareface(&efatest, efa)) return efa; 02091 efa= efa->next; 02092 } 02093 return NULL; 02094 } 02095 02096 /* evaluate if entire quad is a proper convex quad */ 02097 int convex(float *v1, float *v2, float *v3, float *v4) 02098 { 02099 float nor[3], nor1[3], nor2[3], vec[4][2]; 02100 02101 /* define projection, do both trias apart, quad is undefined! */ 02102 normal_tri_v3( nor1,v1, v2, v3); 02103 normal_tri_v3( nor2,v1, v3, v4); 02104 nor[0]= ABS(nor1[0]) + ABS(nor2[0]); 02105 nor[1]= ABS(nor1[1]) + ABS(nor2[1]); 02106 nor[2]= ABS(nor1[2]) + ABS(nor2[2]); 02107 02108 if(nor[2] >= nor[0] && nor[2] >= nor[1]) { 02109 vec[0][0]= v1[0]; vec[0][1]= v1[1]; 02110 vec[1][0]= v2[0]; vec[1][1]= v2[1]; 02111 vec[2][0]= v3[0]; vec[2][1]= v3[1]; 02112 vec[3][0]= v4[0]; vec[3][1]= v4[1]; 02113 } 02114 else if(nor[1] >= nor[0] && nor[1]>= nor[2]) { 02115 vec[0][0]= v1[0]; vec[0][1]= v1[2]; 02116 vec[1][0]= v2[0]; vec[1][1]= v2[2]; 02117 vec[2][0]= v3[0]; vec[2][1]= v3[2]; 02118 vec[3][0]= v4[0]; vec[3][1]= v4[2]; 02119 } 02120 else { 02121 vec[0][0]= v1[1]; vec[0][1]= v1[2]; 02122 vec[1][0]= v2[1]; vec[1][1]= v2[2]; 02123 vec[2][0]= v3[1]; vec[2][1]= v3[2]; 02124 vec[3][0]= v4[1]; vec[3][1]= v4[2]; 02125 } 02126 02127 /* linetests, the 2 diagonals have to instersect to be convex */ 02128 if( isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1; 02129 return 0; 02130 } 02131 02132 02133 /* ********************* Fake Polgon support (FGon) ***************** */ 02134 02135 02136 /* results in: 02137 - faces having ->fgonf flag set (also for draw) 02138 - edges having ->fgoni index set (for select) 02139 */ 02140 02141 float EM_face_area(EditFace *efa) 02142 { 02143 if(efa->v4) return area_quad_v3(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); 02144 else return area_tri_v3(efa->v1->co, efa->v2->co, efa->v3->co); 02145 } 02146 02147 float EM_face_perimeter(EditFace *efa) 02148 { 02149 if(efa->v4) return 02150 len_v3v3(efa->v1->co, efa->v2->co)+ 02151 len_v3v3(efa->v2->co, efa->v3->co)+ 02152 len_v3v3(efa->v3->co, efa->v4->co)+ 02153 len_v3v3(efa->v4->co, efa->v1->co); 02154 02155 else return 02156 len_v3v3(efa->v1->co, efa->v2->co)+ 02157 len_v3v3(efa->v2->co, efa->v3->co)+ 02158 len_v3v3(efa->v3->co, efa->v1->co); 02159 } 02160 02161 void EM_fgon_flags(EditMesh *em) 02162 { 02163 EditFace *efa, *efan, *efamax; 02164 EditEdge *eed; 02165 ListBase listb={NULL, NULL}; 02166 float size, maxsize; 02167 short done, curindex= 1; 02168 02169 // for each face with fgon edge AND not fgon flag set 02170 for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0; // index 02171 for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0; // flag 02172 02173 // for speed & simplicity, put fgon face candidates in new listbase 02174 efa= em->faces.first; 02175 while(efa) { 02176 efan= efa->next; 02177 if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) || 02178 (efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) { 02179 BLI_remlink(&em->faces, efa); 02180 BLI_addtail(&listb, efa); 02181 } 02182 efa= efan; 02183 } 02184 02185 // find an undone face with fgon edge 02186 for(efa= listb.first; efa; efa= efa->next) { 02187 if(efa->fgonf==0) { 02188 02189 // init this face 02190 efa->fgonf= EM_FGON; 02191 if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex; 02192 if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex; 02193 if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex; 02194 if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex; 02195 02196 // we search for largest face, to give facedot drawing rights 02197 maxsize= EM_face_area(efa); 02198 efamax= efa; 02199 02200 // now flush curendex over edges and set faceflags 02201 done= 1; 02202 while(done==1) { 02203 done= 0; 02204 02205 for(efan= listb.first; efan; efan= efan->next) { 02206 if(efan->fgonf==0) { 02207 // if one if its edges has index set, do other too 02208 if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) || 02209 (efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) { 02210 02211 efan->fgonf= EM_FGON; 02212 if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex; 02213 if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex; 02214 if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex; 02215 if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex; 02216 02217 size= EM_face_area(efan); 02218 if(size>maxsize) { 02219 efamax= efan; 02220 maxsize= size; 02221 } 02222 done= 1; 02223 } 02224 } 02225 } 02226 } 02227 02228 efamax->fgonf |= EM_FGON_DRAW; 02229 curindex++; 02230 02231 } 02232 } 02233 02234 // put fgon face candidates back in listbase 02235 efa= listb.first; 02236 while(efa) { 02237 efan= efa->next; 02238 BLI_remlink(&listb, efa); 02239 BLI_addtail(&em->faces, efa); 02240 efa= efan; 02241 } 02242 02243 // remove fgon flags when edge not in fgon (anymore) 02244 for(eed= em->edges.first; eed; eed= eed->next) { 02245 if(eed->fgoni==0) eed->h &= ~EM_FGON; 02246 } 02247 02248 } 02249 02250 /* editmesh vertmap, copied from intern.mesh.c 02251 * if do_face_idx_array is 0 it means we need to run it as well as freeing 02252 * */ 02253 02254 UvVertMap *EM_make_uv_vert_map(EditMesh *em, int selected, int do_face_idx_array, float *limit) 02255 { 02256 EditVert *ev; 02257 EditFace *efa; 02258 int totverts; 02259 02260 /* vars from original func */ 02261 UvVertMap *vmap; 02262 UvMapVert *buf; 02263 MTFace *tf; 02264 unsigned int a; 02265 int i, totuv, nverts; 02266 02267 if (do_face_idx_array) 02268 EM_init_index_arrays(em, 0, 0, 1); 02269 02270 /* we need the vert */ 02271 for (ev= em->verts.first, totverts=0; ev; ev= ev->next, totverts++) { 02272 ev->tmp.l = totverts; 02273 } 02274 02275 totuv = 0; 02276 02277 /* generate UvMapVert array */ 02278 for (efa= em->faces.first; efa; efa= efa->next) 02279 if(!selected || ((!efa->h) && (efa->f & SELECT))) 02280 totuv += (efa->v4)? 4: 3; 02281 02282 if(totuv==0) { 02283 if (do_face_idx_array) 02284 EM_free_index_arrays(); 02285 return NULL; 02286 } 02287 vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap"); 02288 if (!vmap) { 02289 if (do_face_idx_array) 02290 EM_free_index_arrays(); 02291 return NULL; 02292 } 02293 02294 vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*"); 02295 buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert"); 02296 02297 if (!vmap->vert || !vmap->buf) { 02298 free_uv_vert_map(vmap); 02299 if (do_face_idx_array) 02300 EM_free_index_arrays(); 02301 return NULL; 02302 } 02303 02304 for (a=0, efa= em->faces.first; efa; a++, efa= efa->next) { 02305 if(!selected || ((!efa->h) && (efa->f & SELECT))) { 02306 nverts= (efa->v4)? 4: 3; 02307 02308 for(i=0; i<nverts; i++) { 02309 buf->tfindex= i; 02310 buf->f= a; 02311 buf->separate = 0; 02312 02313 buf->next= vmap->vert[(*(&efa->v1 + i))->tmp.l]; 02314 vmap->vert[(*(&efa->v1 + i))->tmp.l]= buf; 02315 02316 buf++; 02317 } 02318 } 02319 } 02320 02321 /* sort individual uvs for each vert */ 02322 for(a=0, ev=em->verts.first; ev; a++, ev= ev->next) { 02323 UvMapVert *newvlist= NULL, *vlist=vmap->vert[a]; 02324 UvMapVert *iterv, *v, *lastv, *next; 02325 float *uv, *uv2, uvdiff[2]; 02326 02327 while(vlist) { 02328 v= vlist; 02329 vlist= vlist->next; 02330 v->next= newvlist; 02331 newvlist= v; 02332 02333 efa = EM_get_face_for_index(v->f); 02334 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02335 uv = tf->uv[v->tfindex]; 02336 02337 lastv= NULL; 02338 iterv= vlist; 02339 02340 while(iterv) { 02341 next= iterv->next; 02342 efa = EM_get_face_for_index(iterv->f); 02343 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 02344 uv2 = tf->uv[iterv->tfindex]; 02345 02346 sub_v2_v2v2(uvdiff, uv2, uv); 02347 02348 if(fabsf(uv[0]-uv2[0]) < limit[0] && fabsf(uv[1]-uv2[1]) < limit[1]) { 02349 if(lastv) lastv->next= next; 02350 else vlist= next; 02351 iterv->next= newvlist; 02352 newvlist= iterv; 02353 } 02354 else 02355 lastv=iterv; 02356 02357 iterv= next; 02358 } 02359 02360 newvlist->separate = 1; 02361 } 02362 02363 vmap->vert[a]= newvlist; 02364 } 02365 02366 if (do_face_idx_array) 02367 EM_free_index_arrays(); 02368 02369 return vmap; 02370 } 02371 02372 UvMapVert *EM_get_uv_map_vert(UvVertMap *vmap, unsigned int v) 02373 { 02374 return vmap->vert[v]; 02375 } 02376 02377 void EM_free_uv_vert_map(UvVertMap *vmap) 02378 { 02379 if (vmap) { 02380 if (vmap->vert) MEM_freeN(vmap->vert); 02381 if (vmap->buf) MEM_freeN(vmap->buf); 02382 MEM_freeN(vmap); 02383 } 02384 } 02385 02386 /* poll call for mesh operators requiring a view3d context */ 02387 int EM_view3d_poll(bContext *C) 02388 { 02389 if(ED_operator_editmesh(C) && ED_operator_view3d_active(C)) 02390 return 1; 02391 return 0; 02392 } 02393 02394 /* higher quality normals */ 02395 02396 /* NormalCalc */ 02397 /* NormalCalc modifier: calculates higher quality normals 02398 */ 02399 02400 /* each edge uses this to */ 02401 typedef struct EdgeFaceRef { 02402 int f1; /* init as -1 */ 02403 int f2; 02404 } EdgeFaceRef; 02405 02406 void EM_make_hq_normals(EditMesh *em) 02407 { 02408 EditFace *efa; 02409 EditVert *eve; 02410 int i; 02411 02412 EdgeHash *edge_hash = BLI_edgehash_new(); 02413 EdgeHashIterator *edge_iter; 02414 int edge_ref_count = 0; 02415 unsigned int ed_v1, ed_v2; /* use when getting the key */ 02416 EdgeFaceRef *edge_ref_array = MEM_callocN(em->totedge * sizeof(EdgeFaceRef), "Edge Connectivity"); 02417 EdgeFaceRef *edge_ref; 02418 float edge_normal[3]; 02419 02420 EM_init_index_arrays(em, 1, 1, 1); 02421 02422 for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { 02423 zero_v3(eve->no); 02424 eve->tmp.l= i; 02425 } 02426 02427 /* This function adds an edge hash if its not there, and adds the face index */ 02428 #define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \ 02429 { \ 02430 const unsigned int mf_v1 = EDV1; \ 02431 const unsigned int mf_v2 = EDV2; \ 02432 edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, mf_v1, mf_v2); \ 02433 if (!edge_ref) { \ 02434 edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ 02435 edge_ref->f1 = i; \ 02436 edge_ref->f2 = -1; \ 02437 BLI_edgehash_insert(edge_hash, mf_v1, mf_v2, edge_ref); \ 02438 } \ 02439 else { \ 02440 edge_ref->f2 = i; \ 02441 } \ 02442 } 02443 02444 02445 efa= em->faces.first; 02446 for(i = 0; i < em->totface; i++, efa= efa->next) { 02447 if(efa->v4) { 02448 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l); 02449 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l); 02450 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v4->tmp.l); 02451 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v4->tmp.l, efa->v1->tmp.l); 02452 } else { 02453 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l); 02454 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l); 02455 NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v1->tmp.l); 02456 } 02457 } 02458 02459 #undef NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE 02460 02461 02462 for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { 02463 /* Get the edge vert indices, and edge value (the face indices that use it)*/ 02464 BLI_edgehashIterator_getKey(edge_iter, &ed_v1, &ed_v2); 02465 edge_ref = BLI_edgehashIterator_getValue(edge_iter); 02466 02467 if (edge_ref->f2 != -1) { 02468 EditFace *ef1= EM_get_face_for_index(edge_ref->f1), *ef2= EM_get_face_for_index(edge_ref->f2); 02469 float angle= angle_normalized_v3v3(ef1->n, ef2->n); 02470 if(angle > 0.0f) { 02471 /* We have 2 faces using this edge, calculate the edges normal 02472 * using the angle between the 2 faces as a weighting */ 02473 add_v3_v3v3(edge_normal, ef1->n, ef2->n); 02474 normalize_v3(edge_normal); 02475 mul_v3_fl(edge_normal, angle); 02476 } 02477 else { 02478 /* cant do anything useful here! 02479 Set the face index for a vert incase it gets a zero normal */ 02480 EM_get_vert_for_index(ed_v1)->tmp.l= 02481 EM_get_vert_for_index(ed_v2)->tmp.l= -(edge_ref->f1 + 1); 02482 continue; 02483 } 02484 } else { 02485 /* only one face attached to that edge */ 02486 /* an edge without another attached- the weight on this is 02487 * undefined, M_PI/2 is 90d in radians and that seems good enough */ 02488 copy_v3_v3(edge_normal, EM_get_face_for_index(edge_ref->f1)->n); 02489 mul_v3_fl(edge_normal, M_PI/2); 02490 } 02491 add_v3_v3(EM_get_vert_for_index(ed_v1)->no, edge_normal ); 02492 add_v3_v3(EM_get_vert_for_index(ed_v2)->no, edge_normal ); 02493 02494 02495 } 02496 BLI_edgehashIterator_free(edge_iter); 02497 BLI_edgehash_free(edge_hash, NULL); 02498 MEM_freeN(edge_ref_array); 02499 02500 /* normalize vertex normals and assign */ 02501 for(eve= em->verts.first; eve; eve= eve->next) { 02502 if(normalize_v3(eve->no) == 0.0f && eve->tmp.l < 0) { 02503 /* exceptional case, totally flat */ 02504 efa= EM_get_face_for_index(-(eve->tmp.l) - 1); 02505 copy_v3_v3(eve->no, efa->n); 02506 } 02507 } 02508 02509 EM_free_index_arrays(); 02510 } 02511 02512 void EM_solidify(EditMesh *em, float dist) 02513 { 02514 EditFace *efa; 02515 EditVert *eve; 02516 float *vert_angles= MEM_callocN(sizeof(float) * em->totvert * 2, "EM_solidify"); /* 2 in 1 */ 02517 float *vert_accum= vert_angles + em->totvert; 02518 float face_angles[4]; 02519 int i, j; 02520 02521 for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { 02522 eve->tmp.l= i; 02523 } 02524 02525 efa= em->faces.first; 02526 for(i = 0; i < em->totface; i++, efa= efa->next) { 02527 02528 if(!(efa->f & SELECT)) 02529 continue; 02530 02531 if(efa->v4) { 02532 angle_quad_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); 02533 j= 3; 02534 } 02535 else { 02536 angle_tri_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co); 02537 j= 2; 02538 } 02539 02540 for(; j>=0; j--) { 02541 eve= *(&efa->v1 + j); 02542 vert_accum[eve->tmp.l] += face_angles[j]; 02543 vert_angles[eve->tmp.l]+= shell_angle_to_dist(angle_normalized_v3v3(eve->no, efa->n)) * face_angles[j]; 02544 } 02545 } 02546 02547 for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { 02548 if(vert_accum[i]) { /* zero if unselected */ 02549 madd_v3_v3fl(eve->co, eve->no, dist * vert_angles[i] / vert_accum[i]); 02550 } 02551 } 02552 02553 MEM_freeN(vert_angles); 02554 } 02555 02556 /* not that optimal!, should be nicer with bmesh */ 02557 static void tag_face_edges(EditFace *efa) 02558 { 02559 if(efa->v4) 02560 efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1; 02561 else 02562 efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1; 02563 } 02564 static int tag_face_edges_test(EditFace *efa) 02565 { 02566 if(efa->v4) 02567 return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l || efa->e4->tmp.l) ? 1:0; 02568 else 02569 return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l) ? 1:0; 02570 } 02571 02572 static void em_deselect_nth_face(EditMesh *em, int nth, EditFace *efa_act) 02573 { 02574 EditFace *efa; 02575 EditEdge *eed; 02576 int ok= 1; 02577 02578 if(efa_act==NULL) { 02579 return; 02580 } 02581 02582 /* to detect loose edges, we put f2 flag on 1 */ 02583 for(eed= em->edges.first; eed; eed= eed->next) { 02584 eed->tmp.l= 0; 02585 } 02586 02587 for (efa= em->faces.first; efa; efa= efa->next) { 02588 efa->tmp.l = 0; 02589 } 02590 02591 efa_act->tmp.l = 1; 02592 02593 while(ok) { 02594 ok = 0; 02595 02596 for (efa= em->faces.first; efa; efa= efa->next) { 02597 if(efa->f & SELECT) { 02598 if(efa->tmp.l==1) { /* initialize */ 02599 tag_face_edges(efa); 02600 } 02601 02602 if(efa->tmp.l) { 02603 efa->tmp.l++; 02604 } 02605 } 02606 } 02607 02608 for (efa= em->faces.first; efa; efa= efa->next) { 02609 if(efa->f & SELECT) { 02610 if(efa->tmp.l==0 && tag_face_edges_test(efa)) { 02611 efa->tmp.l= 1; 02612 ok = 1; /* keep looping */ 02613 } 02614 } 02615 } 02616 } 02617 02618 for (efa= em->faces.first; efa; efa= efa->next) { 02619 if(efa->tmp.l > 0 && efa->tmp.l % nth) { 02620 EM_select_face(efa, 0); 02621 } 02622 } 02623 for (efa= em->faces.first; efa; efa= efa->next) { 02624 if(efa->f & SELECT) { 02625 EM_select_face(efa, 1); 02626 } 02627 } 02628 02629 EM_nvertices_selected(em); 02630 EM_nedges_selected(em); 02631 EM_nfaces_selected(em); 02632 } 02633 02634 /* not that optimal!, should be nicer with bmesh */ 02635 static void tag_edge_verts(EditEdge *eed) 02636 { 02637 eed->v1->tmp.l= eed->v2->tmp.l= 1; 02638 } 02639 static int tag_edge_verts_test(EditEdge *eed) 02640 { 02641 return (eed->v1->tmp.l || eed->v2->tmp.l) ? 1:0; 02642 } 02643 02644 static void em_deselect_nth_edge(EditMesh *em, int nth, EditEdge *eed_act) 02645 { 02646 EditEdge *eed; 02647 EditVert *eve; 02648 int ok= 1; 02649 02650 if(eed_act==NULL) { 02651 return; 02652 } 02653 02654 for(eve= em->verts.first; eve; eve= eve->next) { 02655 eve->tmp.l= 0; 02656 } 02657 02658 for (eed= em->edges.first; eed; eed= eed->next) { 02659 eed->tmp.l = 0; 02660 } 02661 02662 eed_act->tmp.l = 1; 02663 02664 while(ok) { 02665 ok = 0; 02666 02667 for (eed= em->edges.first; eed; eed= eed->next) { 02668 if(eed->f & SELECT) { 02669 if(eed->tmp.l==1) { /* initialize */ 02670 tag_edge_verts(eed); 02671 } 02672 02673 if(eed->tmp.l) { 02674 eed->tmp.l++; 02675 } 02676 } 02677 } 02678 02679 for (eed= em->edges.first; eed; eed= eed->next) { 02680 if(eed->f & SELECT) { 02681 if(eed->tmp.l==0 && tag_edge_verts_test(eed)) { 02682 eed->tmp.l= 1; 02683 ok = 1; /* keep looping */ 02684 } 02685 } 02686 } 02687 } 02688 02689 for (eed= em->edges.first; eed; eed= eed->next) { 02690 if(eed->tmp.l > 0 && eed->tmp.l % nth) { 02691 EM_select_edge(eed, 0); 02692 } 02693 } 02694 for (eed= em->edges.first; eed; eed= eed->next) { 02695 if(eed->f & SELECT) { 02696 EM_select_edge(eed, 1); 02697 } 02698 } 02699 02700 { 02701 /* grr, should be a function */ 02702 EditFace *efa; 02703 for (efa= em->faces.first; efa; efa= efa->next) { 02704 if(efa->v4) { 02705 if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT ); 02706 else efa->f &= ~SELECT; 02707 } 02708 else { 02709 if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT ); 02710 else efa->f &= ~SELECT; 02711 } 02712 } 02713 } 02714 02715 EM_nvertices_selected(em); 02716 EM_nedges_selected(em); 02717 EM_nfaces_selected(em); 02718 } 02719 02720 static void em_deselect_nth_vert(EditMesh *em, int nth, EditVert *eve_act) 02721 { 02722 EditVert *eve; 02723 EditEdge *eed; 02724 int ok= 1; 02725 02726 if(eve_act==NULL) { 02727 return; 02728 } 02729 02730 for (eve= em->verts.first; eve; eve= eve->next) { 02731 eve->tmp.l = 0; 02732 } 02733 02734 eve_act->tmp.l = 1; 02735 02736 while(ok) { 02737 ok = 0; 02738 02739 for (eve= em->verts.first; eve; eve= eve->next) { 02740 if(eve->f & SELECT) { 02741 if(eve->tmp.l) 02742 eve->tmp.l++; 02743 } 02744 } 02745 02746 for (eed= em->edges.first; eed; eed= eed->next) { 02747 if(eed->f & SELECT) { 02748 if(eed->v1->tmp.l==2 && eed->v2->tmp.l==0) { /* initialize */ 02749 eed->v2->tmp.l= 1; 02750 ok = 1; /* keep looping */ 02751 } 02752 else if(eed->v2->tmp.l==2 && eed->v1->tmp.l==0) { /* initialize */ 02753 eed->v1->tmp.l= 1; 02754 ok = 1; /* keep looping */ 02755 } 02756 } 02757 } 02758 } 02759 02760 for (eve= em->verts.first; eve; eve= eve->next) { 02761 if(eve->tmp.l > 0 && eve->tmp.l % nth) { 02762 eve->f &= ~SELECT; 02763 } 02764 } 02765 02766 EM_deselect_flush(em); 02767 02768 EM_nvertices_selected(em); 02769 // EM_nedges_selected(em); // flush does these 02770 // EM_nfaces_selected(em); // flush does these 02771 } 02772 02773 static void deselect_nth_active(EditMesh *em, EditVert **eve_p, EditEdge **eed_p, EditFace **efa_p) 02774 { 02775 EditSelection *ese; 02776 02777 *eve_p= NULL; 02778 *eed_p= NULL; 02779 *efa_p= NULL; 02780 02781 ese= (EditSelection*)em->selected.last; 02782 02783 if(ese) { 02784 switch(ese->type) { 02785 case EDITVERT: 02786 *eve_p= (EditVert *)ese->data; 02787 return; 02788 case EDITEDGE: 02789 *eed_p= (EditEdge *)ese->data; 02790 return; 02791 case EDITFACE: 02792 *efa_p= (EditFace *)ese->data; 02793 return; 02794 } 02795 } 02796 02797 if(em->selectmode & SCE_SELECT_VERTEX) { 02798 EditVert *eve; 02799 for (eve= em->verts.first; eve; eve= eve->next) { 02800 if(eve->f & SELECT) { 02801 *eve_p= eve; 02802 return; 02803 } 02804 } 02805 } 02806 02807 if(em->selectmode & SCE_SELECT_EDGE) { 02808 EditEdge *eed; 02809 for (eed= em->edges.first; eed; eed= eed->next) { 02810 if(eed->f & SELECT) { 02811 *eed_p= eed; 02812 return; 02813 } 02814 } 02815 } 02816 02817 if(em->selectmode & SCE_SELECT_FACE) { 02818 EditFace *efa= EM_get_actFace(em, 1); 02819 if(efa) { 02820 *efa_p= efa; 02821 return; 02822 } 02823 } 02824 } 02825 02826 int EM_deselect_nth(EditMesh *em, int nth) 02827 { 02828 EditVert *eve; 02829 EditEdge *eed; 02830 EditFace *efa; 02831 02832 deselect_nth_active(em, &eve, &eed, &efa); 02833 02834 if(eve) 02835 em_deselect_nth_vert(em, nth, eve); 02836 else if (eed) 02837 em_deselect_nth_edge(em, nth, eed); 02838 else if (efa) 02839 em_deselect_nth_face(em, nth, efa); 02840 else 02841 return 0; 02842 02843 return 1; 02844 } 02845 02846 void EM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, EditMesh *em) 02847 { 02848 EditVert *eve; 02849 for(eve= em->verts.first;eve; eve=eve->next) { 02850 if(eve->f & SELECT) { 02851 float mval[2], vec[3], no_dummy[3]; 02852 int dist_dummy; 02853 mul_v3_m4v3(vec, obedit->obmat, eve->co); 02854 project_float_noclip(ar, vec, mval); 02855 if(snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) { 02856 mul_v3_m4v3(eve->co, obedit->imat, vec); 02857 } 02858 } 02859 } 02860 }