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