|
Blender
V2.59
|
00001 /* 00002 * $Id: editmesh_loop.c 38081 2011-07-04 11:28:39Z ton $ 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_loop: tools with own drawing subloops, select, knife, subdiv 00038 00039 */ 00040 00041 #include <stdlib.h> 00042 #include <string.h> 00043 #include <math.h> 00044 00045 #include "MEM_guardedalloc.h" 00046 00047 00048 #include "DNA_object_types.h" 00049 #include "DNA_scene_types.h" 00050 #include "DNA_screen_types.h" 00051 00052 #include "BLI_blenlib.h" 00053 #include "BLI_math.h" 00054 #include "BLI_utildefines.h" 00055 #include "BLI_editVert.h" 00056 #include "BLI_ghash.h" 00057 00058 #include "BKE_context.h" 00059 #include "BKE_depsgraph.h" 00060 #include "BKE_mesh.h" 00061 #include "BKE_array_mallocn.h" 00062 00063 #include "PIL_time.h" 00064 00065 #include "BIF_gl.h" 00066 00067 #include "RNA_access.h" 00068 #include "RNA_define.h" 00069 00070 #include "WM_api.h" 00071 #include "WM_types.h" 00072 00073 #include "ED_mesh.h" 00074 #include "ED_view3d.h" 00075 00076 #include "mesh_intern.h" 00077 00078 /* **** XXX ******** */ 00079 static void error(const char *UNUSED(arg)) {} 00080 /* **** XXX ******** */ 00081 00082 #if 0 /* UNUSED 2.5 */ 00083 static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int previewlines) 00084 { 00085 EditEdge *eed; 00086 EditFace *efa; 00087 EditVert *v[2][2]; 00088 float co[2][3]; 00089 int looking= 1,i; 00090 00091 /* in eed->f1 we put the valence (amount of faces in edge) */ 00092 /* in eed->f2 we put tagged flag as correct loop */ 00093 /* in efa->f1 we put tagged flag as correct to select */ 00094 00095 for(eed= em->edges.first; eed; eed= eed->next) { 00096 eed->f1= 0; 00097 eed->f2= 0; 00098 } 00099 for(efa= em->faces.first; efa; efa= efa->next) { 00100 efa->f1= 0; 00101 if(efa->h==0) { 00102 efa->e1->f1++; 00103 efa->e2->f1++; 00104 efa->e3->f1++; 00105 if(efa->e4) efa->e4->f1++; 00106 } 00107 } 00108 00109 // tag startedge OK 00110 startedge->f2= 1; 00111 00112 while(looking) { 00113 looking= 0; 00114 00115 for(efa= em->faces.first; efa; efa= efa->next) { 00116 if(efa->e4 && efa->f1==0 && efa->h == 0) { // not done quad 00117 if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok 00118 00119 // if edge tagged, select opposing edge and mark face ok 00120 if(efa->e1->f2) { 00121 efa->e3->f2= 1; 00122 efa->f1= 1; 00123 looking= 1; 00124 } 00125 else if(efa->e2->f2) { 00126 efa->e4->f2= 1; 00127 efa->f1= 1; 00128 looking= 1; 00129 } 00130 if(efa->e3->f2) { 00131 efa->e1->f2= 1; 00132 efa->f1= 1; 00133 looking= 1; 00134 } 00135 if(efa->e4->f2) { 00136 efa->e2->f2= 1; 00137 efa->f1= 1; 00138 looking= 1; 00139 } 00140 } 00141 } 00142 } 00143 } 00144 00145 if(previewlines > 0 && select == 0){ 00146 // XXX persp(PERSP_VIEW); 00147 // XXX glPushMatrix(); 00148 // XXX mymultmatrix(obedit->obmat); 00149 00150 for(efa= em->faces.first; efa; efa= efa->next) { 00151 if(efa->v4 == NULL) { continue; } 00152 if(efa->h == 0){ 00153 if(efa->e1->f2 == 1){ 00154 if(efa->e1->h == 1 || efa->e3->h == 1 ) 00155 continue; 00156 00157 v[0][0] = efa->v1; 00158 v[0][1] = efa->v2; 00159 v[1][0] = efa->v4; 00160 v[1][1] = efa->v3; 00161 } else if(efa->e2->f2 == 1){ 00162 if(efa->e2->h == 1 || efa->e4->h == 1) 00163 continue; 00164 v[0][0] = efa->v2; 00165 v[0][1] = efa->v3; 00166 v[1][0] = efa->v1; 00167 v[1][1] = efa->v4; 00168 } else { continue; } 00169 00170 for(i=1;i<=previewlines;i++){ 00171 co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0]; 00172 co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1]; 00173 co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2]; 00174 00175 co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0]; 00176 co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1]; 00177 co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2]; 00178 glColor3ub(255, 0, 255); 00179 glBegin(GL_LINES); 00180 glVertex3f(co[0][0],co[0][1],co[0][2]); 00181 glVertex3f(co[1][0],co[1][1],co[1][2]); 00182 glEnd(); 00183 } 00184 } 00185 } 00186 glPopMatrix(); 00187 } else { 00188 00189 /* (de)select the edges */ 00190 for(eed= em->edges.first; eed; eed= eed->next) { 00191 if(eed->f2) EM_select_edge(eed, select); 00192 } 00193 } 00194 } 00195 00196 static void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts) 00197 { 00198 ViewContext vc; // XXX 00199 EditEdge *nearest=NULL, *eed; 00200 float fac; 00201 int keys = 0, holdnum=0, selectmode, dist; 00202 int mvalo[2] = {0, 0}, mval[2] = {0, 0}; 00203 short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0; 00204 short hasHidden = 0; 00205 char msg[128]; 00206 00207 selectmode = em->selectmode; 00208 00209 if(em->selectmode & SCE_SELECT_FACE){ 00210 em->selectmode = SCE_SELECT_EDGE; 00211 EM_selectmode_set(em); 00212 } 00213 00214 00215 BIF_undo_push("Loopcut Begin"); 00216 while(choosing && !cancel){ 00217 // XXX getmouseco_areawin(mval); 00218 if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) { 00219 mvalo[0] = mval[0]; 00220 mvalo[1] = mval[1]; 00221 dist= 50; 00222 nearest = findnearestedge(&vc, &dist); // returns actual distance in dist 00223 // scrarea_do_windraw(curarea); // after findnearestedge, backbuf! 00224 00225 BLI_snprintf(msg, sizeof(msg),"Number of Cuts: %d (S)mooth: %s", numcuts, smooth ? "on":"off"); 00226 00227 // headerprint(msg); 00228 /* Need to figure preview */ 00229 if(nearest){ 00230 edgering_sel(em, nearest, 0, numcuts); 00231 } 00232 // XXX screen_swapbuffers(); 00233 00234 /* backbuffer refresh for non-apples (no aux) */ 00235 #ifndef __APPLE__ 00236 // XXX if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) { 00237 // backdrawview3d(0); 00238 // } 00239 #endif 00240 } 00241 else PIL_sleep_ms(10); // idle 00242 00243 00244 while(qtest()) 00245 { 00246 val=0; 00247 // XXX event= extern_qread(&val); 00248 if(val && (event == MOUSEX || event == MOUSEY)){ ; } 00249 else if(val && ((event==LEFTMOUSE || event==RETKEY) || (event == MIDDLEMOUSE || event==PADENTER))) 00250 { 00251 if(event == MIDDLEMOUSE){ 00252 cuthalf = 1; 00253 } 00254 if (nearest==NULL) 00255 cancel = 1; 00256 choosing=0; 00257 mvalo[0] = -1; 00258 } 00259 else if(val && (event==ESCKEY || event==RIGHTMOUSE )) 00260 { 00261 choosing=0; 00262 cancel = 1; 00263 mvalo[0] = -1; 00264 } 00265 else if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE)) 00266 { 00267 numcuts++; 00268 mvalo[0] = -1; 00269 } 00270 else if(val && (event==PADMINUS || event==WHEELDOWNMOUSE)) 00271 { 00272 if(numcuts > 1){ 00273 numcuts--; 00274 mvalo[0] = -1; 00275 } 00276 } 00277 else if(val && event==SKEY) 00278 { 00279 if(smooth){smooth=0;} 00280 else { smooth=1; } 00281 mvalo[0] = -1; 00282 } 00283 00284 else if(val){ 00285 holdnum = -1; 00286 switch(event){ 00287 case PAD9: 00288 case NINEKEY: 00289 holdnum = 9; break; 00290 case PAD8: 00291 case EIGHTKEY: 00292 holdnum = 8;break; 00293 case PAD7: 00294 case SEVENKEY: 00295 holdnum = 7;break; 00296 case PAD6: 00297 case SIXKEY: 00298 holdnum = 6;break; 00299 case PAD5: 00300 case FIVEKEY: 00301 holdnum = 5;break; 00302 case PAD4: 00303 case FOURKEY: 00304 holdnum = 4;break; 00305 case PAD3: 00306 case THREEKEY: 00307 holdnum = 3; break; 00308 case PAD2: 00309 case TWOKEY: 00310 holdnum = 2;break; 00311 case PAD1: 00312 case ONEKEY: 00313 holdnum = 1; break; 00314 case PAD0: 00315 case ZEROKEY: 00316 holdnum = 0;break; 00317 case BACKSPACEKEY: 00318 holdnum = -2;break; 00319 } 00320 if(holdnum >= 0 && numcuts*10 < 130){ 00321 if(keys == 0){ // first level numeric entry 00322 if(holdnum > 0){ 00323 numcuts = holdnum; 00324 keys++; 00325 } 00326 } else if(keys > 0){//highrt level numeric entry 00327 numcuts *= 10; 00328 numcuts += holdnum; 00329 keys++; 00330 } 00331 } else if (holdnum == -2){// backspace 00332 if (keys > 1){ 00333 numcuts /= 10; 00334 keys--; 00335 } else { 00336 numcuts=1; 00337 keys = 0; 00338 } 00339 } 00340 mvalo[0] = -1; 00341 break; 00342 } // End Numeric Entry 00343 } //End while(qtest()) 00344 } // End Choosing 00345 00346 if(cancel){ 00347 return; 00348 } 00349 /* clean selection */ 00350 for(eed=em->edges.first; eed; eed = eed->next){ 00351 EM_select_edge(eed,0); 00352 } 00353 /* select edge ring */ 00354 edgering_sel(em, nearest, 1, 0); 00355 00356 /* now cut the loops */ 00357 if(smooth){ 00358 fac= 1.0f; 00359 // XXX if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return; 00360 fac= 0.292f*fac; 00361 esubdivideflag(obedit, em, SELECT,fac,0,B_SMOOTH,numcuts, SUBDIV_CORNER_PATH, SUBDIV_SELECT_LOOPCUT); 00362 } else { 00363 esubdivideflag(obedit, em, SELECT,0,0,0,numcuts,SUBDIV_CORNER_PATH, SUBDIV_SELECT_LOOPCUT); 00364 } 00365 /* if this was a single cut, enter edgeslide mode */ 00366 if(numcuts == 1 && hasHidden == 0){ 00367 if(cuthalf) 00368 EdgeSlide(em, op, 1,0.0); 00369 else { 00370 if(EdgeSlide(em, op, 0,0.0) == -1){ 00371 BIF_undo(); 00372 } 00373 } 00374 } 00375 00376 if(em->selectmode != selectmode){ 00377 em->selectmode = selectmode; 00378 EM_selectmode_set(em); 00379 } 00380 00381 // DAG_id_tag_update(obedit->data, 0); 00382 return; 00383 } 00384 #endif 00385 00386 /* *************** LOOP SELECT ************* */ 00387 #if 0 00388 static short edgeFaces(EditMesh *em, EditEdge *e) 00389 { 00390 EditFace *search=NULL; 00391 short count = 0; 00392 00393 search = em->faces.first; 00394 while(search){ 00395 if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) 00396 count++; 00397 search = search->next; 00398 } 00399 return count; 00400 } 00401 #endif 00402 00403 00404 00405 /* ***************** TRAIL ************************ 00406 00407 Read a trail of mouse coords and return them as an array of CutCurve structs 00408 len returns number of mouse coords read before commiting with RETKEY 00409 It is up to the caller to free the block when done with it, 00410 00411 XXX Is only used here, so local inside this file (ton) 00412 */ 00413 00414 #define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */ 00415 #define TRAIL_FREEHAND 2 00416 #define TRAIL_MIXED 3 /* (1|2) */ 00417 #define TRAIL_AUTO 4 00418 #define TRAIL_MIDPOINTS 8 00419 00420 typedef struct CutCurve { 00421 float x; 00422 float y; 00423 } CutCurve; 00424 00425 00426 /* ******************************************************************** */ 00427 /* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail 00428 drawn by user. 00429 00430 Currently mapped to KKey when in MeshEdit mode. 00431 Usage: 00432 Hit Shift K, Select Centers or Exact 00433 Hold LMB down to draw path, hit RETKEY. 00434 ESC cancels as expected. 00435 00436 Contributed by Robert Wenzlaff (Det. Thorn). 00437 00438 2.5 revamp: 00439 - non modal (no menu before cutting) 00440 - exit on mouse release 00441 - polygon/segment drawing can become handled by WM cb later 00442 00443 */ 00444 00445 #define KNIFE_EXACT 1 00446 #define KNIFE_MIDPOINT 2 00447 #define KNIFE_MULTICUT 3 00448 00449 static EnumPropertyItem knife_items[]= { 00450 {KNIFE_EXACT, "EXACT", 0, "Exact", ""}, 00451 {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""}, 00452 {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""}, 00453 {0, NULL, 0, NULL, NULL} 00454 }; 00455 00456 /* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */ 00457 00458 static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct GHash *gh) 00459 { 00460 #define MAXSLOPE 100000 00461 float x11, y11, x12=0, y12=0, x2max, x2min, y2max; 00462 float y2min, dist, lastdist=0, xdiff2, xdiff1; 00463 float m1, b1, m2, b2, x21, x22, y21, y22, xi; 00464 float yi, x1min, x1max, y1max, y1min, perc=0; 00465 float *scr; 00466 float threshold; 00467 int i; 00468 00469 threshold = 0.000001; /*tolerance for vertex intersection*/ 00470 // XXX threshold = scene->toolsettings->select_thresh / 100; 00471 00472 /* Get screen coords of verts */ 00473 scr = BLI_ghash_lookup(gh, e->v1); 00474 x21=scr[0]; 00475 y21=scr[1]; 00476 00477 scr = BLI_ghash_lookup(gh, e->v2); 00478 x22=scr[0]; 00479 y22=scr[1]; 00480 00481 xdiff2=(x22-x21); 00482 if (xdiff2) { 00483 m2=(y22-y21)/xdiff2; 00484 b2= ((x22*y21)-(x21*y22))/xdiff2; 00485 } 00486 else { 00487 m2=MAXSLOPE; /* Verticle slope */ 00488 b2=x22; 00489 } 00490 00491 /*check for *exact* vertex intersection first*/ 00492 if(mode!=KNIFE_MULTICUT){ 00493 for (i=0; i<len; i++){ 00494 if (i>0){ 00495 x11=x12; 00496 y11=y12; 00497 } 00498 else { 00499 x11=c[i].x; 00500 y11=c[i].y; 00501 } 00502 x12=c[i].x; 00503 y12=c[i].y; 00504 00505 /*test e->v1*/ 00506 if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){ 00507 e->v1->f1 = 1; 00508 perc = 0; 00509 return(perc); 00510 } 00511 /*test e->v2*/ 00512 else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){ 00513 e->v2->f1 = 1; 00514 perc = 0; 00515 return(perc); 00516 } 00517 } 00518 } 00519 00520 /*now check for edge interesect (may produce vertex intersection as well)*/ 00521 for (i=0; i<len; i++){ 00522 if (i>0){ 00523 x11=x12; 00524 y11=y12; 00525 } 00526 else { 00527 x11=c[i].x; 00528 y11=c[i].y; 00529 } 00530 x12=c[i].x; 00531 y12=c[i].y; 00532 00533 /* Perp. Distance from point to line */ 00534 if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */ 00535 /* change in sign. Skip extra math */ 00536 else dist=x22-x12; 00537 00538 if (i==0) lastdist=dist; 00539 00540 /* if dist changes sign, and intersect point in edge's Bound Box*/ 00541 if ((lastdist*dist)<=0){ 00542 xdiff1=(x12-x11); /* Equation of line between last 2 points */ 00543 if (xdiff1){ 00544 m1=(y12-y11)/xdiff1; 00545 b1= ((x12*y11)-(x11*y12))/xdiff1; 00546 } 00547 else{ 00548 m1=MAXSLOPE; 00549 b1=x12; 00550 } 00551 x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */ 00552 x2min=MIN2(x21,x22)-0.001; /* due to round off error */ 00553 y2max=MAX2(y21,y22)+0.001; 00554 y2min=MIN2(y21,y22)-0.001; 00555 00556 /* Found an intersect, calc intersect point */ 00557 if (m1==m2){ /* co-incident lines */ 00558 /* cut at 50% of overlap area*/ 00559 x1max=MAX2(x11, x12); 00560 x1min=MIN2(x11, x12); 00561 xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0; 00562 00563 y1max=MAX2(y11, y12); 00564 y1min=MIN2(y11, y12); 00565 yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0; 00566 } 00567 else if (m2==MAXSLOPE){ 00568 xi=x22; 00569 yi=m1*x22+b1; 00570 } 00571 else if (m1==MAXSLOPE){ 00572 xi=x12; 00573 yi=m2*x12+b2; 00574 } 00575 else { 00576 xi=(b1-b2)/(m2-m1); 00577 yi=(b1*m2-m1*b2)/(m2-m1); 00578 } 00579 00580 /* Intersect inside bounding box of edge?*/ 00581 if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){ 00582 /*test for vertex intersect that may be 'close enough'*/ 00583 if(mode!=KNIFE_MULTICUT){ 00584 if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){ 00585 if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){ 00586 e->v1->f1 = 1; 00587 perc = 0; 00588 break; 00589 } 00590 } 00591 if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){ 00592 if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){ 00593 e->v2->f1 = 1; 00594 perc = 0; 00595 break; 00596 } 00597 } 00598 } 00599 if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21); 00600 else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/ 00601 //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */ 00602 00603 break; 00604 } 00605 } 00606 lastdist=dist; 00607 } 00608 return(perc); 00609 } 00610 00611 /* for multicut */ 00612 #define MAX_CUTS 256 00613 00614 /* for amount of edges */ 00615 #define MAX_CUT_EDGES 1024 00616 00617 static int knife_cut_exec(bContext *C, wmOperator *op) 00618 { 00619 Object *obedit= CTX_data_edit_object(C); 00620 EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); 00621 ARegion *ar= CTX_wm_region(C); 00622 EditEdge *eed; 00623 EditVert *eve; 00624 CutCurve curve[MAX_CUT_EDGES]; 00625 struct GHash *gh; 00626 float isect=0.0; 00627 float *scr, co[4]; 00628 int len=0; 00629 short numcuts= RNA_int_get(op->ptr, "num_cuts"); 00630 short mode= RNA_enum_get(op->ptr, "type"); 00631 // int corner_cut_pattern= RNA_enum_get(op->ptr,"corner_cut_pattern"); 00632 00633 /* edit-object needed for matrix, and ar->regiondata for projections to work */ 00634 if (ELEM3(NULL, obedit, ar, ar->regiondata)) 00635 return OPERATOR_CANCELLED; 00636 00637 if (EM_nvertices_selected(em) < 2) { 00638 error("No edges are selected to operate on"); 00639 BKE_mesh_end_editmesh(obedit->data, em); 00640 return OPERATOR_CANCELLED; 00641 } 00642 00643 /* get the cut curve */ 00644 RNA_BEGIN(op->ptr, itemptr, "path") { 00645 00646 RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]); 00647 len++; 00648 if(len>= MAX_CUT_EDGES) break; 00649 } 00650 RNA_END; 00651 00652 if(len<2) { 00653 BKE_mesh_end_editmesh(obedit->data, em); 00654 return OPERATOR_CANCELLED; 00655 } 00656 00657 /*store percentage of edge cut for KNIFE_EXACT here.*/ 00658 for(eed=em->edges.first; eed; eed= eed->next) 00659 eed->tmp.fp = 0.0; 00660 00661 /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/ 00662 gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "knife_cut_exec gh"); 00663 for(eve=em->verts.first; eve; eve=eve->next){ 00664 scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates"); 00665 VECCOPY(co, eve->co); 00666 co[3]= 1.0; 00667 mul_m4_v4(obedit->obmat, co); 00668 project_float(ar, co, scr); 00669 BLI_ghash_insert(gh, eve, scr); 00670 eve->f1 = 0; /*store vertex intersection flag here*/ 00671 00672 } 00673 00674 eed= em->edges.first; 00675 while(eed) { 00676 if( eed->v1->f & eed->v2->f & SELECT ){ // NOTE: uses vertex select, subdiv doesnt do edges yet 00677 isect= seg_intersect(eed, curve, len, mode, gh); 00678 if (isect!=0.0f) eed->f2= 1; 00679 else eed->f2=0; 00680 eed->tmp.fp= isect; 00681 } 00682 else { 00683 eed->f2=0; 00684 eed->f1=0; 00685 } 00686 eed= eed->next; 00687 } 00688 00689 if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, 1, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER); 00690 else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE, numcuts, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER); 00691 else esubdivideflag(obedit, em, SELECT, 0, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_CORNER_INNERVERT, SUBDIV_SELECT_INNER); 00692 00693 eed=em->edges.first; 00694 while(eed){ 00695 eed->f2=0; 00696 eed->f1=0; 00697 eed=eed->next; 00698 } 00699 00700 BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN); 00701 00702 BKE_mesh_end_editmesh(obedit->data, em); 00703 00704 DAG_id_tag_update(obedit->data, 0); 00705 WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); 00706 00707 return OPERATOR_FINISHED; 00708 } 00709 00710 00711 void MESH_OT_knife_cut(wmOperatorType *ot) 00712 { 00713 PropertyRNA *prop; 00714 00715 ot->name= "Knife Cut"; 00716 ot->description= "Cut selected edges and faces into parts"; 00717 ot->idname= "MESH_OT_knife_cut"; 00718 00719 ot->invoke= WM_gesture_lines_invoke; 00720 ot->modal= WM_gesture_lines_modal; 00721 ot->exec= knife_cut_exec; 00722 ot->cancel= WM_gesture_lines_cancel; 00723 00724 ot->poll= EM_view3d_poll; 00725 00726 /* flags */ 00727 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00728 00729 RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", ""); 00730 prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); 00731 RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); 00732 RNA_def_int(ot->srna, "num_cuts", 1, 1, MAX_CUTS, "Number of Cuts", "Only for Multi-Cut", 1, MAX_CUTS); 00733 // doesn't work atm.. RNA_def_enum(ot->srna, "corner_cut_pattern", corner_type_items, SUBDIV_CORNER_INNERVERT, "Corner Cut Pattern", "Topology pattern to use to fill a face after cutting across its corner"); 00734 00735 /* internal */ 00736 RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX); 00737 } 00738 00739 /* ******************************************************* */ 00740