Merge branch 'bl/edgeloop'
[plumiferos.git] / source / blender / src / editmesh_tools.c
blobc5b9d70fea21bf7210ac830406aae8d6fbc70901
1 /**
2 * $Id:
4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
12 * about this.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2004 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): Johnny Matthews, Geoffrey Bantle.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
35 editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise in mods.c
39 #include <stdlib.h>
40 #include <string.h>
41 #include <math.h>
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
48 #include "MEM_guardedalloc.h"
50 #include "BMF_Api.h"
51 #include "DNA_mesh_types.h"
52 #include "DNA_material_types.h"
53 #include "DNA_meshdata_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_view3d_types.h"
58 #include "DNA_key_types.h"
60 #include "BLI_blenlib.h"
61 #include "BLI_arithb.h"
62 #include "BLI_editVert.h"
63 #include "BLI_rand.h"
64 #include "BLI_ghash.h"
65 #include "BLI_linklist.h"
66 #include "BLI_heap.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_customdata.h"
70 #include "BKE_global.h"
71 #include "BKE_library.h"
72 #include "BKE_mesh.h"
73 #include "BKE_object.h"
74 #include "BKE_utildefines.h"
76 #ifdef WITH_VERSE
77 #include "BKE_verse.h"
78 #endif
80 #include "BIF_cursors.h"
81 #include "BIF_editmesh.h"
82 #include "BIF_gl.h"
83 #include "BIF_glutil.h"
84 #include "BIF_graphics.h"
85 #include "BIF_interface.h"
86 #include "BIF_mywindow.h"
87 #include "BIF_screen.h"
88 #include "BIF_space.h"
89 #include "BIF_resources.h"
90 #include "BIF_toolbox.h"
91 #include "BIF_transform.h"
93 #ifdef WITH_VERSE
94 #include "BIF_verse.h"
95 #endif
97 #include "BDR_drawobject.h"
98 #include "BDR_editobject.h"
100 #include "BSE_view.h"
101 #include "BSE_edit.h"
103 #include "blendef.h"
104 #include "multires.h"
105 #include "mydevice.h"
107 #include "editmesh.h"
109 #include "MTC_vectorops.h"
111 #include "PIL_time.h"
113 /* local prototypes ---------------*/
114 void bevel_menu(void);
115 static void free_tagged_edges_faces(EditEdge *eed, EditFace *efa);
117 /********* qsort routines *********/
120 typedef struct xvertsort {
121 float x;
122 EditVert *v1;
123 } xvertsort;
125 static int vergxco(const void *v1, const void *v2)
127 const xvertsort *x1=v1, *x2=v2;
129 if( x1->x > x2->x ) return 1;
130 else if( x1->x < x2->x) return -1;
131 return 0;
134 struct facesort {
135 unsigned long x;
136 struct EditFace *efa;
140 static int vergface(const void *v1, const void *v2)
142 const struct facesort *x1=v1, *x2=v2;
144 if( x1->x > x2->x ) return 1;
145 else if( x1->x < x2->x) return -1;
146 return 0;
150 /* *********************************** */
152 void convert_to_triface(int direction)
154 EditMesh *em = G.editMesh;
155 EditFace *efa, *efan, *next;
156 float fac;
158 if(multires_test()) return;
160 efa= em->faces.last;
161 while(efa) {
162 next= efa->prev;
163 if(efa->v4) {
164 if(efa->f & SELECT) {
165 /* choose shortest diagonal for split */
166 fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co);
167 /* this makes sure exact squares get split different in both cases */
168 if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
169 efan= EM_face_from_faces(efa, NULL, 0, 1, 2, -1);
170 if(efa->f & SELECT) EM_select_face(efan, 1);
171 efan= EM_face_from_faces(efa, NULL, 0, 2, 3, -1);
172 if(efa->f & SELECT) EM_select_face(efan, 1);
174 else {
175 efan= EM_face_from_faces(efa, NULL, 0, 1, 3, -1);
176 if(efa->f & SELECT) EM_select_face(efan, 1);
177 efan= EM_face_from_faces(efa, NULL, 1, 2, 3, -1);
178 if(efa->f & SELECT) EM_select_face(efan, 1);
181 BLI_remlink(&em->faces, efa);
182 free_editface(efa);
185 efa= next;
188 EM_fgon_flags(); // redo flags and indices for fgons
190 #ifdef WITH_VERSE
191 if(G.editMesh->vnode)
192 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
193 #endif
194 BIF_undo_push("Convert Quads to Triangles");
198 int removedoublesflag(short flag, float limit) /* return amount */
200 EditMesh *em = G.editMesh;
201 /* all verts with (flag & 'flag') are being evaluated */
202 EditVert *eve, *v1, *nextve;
203 EditEdge *eed, *e1, *nexted;
204 EditFace *efa, *nextvl;
205 xvertsort *sortblock, *sb, *sb1;
206 struct facesort *vlsortblock, *vsb, *vsb1;
207 float dist;
208 int a, b, test, amount;
210 if(multires_test()) return 0;
212 /* flag 128 is cleared, count */
213 eve= em->verts.first;
214 amount= 0;
215 while(eve) {
216 eve->f &= ~128;
217 if(eve->h==0 && (eve->f & flag)) amount++;
218 eve= eve->next;
220 if(amount==0) return 0;
222 /* allocate memory and qsort */
223 sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
224 eve= em->verts.first;
225 while(eve) {
226 if(eve->h==0 && (eve->f & flag)) {
227 sb->x= eve->co[0]+eve->co[1]+eve->co[2];
228 sb->v1= eve;
229 sb++;
231 eve= eve->next;
233 qsort(sortblock, amount, sizeof(xvertsort), vergxco);
235 /* test for doubles */
236 sb= sortblock;
237 for(a=0; a<amount; a++) {
238 eve= sb->v1;
239 if( (eve->f & 128)==0 ) {
240 sb1= sb+1;
241 for(b=a+1; b<amount; b++) {
242 /* first test: simpel dist */
243 dist= sb1->x - sb->x;
244 if(dist > limit) break;
246 /* second test: is vertex allowed */
247 v1= sb1->v1;
248 if( (v1->f & 128)==0 ) {
250 dist= (float)fabs(v1->co[0]-eve->co[0]);
251 if(dist<=limit) {
252 dist= (float)fabs(v1->co[1]-eve->co[1]);
253 if(dist<=limit) {
254 dist= (float)fabs(v1->co[2]-eve->co[2]);
255 if(dist<=limit) {
256 v1->f|= 128;
257 v1->tmp.v = eve;
262 sb1++;
265 sb++;
267 MEM_freeN(sortblock);
269 for(eve = em->verts.first; eve; eve=eve->next)
270 if((eve->f & flag) && (eve->f & 128))
271 EM_data_interp_from_verts(eve, eve->tmp.v, eve->tmp.v, 0.5f);
273 /* test edges and insert again */
274 eed= em->edges.first;
275 while(eed) {
276 eed->f2= 0;
277 eed= eed->next;
279 eed= em->edges.last;
280 while(eed) {
281 nexted= eed->prev;
283 if(eed->f2==0) {
284 if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
285 remedge(eed);
287 if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v;
288 if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v;
289 e1= addedgelist(eed->v1, eed->v2, eed);
291 if(e1) e1->f2= 1;
292 if(e1!=eed) free_editedge(eed);
295 eed= nexted;
298 /* first count amount of test faces */
299 efa= (struct EditFace *)em->faces.first;
300 amount= 0;
301 while(efa) {
302 efa->f1= 0;
303 if(efa->v1->f & 128) efa->f1= 1;
304 else if(efa->v2->f & 128) efa->f1= 1;
305 else if(efa->v3->f & 128) efa->f1= 1;
306 else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1;
308 if(efa->f1==1) amount++;
309 efa= efa->next;
312 /* test faces for double vertices, and if needed remove them */
313 efa= (struct EditFace *)em->faces.first;
314 while(efa) {
315 nextvl= efa->next;
316 if(efa->f1==1) {
318 if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v;
319 if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v;
320 if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v;
321 if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v;
323 test= 0;
324 if(efa->v1==efa->v2) test+=1;
325 if(efa->v2==efa->v3) test+=2;
326 if(efa->v3==efa->v1) test+=4;
327 if(efa->v4==efa->v1) test+=8;
328 if(efa->v3==efa->v4) test+=16;
329 if(efa->v2==efa->v4) test+=32;
331 if(test) {
332 if(efa->v4) {
333 if(test==1 || test==2) {
334 efa->v2= efa->v3;
335 efa->v3= efa->v4;
336 efa->v4= 0;
338 EM_data_interp_from_faces(efa, NULL, efa, 0, 2, 3, 3);
340 test= 0;
342 else if(test==8 || test==16) {
343 efa->v4= 0;
344 test= 0;
346 else {
347 BLI_remlink(&em->faces, efa);
348 free_editface(efa);
349 amount--;
352 else {
353 BLI_remlink(&em->faces, efa);
354 free_editface(efa);
355 amount--;
359 if(test==0) {
360 /* set edge pointers */
361 efa->e1= findedgelist(efa->v1, efa->v2);
362 efa->e2= findedgelist(efa->v2, efa->v3);
363 if(efa->v4==0) {
364 efa->e3= findedgelist(efa->v3, efa->v1);
365 efa->e4= 0;
367 else {
368 efa->e3= findedgelist(efa->v3, efa->v4);
369 efa->e4= findedgelist(efa->v4, efa->v1);
373 efa= nextvl;
376 /* double faces: sort block */
377 /* count again, now all selected faces */
378 amount= 0;
379 efa= em->faces.first;
380 while(efa) {
381 efa->f1= 0;
382 if(faceselectedOR(efa, 1)) {
383 efa->f1= 1;
384 amount++;
386 efa= efa->next;
389 if(amount) {
390 /* double faces: sort block */
391 vsb= vlsortblock= MEM_mallocN(sizeof(struct facesort)*amount, "sortremovedoub");
392 efa= em->faces.first;
393 while(efa) {
394 if(efa->f1 & 1) {
395 if(efa->v4) vsb->x= (unsigned long) MIN4( (unsigned long)efa->v1, (unsigned long)efa->v2, (unsigned long)efa->v3, (unsigned long)efa->v4);
396 else vsb->x= (unsigned long) MIN3( (unsigned long)efa->v1, (unsigned long)efa->v2, (unsigned long)efa->v3);
398 vsb->efa= efa;
399 vsb++;
401 efa= efa->next;
404 qsort(vlsortblock, amount, sizeof(struct facesort), vergface);
406 vsb= vlsortblock;
407 for(a=0; a<amount; a++) {
408 efa= vsb->efa;
409 if( (efa->f1 & 128)==0 ) {
410 vsb1= vsb+1;
412 for(b=a+1; b<amount; b++) {
414 /* first test: same pointer? */
415 if(vsb->x != vsb1->x) break;
417 /* second test: is test permitted? */
418 efa= vsb1->efa;
419 if( (efa->f1 & 128)==0 ) {
420 if( compareface(efa, vsb->efa)) efa->f1 |= 128;
423 vsb1++;
426 vsb++;
429 MEM_freeN(vlsortblock);
431 /* remove double faces */
432 efa= (struct EditFace *)em->faces.first;
433 while(efa) {
434 nextvl= efa->next;
435 if(efa->f1 & 128) {
436 BLI_remlink(&em->faces, efa);
437 free_editface(efa);
439 efa= nextvl;
443 /* remove double vertices */
444 a= 0;
445 eve= (struct EditVert *)em->verts.first;
446 while(eve) {
447 nextve= eve->next;
448 if(eve->f & flag) {
449 if(eve->f & 128) {
450 a++;
451 BLI_remlink(&em->verts, eve);
452 free_editvert(eve);
455 eve= nextve;
458 #ifdef WITH_VERSE
459 if((a>0) && (G.editMesh->vnode)) {
460 sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
461 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
463 #endif
465 return a; /* amount */
468 /* called from buttons */
469 static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index)
471 xvertsort *sortblock = userData;
473 sortblock[index].x = x;
475 void xsortvert_flag(int flag)
477 EditMesh *em = G.editMesh;
478 /* all verts with (flag & 'flag') are sorted */
479 EditVert *eve;
480 xvertsort *sortblock;
481 ListBase tbase;
482 int i, amount = BLI_countlist(&em->verts);
484 if(multires_test()) return;
486 sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort");
487 for (i=0,eve=em->verts.first; eve; i++,eve=eve->next)
488 if(eve->f & flag)
489 sortblock[i].v1 = eve;
490 mesh_foreachScreenVert(xsortvert_flag__doSetX, sortblock, 0);
491 qsort(sortblock, amount, sizeof(xvertsort), vergxco);
493 /* make temporal listbase */
494 tbase.first= tbase.last= 0;
495 for (i=0; i<amount; i++) {
496 eve = sortblock[i].v1;
498 if (eve) {
499 BLI_remlink(&em->verts, eve);
500 BLI_addtail(&tbase, eve);
504 addlisttolist(&em->verts, &tbase);
506 MEM_freeN(sortblock);
508 #ifdef WITH_VERSE
509 if(G.editMesh->vnode)
510 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
511 #endif
513 BIF_undo_push("Xsort");
517 /* called from buttons */
518 void hashvert_flag(int flag)
520 /* switch vertex order using hash table */
521 EditMesh *em = G.editMesh;
522 EditVert *eve;
523 struct xvertsort *sortblock, *sb, onth, *newsort;
524 ListBase tbase;
525 int amount, a, b;
527 if(multires_test()) return;
529 /* count */
530 eve= em->verts.first;
531 amount= 0;
532 while(eve) {
533 if(eve->f & flag) amount++;
534 eve= eve->next;
536 if(amount==0) return;
538 /* allocate memory */
539 sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub");
540 eve= em->verts.first;
541 while(eve) {
542 if(eve->f & flag) {
543 sb->v1= eve;
544 sb++;
546 eve= eve->next;
549 BLI_srand(1);
551 sb= sortblock;
552 for(a=0; a<amount; a++, sb++) {
553 b= (int)(amount*BLI_drand());
554 if(b>=0 && b<amount) {
555 newsort= sortblock+b;
556 onth= *sb;
557 *sb= *newsort;
558 *newsort= onth;
562 /* make temporal listbase */
563 tbase.first= tbase.last= 0;
564 sb= sortblock;
565 while(amount--) {
566 eve= sb->v1;
567 BLI_remlink(&em->verts, eve);
568 BLI_addtail(&tbase, eve);
569 sb++;
572 addlisttolist(&em->verts, &tbase);
574 MEM_freeN(sortblock);
575 #ifdef WITH_VERSE
576 if(G.editMesh->vnode)
577 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
578 #endif
579 BIF_undo_push("Hash");
583 /* generic extern called extruder */
584 void extrude_mesh(void)
586 float nor[3]= {0.0, 0.0, 0.0};
587 short nr, transmode= 0;
589 TEST_EDITMESH
590 if(multires_test()) return;
592 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
593 if(G.totvertsel==0) nr= 0;
594 else if(G.totvertsel==1) nr= 4;
595 else if(G.totedgesel==0) nr= 4;
596 else if(G.totfacesel==0)
597 nr= pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
598 else if(G.totfacesel==1)
599 nr= pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
600 else
601 nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
603 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
604 if (G.totedgesel==0) nr = 0;
605 else if (G.totedgesel==1) nr = 3;
606 else if(G.totfacesel==0) nr = 3;
607 else if(G.totfacesel==1)
608 nr= pupmenu("Extrude %t|Region %x1|Only Edges%x3");
609 else
610 nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
612 else {
613 if (G.totfacesel == 0) nr = 0;
614 else if (G.totfacesel == 1) nr = 1;
615 else
616 nr= pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
619 if(nr<1) return;
621 if(nr==1) transmode= extrudeflag(SELECT, nor);
622 else if(nr==4) transmode= extrudeflag_verts_indiv(SELECT, nor);
623 else if(nr==3) transmode= extrudeflag_edges_indiv(SELECT, nor);
624 else transmode= extrudeflag_face_indiv(SELECT, nor);
626 if(transmode==0) {
627 error("No valid selection");
629 else {
630 EM_fgon_flags();
631 countall();
633 /* We need to force immediate calculation here because
634 * transform may use derived objects (which are now stale).
636 * This shouldn't be necessary, derived queries should be
637 * automatically building this data if invalid. Or something.
639 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
640 object_handle_update(G.obedit);
642 /* individual faces? */
643 BIF_TransformSetUndo("Extrude");
644 if(nr==2) {
645 initTransform(TFM_SHRINKFATTEN, CTX_NO_PET);
646 Transform();
648 else {
649 initTransform(TFM_TRANSLATION, CTX_NO_PET);
650 if(transmode=='n') {
651 Mat4MulVecfl(G.obedit->obmat, nor);
652 VecSubf(nor, nor, G.obedit->obmat[3]);
653 BIF_setSingleAxisConstraint(nor, NULL);
655 Transform();
661 void split_mesh(void)
664 TEST_EDITMESH
665 if(multires_test()) return;
667 if(okee(" Split ")==0) return;
669 waitcursor(1);
671 /* make duplicate first */
672 adduplicateflag(SELECT);
673 /* old faces have flag 128 set, delete them */
674 delfaceflag(128);
675 recalc_editnormals();
677 waitcursor(0);
679 countall();
680 allqueue(REDRAWVIEW3D, 0);
681 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
683 #ifdef WITH_VERSE
684 if(G.editMesh->vnode)
685 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
686 #endif
688 BIF_undo_push("Split");
692 void extrude_repeat_mesh(int steps, float offs)
694 float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
695 short a;
697 TEST_EDITMESH
698 if(multires_test()) return;
700 /* dvec */
701 dvec[0]= G.vd->persinv[2][0];
702 dvec[1]= G.vd->persinv[2][1];
703 dvec[2]= G.vd->persinv[2][2];
704 Normalize(dvec);
705 dvec[0]*= offs;
706 dvec[1]*= offs;
707 dvec[2]*= offs;
709 /* base correction */
710 Mat3CpyMat4(bmat, G.obedit->obmat);
711 Mat3Inv(tmat, bmat);
712 Mat3MulVecfl(tmat, dvec);
714 for(a=0; a<steps; a++) {
715 extrudeflag(SELECT, nor);
716 translateflag(SELECT, dvec);
719 recalc_editnormals();
721 EM_fgon_flags();
722 countall();
724 allqueue(REDRAWVIEW3D, 0);
725 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
727 BIF_undo_push("Extrude Repeat");
730 void spin_mesh(int steps, float degr, float *dvec, int mode)
732 EditMesh *em = G.editMesh;
733 EditVert *eve,*nextve;
734 float nor[3]= {0.0, 0.0, 0.0};
735 float *curs, si,n[3],q[4],cmat[3][3],imat[3][3], tmat[3][3];
736 float cent[3],bmat[3][3];
737 float phi;
738 short a,ok;
740 TEST_EDITMESH
741 if(multires_test()) return;
743 /* imat and center and size */
744 Mat3CpyMat4(bmat, G.obedit->obmat);
745 Mat3Inv(imat,bmat);
747 curs= give_cursor();
748 VECCOPY(cent, curs);
749 cent[0]-= G.obedit->obmat[3][0];
750 cent[1]-= G.obedit->obmat[3][1];
751 cent[2]-= G.obedit->obmat[3][2];
752 Mat3MulVecfl(imat, cent);
754 phi= degr*M_PI/360.0;
755 phi/= steps;
756 if(G.scene->toolsettings->editbutflag & B_CLOCKWISE) phi= -phi;
758 if(dvec) {
759 n[0]= G.vd->viewinv[1][0];
760 n[1]= G.vd->viewinv[1][1];
761 n[2]= G.vd->viewinv[1][2];
762 } else {
763 n[0]= G.vd->viewinv[2][0];
764 n[1]= G.vd->viewinv[2][1];
765 n[2]= G.vd->viewinv[2][2];
767 Normalize(n);
769 q[0]= (float)cos(phi);
770 si= (float)sin(phi);
771 q[1]= n[0]*si;
772 q[2]= n[1]*si;
773 q[3]= n[2]*si;
774 QuatToMat3(q, cmat);
776 Mat3MulMat3(tmat,cmat,bmat);
777 Mat3MulMat3(bmat,imat,tmat);
779 if(mode==0) if(G.scene->toolsettings->editbutflag & B_KEEPORIG) adduplicateflag(1);
780 ok= 1;
782 for(a=0;a<steps;a++) {
783 if(mode==0) ok= extrudeflag(SELECT, nor);
784 else adduplicateflag(SELECT);
785 if(ok==0) {
786 error("No valid vertices are selected");
787 break;
789 rotateflag(SELECT, cent, bmat);
790 if(dvec) {
791 Mat3MulVecfl(bmat,dvec);
792 translateflag(SELECT, dvec);
796 if(ok==0) {
797 /* no vertices or only loose ones selected, remove duplicates */
798 eve= em->verts.first;
799 while(eve) {
800 nextve= eve->next;
801 if(eve->f & SELECT) {
802 BLI_remlink(&em->verts,eve);
803 free_editvert(eve);
805 eve= nextve;
808 recalc_editnormals();
810 EM_fgon_flags();
811 countall();
812 allqueue(REDRAWVIEW3D, 0);
813 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
816 if(dvec==NULL) BIF_undo_push("Spin");
819 void screw_mesh(int steps, int turns)
821 EditMesh *em = G.editMesh;
822 EditVert *eve,*v1=0,*v2=0;
823 EditEdge *eed;
824 float dvec[3], nor[3];
826 TEST_EDITMESH
827 if(multires_test()) return;
829 /* clear flags */
830 eve= em->verts.first;
831 while(eve) {
832 eve->f1= 0;
833 eve= eve->next;
835 /* edges set flags in verts */
836 eed= em->edges.first;
837 while(eed) {
838 if(eed->v1->f & SELECT) {
839 if(eed->v2->f & SELECT) {
840 /* watch: f1 is a byte */
841 if(eed->v1->f1<2) eed->v1->f1++;
842 if(eed->v2->f1<2) eed->v2->f1++;
845 eed= eed->next;
847 /* find two vertices with eve->f1==1, more or less is wrong */
848 eve= em->verts.first;
849 while(eve) {
850 if(eve->f1==1) {
851 if(v1==0) v1= eve;
852 else if(v2==0) v2= eve;
853 else {
854 v1=0;
855 break;
858 eve= eve->next;
860 if(v1==0 || v2==0) {
861 error("You have to select a string of connected vertices too");
862 return;
865 /* calculate dvec */
866 dvec[0]= ( (v1->co[0]- v2->co[0]) )/(steps);
867 dvec[1]= ( (v1->co[1]- v2->co[1]) )/(steps);
868 dvec[2]= ( (v1->co[2]- v2->co[2]) )/(steps);
870 VECCOPY(nor, G.obedit->obmat[2]);
872 if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) {
873 dvec[0]= -dvec[0];
874 dvec[1]= -dvec[1];
875 dvec[2]= -dvec[2];
878 spin_mesh(turns*steps, turns*360, dvec, 0);
880 BIF_undo_push("Spin");
884 static void erase_edges(ListBase *l)
886 EditEdge *ed, *nexted;
888 ed = (EditEdge *) l->first;
889 while(ed) {
890 nexted= ed->next;
891 if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) {
892 remedge(ed);
893 free_editedge(ed);
895 ed= nexted;
899 static void erase_faces(ListBase *l)
901 EditFace *f, *nextf;
903 f = (EditFace *) l->first;
905 while(f) {
906 nextf= f->next;
907 if( faceselectedOR(f, SELECT) ) {
908 BLI_remlink(l, f);
909 free_editface(f);
911 f = nextf;
915 static void erase_vertices(ListBase *l)
917 EditVert *v, *nextv;
919 v = (EditVert *) l->first;
920 while(v) {
921 nextv= v->next;
922 if(v->f & 1) {
923 BLI_remlink(l, v);
924 free_editvert(v);
926 v = nextv;
930 void delete_mesh(void)
932 EditMesh *em = G.editMesh;
933 EditFace *efa, *nextvl;
934 EditVert *eve,*nextve;
935 EditEdge *eed,*nexted;
936 short event;
937 int count;
938 char *str="Erase";
940 TEST_EDITMESH
941 if(multires_test()) return;
943 event= pupmenu("Erase %t|Vertices%x10|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4|Only Faces%x5|Edge Loop%x6");
944 if(event<1) return;
946 if(event==10 ) {
947 str= "Erase Vertices";
948 erase_edges(&em->edges);
949 erase_faces(&em->faces);
950 erase_vertices(&em->verts);
952 else if(event==6) {
953 if(!EdgeLoopDelete())
954 return;
956 str= "Erase Edge Loop";
958 else if(event==4) {
959 str= "Erase Edges & Faces";
960 efa= em->faces.first;
961 while(efa) {
962 nextvl= efa->next;
963 /* delete only faces with 1 or more edges selected */
964 count= 0;
965 if(efa->e1->f & SELECT) count++;
966 if(efa->e2->f & SELECT) count++;
967 if(efa->e3->f & SELECT) count++;
968 if(efa->e4 && (efa->e4->f & SELECT)) count++;
969 if(count) {
970 BLI_remlink(&em->faces, efa);
971 free_editface(efa);
973 efa= nextvl;
975 eed= em->edges.first;
976 while(eed) {
977 nexted= eed->next;
978 if(eed->f & SELECT) {
979 remedge(eed);
980 free_editedge(eed);
982 eed= nexted;
984 efa= em->faces.first;
985 while(efa) {
986 nextvl= efa->next;
987 event=0;
988 if( efa->v1->f & SELECT) event++;
989 if( efa->v2->f & SELECT) event++;
990 if( efa->v3->f & SELECT) event++;
991 if(efa->v4 && (efa->v4->f & SELECT)) event++;
993 if(event>1) {
994 BLI_remlink(&em->faces, efa);
995 free_editface(efa);
997 efa= nextvl;
1000 else if(event==1) {
1001 str= "Erase Edges";
1002 // faces first
1003 efa= em->faces.first;
1004 while(efa) {
1005 nextvl= efa->next;
1006 event=0;
1007 if( efa->e1->f & SELECT) event++;
1008 if( efa->e2->f & SELECT) event++;
1009 if( efa->e3->f & SELECT) event++;
1010 if(efa->e4 && (efa->e4->f & SELECT)) event++;
1012 if(event) {
1013 BLI_remlink(&em->faces, efa);
1014 free_editface(efa);
1016 efa= nextvl;
1018 eed= em->edges.first;
1019 while(eed) {
1020 nexted= eed->next;
1021 if(eed->f & SELECT) {
1022 remedge(eed);
1023 free_editedge(eed);
1025 eed= nexted;
1027 /* to remove loose vertices: */
1028 eed= em->edges.first;
1029 while(eed) {
1030 if( eed->v1->f & SELECT) eed->v1->f-=SELECT;
1031 if( eed->v2->f & SELECT) eed->v2->f-=SELECT;
1032 eed= eed->next;
1034 eve= em->verts.first;
1035 while(eve) {
1036 nextve= eve->next;
1037 if(eve->f & SELECT) {
1038 BLI_remlink(&em->verts,eve);
1039 free_editvert(eve);
1041 eve= nextve;
1045 else if(event==2) {
1046 str="Erase Faces";
1047 delfaceflag(SELECT);
1049 else if(event==3) {
1050 str= "Erase All";
1051 if(em->verts.first) free_vertlist(&em->verts);
1052 if(em->edges.first) free_edgelist(&em->edges);
1053 if(em->faces.first) free_facelist(&em->faces);
1054 if(em->selected.first) BLI_freelistN(&(em->selected));
1056 else if(event==5) {
1057 str= "Erase Only Faces";
1058 efa= em->faces.first;
1059 while(efa) {
1060 nextvl= efa->next;
1061 if(efa->f & SELECT) {
1062 BLI_remlink(&em->faces, efa);
1063 free_editface(efa);
1065 efa= nextvl;
1069 EM_fgon_flags(); // redo flags and indices for fgons
1071 countall();
1072 allqueue(REDRAWVIEW3D, 0);
1073 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1074 BIF_undo_push(str);
1078 /* Got this from scanfill.c. You will need to juggle around the
1079 * callbacks for the scanfill.c code a bit for this to work. */
1080 void fill_mesh(void)
1082 EditMesh *em = G.editMesh;
1083 EditVert *eve,*v1;
1084 EditEdge *eed,*e1,*nexted;
1085 EditFace *efa,*nextvl, *efan;
1086 short ok;
1088 if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
1089 if(multires_test()) return;
1091 waitcursor(1);
1093 /* copy all selected vertices */
1094 eve= em->verts.first;
1095 while(eve) {
1096 if(eve->f & SELECT) {
1097 v1= BLI_addfillvert(eve->co);
1098 eve->tmp.v= v1;
1099 v1->tmp.v= eve;
1100 v1->xs= 0; // used for counting edges
1102 eve= eve->next;
1104 /* copy all selected edges */
1105 eed= em->edges.first;
1106 while(eed) {
1107 if( (eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) {
1108 e1= BLI_addfilledge(eed->v1->tmp.v, eed->v2->tmp.v);
1109 e1->v1->xs++;
1110 e1->v2->xs++;
1112 eed= eed->next;
1114 /* from all selected faces: remove vertices and edges to prevent doubles */
1115 /* all edges add values, faces subtract,
1116 then remove edges with vertices ->xs<2 */
1117 efa= em->faces.first;
1118 ok= 0;
1119 while(efa) {
1120 nextvl= efa->next;
1121 if( faceselectedAND(efa, 1) ) {
1122 efa->v1->tmp.v->xs--;
1123 efa->v2->tmp.v->xs--;
1124 efa->v3->tmp.v->xs--;
1125 if(efa->v4) efa->v4->tmp.v->xs--;
1126 ok= 1;
1129 efa= nextvl;
1131 if(ok) { /* there are faces selected */
1132 eed= filledgebase.first;
1133 while(eed) {
1134 nexted= eed->next;
1135 if(eed->v1->xs<2 || eed->v2->xs<2) {
1136 BLI_remlink(&filledgebase,eed);
1138 eed= nexted;
1142 if(BLI_edgefill(0, (G.obedit && G.obedit->actcol)?(G.obedit->actcol-1):0)) {
1143 efa= fillfacebase.first;
1144 while(efa) {
1145 /* normals default pointing up */
1146 efan= addfacelist(efa->v3->tmp.v, efa->v2->tmp.v,
1147 efa->v1->tmp.v, 0, NULL, NULL);
1148 if(efan) EM_select_face(efan, 1);
1149 efa= efa->next;
1153 BLI_end_edgefill();
1155 waitcursor(0);
1156 EM_select_flush();
1157 countall();
1158 allqueue(REDRAWVIEW3D, 0);
1159 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1161 #ifdef WITH_VERSE
1162 if(G.editMesh->vnode)
1163 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
1164 #endif
1166 BIF_undo_push("Fill");
1168 /*GB*/
1169 /*-------------------------------------------------------------------------------*/
1170 /*--------------------------- Edge Based Subdivide ------------------------------*/
1172 #define EDGENEW 2
1173 #define FACENEW 2
1174 #define EDGEINNER 4
1175 #define EDGEOLD 8
1177 /*used by faceloop cut to select only edges valid for edge slide*/
1178 #define DOUBLEOPFILL 16
1180 /* calculates offset for co, based on fractal, sphere or smooth settings */
1181 static void alter_co(float *co, EditEdge *edge, float rad, int beauty, float perc)
1183 float vec1[3], fac;
1185 if(beauty & B_SMOOTH) {
1186 /* we calculate an offset vector vec1[], to be added to *co */
1187 float len, fac, nor[3], nor1[3], nor2[3];
1189 VecSubf(nor, edge->v1->co, edge->v2->co);
1190 len= 0.5f*Normalize(nor);
1192 VECCOPY(nor1, edge->v1->no);
1193 VECCOPY(nor2, edge->v2->no);
1195 /* cosine angle */
1196 fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
1198 vec1[0]= fac*nor1[0];
1199 vec1[1]= fac*nor1[1];
1200 vec1[2]= fac*nor1[2];
1202 /* cosine angle */
1203 fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
1205 vec1[0]+= fac*nor2[0];
1206 vec1[1]+= fac*nor2[1];
1207 vec1[2]+= fac*nor2[2];
1209 vec1[0]*= rad*len;
1210 vec1[1]*= rad*len;
1211 vec1[2]*= rad*len;
1213 co[0] += vec1[0];
1214 co[1] += vec1[1];
1215 co[2] += vec1[2];
1217 else {
1218 if(rad > 0.0) { /* subdivide sphere */
1219 Normalize(co);
1220 co[0]*= rad;
1221 co[1]*= rad;
1222 co[2]*= rad;
1224 else if(rad< 0.0) { /* fractal subdivide */
1225 fac= rad* VecLenf(edge->v1->co, edge->v2->co);
1226 vec1[0]= fac*(float)(0.5-BLI_drand());
1227 vec1[1]= fac*(float)(0.5-BLI_drand());
1228 vec1[2]= fac*(float)(0.5-BLI_drand());
1229 VecAddf(co, co, vec1);
1235 /* assumes in the edge is the correct interpolated vertices already */
1236 /* percent defines the interpolation, rad and beauty are for special options */
1237 /* results in new vertex with correct coordinate, vertex normal and weight group info */
1238 static EditVert *subdivide_edge_addvert(EditEdge *edge, float rad, int beauty, float percent)
1240 EditVert *ev;
1241 float co[3];
1243 co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0];
1244 co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1];
1245 co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];
1247 /* offset for smooth or sphere or fractal */
1248 alter_co(co, edge, rad, beauty, percent);
1250 ev = addvertlist(co, NULL);
1252 /* vert data (vgroups, ..) */
1253 EM_data_interp_from_verts(edge->v1, edge->v2, ev, percent);
1255 /* normal */
1256 ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0];
1257 ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1];
1258 ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2];
1259 Normalize(ev->no);
1261 return ev;
1264 static void flipvertarray(EditVert** arr, short size)
1266 EditVert *hold;
1267 int i;
1269 for(i=0; i<size/2; i++) {
1270 hold = arr[i];
1271 arr[i] = arr[size-i-1];
1272 arr[size-i-1] = hold;
1276 static void facecopy(EditFace *source, EditFace *target)
1278 EditMesh *em= G.editMesh;
1279 float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co;
1280 float *v4 = source->v4? source->v4->co: NULL;
1281 float w[4][4];
1283 CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data);
1285 target->mat_nr = source->mat_nr;
1286 target->flag = source->flag;
1287 target->h = source->h;
1289 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]);
1290 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]);
1291 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]);
1292 if (target->v4)
1293 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]);
1295 CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data);
1298 static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype)
1300 EditEdge *cedge=NULL;
1301 EditVert *v[4], **verts;
1302 EditFace *hold;
1303 short start=0, end, left, right, vertsize,i;
1305 v[0] = efa->v1;
1306 v[1] = efa->v2;
1307 v[2] = efa->v3;
1308 v[3] = efa->v4;
1310 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
1311 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
1312 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
1313 else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
1315 // Point verts to the array of new verts for cedge
1316 verts = BLI_ghash_lookup(gh, cedge);
1317 //This is the index size of the verts array
1318 vertsize = numcuts+2;
1320 // Is the original v1 the same as the first vert on the selected edge?
1321 // if not, the edge is running the opposite direction in this face so flip
1322 // the array to the correct direction
1324 if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
1325 end = (start+1)%4;
1326 left = (start+2)%4;
1327 right = (start+3)%4;
1330 We should have something like this now
1332 end start
1333 3 2 1 0
1334 |---*---*---|
1336 | |
1338 -------------
1339 left right
1341 where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
1342 and 0,1,2... are the indexes of the new verts stored in verts
1344 We will fill this case like this or this depending on even or odd cuts
1346 |---*---*---| |---*---|
1347 | / \ | | / \ |
1348 | / \ | | / \ |
1349 |/ \| |/ \|
1350 ------------- ---------
1353 // Make center face
1354 if(vertsize % 2 == 0) {
1355 hold = addfacelist(verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
1356 hold->e2->f2 |= EDGEINNER;
1357 hold->e4->f2 |= EDGEINNER;
1358 }else{
1359 hold = addfacelist(verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
1360 hold->e1->f2 |= EDGEINNER;
1361 hold->e3->f2 |= EDGEINNER;
1363 facecopy(efa,hold);
1365 // Make side faces
1366 for(i=0;i<(vertsize-1)/2;i++) {
1367 hold = addfacelist(verts[i],verts[i+1],v[right],NULL,NULL,NULL);
1368 facecopy(efa,hold);
1369 if(i+1 != (vertsize-1)/2) {
1370 if(seltype == SUBDIV_SELECT_INNER) {
1371 hold->e2->f2 |= EDGEINNER;
1374 hold = addfacelist(verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
1375 facecopy(efa,hold);
1376 if(i+1 != (vertsize-1)/2) {
1377 if(seltype == SUBDIV_SELECT_INNER) {
1378 hold->e3->f2 |= EDGEINNER;
1384 static void fill_tri_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype)
1386 EditEdge *cedge=NULL;
1387 EditVert *v[3], **verts;
1388 EditFace *hold;
1389 short start=0, end, op, vertsize,i;
1391 v[0] = efa->v1;
1392 v[1] = efa->v2;
1393 v[2] = efa->v3;
1395 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
1396 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
1397 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
1399 // Point verts to the array of new verts for cedge
1400 verts = BLI_ghash_lookup(gh, cedge);
1401 //This is the index size of the verts array
1402 vertsize = numcuts+2;
1404 // Is the original v1 the same as the first vert on the selected edge?
1405 // if not, the edge is running the opposite direction in this face so flip
1406 // the array to the correct direction
1408 if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
1409 end = (start+1)%3;
1410 op = (start+2)%3;
1413 We should have something like this now
1415 end start
1416 3 2 1 0
1417 |---*---*---|
1419 \ |
1426 where start,end,op are indexes of EditFace->v1, etc (stored in v)
1427 and 0,1,2... are the indexes of the new verts stored in verts
1429 We will fill this case like this or this depending on even or odd cuts
1431 3 2 1 0
1432 |---*---*---|
1433 \ \ \ |
1434 \ \ \ |
1435 \ \ \ |
1436 \ \ \|
1437 \ \\|
1442 // Make side faces
1443 for(i=0;i<(vertsize-1);i++) {
1444 hold = addfacelist(verts[i],verts[i+1],v[op],NULL,NULL,NULL);
1445 if(i+1 != vertsize-1) {
1446 if(seltype == SUBDIV_SELECT_INNER) {
1447 hold->e2->f2 |= EDGEINNER;
1450 facecopy(efa,hold);
1454 static void fill_quad_double_op(EditFace *efa, struct GHash *gh, int numcuts)
1456 EditEdge *cedge[2]={NULL, NULL};
1457 EditVert *v[4], **verts[2];
1458 EditFace *hold;
1459 short start=0, end, left, right, vertsize,i;
1461 v[0] = efa->v1;
1462 v[1] = efa->v2;
1463 v[2] = efa->v3;
1464 v[3] = efa->v4;
1466 if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;}
1467 else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;}
1469 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1470 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1471 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1472 //This is the index size of the verts array
1473 vertsize = numcuts+2;
1475 // Is the original v1 the same as the first vert on the selected edge?
1476 // if not, the edge is running the opposite direction in this face so flip
1477 // the array to the correct direction
1479 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1480 end = (start+1)%4;
1481 left = (start+2)%4;
1482 right = (start+3)%4;
1483 if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}
1485 We should have something like this now
1487 end start
1488 3 2 1 0
1489 |---*---*---|
1491 | |
1493 |---*---*---|
1494 0 1 2 3
1495 left right
1497 We will fill this case like this or this depending on even or odd cuts
1499 |---*---*---|
1500 | | | |
1501 | | | |
1502 | | | |
1503 |---*---*---|
1506 // Make side faces
1507 for(i=0;i<vertsize-1;i++) {
1508 hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
1509 if(i < vertsize-2) {
1510 hold->e2->f2 |= EDGEINNER;
1511 hold->e2->f2 |= DOUBLEOPFILL;
1513 facecopy(efa,hold);
1517 static void fill_quad_double_adj_path(EditFace *efa, struct GHash *gh, int numcuts)
1519 EditEdge *cedge[2]={NULL, NULL};
1520 EditVert *v[4], **verts[2];
1521 EditFace *hold;
1522 short start=0, start2=0, vertsize,i;
1524 v[0] = efa->v1;
1525 v[1] = efa->v2;
1526 v[2] = efa->v3;
1527 v[3] = efa->v4;
1529 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
1530 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
1531 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;}
1532 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;}
1534 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1535 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1536 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1537 //This is the index size of the verts array
1538 vertsize = numcuts+2;
1540 // Is the original v1 the same as the first vert on the selected edge?
1541 // if not, the edge is running the opposite direction in this face so flip
1542 // the array to the correct direction
1544 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1545 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1547 We should have something like this now
1549 end start
1550 3 2 1 0
1551 start2 0|---*---*---|
1553 1* |
1555 2* |
1557 end2 3|-----------|
1559 We will fill this case like this or this depending on even or odd cuts
1560 |---*---*---|
1561 | / / / |
1562 * / / |
1563 | / / |
1564 * / |
1565 | / |
1566 |-----------|
1569 // Make outside tris
1570 hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
1571 /* when ctrl is depressed, only want verts on the cutline selected */
1572 if (G.qual != LR_CTRLKEY)
1573 hold->e3->f2 |= EDGEINNER;
1574 facecopy(efa,hold);
1575 hold = addfacelist(verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
1576 /* when ctrl is depressed, only want verts on the cutline selected */
1577 if (G.qual != LR_CTRLKEY)
1578 hold->e1->f2 |= EDGEINNER;
1579 facecopy(efa,hold);
1580 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1581 // hold->e1->h |= EM_FGON;
1582 //}
1583 // Make side faces
1585 for(i=0;i<numcuts;i++) {
1586 hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
1587 hold->e2->f2 |= EDGEINNER;
1588 facecopy(efa,hold);
1590 //EM_fgon_flags();
1594 static void fill_quad_double_adj_fan(EditFace *efa, struct GHash *gh, int numcuts)
1596 EditEdge *cedge[2]={NULL, NULL};
1597 EditVert *v[4], *op=NULL, **verts[2];
1598 EditFace *hold;
1599 short start=0, start2=0, vertsize,i;
1601 v[0] = efa->v1;
1602 v[1] = efa->v2;
1603 v[2] = efa->v3;
1604 v[3] = efa->v4;
1606 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
1607 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
1608 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
1609 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
1612 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1613 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1614 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1615 //This is the index size of the verts array
1616 vertsize = numcuts+2;
1618 // Is the original v1 the same as the first vert on the selected edge?
1619 // if not, the edge is running the opposite direction in this face so flip
1620 // the array to the correct direction
1622 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1623 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1625 We should have something like this now
1627 end start
1628 3 2 1 0
1629 start2 0|---*---*---|
1631 1* |
1633 2* |
1635 end2 3|-----------|op
1637 We will fill this case like this or this (warning horrible ascii art follows)
1638 |---*---*---|
1639 | \ \ \ |
1640 *---\ \ \ |
1641 | \ \ \ \|
1642 *---- \ \ \ |
1643 | --- \\\|
1644 |-----------|
1647 for(i=0;i<=numcuts;i++) {
1648 hold = addfacelist(op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);
1649 hold->e1->f2 |= EDGEINNER;
1650 facecopy(efa,hold);
1652 hold = addfacelist(op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);
1653 hold->e3->f2 |= EDGEINNER;
1654 facecopy(efa,hold);
1658 static void fill_quad_double_adj_inner(EditFace *efa, struct GHash *gh, int numcuts)
1660 EditEdge *cedge[2]={NULL, NULL};
1661 EditVert *v[4], *op=NULL, **verts[2],**inner;
1662 EditFace *hold;
1663 short start=0, start2=0, vertsize,i;
1664 float co[3];
1666 v[0] = efa->v1;
1667 v[1] = efa->v2;
1668 v[2] = efa->v3;
1669 v[3] = efa->v4;
1671 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
1672 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
1673 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
1674 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
1677 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1678 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1679 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1680 //This is the index size of the verts array
1681 vertsize = numcuts+2;
1683 // Is the original v1 the same as the first vert on the selected edge?
1684 // if not, the edge is running the opposite direction in this face so flip
1685 // the array to the correct direction
1687 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1688 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1690 We should have something like this now
1692 end start
1693 3 2 1 0
1694 start2 0|---*---*---|
1696 1* |
1698 2* |
1700 end2 3|-----------|op
1702 We will fill this case like this or this (warning horrible ascii art follows)
1703 |---*-----*---|
1704 | * / |
1705 * \ / |
1706 | * |
1707 | / \ |
1708 * \ |
1709 | \ |
1710 |-------------|
1713 // Add Inner Vert(s)
1714 inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts");
1716 for(i=0;i<numcuts;i++) {
1717 co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ;
1718 co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ;
1719 co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ;
1720 inner[i] = addvertlist(co, NULL);
1721 inner[i]->f2 |= EDGEINNER;
1723 EM_data_interp_from_verts(verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f);
1726 // Add Corner Quad
1727 hold = addfacelist(verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);
1728 hold->e2->f2 |= EDGEINNER;
1729 hold->e3->f2 |= EDGEINNER;
1730 facecopy(efa,hold);
1731 // Add Bottom Quads
1732 hold = addfacelist(verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);
1733 hold->e2->f2 |= EDGEINNER;
1734 facecopy(efa,hold);
1736 hold = addfacelist(op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);
1737 hold->e2->f2 |= EDGEINNER;
1738 facecopy(efa,hold);
1740 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1741 // hold->e1->h |= EM_FGON;
1742 //}
1743 // Add Fill Quads (if # cuts > 1)
1745 for(i=0;i<numcuts-1;i++) {
1746 hold = addfacelist(inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);
1747 hold->e1->f2 |= EDGEINNER;
1748 hold->e3->f2 |= EDGEINNER;
1749 facecopy(efa,hold);
1751 hold = addfacelist(inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);
1752 hold->e2->f2 |= EDGEINNER;
1753 hold->e4->f2 |= EDGEINNER;
1754 facecopy(efa,hold);
1756 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1757 // hold->e1->h |= EM_FGON;
1758 //}
1761 //EM_fgon_flags();
1763 MEM_freeN(inner);
1766 static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts)
1768 EditEdge *cedge[2]={NULL, NULL};
1769 EditVert *v[3], **verts[2];
1770 EditFace *hold;
1771 short start=0, start2=0, vertsize,i;
1773 v[0] = efa->v1;
1774 v[1] = efa->v2;
1775 v[2] = efa->v3;
1777 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
1778 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
1779 if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;}
1781 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1782 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1783 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1784 //This is the index size of the verts array
1785 vertsize = numcuts+2;
1787 // Is the original v1 the same as the first vert on the selected edge?
1788 // if not, the edge is running the opposite direction in this face so flip
1789 // the array to the correct direction
1791 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1792 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1794 We should have something like this now
1796 end start
1797 3 2 1 0
1798 start2 0|---*---*---|
1799 | /
1800 1* /
1801 | /
1802 2* /
1803 | /
1804 end2 3|
1806 We will fill this case like this or this depending on even or odd cuts
1807 |---*---*---|
1808 | / / /
1809 * / /
1810 | / /
1811 * /
1812 | /
1816 // Make outside tri
1817 hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
1818 hold->e3->f2 |= EDGEINNER;
1819 facecopy(efa,hold);
1820 // Make side faces
1822 for(i=0;i<numcuts;i++) {
1823 hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
1824 hold->e2->f2 |= EDGEINNER;
1825 facecopy(efa,hold);
1829 static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts)
1831 EditEdge *cedge[3]={0};
1832 EditVert *v[4], **verts[3];
1833 EditFace *hold;
1834 short start=0, start2=0, start3=0, vertsize, i, repeats;
1836 v[0] = efa->v1;
1837 v[1] = efa->v2;
1838 v[2] = efa->v3;
1839 v[3] = efa->v4;
1841 if(!(efa->e1->f & SELECT)) {
1842 cedge[0] = efa->e2;
1843 cedge[1] = efa->e3;
1844 cedge[2] = efa->e4;
1845 start = 1;start2 = 2;start3 = 3;
1847 if(!(efa->e2->f & SELECT)) {
1848 cedge[0] = efa->e3;
1849 cedge[1] = efa->e4;
1850 cedge[2] = efa->e1;
1851 start = 2;start2 = 3;start3 = 0;
1853 if(!(efa->e3->f & SELECT)) {
1854 cedge[0] = efa->e4;
1855 cedge[1] = efa->e1;
1856 cedge[2] = efa->e2;
1857 start = 3;start2 = 0;start3 = 1;
1859 if(!(efa->e4->f & SELECT)) {
1860 cedge[0] = efa->e1;
1861 cedge[1] = efa->e2;
1862 cedge[2] = efa->e3;
1863 start = 0;start2 = 1;start3 = 2;
1865 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1866 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1867 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1868 verts[2] = BLI_ghash_lookup(gh, cedge[2]);
1869 //This is the index size of the verts array
1870 vertsize = numcuts+2;
1872 // Is the original v1 the same as the first vert on the selected edge?
1873 // if not, the edge is running the opposite direction in this face so flip
1874 // the array to the correct direction
1876 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1877 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1878 if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}
1880 We should have something like this now
1882 start2
1883 3 2 1 0
1884 start3 0|---*---*---|3
1886 1* *2
1888 2* *1
1890 3|-----------|0 start
1892 We will fill this case like this or this depending on even or odd cuts
1893 there are a couple of differences. For odd cuts, there is a tri in the
1894 middle as well as 1 quad at the bottom (not including the extra quads
1895 for odd cuts > 1
1897 For even cuts, there is a quad in the middle and 2 quads on the bottom
1899 they are numbered here for clarity
1901 1 outer tris and bottom quads
1902 2 inner tri or quad
1903 3 repeating quads
1905 |---*---*---*---|
1906 |1/ / \ \ 1|
1907 |/ 3 / \ 3 \|
1908 * / 2 \ *
1909 | / \ |
1910 |/ \ |
1911 *---------------*
1912 | 3 |
1913 | |
1914 *---------------*
1916 | 1 |
1918 |---------------|
1920 |---*---*---*---*---|
1921 | 1/ / \ \ 1|
1922 | / / \ \ |
1923 |/ 3 / \ 3 \|
1924 * / \ *
1925 | / \ |
1926 | / 2 \ |
1927 |/ \|
1928 *-------------------*
1930 | 3 |
1931 | |
1932 *-------------------*
1934 | 1 |
1935 | |
1936 *-------------------*
1938 | 1 |
1939 | |
1940 |-------------------|
1944 // Make outside tris
1945 hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
1946 hold->e3->f2 |= EDGEINNER;
1947 facecopy(efa,hold);
1948 hold = addfacelist(verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
1949 hold->e3->f2 |= EDGEINNER;
1950 facecopy(efa,hold);
1951 // Make bottom quad
1952 hold = addfacelist(verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
1953 hold->e2->f2 |= EDGEINNER;
1954 facecopy(efa,hold);
1955 //If it is even cuts, add the 2nd lower quad
1956 if(numcuts % 2 == 0) {
1957 hold = addfacelist(verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
1958 hold->e2->f2 |= EDGEINNER;
1959 facecopy(efa,hold);
1960 // Also Make inner quad
1961 hold = addfacelist(verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
1962 hold->e3->f2 |= EDGEINNER;
1963 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1964 // hold->e3->h |= EM_FGON;
1966 facecopy(efa,hold);
1967 repeats = (numcuts / 2) -1;
1968 } else {
1969 // Make inner tri
1970 hold = addfacelist(verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
1971 hold->e2->f2 |= EDGEINNER;
1972 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1973 // hold->e2->h |= EM_FGON;
1975 facecopy(efa,hold);
1976 repeats = ((numcuts+1) / 2)-1;
1979 // cuts for 1 and 2 do not have the repeating quads
1980 if(numcuts < 3) {repeats = 0;}
1981 for(i=0;i<repeats;i++) {
1982 //Make side repeating Quads
1983 hold = addfacelist(verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
1984 hold->e2->f2 |= EDGEINNER;
1985 facecopy(efa,hold);
1986 hold = addfacelist(verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
1987 hold->e4->f2 |= EDGEINNER;
1988 facecopy(efa,hold);
1990 // Do repeating bottom quads
1991 for(i=0;i<repeats;i++) {
1992 if(numcuts % 2 == 1) {
1993 hold = addfacelist(verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
1994 } else {
1995 hold = addfacelist(verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
1997 hold->e2->f2 |= EDGEINNER;
1998 facecopy(efa,hold);
2000 //EM_fgon_flags();
2003 static void fill_quad_quadruple(EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
2005 EditVert **verts[4], ***innerverts;
2006 EditFace *hold;
2007 EditEdge temp;
2008 short vertsize, i, j;
2010 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2011 verts[0] = BLI_ghash_lookup(gh, efa->e1);
2012 verts[1] = BLI_ghash_lookup(gh, efa->e2);
2013 verts[2] = BLI_ghash_lookup(gh, efa->e3);
2014 verts[3] = BLI_ghash_lookup(gh, efa->e4);
2016 //This is the index size of the verts array
2017 vertsize = numcuts+2;
2019 // Is the original v1 the same as the first vert on the selected edge?
2020 // if not, the edge is running the opposite direction in this face so flip
2021 // the array to the correct direction
2023 if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
2024 if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
2025 if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
2026 if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
2028 We should have something like this now
2031 3 2 1 0
2032 0|---*---*---|0
2034 1* *1
2035 2 | | 4
2036 2* *2
2038 3|---*---*---|3
2039 3 2 1 0
2042 // we will fill a 2 dim array of editvert*s to make filling easier
2043 // the innervert order is shown
2045 0 0---1---2---3
2046 | | | |
2047 1 0---1---2---3
2048 | | | |
2049 2 0---1---2---3
2050 | | | |
2051 3 0---1---2---3
2054 innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
2055 for(i=0;i<numcuts+2;i++) {
2056 innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
2059 // first row is e1 last row is e3
2060 for(i=0;i<numcuts+2;i++) {
2061 innerverts[0][i] = verts[0][(numcuts+1)-i];
2062 innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i];
2065 for(i=1;i<=numcuts;i++) {
2066 /* we create a fake edge for the next loop */
2067 temp.v2 = innerverts[i][0] = verts[1][i];
2068 temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
2070 for(j=1;j<=numcuts;j++) {
2071 float percent= (float)j/(float)(numcuts+1);
2073 innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(&temp, rad, beauty, percent);
2076 // Fill with faces
2077 for(i=0;i<numcuts+1;i++) {
2078 for(j=0;j<numcuts+1;j++) {
2079 hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
2080 hold->e1->f2 = EDGENEW;
2081 hold->e2->f2 = EDGENEW;
2082 hold->e3->f2 = EDGENEW;
2083 hold->e4->f2 = EDGENEW;
2085 if(i != 0) { hold->e1->f2 |= EDGEINNER; }
2086 if(j != 0) { hold->e2->f2 |= EDGEINNER; }
2087 if(i != numcuts) { hold->e3->f2 |= EDGEINNER; }
2088 if(j != numcuts) { hold->e4->f2 |= EDGEINNER; }
2090 facecopy(efa,hold);
2093 // Clean up our dynamic multi-dim array
2094 for(i=0;i<numcuts+2;i++) {
2095 MEM_freeN(innerverts[i]);
2097 MEM_freeN(innerverts);
2100 static void fill_tri_triple(EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
2102 EditVert **verts[3], ***innerverts;
2103 short vertsize, i, j;
2104 EditFace *hold;
2105 EditEdge temp;
2107 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2108 verts[0] = BLI_ghash_lookup(gh, efa->e1);
2109 verts[1] = BLI_ghash_lookup(gh, efa->e2);
2110 verts[2] = BLI_ghash_lookup(gh, efa->e3);
2112 //This is the index size of the verts array
2113 vertsize = numcuts+2;
2115 // Is the original v1 the same as the first vert on the selected edge?
2116 // if not, the edge is running the opposite direction in this face so flip
2117 // the array to the correct direction
2119 if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
2120 if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
2121 if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
2123 We should have something like this now
2126 3 2 1 0
2127 0|---*---*---|3
2128 | /
2129 1 1* *2
2130 | /
2131 2* *1 2
2132 | /
2133 3|/
2136 we will fill a 2 dim array of editvert*s to make filling easier
2140 0 0---1---2---3---4
2141 | / | / |/ | /
2142 1 0---1----2---3
2143 1 | / | / | /
2144 2 0----1---2 2
2145 | / | /
2146 |/ |/
2147 3 0---1
2150 4 0
2154 innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
2155 for(i=0;i<numcuts+2;i++) {
2156 innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
2158 //top row is e3 backwards
2159 for(i=0;i<numcuts+2;i++) {
2160 innerverts[0][i] = verts[2][(numcuts+1)-i];
2163 for(i=1;i<=numcuts+1;i++) {
2164 //fake edge, first vert is from e1, last is from e2
2165 temp.v1= innerverts[i][0] = verts[0][i];
2166 temp.v2= innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i];
2168 for(j=1;j<(numcuts+1)-i;j++) {
2169 float percent= (float)j/(float)((numcuts+1)-i);
2171 innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(&temp, rad, beauty, 1-percent);
2175 // Now fill the verts with happy little tris :)
2176 for(i=0;i<=numcuts+1;i++) {
2177 for(j=0;j<(numcuts+1)-i;j++) {
2178 //We always do the first tri
2179 hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
2180 hold->e1->f2 |= EDGENEW;
2181 hold->e2->f2 |= EDGENEW;
2182 hold->e3->f2 |= EDGENEW;
2183 if(i != 0) { hold->e1->f2 |= EDGEINNER; }
2184 if(j != 0) { hold->e2->f2 |= EDGEINNER; }
2185 if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;}
2187 facecopy(efa,hold);
2188 //if there are more to come, we do the 2nd
2189 if(j+1 <= numcuts-i) {
2190 hold = addfacelist(innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
2191 facecopy(efa,hold);
2192 hold->e1->f2 |= EDGENEW;
2193 hold->e2->f2 |= EDGENEW;
2194 hold->e3->f2 |= EDGENEW;
2199 // Clean up our dynamic multi-dim array
2200 for(i=0;i<numcuts+2;i++) {
2201 MEM_freeN(innerverts[i]);
2203 MEM_freeN(innerverts);
2206 //Next two fill types are for knife exact only and are provided to allow for knifing through vertices
2207 //This means there is no multicut!
2208 static void fill_quad_doublevert(EditFace *efa, int v1, int v2){
2209 EditFace *hold;
2211 Depending on which two vertices have been knifed through (v1 and v2), we
2212 triangulate like the patterns below.
2213 X-------| |-------X
2214 | \ | | / |
2215 | \ | | / |
2216 | \ | | / |
2217 --------X X--------
2220 if(v1 == 1 && v2 == 3){
2221 hold= addfacelist(efa->v1, efa->v2, efa->v3, 0, efa, NULL);
2222 hold->e1->f2 |= EDGENEW;
2223 hold->e2->f2 |= EDGENEW;
2224 hold->e3->f2 |= EDGENEW;
2225 hold->e3->f2 |= EDGEINNER;
2226 facecopy(efa, hold);
2228 hold= addfacelist(efa->v1, efa->v3, efa->v4, 0, efa, NULL);
2229 hold->e1->f2 |= EDGENEW;
2230 hold->e2->f2 |= EDGENEW;
2231 hold->e3->f2 |= EDGENEW;
2232 hold->e1->f2 |= EDGEINNER;
2233 facecopy(efa, hold);
2235 else{
2236 hold= addfacelist(efa->v1, efa->v2, efa->v4, 0, efa, NULL);
2237 hold->e1->f2 |= EDGENEW;
2238 hold->e2->f2 |= EDGENEW;
2239 hold->e3->f2 |= EDGENEW;
2240 hold->e2->f2 |= EDGEINNER;
2241 facecopy(efa, hold);
2243 hold= addfacelist(efa->v2, efa->v3, efa->v4, 0, efa, NULL);
2244 hold->e1->f2 |= EDGENEW;
2245 hold->e2->f2 |= EDGENEW;
2246 hold->e3->f2 |= EDGENEW;
2247 hold->e3->f2 |= EDGEINNER;
2248 facecopy(efa, hold);
2252 static void fill_quad_singlevert(EditFace *efa, struct GHash *gh)
2254 EditEdge *cedge=NULL;
2255 EditVert *v[4], **verts;
2256 EditFace *hold;
2257 short start=0, end, left, right, vertsize;
2259 v[0] = efa->v1;
2260 v[1] = efa->v2;
2261 v[2] = efa->v3;
2262 v[3] = efa->v4;
2264 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
2265 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
2266 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
2267 else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
2269 // Point verts to the array of new verts for cedge
2270 verts = BLI_ghash_lookup(gh, cedge);
2271 //This is the index size of the verts array
2272 vertsize = 3;
2274 // Is the original v1 the same as the first vert on the selected edge?
2275 // if not, the edge is running the opposite direction in this face so flip
2276 // the array to the correct direction
2278 if(verts[0] != v[start]) {flipvertarray(verts,3);}
2279 end = (start+1)%4;
2280 left = (start+2)%4;
2281 right = (start+3)%4;
2284 We should have something like this now
2286 end start
2287 2 1 0
2288 |-----*-----|
2290 | |
2292 -------------
2293 left right
2295 where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
2296 and 0,1,2 are the indexes of the new verts stored in verts. We fill like
2297 this, depending on whether its vertex 'left' or vertex 'right' thats
2298 been knifed through...
2300 |---*---| |---*---|
2301 | / | | \ |
2302 | / | | \ |
2303 |/ | | \|
2304 X-------- --------X
2307 if(v[left]->f1){
2308 //triangle is composed of cutvert, end and left
2309 hold = addfacelist(verts[1],v[end],v[left],NULL, NULL,NULL);
2310 hold->e1->f2 |= EDGENEW;
2311 hold->e2->f2 |= EDGENEW;
2312 hold->e3->f2 |= EDGENEW;
2313 hold->e3->f2 |= EDGEINNER;
2314 facecopy(efa, hold);
2316 //quad is composed of cutvert, left, right and start
2317 hold = addfacelist(verts[1],v[left],v[right],v[start], NULL, NULL);
2318 hold->e1->f2 |= EDGENEW;
2319 hold->e2->f2 |= EDGENEW;
2320 hold->e3->f2 |= EDGENEW;
2321 hold->e4->f2 |= EDGENEW;
2322 hold->e1->f2 |= EDGEINNER;
2323 facecopy(efa, hold);
2325 else if(v[right]->f1){
2326 //triangle is composed of cutvert, right and start
2327 hold = addfacelist(verts[1],v[right],v[start], NULL, NULL, NULL);
2328 hold->e1->f2 |= EDGENEW;
2329 hold->e2->f2 |= EDGENEW;
2330 hold->e3->f2 |= EDGENEW;
2331 hold->e1->f2 |= EDGEINNER;
2332 facecopy(efa, hold);
2333 //quad is composed of cutvert, end, left, right
2334 hold = addfacelist(verts[1],v[end], v[left], v[right], NULL, NULL);
2335 hold->e1->f2 |= EDGENEW;
2336 hold->e2->f2 |= EDGENEW;
2337 hold->e3->f2 |= EDGENEW;
2338 hold->e4->f2 |= EDGENEW;
2339 hold->e4->f2 |= EDGEINNER;
2340 facecopy(efa, hold);
2345 // This function takes an example edge, the current point to create and
2346 // the total # of points to create, then creates the point and return the
2347 // editvert pointer to it.
2348 static EditVert *subdivideedgenum(EditEdge *edge, int curpoint, int totpoint, float rad, int beauty)
2350 EditVert *ev;
2351 float percent;
2353 if (beauty & (B_PERCENTSUBD) && totpoint == 1)
2354 //percent=(float)(edge->tmp.l)/32768.0f;
2355 percent= edge->tmp.fp;
2356 else
2357 percent= (float)curpoint/(float)(totpoint+1);
2359 ev= subdivide_edge_addvert(edge, rad, beauty, percent);
2360 ev->f = edge->v1->f;
2362 return ev;
2365 void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
2367 EditMesh *em = G.editMesh;
2368 EditFace *ef;
2369 EditEdge *eed, *cedge, *sort[4];
2370 EditVert **templist;
2371 struct GHash *gh;
2372 float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3];
2373 int i, j, edgecount, touchcount, facetype,hold;
2375 if(multires_test()) return;
2377 //Set faces f1 to 0 cause we need it later
2378 for(ef=em->faces.first;ef;ef = ef->next) {
2379 ef->f1 = 0;
2382 //Flush vertex flags upward to the edges
2383 for(eed = em->edges.first;eed;eed = eed->next) {
2384 //if(eed->f & flag && eed->v1->f == eed->v2->f) {
2385 // eed->f |= eed->v1->f;
2386 // }
2387 eed->f2 = 0;
2388 if(eed->f & flag) {
2389 eed->f2 |= EDGEOLD;
2394 // We store an array of verts for each edge that is subdivided,
2395 // we put this array as a value in a ghash which is keyed by the EditEdge*
2397 // Now for beauty subdivide deselect edges based on length
2398 if(beauty & B_BEAUTY) {
2399 for(ef = em->faces.first;ef;ef = ef->next) {
2400 if(!ef->v4) {
2401 continue;
2403 if(ef->f & SELECT) {
2404 VECCOPY(v1mat, ef->v1->co);
2405 VECCOPY(v2mat, ef->v2->co);
2406 VECCOPY(v3mat, ef->v3->co);
2407 VECCOPY(v4mat, ef->v4->co);
2408 Mat4Mul3Vecfl(G.obedit->obmat, v1mat);
2409 Mat4Mul3Vecfl(G.obedit->obmat, v2mat);
2410 Mat4Mul3Vecfl(G.obedit->obmat, v3mat);
2411 Mat4Mul3Vecfl(G.obedit->obmat, v4mat);
2413 length[0] = VecLenf(v1mat, v2mat);
2414 length[1] = VecLenf(v2mat, v3mat);
2415 length[2] = VecLenf(v3mat, v4mat);
2416 length[3] = VecLenf(v4mat, v1mat);
2417 sort[0] = ef->e1;
2418 sort[1] = ef->e2;
2419 sort[2] = ef->e3;
2420 sort[3] = ef->e4;
2423 // Beauty Short Edges
2424 if(beauty & B_BEAUTY_SHORT) {
2425 for(j=0;j<2;j++) {
2426 hold = -1;
2427 for(i=0;i<4;i++) {
2428 if(length[i] < 0) {
2429 continue;
2430 } else if(hold == -1) {
2431 hold = i;
2432 } else {
2433 if(length[hold] < length[i]) {
2434 hold = i;
2438 sort[hold]->f &= ~SELECT;
2439 sort[hold]->f2 |= EDGENEW;
2440 length[hold] = -1;
2444 // Beauty Long Edges
2445 else {
2446 for(j=0;j<2;j++) {
2447 hold = -1;
2448 for(i=0;i<4;i++) {
2449 if(length[i] < 0) {
2450 continue;
2451 } else if(hold == -1) {
2452 hold = i;
2453 } else {
2454 if(length[hold] > length[i]) {
2455 hold = i;
2459 sort[hold]->f &= ~SELECT;
2460 sort[hold]->f2 |= EDGENEW;
2461 length[hold] = -1;
2468 gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
2470 // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
2471 if(beauty & B_KNIFE) {
2472 for(eed= em->edges.first;eed;eed=eed->next) {
2473 if( eed->tmp.fp == 0 ) {
2474 EM_select_edge(eed,0);
2478 // So for each edge, if it is selected, we allocate an array of size cuts+2
2479 // so we can have a place for the v1, the new verts and v2
2480 for(eed=em->edges.first;eed;eed = eed->next) {
2481 if(eed->f & flag) {
2482 templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
2483 templist[0] = eed->v1;
2484 for(i=0;i<numcuts;i++) {
2485 // This function creates the new vert and returns it back
2486 // to the array
2487 templist[i+1] = subdivideedgenum(eed, i+1, numcuts, rad, beauty);
2488 //while we are here, we can copy edge info from the original edge
2489 cedge = addedgelist(templist[i],templist[i+1],eed);
2490 // Also set the edge f2 to EDGENEW so that we can use this info later
2491 cedge->f2 = EDGENEW;
2493 templist[i+1] = eed->v2;
2494 //Do the last edge too
2495 cedge = addedgelist(templist[i],templist[i+1],eed);
2496 cedge->f2 = EDGENEW;
2497 // Now that the edge is subdivided, we can put its verts in the ghash
2498 BLI_ghash_insert(gh, eed, templist);
2502 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2503 // Now for each face in the mesh we need to figure out How many edges were cut
2504 // and which filling method to use for that face
2505 for(ef = em->faces.first;ef;ef = ef->next) {
2506 edgecount = 0;
2507 facetype = 3;
2508 if(ef->e1->f & flag) {edgecount++;}
2509 if(ef->e2->f & flag) {edgecount++;}
2510 if(ef->e3->f & flag) {edgecount++;}
2511 if(ef->v4) {
2512 facetype = 4;
2513 if(ef->e4->f & flag) {edgecount++;}
2515 if(facetype == 4) {
2516 switch(edgecount) {
2517 case 0:
2518 if(beauty & B_KNIFE && numcuts == 1){
2519 /*Test for when knifing through two opposite verts but no edges*/
2520 touchcount = 0;
2521 if(ef->v1->f1) touchcount++;
2522 if(ef->v2->f1) touchcount++;
2523 if(ef->v3->f1) touchcount++;
2524 if(ef->v4->f1) touchcount++;
2525 if(touchcount == 2){
2526 if(ef->v1->f1 && ef->v3->f1){
2527 ef->f1 = SELECT;
2528 fill_quad_doublevert(ef, 1, 3);
2530 else if(ef->v2->f1 && ef->v4->f1){
2531 ef->f1 = SELECT;
2532 fill_quad_doublevert(ef, 2, 4);
2536 break;
2538 case 1:
2539 if(beauty & B_KNIFE && numcuts == 1){
2540 /*Test for when knifing through an edge and one vert*/
2541 touchcount = 0;
2542 if(ef->v1->f1) touchcount++;
2543 if(ef->v2->f1) touchcount++;
2544 if(ef->v3->f1) touchcount++;
2545 if(ef->v4->f1) touchcount++;
2547 if(touchcount == 1){
2548 if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) ||
2549 (ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) ||
2550 (ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) ||
2551 (ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){
2553 ef->f1 = SELECT;
2554 fill_quad_singlevert(ef, gh);
2556 else{
2557 ef->f1 = SELECT;
2558 fill_quad_single(ef, gh, numcuts, seltype);
2561 else{
2562 ef->f1 = SELECT;
2563 fill_quad_single(ef, gh, numcuts, seltype);
2566 else{
2567 ef->f1 = SELECT;
2568 fill_quad_single(ef, gh, numcuts, seltype);
2570 break;
2571 case 2: ef->f1 = SELECT;
2572 // if there are 2, we check if edge 1 and 3 are either both on or off that way
2573 // we can tell if the selected pair is Adjacent or Opposite of each other
2574 if((ef->e1->f & flag && ef->e3->f & flag) ||
2575 (ef->e2->f & flag && ef->e4->f & flag)) {
2576 fill_quad_double_op(ef, gh, numcuts);
2577 }else{
2578 switch(G.scene->toolsettings->cornertype) {
2579 case 0: fill_quad_double_adj_path(ef, gh, numcuts); break;
2580 case 1: fill_quad_double_adj_inner(ef, gh, numcuts); break;
2581 case 2: fill_quad_double_adj_fan(ef, gh, numcuts); break;
2585 break;
2586 case 3: ef->f1 = SELECT;
2587 fill_quad_triple(ef, gh, numcuts);
2588 break;
2589 case 4: ef->f1 = SELECT;
2590 fill_quad_quadruple(ef, gh, numcuts, rad, beauty);
2591 break;
2593 } else {
2594 switch(edgecount) {
2595 case 0: break;
2596 case 1: ef->f1 = SELECT;
2597 fill_tri_single(ef, gh, numcuts, seltype);
2598 break;
2599 case 2: ef->f1 = SELECT;
2600 fill_tri_double(ef, gh, numcuts);
2601 break;
2602 case 3: ef->f1 = SELECT;
2603 fill_tri_triple(ef, gh, numcuts, rad, beauty);
2604 break;
2609 // Delete Old Edges and Faces
2610 for(eed = em->edges.first;eed;eed = eed->next) {
2611 if(BLI_ghash_haskey(gh,eed)) {
2612 eed->f1 = SELECT;
2613 } else {
2614 eed->f1 = 0;
2617 free_tagged_edges_faces(em->edges.first, em->faces.first);
2619 if(seltype == SUBDIV_SELECT_ORIG && G.qual != LR_CTRLKEY) {
2620 for(eed = em->edges.first;eed;eed = eed->next) {
2621 if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) {
2622 eed->f |= flag;
2623 EM_select_edge(eed,1);
2625 }else{
2626 eed->f &= !flag;
2627 EM_select_edge(eed,0);
2630 } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| G.qual == LR_CTRLKEY) {
2631 for(eed = em->edges.first;eed;eed = eed->next) {
2632 if(eed->f2 & EDGEINNER) {
2633 eed->f |= flag;
2634 EM_select_edge(eed,1);
2635 if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT;
2636 if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT;
2637 }else{
2638 eed->f &= !flag;
2639 EM_select_edge(eed,0);
2642 } else if(seltype == SUBDIV_SELECT_LOOPCUT){
2643 for(eed = em->edges.first;eed;eed = eed->next) {
2644 if(eed->f2 & DOUBLEOPFILL){
2645 eed->f |= flag;
2646 EM_select_edge(eed,1);
2647 }else{
2648 eed->f &= !flag;
2649 EM_select_edge(eed,0);
2653 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2654 for(eed = em->edges.first;eed;eed = eed->next) {
2655 if(eed->f & SELECT) {
2656 eed->v1->f |= SELECT;
2657 eed->v2->f |= SELECT;
2662 //fix hide flags for edges. First pass, hide edges of hidden faces
2663 for(ef=em->faces.first; ef; ef=ef->next){
2664 if(ef->h){
2665 ef->e1->h |= 1;
2666 ef->e2->h |= 1;
2667 ef->e3->h |= 1;
2668 if(ef->e4) ef->e4->h |= 1;
2671 //second pass: unhide edges of visible faces adjacent to hidden faces
2672 for(ef=em->faces.first; ef; ef=ef->next){
2673 if(ef->h == 0){
2674 ef->e1->h &= ~1;
2675 ef->e2->h &= ~1;
2676 ef->e3->h &= ~1;
2677 if(ef->e4) ef->e4->h &= ~1;
2681 // Free the ghash and call MEM_freeN on all the value entries to return
2682 // that memory
2683 BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
2685 EM_selectmode_flush();
2686 for(ef=em->faces.first;ef;ef = ef->next) {
2687 if(ef->e4) {
2688 if( (ef->e1->f & SELECT && ef->e2->f & SELECT) &&
2689 (ef->e3->f & SELECT && ef->e4->f & SELECT) ) {
2690 ef->f |= SELECT;
2692 } else {
2693 if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) {
2694 ef->f |= SELECT;
2699 recalc_editnormals();
2700 countall();
2701 allqueue(REDRAWVIEW3D, 0);
2702 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2705 static int count_selected_edges(EditEdge *ed)
2707 int totedge = 0;
2708 while(ed) {
2709 ed->tmp.p = 0;
2710 if( ed->f & SELECT ) totedge++;
2711 ed= ed->next;
2713 return totedge;
2716 /* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */
2717 typedef EditFace *EVPtr;
2718 typedef EVPtr EVPTuple[2];
2720 /** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
2721 sharing one edge.
2722 arguments: selected edge list, face list.
2723 Edges will also be tagged accordingly (see eed->f2) */
2725 static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
2727 EditEdge *e1, *e2, *e3;
2728 EVPtr *evp;
2729 int i = 0;
2731 /* run through edges, if selected, set pointer edge-> facearray */
2732 while(eed) {
2733 eed->f2= 0;
2734 eed->f1= 0;
2735 if( eed->f & SELECT ) {
2736 eed->tmp.p = (EditVert *) (&efaa[i]);
2737 i++;
2739 else eed->tmp.p = NULL;
2741 eed= eed->next;
2745 /* find edges pointing to 2 faces by procedure:
2747 - run through faces and their edges, increase
2748 face counter e->f1 for each face
2751 while(efa) {
2752 efa->f1= 0;
2753 if(efa->v4==0 && (efa->f & SELECT)) { /* if selected triangle */
2754 e1= efa->e1;
2755 e2= efa->e2;
2756 e3= efa->e3;
2757 if(e1->f2<3 && e1->tmp.p) {
2758 if(e1->f2<2) {
2759 evp= (EVPtr *) e1->tmp.p;
2760 evp[(int)e1->f2] = efa;
2762 e1->f2+= 1;
2764 if(e2->f2<3 && e2->tmp.p) {
2765 if(e2->f2<2) {
2766 evp= (EVPtr *) e2->tmp.p;
2767 evp[(int)e2->f2]= efa;
2769 e2->f2+= 1;
2771 if(e3->f2<3 && e3->tmp.p) {
2772 if(e3->f2<2) {
2773 evp= (EVPtr *) e3->tmp.p;
2774 evp[(int)e3->f2]= efa;
2776 e3->f2+= 1;
2779 else {
2780 /* set to 3 to make sure these are not flipped or joined */
2781 efa->e1->f2= 3;
2782 efa->e2->f2= 3;
2783 efa->e3->f2= 3;
2784 if (efa->e4) efa->e4->f2= 3;
2787 efa= efa->next;
2789 return i;
2793 /* returns vertices of two adjacent triangles forming a quad
2794 - can be righthand or lefthand
2796 4-----3
2797 |\ |
2798 | \ 2 | <- efa1
2799 | \ |
2800 efa-> | 1 \ |
2801 | \|
2802 1-----2
2805 #define VTEST(face, num, other) \
2806 (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)
2808 static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex)
2810 if VTEST(efa, 1, efa1) {
2811 *v1= efa->v1;
2812 *v2= efa->v2;
2813 vindex[0]= 0;
2814 vindex[1]= 1;
2816 else if VTEST(efa, 2, efa1) {
2817 *v1= efa->v2;
2818 *v2= efa->v3;
2819 vindex[0]= 1;
2820 vindex[1]= 2;
2822 else if VTEST(efa, 3, efa1) {
2823 *v1= efa->v3;
2824 *v2= efa->v1;
2825 vindex[0]= 2;
2826 vindex[1]= 0;
2829 if VTEST(efa1, 1, efa) {
2830 *v3= efa1->v1;
2831 *v4= efa1->v2;
2832 vindex[2]= 0;
2833 vindex[3]= 1;
2835 else if VTEST(efa1, 2, efa) {
2836 *v3= efa1->v2;
2837 *v4= efa1->v3;
2838 vindex[2]= 1;
2839 vindex[3]= 2;
2841 else if VTEST(efa1, 3, efa) {
2842 *v3= efa1->v3;
2843 *v4= efa1->v1;
2844 vindex[2]= 2;
2845 vindex[3]= 0;
2847 else
2848 *v3= *v4= NULL;
2851 /* Helper functions for edge/quad edit features*/
2852 static void untag_edges(EditFace *f)
2854 f->e1->f1 = 0;
2855 f->e2->f1 = 0;
2856 f->e3->f1 = 0;
2857 if (f->e4) f->e4->f1 = 0;
2860 /** remove and free list of tagged edges and faces */
2861 static void free_tagged_edges_faces(EditEdge *eed, EditFace *efa)
2863 EditMesh *em= G.editMesh;
2864 EditEdge *nexted;
2865 EditFace *nextvl;
2867 while(efa) {
2868 nextvl= efa->next;
2869 if(efa->f1) {
2870 BLI_remlink(&em->faces, efa);
2871 free_editface(efa);
2873 else
2874 /* avoid deleting edges that are still in use */
2875 untag_edges(efa);
2876 efa= nextvl;
2879 while(eed) {
2880 nexted= eed->next;
2881 if(eed->f1) {
2882 remedge(eed);
2883 free_editedge(eed);
2885 eed= nexted;
2889 /* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
2890 edge/face flags, with very mixed results.... */
2891 void beauty_fill(void)
2893 EditMesh *em = G.editMesh;
2894 EditVert *v1, *v2, *v3, *v4;
2895 EditEdge *eed, *nexted;
2896 EditEdge dia1, dia2;
2897 EditFace *efa, *w;
2898 // void **efaar, **efaa;
2899 EVPTuple *efaar;
2900 EVPtr *efaa;
2901 float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
2902 int totedge, ok, notbeauty=8, onedone, vindex[4];
2904 if(multires_test()) return;
2906 /* - all selected edges with two faces
2907 * - find the faces: store them in edges (using datablock)
2908 * - per edge: - test convex
2909 * - test edge: flip?
2910 * - if true: remedge, addedge, all edges at the edge get new face pointers
2913 EM_selectmode_set(); // makes sure in selectmode 'face' the edges of selected faces are selected too
2915 totedge = count_selected_edges(em->edges.first);
2916 if(totedge==0) return;
2918 if(okee("Beautify fill")==0) return;
2920 /* temp block with face pointers */
2921 efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
2923 while (notbeauty) {
2924 notbeauty--;
2926 ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
2928 /* there we go */
2929 onedone= 0;
2931 eed= em->edges.first;
2932 while(eed) {
2933 nexted= eed->next;
2935 /* f2 is set in collect_quadedges() */
2936 if(eed->f2==2 && eed->h==0) {
2938 efaa = (EVPtr *) eed->tmp.p;
2940 /* none of the faces should be treated before, nor be part of fgon */
2941 ok= 1;
2942 efa= efaa[0];
2943 if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
2944 if(efa->fgonf) ok= 0;
2945 efa= efaa[1];
2946 if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
2947 if(efa->fgonf) ok= 0;
2949 if(ok) {
2950 /* test convex */
2951 givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
2952 if(v1 && v2 && v3 && v4) {
2953 if( convex(v1->co, v2->co, v3->co, v4->co) ) {
2955 /* test edges */
2956 if( (v1) > (v3) ) {
2957 dia1.v1= v3;
2958 dia1.v2= v1;
2960 else {
2961 dia1.v1= v1;
2962 dia1.v2= v3;
2965 if( (v2) > (v4) ) {
2966 dia2.v1= v4;
2967 dia2.v2= v2;
2969 else {
2970 dia2.v1= v2;
2971 dia2.v2= v4;
2974 /* testing rule:
2975 * the area divided by the total edge lengths
2978 len1= VecLenf(v1->co, v2->co);
2979 len2= VecLenf(v2->co, v3->co);
2980 len3= VecLenf(v3->co, v4->co);
2981 len4= VecLenf(v4->co, v1->co);
2982 len5= VecLenf(v1->co, v3->co);
2983 len6= VecLenf(v2->co, v4->co);
2985 opp1= AreaT3Dfl(v1->co, v2->co, v3->co);
2986 opp2= AreaT3Dfl(v1->co, v3->co, v4->co);
2988 fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
2990 opp1= AreaT3Dfl(v2->co, v3->co, v4->co);
2991 opp2= AreaT3Dfl(v2->co, v4->co, v1->co);
2993 fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
2995 ok= 0;
2996 if(fac1 > fac2) {
2997 if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
2998 eed->f1= 1;
2999 efa= efaa[0];
3000 efa->f1= 1;
3001 efa= efaa[1];
3002 efa->f1= 1;
3004 w= EM_face_from_faces(efaa[0], efaa[1],
3005 vindex[0], vindex[1], 4+vindex[2], -1);
3006 w->f |= SELECT;
3009 w= EM_face_from_faces(efaa[0], efaa[1],
3010 vindex[0], 4+vindex[2], 4+vindex[3], -1);
3011 w->f |= SELECT;
3013 onedone= 1;
3016 else if(fac1 < fac2) {
3017 if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
3018 eed->f1= 1;
3019 efa= efaa[0];
3020 efa->f1= 1;
3021 efa= efaa[1];
3022 efa->f1= 1;
3025 w= EM_face_from_faces(efaa[0], efaa[1],
3026 vindex[1], 4+vindex[2], 4+vindex[3], -1);
3027 w->f |= SELECT;
3030 w= EM_face_from_faces(efaa[0], efaa[1],
3031 vindex[0], 4+vindex[1], 4+vindex[3], -1);
3032 w->f |= SELECT;
3034 onedone= 1;
3042 eed= nexted;
3045 free_tagged_edges_faces(em->edges.first, em->faces.first);
3047 if(onedone==0) break;
3049 EM_selectmode_set(); // new edges/faces were added
3052 MEM_freeN(efaar);
3054 EM_select_flush();
3056 allqueue(REDRAWVIEW3D, 0);
3057 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
3058 #ifdef WITH_VERSE
3059 if(G.editMesh->vnode)
3060 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
3061 #endif
3062 BIF_undo_push("Beauty Fill");
3066 /* ******************** BEGIN TRIANGLE TO QUAD ************************************* */
3067 static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, float limit){
3069 /*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/
3070 /*Note: this is more complicated than it needs to be and should be cleaned up...*/
3071 float measure = 0.0, noA1[3], noA2[3], noB1[3], noB2[3], normalADiff, normalBDiff,
3072 edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3], diff,
3073 minarea, maxarea, areaA, areaB;
3075 /*First Test: Normal difference*/
3076 CalcNormFloat(v1->co, v2->co, v3->co, noA1);
3077 CalcNormFloat(v1->co, v3->co, v4->co, noA2);
3079 if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0;
3080 else normalADiff = VecAngle2(noA1, noA2);
3081 //if(!normalADiff) normalADiff = 179;
3082 CalcNormFloat(v2->co, v3->co, v4->co, noB1);
3083 CalcNormFloat(v4->co, v1->co, v2->co, noB2);
3085 if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0;
3086 else normalBDiff = VecAngle2(noB1, noB2);
3087 //if(!normalBDiff) normalBDiff = 179;
3089 measure += (normalADiff/360) + (normalBDiff/360);
3090 if(measure > limit) return measure;
3092 /*Second test: Colinearity*/
3093 VecSubf(edgeVec1, v1->co, v2->co);
3094 VecSubf(edgeVec2, v2->co, v3->co);
3095 VecSubf(edgeVec3, v3->co, v4->co);
3096 VecSubf(edgeVec4, v4->co, v1->co);
3098 diff = 0.0;
3100 diff = (
3101 fabs(VecAngle2(edgeVec1, edgeVec2) - 90) +
3102 fabs(VecAngle2(edgeVec2, edgeVec3) - 90) +
3103 fabs(VecAngle2(edgeVec3, edgeVec4) - 90) +
3104 fabs(VecAngle2(edgeVec4, edgeVec1) - 90)) / 360;
3105 if(!diff) return 0.0;
3107 measure += diff;
3108 if(measure > limit) return measure;
3110 /*Third test: Concavity*/
3111 areaA = AreaT3Dfl(v1->co, v2->co, v3->co) + AreaT3Dfl(v1->co, v3->co, v4->co);
3112 areaB = AreaT3Dfl(v2->co, v3->co, v4->co) + AreaT3Dfl(v4->co, v1->co, v2->co);
3114 if(areaA <= areaB) minarea = areaA;
3115 else minarea = areaB;
3117 if(areaA >= areaB) maxarea = areaA;
3118 else maxarea = areaB;
3120 if(!maxarea) measure += 1;
3121 else measure += (1 - (minarea / maxarea));
3123 return measure;
3126 #define T2QUV_LIMIT 0.005
3127 #define T2QCOL_LIMIT 3
3128 static int compareFaceAttribs(EditFace *f1, EditFace *f2, EditEdge *eed)
3130 /*Test to see if the per-face attributes for the joining edge match within limit*/
3131 MTFace *tf1, *tf2;
3132 unsigned int *col1, *col2;
3133 short i,attrok=0, flag = G.scene->toolsettings->editbutflag, fe1[2], fe2[2];
3135 tf1 = CustomData_em_get(&G.editMesh->fdata, f1->data, CD_MTFACE);
3136 tf2 = CustomData_em_get(&G.editMesh->fdata, f2->data, CD_MTFACE);
3138 col1 = CustomData_em_get(&G.editMesh->fdata, f1->data, CD_MCOL);
3139 col2 = CustomData_em_get(&G.editMesh->fdata, f2->data, CD_MCOL);
3141 /*store indices for faceedges*/
3142 f1->v1->f1 = 0;
3143 f1->v2->f1 = 1;
3144 f1->v3->f1 = 2;
3146 fe1[0] = eed->v1->f1;
3147 fe1[1] = eed->v2->f1;
3149 f2->v1->f1 = 0;
3150 f2->v2->f1 = 1;
3151 f2->v3->f1 = 2;
3153 fe2[0] = eed->v1->f1;
3154 fe2[1] = eed->v2->f1;
3156 /*compare faceedges for each face attribute. Additional per face attributes can be added later*/
3157 /*do UVs*/
3158 if(flag & B_JOINTRIA_UV){
3160 if(tf1 == NULL || tf2 == NULL) attrok |= B_JOINTRIA_UV;
3161 else if(tf1->tpage != tf2->tpage); /*do nothing*/
3162 else{
3163 for(i = 0; i < 2; i++){
3164 if(tf1->uv[fe1[i]][0] + T2QUV_LIMIT > tf2->uv[fe2[i]][0] && tf1->uv[fe1[i]][0] - T2QUV_LIMIT < tf2->uv[fe2[i]][0] &&
3165 tf1->uv[fe1[i]][1] + T2QUV_LIMIT > tf2->uv[fe2[i]][1] && tf1->uv[fe1[i]][1] - T2QUV_LIMIT < tf2->uv[fe2[i]][1]) attrok |= B_JOINTRIA_UV;
3170 /*do VCOLs*/
3171 if(flag & B_JOINTRIA_VCOL){
3172 if(!col1 || !col2) attrok |= B_JOINTRIA_VCOL;
3173 else{
3174 char *f1vcol, *f2vcol;
3175 for(i = 0; i < 2; i++){
3176 f1vcol = (char *)&(col1[fe1[i]]);
3177 f2vcol = (char *)&(col2[fe2[i]]);
3179 /*compare f1vcol with f2vcol*/
3180 if( f1vcol[1] + T2QCOL_LIMIT > f2vcol[1] && f1vcol[1] - T2QCOL_LIMIT < f2vcol[1] &&
3181 f1vcol[2] + T2QCOL_LIMIT > f2vcol[2] && f1vcol[2] - T2QCOL_LIMIT < f2vcol[2] &&
3182 f1vcol[3] + T2QCOL_LIMIT > f2vcol[3] && f1vcol[3] - T2QCOL_LIMIT < f2vcol[3]) attrok |= B_JOINTRIA_VCOL;
3187 if( ((attrok & B_JOINTRIA_UV) == (flag & B_JOINTRIA_UV)) && ((attrok & B_JOINTRIA_VCOL) == (flag & B_JOINTRIA_VCOL)) ) return 1;
3188 return 0;
3191 static int fplcmp(const void *v1, const void *v2)
3193 const EditEdge *e1= *((EditEdge**)v1), *e2=*((EditEdge**)v2);
3195 if( e1->crease > e2->crease) return 1;
3196 else if( e1->crease < e2->crease) return -1;
3198 return 0;
3201 /*Bitflags for edges.*/
3202 #define T2QDELETE 1
3203 #define T2QCOMPLEX 2
3204 #define T2QJOIN 4
3205 void join_triangles(void)
3207 EditMesh *em=G.editMesh;
3208 EditVert *v1, *v2, *v3, *v4, *eve;
3209 EditEdge *eed, **edsortblock = NULL, **edb = NULL;
3210 EditFace *efa;
3211 EVPTuple *efaar = NULL;
3212 EVPtr *efaa = NULL;
3213 float *creases = NULL;
3214 float measure; /*Used to set tolerance*/
3215 float limit = G.scene->toolsettings->jointrilimit;
3216 int i, ok, totedge=0, totseledge=0, complexedges, vindex[4];
3218 /*test for multi-resolution data*/
3219 if(multires_test()) return;
3221 /*if we take a long time on very dense meshes we want waitcursor to display*/
3222 waitcursor(1);
3224 totseledge = count_selected_edges(em->edges.first);
3225 if(totseledge==0) return;
3227 /*abusing crease value to store weights for edge pairs. Nasty*/
3228 for(eed=em->edges.first; eed; eed=eed->next) totedge++;
3229 if(totedge) creases = MEM_callocN(sizeof(float) * totedge, "Join Triangles Crease Array");
3230 for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++){
3231 creases[i] = eed->crease;
3232 eed->crease = 0.0;
3235 /*clear temp flags*/
3236 for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = eve->f2 = 0;
3237 for(eed=em->edges.first; eed; eed=eed->next) eed->f2 = eed->f1 = 0;
3238 for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = efa->tmp.l = 0;
3240 /*For every selected 2 manifold edge, create pointers to its two faces.*/
3241 efaar= (EVPTuple *) MEM_callocN(totseledge * sizeof(EVPTuple), "Tri2Quad");
3242 ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
3243 complexedges = 0;
3245 if(ok){
3248 /*clear tmp.l flag and store number of faces that are selected and coincident to current face here.*/
3249 for(eed=em->edges.first; eed; eed=eed->next){
3250 /* eed->f2 is 2 only if this edge is part of exactly two
3251 triangles, and both are selected, and it has EVPTuple assigned */
3252 if(eed->f2 == 2){
3253 efaa= (EVPtr *) eed->tmp.p;
3254 efaa[0]->tmp.l++;
3255 efaa[1]->tmp.l++;
3259 for(eed=em->edges.first; eed; eed=eed->next){
3260 if(eed->f2 == 2){
3261 efaa= (EVPtr *) eed->tmp.p;
3262 v1 = v2 = v3 = v4 = NULL;
3263 givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
3264 if(v1 && v2 && v3 && v4){
3265 /*test if simple island first. This mimics 2.42 behaviour and the tests are less restrictive.*/
3266 if(efaa[0]->tmp.l == 1 && efaa[1]->tmp.l == 1){
3267 if( convex(v1->co, v2->co, v3->co, v4->co) ){
3268 eed->f1 |= T2QJOIN;
3269 efaa[0]->f1 = 1; //mark for join
3270 efaa[1]->f1 = 1; //mark for join
3273 else{
3275 /* The face pair is part of a 'complex' island, so the rules for dealing with it are more involved.
3276 Depending on what options the user has chosen, this face pair can be 'thrown out' based upon the following criteria:
3278 1: the two faces do not share the same material
3279 2: the edge joining the two faces is marked as sharp.
3280 3: the two faces UV's do not make a good match
3281 4: the two faces Vertex colors do not make a good match
3283 If the face pair passes all the applicable tests, it is then given a 'weight' with the measure_facepair() function.
3284 This measures things like concavity, colinearity ect. If this weight is below the threshold set by the user
3285 the edge joining them is marked as being 'complex' and will be compared against other possible pairs which contain one of the
3286 same faces in the current pair later.
3288 This technique is based upon an algorithm that Campbell Barton developed for his Tri2Quad script that was previously part of
3289 the python scripts bundled with Blender releases.
3292 if(G.scene->toolsettings->editbutflag & B_JOINTRIA_SHARP && eed->sharp); /*do nothing*/
3293 else if(G.scene->toolsettings->editbutflag & B_JOINTRIA_MAT && efaa[0]->mat_nr != efaa[1]->mat_nr); /*do nothing*/
3294 else if(((G.scene->toolsettings->editbutflag & B_JOINTRIA_UV) || (G.scene->toolsettings->editbutflag & B_JOINTRIA_VCOL)) &&
3295 compareFaceAttribs(efaa[0], efaa[1], eed) == 0); /*do nothing*/
3296 else{
3297 measure = measure_facepair(v1, v2, v3, v4, limit);
3298 if(measure < limit){
3299 complexedges++;
3300 eed->f1 |= T2QCOMPLEX;
3301 eed->crease = measure; /*we dont mark edges for join yet*/
3309 /*Quicksort the complex edges according to their weighting*/
3310 if(complexedges){
3311 edsortblock = edb = MEM_callocN(sizeof(EditEdge*) * complexedges, "Face Pairs quicksort Array");
3312 for(eed = em->edges.first; eed; eed=eed->next){
3313 if(eed->f1 & T2QCOMPLEX){
3314 *edb = eed;
3315 edb++;
3318 qsort(edsortblock, complexedges, sizeof(EditEdge*), fplcmp);
3319 /*now go through and mark the edges who get the highest weighting*/
3320 for(edb=edsortblock, i=0; i < complexedges; edb++, i++){
3321 efaa = (EVPtr *)((*edb)->tmp.p); /*suspect!*/
3322 if( !efaa[0]->f1 && !efaa[1]->f1){
3323 efaa[0]->f1 = 1; //mark for join
3324 efaa[1]->f1 = 1; //mark for join
3325 (*edb)->f1 |= T2QJOIN;
3330 /*finally go through all edges marked for join (simple and complex) and create new faces*/
3331 for(eed=em->edges.first; eed; eed=eed->next){
3332 if(eed->f1 & T2QJOIN){
3333 efaa= (EVPtr *)eed->tmp.p;
3334 v1 = v2 = v3 = v4 = NULL;
3335 givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
3336 if((v1 && v2 && v3 && v4) && (exist_face(v1, v2, v3, v4)==0)){ /*exist_face is very slow! Needs to be adressed.*/
3337 /*flag for delete*/
3338 eed->f1 |= T2QDELETE;
3339 /*create new quad and select*/
3340 efa = EM_face_from_faces(efaa[0], efaa[1], vindex[0], vindex[1], 4+vindex[2], 4+vindex[3]);
3341 EM_select_face(efa,1);
3343 else{
3344 efaa[0]->f1 = 0;
3345 efaa[1]->f1 = 0;
3351 /*free data and cleanup*/
3352 if(creases){
3353 for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++) eed->crease = creases[i];
3354 MEM_freeN(creases);
3356 for(eed=em->edges.first; eed; eed=eed->next){
3357 if(eed->f1 & T2QDELETE) eed->f1 = 1;
3358 else eed->f1 = 0;
3360 free_tagged_edges_faces(em->edges.first, em->faces.first);
3361 if(efaar) MEM_freeN(efaar);
3362 if(edsortblock) MEM_freeN(edsortblock);
3364 EM_selectmode_flush();
3365 countall();
3366 allqueue(REDRAWVIEW3D, 0);
3367 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
3368 #ifdef WITH_VERSE
3369 if(G.editMesh->vnode)
3370 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
3371 #endif
3372 waitcursor(0);
3373 BIF_undo_push("Convert Triangles to Quads");
3375 /* ******************** END TRIANGLE TO QUAD ************************************* */
3377 #define FACE_MARKCLEAR(f) (f->f1 = 1)
3379 /* quick hack, basically a copy of beauty_fill */
3380 void edge_flip(void)
3382 EditMesh *em = G.editMesh;
3383 EditVert *v1, *v2, *v3, *v4;
3384 EditEdge *eed, *nexted;
3385 EditFace *efa, *w;
3386 //void **efaar, **efaa;
3387 EVPTuple *efaar;
3388 EVPtr *efaa;
3389 int totedge, ok, vindex[4];
3391 /* - all selected edges with two faces
3392 * - find the faces: store them in edges (using datablock)
3393 * - per edge: - test convex
3394 * - test edge: flip?
3395 - if true: remedge, addedge, all edges at the edge get new face pointers
3398 EM_selectmode_flush(); // makes sure in selectmode 'face' the edges of selected faces are selected too
3400 totedge = count_selected_edges(em->edges.first);
3401 if(totedge==0) return;
3403 /* temporary array for : edge -> face[1], face[2] */
3404 efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
3406 ok = collect_quadedges(efaar, em->edges.first, em->faces.first);
3408 eed= em->edges.first;
3409 while(eed) {
3410 nexted= eed->next;
3412 if(eed->f2==2) { /* points to 2 faces */
3414 efaa= (EVPtr *) eed->tmp.p;
3416 /* don't do it if flagged */
3418 ok= 1;
3419 efa= efaa[0];
3420 if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
3421 efa= efaa[1];
3422 if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0;
3424 if(ok) {
3425 /* test convex */
3426 givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex);
3429 4-----3 4-----3
3430 |\ | | /|
3431 | \ 1 | | 1 / |
3432 | \ | -> | / |
3433 | 0 \ | | / 0 |
3434 | \| |/ |
3435 1-----2 1-----2
3437 /* make new faces */
3438 if (v1 && v2 && v3) {
3439 if( convex(v1->co, v2->co, v3->co, v4->co) ) {
3440 if(exist_face(v1, v2, v3, v4)==0) {
3441 /* outch this may break seams */
3442 w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
3443 vindex[1], 4+vindex[2], -1);
3445 EM_select_face(w, 1);
3447 /* outch this may break seams */
3448 w= EM_face_from_faces(efaa[0], efaa[1], vindex[0],
3449 4+vindex[2], 4+vindex[3], -1);
3451 EM_select_face(w, 1);
3453 /* tag as to-be-removed */
3454 FACE_MARKCLEAR(efaa[1]);
3455 FACE_MARKCLEAR(efaa[0]);
3456 eed->f1 = 1;
3458 } /* endif test convex */
3462 eed= nexted;
3465 /* clear tagged edges and faces: */
3466 free_tagged_edges_faces(em->edges.first, em->faces.first);
3468 MEM_freeN(efaar);
3470 allqueue(REDRAWVIEW3D, 0);
3471 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
3472 #ifdef WITH_VERSE
3473 if(G.editMesh->vnode)
3474 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
3475 #endif
3476 BIF_undo_push("Flip Triangle Edges");
3480 static void edge_rotate(EditEdge *eed,int dir)
3482 EditMesh *em = G.editMesh;
3483 EditVert **verts[2];
3484 EditFace *face[2], *efa, *newFace[2];
3485 EditEdge **edges[2], **hiddenedges, *srchedge;
3486 int facecount, p1, p2, p3, p4, fac1, fac2, i, j;
3487 int numhidden, numshared, p[2][4];
3489 /* check to make sure that the edge is only part of 2 faces */
3490 facecount = 0;
3491 for(efa = em->faces.first;efa;efa = efa->next) {
3492 if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)) {
3493 if(facecount >= 2) {
3494 /* more than two faces with this edge */
3495 return;
3497 else {
3498 face[facecount] = efa;
3499 facecount++;
3504 if(facecount < 2)
3505 return;
3507 /* how many edges does each face have */
3508 if(face[0]->e4) fac1= 4;
3509 else fac1= 3;
3511 if(face[1]->e4) fac2= 4;
3512 else fac2= 3;
3514 /* make a handy array for verts and edges */
3515 verts[0]= &face[0]->v1;
3516 edges[0]= &face[0]->e1;
3517 verts[1]= &face[1]->v1;
3518 edges[1]= &face[1]->e1;
3520 /* we don't want to rotate edges between faces that share more than one edge */
3521 numshared= 0;
3522 for(i=0; i<fac1; i++)
3523 for(j=0; j<fac2; j++)
3524 if (edges[0][i] == edges[1][j])
3525 numshared++;
3527 if(numshared > 1)
3528 return;
3530 /* coplaner faces only please */
3531 if(Inpf(face[0]->n,face[1]->n) <= 0.000001)
3532 return;
3534 /* we want to construct an array of vertex indicis in both faces, starting at
3535 the last vertex of the edge being rotated.
3536 - first we find the two vertices that lie on the rotating edge
3537 - then we make sure they are ordered according to the face vertex order
3538 - and then we construct the array */
3539 p1= p2= p3= p4= 0;
3541 for(i=0; i<4; i++) {
3542 if(eed->v1 == verts[0][i]) p1 = i;
3543 if(eed->v2 == verts[0][i]) p2 = i;
3544 if(eed->v1 == verts[1][i]) p3 = i;
3545 if(eed->v2 == verts[1][i]) p4 = i;
3548 if((p1+1)%fac1 == p2)
3549 SWAP(int, p1, p2);
3550 if((p3+1)%fac2 == p4)
3551 SWAP(int, p3, p4);
3553 for (i = 0; i < 4; i++) {
3554 p[0][i]= (p1 + i)%fac1;
3555 p[1][i]= (p3 + i)%fac2;
3558 /* create an Array of the Edges who have h set prior to rotate */
3559 numhidden = 0;
3560 for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next)
3561 if(srchedge->h && ((srchedge->v1->f & SELECT) || (srchedge->v2->f & SELECT)))
3562 numhidden++;
3564 hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts");
3565 if(!hiddenedges) {
3566 error("Malloc Was not happy!");
3567 return;
3570 numhidden = 0;
3571 for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
3572 if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT))
3573 hiddenedges[numhidden++] = srchedge;
3575 /* create the 2 new faces */
3576 if(fac1 == 3 && fac2 == 3) {
3577 /* no need of reverse setup */
3579 newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
3580 newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
3582 else if(fac1 == 4 && fac2 == 3) {
3583 if(dir == 1) {
3584 newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
3585 newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1);
3586 } else if (dir == 2) {
3587 newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]);
3588 newFace[1]= EM_face_from_faces(face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1);
3590 verts[0][p[0][2]]->f |= SELECT;
3591 verts[1][p[1][1]]->f |= SELECT;
3594 else if(fac1 == 3 && fac2 == 4) {
3595 if(dir == 1) {
3596 newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1);
3597 newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
3598 } else if (dir == 2) {
3599 newFace[0]= EM_face_from_faces(face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1);
3600 newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]);
3602 verts[0][p[0][1]]->f |= SELECT;
3603 verts[1][p[1][2]]->f |= SELECT;
3607 else if(fac1 == 4 && fac2 == 4) {
3608 if(dir == 1) {
3609 newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]);
3610 newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]);
3611 } else if (dir == 2) {
3612 newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]);
3613 newFace[1]= EM_face_from_faces(face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]);
3615 verts[0][p[0][2]]->f |= SELECT;
3616 verts[1][p[1][2]]->f |= SELECT;
3619 else
3620 return; /* This should never happen */
3622 if(dir == 1 || (fac1 == 3 && fac2 == 3)) {
3623 verts[0][p[0][1]]->f |= SELECT;
3624 verts[1][p[1][1]]->f |= SELECT;
3627 /* copy old edge's flags to new center edge*/
3628 for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) {
3629 if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) {
3630 srchedge->f = eed->f;
3631 srchedge->h = eed->h;
3632 srchedge->dir = eed->dir;
3633 srchedge->seam = eed->seam;
3634 srchedge->crease = eed->crease;
3638 /* resetting hidden flag */
3639 for(numhidden--; numhidden>=0; numhidden--)
3640 hiddenedges[numhidden]->h= 1;
3642 /* check for orhphan edges */
3643 for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next)
3644 srchedge->f1= -1;
3646 /* cleanup */
3647 MEM_freeN(hiddenedges);
3649 /* get rid of the old edge and faces*/
3650 remedge(eed);
3651 free_editedge(eed);
3652 BLI_remlink(&em->faces, face[0]);
3653 free_editface(face[0]);
3654 BLI_remlink(&em->faces, face[1]);
3655 free_editface(face[1]);
3658 /* only accepts 1 selected edge, or 2 selected faces */
3659 void edge_rotate_selected(int dir)
3661 EditEdge *eed;
3662 EditFace *efa;
3663 short edgeCount = 0;
3665 /*clear new flag for new edges, count selected edges */
3666 for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
3667 eed->f1= 0;
3668 eed->f2 &= ~2;
3669 if(eed->f & SELECT) edgeCount++;
3672 if(edgeCount>1) {
3673 /* more selected edges, check faces */
3674 for(efa= G.editMesh->faces.first; efa; efa= efa->next) {
3675 if(efa->f & SELECT) {
3676 efa->e1->f1++;
3677 efa->e2->f1++;
3678 efa->e3->f1++;
3679 if(efa->e4) efa->e4->f1++;
3682 edgeCount= 0;
3683 for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
3684 if(eed->f1==2) edgeCount++;
3686 if(edgeCount==1) {
3687 for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
3688 if(eed->f1==2) {
3689 edge_rotate(eed,dir);
3690 break;
3694 else error("Select one edge or two adjacent faces");
3696 else if(edgeCount==1) {
3697 for(eed= G.editMesh->edges.first; eed; eed= eed->next) {
3698 if(eed->f & SELECT) {
3699 EM_select_edge(eed, 0);
3700 edge_rotate(eed,dir);
3701 break;
3705 else error("Select one edge or two adjacent faces");
3708 /* flush selected vertices (again) to edges/faces */
3709 EM_select_flush();
3711 allqueue(REDRAWVIEW3D, 0);
3712 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
3714 #ifdef WITH_VERSE
3715 if(G.editMesh->vnode)
3716 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
3717 #endif
3719 BIF_undo_push("Rotate Edge");
3722 /******************* BEVEL CODE STARTS HERE ********************/
3724 static void bevel_displace_vec(float *midvec, float *v1, float *v2, float *v3, float d, float no[3])
3726 float a[3], c[3], n_a[3], n_c[3], mid[3], ac, ac2, fac;
3728 VecSubf(a, v1, v2);
3729 VecSubf(c, v3, v2);
3731 Crossf(n_a, a, no);
3732 Normalize(n_a);
3733 Crossf(n_c, no, c);
3734 Normalize(n_c);
3736 Normalize(a);
3737 Normalize(c);
3738 ac = Inpf(a, c);
3740 if (ac == 1 || ac == -1) {
3741 midvec[0] = midvec[1] = midvec[2] = 0;
3742 return;
3744 ac2 = ac * ac;
3745 fac = (float)sqrt((ac2 + 2*ac + 1)/(1 - ac2) + 1);
3746 VecAddf(mid, n_c, n_a);
3747 Normalize(mid);
3748 VecMulf(mid, d * fac);
3749 VecAddf(mid, mid, v2);
3750 VecCopyf(midvec, mid);
3753 /* Finds the new point using the sinus law to extrapolate a triangle
3754 Lots of sqrts which would not be good for a real time algo
3755 Using the mid point of the extrapolation of both sides
3756 Useless for coplanar quads, but that doesn't happen too often */
3757 static void fix_bevel_wrap(float *midvec, float *v1, float *v2, float *v3, float *v4, float d, float no[3])
3759 float a[3], b[3], c[3], l_a, l_b, l_c, s_a, s_b, s_c, Pos1[3], Pos2[3], Dir[3];
3761 VecSubf(a, v3, v2);
3762 l_a = Normalize(a);
3763 VecSubf(b, v4, v3);
3764 Normalize(b);
3765 VecSubf(c, v1, v2);
3766 Normalize(c);
3768 s_b = Inpf(a, c);
3769 s_b = (float)sqrt(1 - (s_b * s_b));
3770 s_a = Inpf(b, c);
3771 s_a = (float)sqrt(1 - (s_a * s_a));
3772 VecMulf(a, -1);
3773 s_c = Inpf(a, b);
3774 s_c = (float)sqrt(1 - (s_c * s_c));
3776 l_b = s_b * l_a / s_a;
3777 l_c = s_c * l_a / s_a;
3779 VecMulf(b, l_b);
3780 VecMulf(c, l_c);
3782 VecAddf(Pos1, v2, c);
3783 VecAddf(Pos2, v3, b);
3785 VecAddf(Dir, Pos1, Pos2);
3786 VecMulf(Dir, 0.5);
3788 bevel_displace_vec(midvec, v3, Dir, v2, d, no);
3793 static char detect_wrap(float *o_v1, float *o_v2, float *v1, float *v2, float *no)
3795 float o_a[3], a[3], o_c[3], c[3];
3797 VecSubf(o_a, o_v1, o_v2);
3798 VecSubf(a, v1, v2);
3800 Crossf(o_c, o_a, no);
3801 Crossf(c, a, no);
3803 if (Inpf(c, o_c) <= 0)
3804 return 1;
3805 else
3806 return 0;
3809 // Detects and fix a quad wrapping after the resize
3810 // Arguments are the orginal verts followed by the final verts and then the bevel size and the normal
3811 static void fix_bevel_quad_wrap(float *o_v1, float *o_v2, float *o_v3, float *o_v4, float *v1, float *v2, float *v3, float *v4, float d, float *no)
3813 float vec[3];
3814 char wrap[4];
3816 // Quads can wrap partially. Watch out
3817 wrap[0] = detect_wrap(o_v1, o_v2, v1, v2, no); // Edge 1-2
3818 wrap[1] = detect_wrap(o_v2, o_v3, v2, v3, no); // Edge 2-3
3819 wrap[2] = detect_wrap(o_v3, o_v4, v3, v4, no); // Edge 3-4
3820 wrap[3] = detect_wrap(o_v4, o_v1, v4, v1, no); // Edge 4-1
3822 // Edge 1 inverted
3823 if (wrap[0] == 1 && wrap[1] == 0 && wrap[2] == 0 && wrap[3] == 0) {
3824 fix_bevel_wrap(vec, o_v2, o_v3, o_v4, o_v1, d, no);
3825 VECCOPY(v1, vec);
3826 VECCOPY(v2, vec);
3828 // Edge 2 inverted
3829 else if (wrap[0] == 0 && wrap[1] == 1 && wrap[2] == 0 && wrap[3] == 0) {
3830 fix_bevel_wrap(vec, o_v3, o_v4, o_v1, o_v2, d, no);
3831 VECCOPY(v2, vec);
3832 VECCOPY(v3, vec);
3834 // Edge 3 inverted
3835 else if (wrap[0] == 0 && wrap[1] == 0 && wrap[2] == 1 && wrap[3] == 0) {
3836 fix_bevel_wrap(vec, o_v4, o_v1, o_v2, o_v3, d, no);
3837 VECCOPY(v3, vec);
3838 VECCOPY(v4, vec);
3840 // Edge 4 inverted
3841 else if (wrap[0] == 0 && wrap[1] == 0 && wrap[2] == 0 && wrap[3] == 1) {
3842 fix_bevel_wrap(vec, o_v1, o_v2, o_v3, o_v4, d, no);
3843 VECCOPY(v4, vec);
3844 VECCOPY(v1, vec);
3846 // Edge 2 and 4 inverted
3847 else if (wrap[0] == 0 && wrap[1] == 1 && wrap[2] == 0 && wrap[3] == 1) {
3848 VecAddf(vec, v2, v3);
3849 VecMulf(vec, 0.5);
3850 VECCOPY(v2, vec);
3851 VECCOPY(v3, vec);
3852 VecAddf(vec, v1, v4);
3853 VecMulf(vec, 0.5);
3854 VECCOPY(v1, vec);
3855 VECCOPY(v4, vec);
3857 // Edge 1 and 3 inverted
3858 else if (wrap[0] == 1 && wrap[1] == 0 && wrap[2] == 1 && wrap[3] == 0) {
3859 VecAddf(vec, v1, v2);
3860 VecMulf(vec, 0.5);
3861 VECCOPY(v1, vec);
3862 VECCOPY(v2, vec);
3863 VecAddf(vec, v3, v4);
3864 VecMulf(vec, 0.5);
3865 VECCOPY(v3, vec);
3866 VECCOPY(v4, vec);
3868 // Totally inverted
3869 else if (wrap[0] == 1 && wrap[1] == 1 && wrap[2] == 1 && wrap[3] == 1) {
3870 VecAddf(vec, v1, v2);
3871 VecAddf(vec, vec, v3);
3872 VecAddf(vec, vec, v4);
3873 VecMulf(vec, 0.25);
3874 VECCOPY(v1, vec);
3875 VECCOPY(v2, vec);
3876 VECCOPY(v3, vec);
3877 VECCOPY(v4, vec);
3882 // Detects and fix a tri wrapping after the resize
3883 // Arguments are the orginal verts followed by the final verts and the normal
3884 // Triangles cannot wrap partially (not in this situation
3885 static void fix_bevel_tri_wrap(float *o_v1, float *o_v2, float *o_v3, float *v1, float *v2, float *v3, float *no)
3887 if (detect_wrap(o_v1, o_v2, v1, v2, no)) {
3888 float vec[3];
3889 VecAddf(vec, o_v1, o_v2);
3890 VecAddf(vec, vec, o_v3);
3891 VecMulf(vec, 1.0f/3.0f);
3892 VECCOPY(v1, vec);
3893 VECCOPY(v2, vec);
3894 VECCOPY(v3, vec);
3898 static void bevel_shrink_faces(float d, int flag)
3900 EditMesh *em = G.editMesh;
3901 EditFace *efa;
3902 float vec[3], no[3], v1[3], v2[3], v3[3], v4[3];
3904 /* move edges of all faces with efa->f1 & flag closer towards their centers */
3905 efa= em->faces.first;
3906 while (efa) {
3907 if (efa->f1 & flag) {
3908 VECCOPY(v1, efa->v1->co);
3909 VECCOPY(v2, efa->v2->co);
3910 VECCOPY(v3, efa->v3->co);
3911 VECCOPY(no, efa->n);
3912 if (efa->v4 == NULL) {
3913 bevel_displace_vec(vec, v1, v2, v3, d, no);
3914 VECCOPY(efa->v2->co, vec);
3915 bevel_displace_vec(vec, v2, v3, v1, d, no);
3916 VECCOPY(efa->v3->co, vec);
3917 bevel_displace_vec(vec, v3, v1, v2, d, no);
3918 VECCOPY(efa->v1->co, vec);
3920 fix_bevel_tri_wrap(v1, v2, v3, efa->v1->co, efa->v2->co, efa->v3->co, no);
3921 } else {
3922 VECCOPY(v4, efa->v4->co);
3923 bevel_displace_vec(vec, v1, v2, v3, d, no);
3924 VECCOPY(efa->v2->co, vec);
3925 bevel_displace_vec(vec, v2, v3, v4, d, no);
3926 VECCOPY(efa->v3->co, vec);
3927 bevel_displace_vec(vec, v3, v4, v1, d, no);
3928 VECCOPY(efa->v4->co, vec);
3929 bevel_displace_vec(vec, v4, v1, v2, d, no);
3930 VECCOPY(efa->v1->co, vec);
3932 fix_bevel_quad_wrap(v1, v2, v3, v4, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, d, no);
3935 efa= efa->next;
3939 static void bevel_shrink_draw(float d, int flag)
3941 EditMesh *em = G.editMesh;
3942 EditFace *efa;
3943 float vec[3], no[3], v1[3], v2[3], v3[3], v4[3], fv1[3], fv2[3], fv3[3], fv4[3];
3945 /* move edges of all faces with efa->f1 & flag closer towards their centers */
3946 efa= em->faces.first;
3947 while (efa) {
3948 VECCOPY(v1, efa->v1->co);
3949 VECCOPY(v2, efa->v2->co);
3950 VECCOPY(v3, efa->v3->co);
3951 VECCOPY(no, efa->n);
3952 if (efa->v4 == NULL) {
3953 bevel_displace_vec(vec, v1, v2, v3, d, no);
3954 VECCOPY(fv2, vec);
3955 bevel_displace_vec(vec, v2, v3, v1, d, no);
3956 VECCOPY(fv3, vec);
3957 bevel_displace_vec(vec, v3, v1, v2, d, no);
3958 VECCOPY(fv1, vec);
3960 fix_bevel_tri_wrap(v1, v2, v3, fv1, fv2, fv3, no);
3962 glBegin(GL_LINES);
3963 glVertex3fv(fv1);
3964 glVertex3fv(fv2);
3965 glEnd();
3966 glBegin(GL_LINES);
3967 glVertex3fv(fv2);
3968 glVertex3fv(fv3);
3969 glEnd();
3970 glBegin(GL_LINES);
3971 glVertex3fv(fv1);
3972 glVertex3fv(fv3);
3973 glEnd();
3974 } else {
3975 VECCOPY(v4, efa->v4->co);
3976 bevel_displace_vec(vec, v4, v1, v2, d, no);
3977 VECCOPY(fv1, vec);
3978 bevel_displace_vec(vec, v1, v2, v3, d, no);
3979 VECCOPY(fv2, vec);
3980 bevel_displace_vec(vec, v2, v3, v4, d, no);
3981 VECCOPY(fv3, vec);
3982 bevel_displace_vec(vec, v3, v4, v1, d, no);
3983 VECCOPY(fv4, vec);
3985 fix_bevel_quad_wrap(v1, v2, v3, v4, fv1, fv2, fv3, fv4, d, no);
3987 glBegin(GL_LINES);
3988 glVertex3fv(fv1);
3989 glVertex3fv(fv2);
3990 glEnd();
3991 glBegin(GL_LINES);
3992 glVertex3fv(fv2);
3993 glVertex3fv(fv3);
3994 glEnd();
3995 glBegin(GL_LINES);
3996 glVertex3fv(fv3);
3997 glVertex3fv(fv4);
3998 glEnd();
3999 glBegin(GL_LINES);
4000 glVertex3fv(fv1);
4001 glVertex3fv(fv4);
4002 glEnd();
4004 efa= efa->next;
4008 static void bevel_mesh(float bsize, int allfaces)
4010 EditMesh *em = G.editMesh;
4011 //#define BEV_DEBUG
4012 /* Enables debug printfs and assigns material indices: */
4013 /* 2 = edge quad */
4014 /* 3 = fill polygon (vertex clusters) */
4016 EditFace *efa, *example; //, *nextvl;
4017 EditEdge *eed, *eed2;
4018 EditVert *neweve[1024], *eve, *eve2, *eve3, *v1, *v2, *v3, *v4; //, *eve4;
4019 //short found4, search;
4020 //float f1, f2, f3, f4;
4021 float cent[3], min[3], max[3];
4022 int a, b, c;
4023 float limit= 0.001f;
4025 if(multires_test()) return;
4027 waitcursor(1);
4029 removedoublesflag(1, limit);
4031 /* tag all original faces */
4032 efa= em->faces.first;
4033 while (efa) {
4034 efa->f1= 0;
4035 if (faceselectedAND(efa, 1)||allfaces) {
4036 efa->f1= 1;
4037 efa->v1->f |= 128;
4038 efa->v2->f |= 128;
4039 efa->v3->f |= 128;
4040 if (efa->v4) efa->v4->f |= 128;
4042 efa->v1->f &= ~64;
4043 efa->v2->f &= ~64;
4044 efa->v3->f &= ~64;
4045 if (efa->v4) efa->v4->f &= ~64;
4047 efa= efa->next;
4050 #ifdef BEV_DEBUG
4051 fprintf(stderr,"bevel_mesh: split\n");
4052 #endif
4054 efa= em->faces.first;
4055 while (efa) {
4056 if (efa->f1 & 1) {
4057 efa->f1-= 1;
4058 v1= addvertlist(efa->v1->co, efa->v1);
4059 v1->f= efa->v1->f & ~128;
4060 efa->v1->tmp.v = v1;
4062 v1= addvertlist(efa->v2->co, efa->v2);
4063 v1->f= efa->v2->f & ~128;
4064 efa->v2->tmp.v = v1;
4066 v1= addvertlist(efa->v3->co, efa->v3);
4067 v1->f= efa->v3->f & ~128;
4068 efa->v3->tmp.v = v1;
4070 if (efa->v4) {
4071 v1= addvertlist(efa->v4->co, efa->v4);
4072 v1->f= efa->v4->f & ~128;
4073 efa->v4->tmp.v = v1;
4076 /* Needs better adaption of creases? */
4077 addedgelist(efa->e1->v1->tmp.v,
4078 efa->e1->v2->tmp.v,
4079 efa->e1);
4080 addedgelist(efa->e2->v1->tmp.v,
4081 efa->e2->v2->tmp.v,
4082 efa->e2);
4083 addedgelist(efa->e3->v1->tmp.v,
4084 efa->e3->v2->tmp.v,
4085 efa->e3);
4086 if (efa->e4) addedgelist(efa->e4->v1->tmp.v,
4087 efa->e4->v2->tmp.v,
4088 efa->e4);
4090 if(efa->v4) {
4091 v1 = efa->v1->tmp.v;
4092 v2 = efa->v2->tmp.v;
4093 v3 = efa->v3->tmp.v;
4094 v4 = efa->v4->tmp.v;
4095 addfacelist(v1, v2, v3, v4, efa,NULL);
4096 } else {
4097 v1= efa->v1->tmp.v;
4098 v2= efa->v2->tmp.v;
4099 v3= efa->v3->tmp.v;
4100 addfacelist(v1, v2, v3, 0, efa,NULL);
4103 efa= efa-> next;
4104 } else {
4105 efa= efa->next;
4109 for(efa= em->faces.first; efa; efa= efa->next) {
4110 if( (efa->v1->f & 128) && (efa->v2->f & 128) && (efa->v3->f & 128) ) {
4111 if(efa->v4==NULL || (efa->v4->f & 128)) efa->f |= 128;
4115 delfaceflag(128); // works with face flag now
4117 /* tag all faces for shrink*/
4118 efa= em->faces.first;
4119 while (efa) {
4120 if (faceselectedAND(efa, 1)||allfaces) {
4121 efa->f1= 2;
4123 efa= efa->next;
4126 #ifdef BEV_DEBUG
4127 fprintf(stderr,"bevel_mesh: make edge quads\n");
4128 #endif
4130 /* find edges that are on each other and make quads between them */
4132 eed= em->edges.first;
4133 while(eed) {
4134 eed->f2= eed->f1= 0;
4135 if ( ((eed->v1->f & eed->v2->f) & 1) || allfaces)
4136 eed->f1 |= 4; /* original edges */
4137 eed->tmp.v = 0;
4138 eed= eed->next;
4141 eed= em->edges.first;
4142 while (eed) {
4143 if ( ((eed->f1 & 2)==0) && (eed->f1 & 4) ) {
4144 eed2= em->edges.first;
4145 while (eed2) {
4146 if ( (eed2 != eed) && ((eed2->f1 & 2)==0) && (eed->f1 & 4) ) {
4147 if (
4148 (eed->v1 != eed2->v1) &&
4149 (eed->v1 != eed2->v2) &&
4150 (eed->v2 != eed2->v1) &&
4151 (eed->v2 != eed2->v2) && (
4152 ( VecCompare(eed->v1->co, eed2->v1->co, limit) &&
4153 VecCompare(eed->v2->co, eed2->v2->co, limit) ) ||
4154 ( VecCompare(eed->v1->co, eed2->v2->co, limit) &&
4155 VecCompare(eed->v2->co, eed2->v1->co, limit) ) ) )
4158 #ifdef BEV_DEBUG
4159 fprintf(stderr, "bevel_mesh: edge quad\n");
4160 #endif
4162 eed->f1 |= 2; /* these edges are finished */
4163 eed2->f1 |= 2;
4165 example= NULL;
4166 efa= em->faces.first; /* search example face (for mat_nr, ME_SMOOTH, ...) */
4167 while (efa) {
4168 if ( (efa->e1 == eed) ||
4169 (efa->e2 == eed) ||
4170 (efa->e3 == eed) ||
4171 (efa->e4 && (efa->e4 == eed)) ) {
4172 example= efa;
4173 efa= NULL;
4175 if (efa) efa= efa->next;
4178 neweve[0]= eed->v1; neweve[1]= eed->v2;
4179 neweve[2]= eed2->v1; neweve[3]= eed2->v2;
4181 if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
4182 efa= NULL;
4184 if (VecCompare(eed->v1->co, eed2->v2->co, limit)) {
4185 efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], example,NULL);
4186 } else {
4187 efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], example,NULL);
4190 if(efa) {
4191 float inp;
4192 CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
4193 inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
4194 if(inp < 0.0) flipface(efa);
4195 #ifdef BEV_DEBUG
4196 efa->mat_nr= 1;
4197 #endif
4198 } else fprintf(stderr,"bevel_mesh: error creating face\n");
4200 eed2= NULL;
4203 if (eed2) eed2= eed2->next;
4206 eed= eed->next;
4209 eed= em->edges.first;
4210 while(eed) {
4211 eed->f2= eed->f1= 0;
4212 eed->f1= 0;
4213 eed->v1->f1 &= ~1;
4214 eed->v2->f1 &= ~1;
4215 eed->tmp.v = 0;
4216 eed= eed->next;
4219 #ifdef BEV_DEBUG
4220 fprintf(stderr,"bevel_mesh: find clusters\n");
4221 #endif
4223 /* Look for vertex clusters */
4225 eve= em->verts.first;
4226 while (eve) {
4227 eve->f &= ~(64|128);
4228 eve->tmp.v = NULL;
4229 eve= eve->next;
4232 /* eve->f: 128: first vertex in a list (->tmp.v) */
4233 /* 64: vertex is in a list */
4235 eve= em->verts.first;
4236 while (eve) {
4237 eve2= em->verts.first;
4238 eve3= NULL;
4239 while (eve2) {
4240 if ((eve2 != eve) && ((eve2->f & (64|128))==0)) {
4241 if (VecCompare(eve->co, eve2->co, limit)) {
4242 if ((eve->f & (128|64)) == 0) {
4243 /* fprintf(stderr,"Found vertex cluster:\n *\n *\n"); */
4244 eve->f |= 128;
4245 eve->tmp.v = eve2;
4246 eve3= eve2;
4247 } else if ((eve->f & 64) == 0) {
4248 /* fprintf(stderr," *\n"); */
4249 if (eve3) eve3->tmp.v = eve2;
4250 eve2->f |= 64;
4251 eve3= eve2;
4255 eve2= eve2->next;
4256 if (!eve2) {
4257 if (eve3) eve3->tmp.v = NULL;
4260 eve= eve->next;
4263 #ifdef BEV_DEBUG
4264 fprintf(stderr,"bevel_mesh: shrink faces\n");
4265 #endif
4267 bevel_shrink_faces(bsize, 2);
4269 #ifdef BEV_DEBUG
4270 fprintf(stderr,"bevel_mesh: fill clusters\n");
4271 #endif
4273 /* Make former vertex clusters faces */
4275 eve= em->verts.first;
4276 while (eve) {
4277 eve->f &= ~64;
4278 eve= eve->next;
4281 eve= em->verts.first;
4282 while (eve) {
4283 if (eve->f & 128) {
4284 eve->f &= ~128;
4285 a= 0;
4286 neweve[a]= eve;
4287 eve2 = eve->tmp.v;
4288 while (eve2) {
4289 a++;
4290 neweve[a]= eve2;
4291 eve2 = eve2->tmp.v;
4293 a++;
4294 efa= NULL;
4295 if (a>=3) {
4296 example= NULL;
4297 efa= em->faces.first; /* search example face */
4298 while (efa) {
4299 if ( (efa->v1 == neweve[0]) ||
4300 (efa->v2 == neweve[0]) ||
4301 (efa->v3 == neweve[0]) ||
4302 (efa->v4 && (efa->v4 == neweve[0])) ) {
4303 example= efa;
4304 efa= NULL;
4306 if (efa) efa= efa->next;
4308 #ifdef BEV_DEBUG
4309 fprintf(stderr,"bevel_mesh: Making %d-gon\n", a);
4310 #endif
4311 if (a>4) {
4312 cent[0]= cent[1]= cent[2]= 0.0;
4313 INIT_MINMAX(min, max);
4314 for (b=0; b<a; b++) {
4315 VecAddf(cent, cent, neweve[b]->co);
4316 DO_MINMAX(neweve[b]->co, min, max);
4318 cent[0]= (min[0]+max[0])/2;
4319 cent[1]= (min[1]+max[1])/2;
4320 cent[2]= (min[2]+max[2])/2;
4321 eve2= addvertlist(cent, NULL);
4322 eve2->f |= 1;
4323 eed= em->edges.first;
4324 while (eed) {
4325 c= 0;
4326 for (b=0; b<a; b++)
4327 if ((neweve[b]==eed->v1) || (neweve[b]==eed->v2)) c++;
4328 if (c==2) {
4329 if(exist_face(eed->v1, eed->v2, eve2, 0)==0) {
4330 efa= addfacelist(eed->v1, eed->v2, eve2, 0, example,NULL);
4331 #ifdef BEV_DEBUG
4332 efa->mat_nr= 2;
4333 #endif
4336 eed= eed->next;
4338 } else if (a==4) {
4339 if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
4340 /* the order of vertices can be anything, three cases to check */
4341 if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
4342 efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
4344 else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
4345 efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
4347 else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
4348 efa= addfacelist(neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
4352 else if (a==3) {
4353 if(exist_face(neweve[0], neweve[1], neweve[2], 0)==0)
4354 efa= addfacelist(neweve[0], neweve[1], neweve[2], 0, example, NULL);
4356 if(efa) {
4357 float inp;
4358 CalcNormFloat(neweve[0]->co, neweve[1]->co, neweve[2]->co, efa->n);
4359 inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
4360 if(inp < 0.0) flipface(efa);
4361 #ifdef BEV_DEBUG
4362 efa->mat_nr= 2;
4363 #endif
4367 eve= eve->next;
4370 eve= em->verts.first;
4371 while (eve) {
4372 eve->f1= 0;
4373 eve->f &= ~(128|64);
4374 eve->tmp.v= NULL;
4375 eve= eve->next;
4378 recalc_editnormals();
4379 waitcursor(0);
4380 countall();
4381 allqueue(REDRAWVIEW3D, 0);
4382 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
4384 removedoublesflag(1, limit);
4386 /* flush selected vertices to edges/faces */
4387 EM_select_flush();
4389 #undef BEV_DEBUG
4392 static void bevel_mesh_recurs(float bsize, short recurs, int allfaces)
4394 float d;
4395 short nr;
4397 d= bsize;
4398 for (nr=0; nr<recurs; nr++) {
4399 bevel_mesh(d, allfaces);
4400 if (nr==0) d /= 3; else d /= 2;
4404 void bevel_menu()
4406 char Finished = 0, Canceled = 0, str[100], Recalc = 0;
4407 short mval[2], oval[2], curval[2], event = 0, recurs = 1, nr;
4408 float vec[3], d, drawd=0.0, center[3], fac = 1;
4410 getmouseco_areawin(mval);
4411 oval[0] = mval[0]; oval[1] = mval[1];
4413 // Silly hackish code to initialise the variable (warning if not done)
4414 // while still drawing in the first iteration (and without using another variable)
4415 curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
4417 // Init grabz for window to vec conversions
4418 initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]);
4419 window_to_3d(center, mval[0], mval[1]);
4421 if(button(&recurs, 1, 4, "Recursion:")==0) return;
4423 for (nr=0; nr<recurs-1; nr++) {
4424 if (nr==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * nr * 2.0f);
4427 EM_set_flag_all(SELECT);
4429 SetBlenderCursor(SYSCURSOR);
4431 while (Finished == 0)
4433 getmouseco_areawin(mval);
4434 if (mval[0] != curval[0] || mval[1] != curval[1] || (Recalc == 1))
4436 Recalc = 0;
4437 curval[0] = mval[0];
4438 curval[1] = mval[1];
4440 window_to_3d(vec, mval[0]-oval[0], mval[1]-oval[1]);
4441 d = Normalize(vec) / 10;
4444 drawd = d * fac;
4445 if (G.qual & LR_CTRLKEY)
4446 drawd = (float) floor(drawd * 10.0f)/10.0f;
4447 if (G.qual & LR_SHIFTKEY)
4448 drawd /= 10;
4450 /*------------- Preview lines--------------- */
4452 /* uses callback mechanism to draw it all in current area */
4453 scrarea_do_windraw(curarea);
4455 /* set window matrix to perspective, default an area returns with buttons transform */
4456 persp(PERSP_VIEW);
4457 /* make a copy, for safety */
4458 glPushMatrix();
4459 /* multiply with the object transformation */
4460 mymultmatrix(G.obedit->obmat);
4462 glColor3ub(255, 255, 0);
4464 // PREVIEW CODE GOES HERE
4465 bevel_shrink_draw(drawd, 2);
4467 /* restore matrix transform */
4468 glPopMatrix();
4470 sprintf(str, "Bevel Size: %.4f LMB to confirm, RMB to cancel, SPACE to input directly.", drawd);
4471 headerprint(str);
4473 /* this also verifies other area/windows for clean swap */
4474 screen_swapbuffers();
4476 persp(PERSP_WIN);
4478 glDrawBuffer(GL_FRONT);
4480 BIF_ThemeColor(TH_WIRE);
4482 setlinestyle(3);
4483 glBegin(GL_LINE_STRIP);
4484 glVertex2sv(mval);
4485 glVertex2sv(oval);
4486 glEnd();
4487 setlinestyle(0);
4489 persp(PERSP_VIEW);
4490 bglFlush(); // flush display for frontbuffer
4491 glDrawBuffer(GL_BACK);
4493 while(qtest()) {
4494 short val=0;
4495 event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
4497 /* val==0 on key-release event */
4498 if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY || event==ESCKEY)) {
4499 if (event==RIGHTMOUSE || event==ESCKEY)
4500 Canceled = 1;
4501 Finished = 1;
4503 else if (val && event==SPACEKEY) {
4504 if (fbutton(&d, 0.000, 10.000, 10, 0, "Width:")!=0) {
4505 drawd = d * fac;
4506 Finished = 1;
4509 else if (val) {
4510 /* On any other keyboard event, recalc */
4511 Recalc = 1;
4516 if (Canceled==0) {
4517 SetBlenderCursor(BC_WAITCURSOR);
4518 bevel_mesh_recurs(drawd/fac, recurs, 1);
4519 righthandfaces(1);
4520 SetBlenderCursor(SYSCURSOR);
4521 BIF_undo_push("Bevel");
4525 /* *********** END BEVEL *********/
4527 typedef struct SlideVert {
4528 EditEdge *up,*down;
4529 EditVert origvert;
4530 } SlideVert;
4532 int EdgeLoopDelete(void) {
4533 if(!EdgeSlide(1, 1)) {
4534 return 0;
4536 EM_select_more();
4537 removedoublesflag(1,0.001);
4538 EM_select_flush();
4539 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
4540 return 1;
4543 int EdgeSlide(short immediate, float imperc)
4545 EditMesh *em = G.editMesh;
4546 EditFace *efa;
4547 EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
4548 EditVert *ev, *nearest;
4549 LinkNode *edgelist = NULL, *vertlist=NULL, *look;
4550 GHash *vertgh;
4551 SlideVert *tempsv;
4552 float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4];
4553 float shiftlabda= 0.0f,len = 0.0f;
4554 int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0;
4555 int wasshift = 0;
4556 short event, draw=1;
4557 short mval[2], mvalo[2];
4558 char str[128];
4559 float labda = 0.0f;
4561 view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat);
4563 mvalo[0] = -1; mvalo[1] = -1;
4564 numsel =0;
4566 // Get number of selected edges and clear some flags
4567 for(eed=em->edges.first;eed;eed=eed->next) {
4568 eed->f1 = 0;
4569 eed->f2 = 0;
4570 if(eed->f & SELECT) numsel++;
4573 for(ev=em->verts.first;ev;ev=ev->next) {
4574 ev->f1 = 0;
4577 //Make sure each edge only has 2 faces
4578 // make sure loop doesn't cross face
4579 for(efa=em->faces.first;efa;efa=efa->next) {
4580 int ct = 0;
4581 if(efa->e1->f & SELECT) {
4582 ct++;
4583 efa->e1->f1++;
4584 if(efa->e1->f1 > 2) {
4585 error("3+ face edge");
4586 return 0;
4589 if(efa->e2->f & SELECT) {
4590 ct++;
4591 efa->e2->f1++;
4592 if(efa->e2->f1 > 2) {
4593 error("3+ face edge");
4594 return 0;
4597 if(efa->e3->f & SELECT) {
4598 ct++;
4599 efa->e3->f1++;
4600 if(efa->e3->f1 > 2) {
4601 error("3+ face edge");
4602 return 0;
4605 if(efa->e4 && efa->e4->f & SELECT) {
4606 ct++;
4607 efa->e4->f1++;
4608 if(efa->e4->f1 > 2) {
4609 error("3+ face edge");
4610 return 0;
4613 // Make sure loop is not 2 edges of same face
4614 if(ct > 1) {
4615 error("loop crosses itself");
4616 return 0;
4619 // Get # of selected verts
4620 for(ev=em->verts.first;ev;ev=ev->next) {
4621 if(ev->f & SELECT) vertsel++;
4624 // Test for multiple segments
4625 if(vertsel > numsel+1) {
4626 error("Was not a single edge loop");
4627 return 0;
4630 // Get the edgeloop in order - mark f1 with SELECT once added
4631 for(eed=em->edges.first;eed;eed=eed->next) {
4632 if((eed->f & SELECT) && !(eed->f1 & SELECT)) {
4633 // If this is the first edge added, just put it in
4634 if(!edgelist) {
4635 BLI_linklist_prepend(&edgelist,eed);
4636 numadded++;
4637 first = eed;
4638 last = eed;
4639 eed->f1 = SELECT;
4640 } else {
4641 if(editedge_getSharedVert(eed, last)) {
4642 BLI_linklist_append(&edgelist,eed);
4643 eed->f1 = SELECT;
4644 numadded++;
4645 last = eed;
4646 } else if(editedge_getSharedVert(eed, first)) {
4647 BLI_linklist_prepend(&edgelist,eed);
4648 eed->f1 = SELECT;
4649 numadded++;
4650 first = eed;
4654 if(eed->next == NULL && numadded != numsel) {
4655 eed=em->edges.first;
4656 timesthrough++;
4659 // It looks like there was an unexpected case - Hopefully should not happen
4660 if(timesthrough >= numsel*2) {
4661 BLI_linklist_free(edgelist,NULL);
4662 error("could not order loop");
4663 return 0;
4667 // Put the verts in order in a linklist
4668 look = edgelist;
4669 while(look) {
4670 eed = look->link;
4671 if(!vertlist) {
4672 if(look->next) {
4673 temp = look->next->link;
4675 //This is the first entry takes care of extra vert
4676 if(eed->v1 != temp->v1 && eed->v1 != temp->v2) {
4677 BLI_linklist_append(&vertlist,eed->v1);
4678 eed->v1->f1 = 1;
4679 } else {
4680 BLI_linklist_append(&vertlist,eed->v2);
4681 eed->v2->f1 = 1;
4683 } else {
4684 //This is the case that we only have 1 edge
4685 BLI_linklist_append(&vertlist,eed->v1);
4686 eed->v1->f1 = 1;
4689 // for all the entries
4690 if(eed->v1->f1 != 1) {
4691 BLI_linklist_append(&vertlist,eed->v1);
4692 eed->v1->f1 = 1;
4693 } else if(eed->v2->f1 != 1) {
4694 BLI_linklist_append(&vertlist,eed->v2);
4695 eed->v2->f1 = 1;
4697 look = look->next;
4700 // populate the SlideVerts
4702 vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
4703 look = vertlist;
4704 while(look) {
4705 i=0;
4706 j=0;
4707 ev = look->link;
4708 tempsv = (struct SlideVert*)MEM_mallocN(sizeof(struct SlideVert),"SlideVert");
4709 tempsv->up = NULL;
4710 tempsv->down = NULL;
4711 tempsv->origvert.co[0] = ev->co[0];
4712 tempsv->origvert.co[1] = ev->co[1];
4713 tempsv->origvert.co[2] = ev->co[2];
4714 tempsv->origvert.no[0] = ev->no[0];
4715 tempsv->origvert.no[1] = ev->no[1];
4716 tempsv->origvert.no[2] = ev->no[2];
4717 // i is total edges that vert is on
4718 // j is total selected edges that vert is on
4720 for(eed=em->edges.first;eed;eed=eed->next) {
4721 if(eed->v1 == ev || eed->v2 == ev) {
4722 i++;
4723 if(eed->f & SELECT) {
4724 j++;
4728 // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
4729 if(i == 4 && j == 2) {
4730 for(eed=em->edges.first;eed;eed=eed->next) {
4731 if(editedge_containsVert(eed, ev)) {
4732 if(!(eed->f & SELECT)) {
4733 if(!tempsv->up) {
4734 tempsv->up = eed;
4735 } else if (!(tempsv->down)) {
4736 tempsv->down = eed;
4742 // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
4743 if(i >= 3 && j == 1) {
4744 for(eed=em->edges.first;eed;eed=eed->next) {
4745 if(editedge_containsVert(eed, ev) && eed->f & SELECT) {
4746 for(efa = em->faces.first;efa;efa=efa->next) {
4747 if(editface_containsEdge(efa, eed)) {
4748 if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) {
4749 if(!tempsv->up) {
4750 tempsv->up = efa->e1;
4751 } else if (!(tempsv->down)) {
4752 tempsv->down = efa->e1;
4755 if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) {
4756 if(!tempsv->up) {
4757 tempsv->up = efa->e2;
4758 } else if (!(tempsv->down)) {
4759 tempsv->down = efa->e2;
4762 if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) {
4763 if(!tempsv->up) {
4764 tempsv->up = efa->e3;
4765 } else if (!(tempsv->down)) {
4766 tempsv->down = efa->e3;
4769 if(efa->e4) {
4770 if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) {
4771 if(!tempsv->up) {
4772 tempsv->up = efa->e4;
4773 } else if (!(tempsv->down)) {
4774 tempsv->down = efa->e4;
4784 if(i > 4 && j == 2) {
4785 BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
4786 BLI_linklist_free(vertlist,NULL);
4787 BLI_linklist_free(edgelist,NULL);
4788 return 0;
4790 BLI_ghash_insert(vertgh,ev,tempsv);
4792 look = look->next;
4795 // make sure the UPs nad DOWNs are 'faceloops'
4796 // Also find the nearest slidevert to the cursor
4797 getmouseco_areawin(mval);
4798 look = vertlist;
4799 nearest = NULL;
4800 vertdist = -1;
4801 while(look) {
4802 if(look->next != NULL) {
4803 SlideVert *sv;
4805 tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
4806 sv = BLI_ghash_lookup(vertgh,(EditVert*)look->next->link);
4808 if(!tempsv->up || !tempsv->down) {
4809 error("Missing rails");
4810 BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
4811 BLI_linklist_free(vertlist,NULL);
4812 BLI_linklist_free(edgelist,NULL);
4813 return 0;
4816 if(G.f & G_DRAW_EDGELEN) {
4817 if(!(tempsv->up->f & SELECT)) {
4818 tempsv->up->f |= SELECT;
4819 tempsv->up->f2 |= 16;
4820 } else {
4821 tempsv->up->f2 |= ~16;
4823 if(!(tempsv->down->f & SELECT)) {
4824 tempsv->down->f |= SELECT;
4825 tempsv->down->f2 |= 16;
4826 } else {
4827 tempsv->down->f2 |= ~16;
4831 if(sv) {
4832 float tempdist, co[2];
4834 if(!sharesFace(tempsv->up,sv->up)) {
4835 EditEdge *swap;
4836 swap = sv->up;
4837 sv->up = sv->down;
4838 sv->down = swap;
4841 view3d_project_float(curarea, tempsv->origvert.co, co, projectMat);
4843 tempdist = sqrt(pow(co[0] - mval[0],2)+pow(co[1] - mval[1],2));
4845 if(vertdist < 0) {
4846 vertdist = tempdist;
4847 nearest = (EditVert*)look->link;
4848 } else if ( tempdist < vertdist ) {
4849 vertdist = tempdist;
4850 nearest = (EditVert*)look->link;
4857 look = look->next;
4859 // we should have enough info now to slide
4861 len = 0.0f;
4863 percp = -1;
4864 while(draw) {
4865 /* For the % calculation */
4866 short mval[2];
4867 float rc[2];
4868 float v2[2], v3[2];
4869 EditVert *centerVert, *upVert, *downVert;
4873 getmouseco_areawin(mval);
4875 if (!immediate && (mval[0] == mvalo[0] && mval[1] == mvalo[1])) {
4876 PIL_sleep_ms(10);
4877 } else {
4879 mvalo[0] = mval[0];
4880 mvalo[1] = mval[1];
4882 //Adjust Edgeloop
4883 if(immediate) {
4884 perc = imperc;
4886 percp = perc;
4887 if(prop) {
4888 look = vertlist;
4889 while(look) {
4890 EditVert *tempev;
4891 ev = look->link;
4892 tempsv = BLI_ghash_lookup(vertgh,ev);
4894 tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev);
4895 VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc));
4897 look = look->next;
4900 else {
4901 //Non prop code
4902 look = vertlist;
4903 while(look) {
4904 float newlen;
4905 ev = look->link;
4906 tempsv = BLI_ghash_lookup(vertgh,ev);
4907 newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co));
4908 if(newlen > 1.0) {newlen = 1.0;}
4909 if(newlen < 0.0) {newlen = 0.0;}
4910 if(flip == 0) {
4911 VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));
4912 } else{
4913 VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));
4915 look = look->next;
4920 tempsv = BLI_ghash_lookup(vertgh,nearest);
4922 centerVert = editedge_getSharedVert(tempsv->up, tempsv->down);
4923 upVert = editedge_getOtherVert(tempsv->up, centerVert);
4924 downVert = editedge_getOtherVert(tempsv->down, centerVert);
4925 // Highlight the Control Edges
4927 scrarea_do_windraw(curarea);
4928 persp(PERSP_VIEW);
4929 glPushMatrix();
4930 mymultmatrix(G.obedit->obmat);
4932 glColor3ub(0, 255, 0);
4933 glBegin(GL_LINES);
4934 glVertex3fv(upVert->co);
4935 glVertex3fv(downVert->co);
4936 glEnd();
4938 if(prop == 0) {
4939 // draw start edge for non-prop
4940 glPointSize(5);
4941 glBegin(GL_POINTS);
4942 glColor3ub(255,0,255);
4943 if(flip) {
4944 glVertex3fv(upVert->co);
4945 } else {
4946 glVertex3fv(downVert->co);
4948 glEnd();
4952 glPopMatrix();
4954 view3d_project_float(curarea, upVert->co, v2, projectMat);
4955 view3d_project_float(curarea, downVert->co, v3, projectMat);
4957 /* Determine the % on which the loop should be cut */
4959 rc[0]= v3[0]-v2[0];
4960 rc[1]= v3[1]-v2[1];
4961 len= rc[0]*rc[0]+ rc[1]*rc[1];
4962 if (len==0) {len = 0.0001;}
4964 if ((G.qual & LR_SHIFTKEY)==0) {
4965 wasshift = 0;
4966 labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;
4968 else {
4969 if (wasshift==0) {
4970 wasshift = 1;
4971 shiftlabda = labda;
4973 labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;
4977 if(labda<=0.0) labda=0.0;
4978 else if(labda>=1.0)labda=1.0;
4980 perc=((1-labda)*2)-1;
4982 if(G.qual == 0) {
4983 perc *= 100;
4984 perc = floor(perc);
4985 perc /= 100;
4986 } else if (G.qual == LR_CTRLKEY) {
4987 perc *= 10;
4988 perc = floor(perc);
4989 perc /= 10;
4991 if(prop) {
4992 sprintf(str, "(P)ercentage: %f", perc);
4993 } else {
4994 len = VecLenf(upVert->co,downVert->co)*((perc+1)/2);
4995 if(flip == 1) {
4996 len = VecLenf(upVert->co,downVert->co) - len;
4998 sprintf(str, "Non (P)rop Length: %f, Press (F) to flip control side", len);
5003 headerprint(str);
5004 screen_swapbuffers();
5006 if(!immediate) {
5007 while(qtest()) {
5008 short val=0;
5009 event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
5011 /* val==0 on key-release event */
5012 if (val) {
5013 if(ELEM(event, ESCKEY, RIGHTMOUSE)) {
5014 prop = 1; // Go back to prop mode
5015 imperc = 0; // This is the % that gets set for immediate
5016 immediate = 1; //Run through eval code 1 more time
5017 cancel = 1; // Return -1
5018 mvalo[0] = -1;
5019 } else if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)) {
5020 draw = 0; // End looping now
5021 } else if(event==MIDDLEMOUSE) {
5022 perc = 0;
5023 immediate = 1;
5024 } else if(event==PKEY) {
5025 (prop == 1) ? (prop = 0):(prop = 1);
5026 mvalo[0] = -1;
5027 } else if(event==FKEY) {
5028 (flip == 1) ? (flip = 0):(flip = 1);
5029 mvalo[0] = -1;
5030 } else if(ELEM(event, RIGHTARROWKEY, WHEELUPMOUSE)) { // Scroll through Control Edges
5031 look = vertlist;
5032 while(look) {
5033 if(nearest == (EditVert*)look->link) {
5034 if(look->next == NULL) {
5035 nearest = (EditVert*)vertlist->link;
5036 } else {
5037 nearest = (EditVert*)look->next->link;
5039 mvalo[0] = -1;
5040 break;
5042 look = look->next;
5044 } else if(ELEM(event, LEFTARROWKEY, WHEELDOWNMOUSE)) { // Scroll through Control Edges
5045 look = vertlist;
5046 while(look) {
5047 if(look->next) {
5048 if(look->next->link == nearest) {
5049 nearest = (EditVert*)look->link;
5050 mvalo[0] = -1;
5051 break;
5053 } else {
5054 if((EditVert*)vertlist->link == nearest) {
5055 nearest = look->link;
5056 mvalo[0] = -1;
5057 break;
5060 look = look->next;
5065 } else {
5066 draw = 0;
5068 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
5072 if(G.f & G_DRAW_EDGELEN) {
5073 look = vertlist;
5074 while(look) {
5075 tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
5076 if(tempsv != NULL) {
5077 tempsv->up->f &= !SELECT;
5078 tempsv->down->f &= !SELECT;
5080 look = look->next;
5084 force_draw(0);
5085 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
5086 scrarea_queue_winredraw(curarea);
5088 //BLI_ghash_free(edgesgh, freeGHash, NULL);
5089 BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
5090 BLI_linklist_free(vertlist,NULL);
5091 BLI_linklist_free(edgelist,NULL);
5093 if(cancel == 1) {
5094 return -1;
5096 else {
5097 #ifdef WITH_VERSE
5098 if(G.editMesh->vnode) {
5099 sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
5100 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
5102 #endif
5104 return 1;
5107 /* -------------------- More tools ------------------ */
5109 void mesh_set_smooth_faces(short event)
5111 EditMesh *em = G.editMesh;
5112 EditFace *efa;
5114 if(G.obedit==0) return;
5116 if(G.obedit->type != OB_MESH) return;
5118 efa= em->faces.first;
5119 while(efa) {
5120 if(efa->f & SELECT) {
5121 if(event==1) efa->flag |= ME_SMOOTH;
5122 else if(event==0) efa->flag &= ~ME_SMOOTH;
5124 efa= efa->next;
5127 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
5128 allqueue(REDRAWVIEW3D, 0);
5130 if(event==1) BIF_undo_push("Set Smooth");
5131 else if(event==0) BIF_undo_push("Set Solid");
5134 /* helper to find edge for edge_rip */
5135 static float mesh_rip_edgedist(float mat[][4], float *co1, float *co2, short *mval)
5137 float vec1[3], vec2[3], mvalf[2];
5139 view3d_project_float(curarea, co1, vec1, mat);
5140 view3d_project_float(curarea, co2, vec2, mat);
5141 mvalf[0]= (float)mval[0];
5142 mvalf[1]= (float)mval[1];
5144 return PdistVL2Dfl(mvalf, vec1, vec2);
5147 /* helper for below */
5148 static void mesh_rip_setface(EditFace *sefa)
5150 /* put new vertices & edges in best face */
5151 if(sefa->v1->tmp.v) sefa->v1= sefa->v1->tmp.v;
5152 if(sefa->v2->tmp.v) sefa->v2= sefa->v2->tmp.v;
5153 if(sefa->v3->tmp.v) sefa->v3= sefa->v3->tmp.v;
5154 if(sefa->v4 && sefa->v4->tmp.v) sefa->v4= sefa->v4->tmp.v;
5156 sefa->e1= addedgelist(sefa->v1, sefa->v2, sefa->e1);
5157 sefa->e2= addedgelist(sefa->v2, sefa->v3, sefa->e2);
5158 if(sefa->v4) {
5159 sefa->e3= addedgelist(sefa->v3, sefa->v4, sefa->e3);
5160 sefa->e4= addedgelist(sefa->v4, sefa->v1, sefa->e4);
5162 else
5163 sefa->e3= addedgelist(sefa->v3, sefa->v1, sefa->e3);
5167 /* based on mouse cursor position, it defines how is being ripped */
5168 void mesh_rip(void)
5170 extern void faceloop_select(EditEdge *startedge, int select);
5171 EditMesh *em = G.editMesh;
5172 EditVert *eve, *nextve;
5173 EditEdge *eed, *seed= NULL;
5174 EditFace *efa, *sefa= NULL;
5175 float projectMat[4][4], viewMat[4][4], vec[3], dist, mindist;
5176 short doit= 1, mval[2],propmode,prop;
5178 propmode = G.scene->prop_mode;
5179 G.scene->prop_mode = 0;
5180 prop = G.scene->proportional;
5181 G.scene->proportional = 0;
5183 /* select flush... vertices are important */
5184 EM_selectmode_set();
5186 getmouseco_areawin(mval);
5187 view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat);
5189 /* find best face, exclude triangles and break on face select or faces with 2 edges select */
5190 mindist= 1000000.0f;
5191 for(efa= em->faces.first; efa; efa=efa->next) {
5192 if( efa->f & 1)
5193 break;
5194 if(efa->v4 && faceselectedOR(efa, SELECT) ) {
5195 int totsel=0;
5197 if(efa->e1->f & SELECT) totsel++;
5198 if(efa->e2->f & SELECT) totsel++;
5199 if(efa->e3->f & SELECT) totsel++;
5200 if(efa->e4->f & SELECT) totsel++;
5202 if(totsel>1)
5203 break;
5204 view3d_project_float(curarea, efa->cent, vec, projectMat);
5205 dist= sqrt( (vec[0]-mval[0])*(vec[0]-mval[0]) + (vec[1]-mval[1])*(vec[1]-mval[1]) );
5206 if(dist<mindist) {
5207 mindist= dist;
5208 sefa= efa;
5213 if(efa) {
5214 error("Can't perform ripping with faces selected this way");
5215 return;
5217 if(sefa==NULL) {
5218 error("No proper selection or faces included");
5219 return;
5223 /* duplicate vertices, new vertices get selected */
5224 for(eve = em->verts.last; eve; eve= eve->prev) {
5225 eve->tmp.v = NULL;
5226 if(eve->f & SELECT) {
5227 eve->tmp.v = addvertlist(eve->co, eve);
5228 eve->f &= ~SELECT;
5229 eve->tmp.v->f |= SELECT;
5233 /* find the best candidate edge */
5234 /* or one of sefa edges is selected... */
5235 if(sefa->e1->f & SELECT) seed= sefa->e2;
5236 if(sefa->e2->f & SELECT) seed= sefa->e1;
5237 if(sefa->e3->f & SELECT) seed= sefa->e2;
5238 if(sefa->e4 && sefa->e4->f & SELECT) seed= sefa->e3;
5240 /* or we do the distance trick */
5241 if(seed==NULL) {
5242 mindist= 1000000.0f;
5243 if(sefa->e1->v1->tmp.v || sefa->e1->v2->tmp.v) {
5244 dist = mesh_rip_edgedist(projectMat,
5245 sefa->e1->v1->co,
5246 sefa->e1->v2->co, mval);
5247 if(dist<mindist) {
5248 seed= sefa->e1;
5249 mindist= dist;
5252 if(sefa->e2->v1->tmp.v || sefa->e2->v2->tmp.v) {
5253 dist = mesh_rip_edgedist(projectMat,
5254 sefa->e2->v1->co,
5255 sefa->e2->v2->co, mval);
5256 if(dist<mindist) {
5257 seed= sefa->e2;
5258 mindist= dist;
5261 if(sefa->e3->v1->tmp.v || sefa->e3->v2->tmp.v) {
5262 dist= mesh_rip_edgedist(projectMat,
5263 sefa->e3->v1->co,
5264 sefa->e3->v2->co, mval);
5265 if(dist<mindist) {
5266 seed= sefa->e3;
5267 mindist= dist;
5270 if(sefa->e4 && (sefa->e4->v1->tmp.v || sefa->e4->v2->tmp.v)) {
5271 dist= mesh_rip_edgedist(projectMat,
5272 sefa->e4->v1->co,
5273 sefa->e4->v2->co, mval);
5274 if(dist<mindist) {
5275 seed= sefa->e4;
5276 mindist= dist;
5281 if(seed==NULL) { // never happens?
5282 error("No proper edge found to start");
5283 return;
5286 faceloop_select(seed, 2); // tmp abuse for finding all edges that need duplicated, returns OK faces with f1
5288 /* duplicate edges in the loop, with at least 1 vertex selected, needed for selection flip */
5289 for(eed = em->edges.last; eed; eed= eed->prev) {
5290 eed->tmp.v = NULL;
5291 if((eed->v1->tmp.v) || (eed->v2->tmp.v)) {
5292 EditEdge *newed;
5294 newed= addedgelist(eed->v1->tmp.v?eed->v1->tmp.v:eed->v1,
5295 eed->v2->tmp.v?eed->v2->tmp.v:eed->v2, eed);
5296 if(eed->f & SELECT) {
5297 eed->f &= ~SELECT;
5298 newed->f |= SELECT;
5300 eed->tmp.v = (EditVert *)newed;
5304 /* first clear edges to help finding neighbours */
5305 for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
5307 /* put new vertices & edges && flag in best face */
5308 mesh_rip_setface(sefa);
5310 /* starting with neighbours of best face, we loop over the seam */
5311 sefa->f1= 2;
5312 doit= 1;
5313 while(doit) {
5314 doit= 0;
5316 for(efa= em->faces.first; efa; efa=efa->next) {
5317 /* new vert in face */
5318 if (efa->v1->tmp.v || efa->v2->tmp.v ||
5319 efa->v3->tmp.v || (efa->v4 && efa->v4->tmp.v)) {
5320 /* face is tagged with loop */
5321 if(efa->f1==1) {
5322 mesh_rip_setface(efa);
5323 efa->f1= 2;
5324 doit= 1;
5330 /* remove loose edges, that were part of a ripped face */
5331 for(eve = em->verts.first; eve; eve= eve->next) eve->f1= 0;
5332 for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0;
5333 for(efa= em->faces.first; efa; efa=efa->next) {
5334 efa->e1->f1= 1;
5335 efa->e2->f1= 1;
5336 efa->e3->f1= 1;
5337 if(efa->e4) efa->e4->f1= 1;
5340 for(eed = em->edges.last; eed; eed= seed) {
5341 seed= eed->prev;
5342 if(eed->f1==0) {
5343 if(eed->v1->tmp.v || eed->v2->tmp.v ||
5344 (eed->v1->f & SELECT) || (eed->v2->f & SELECT)) {
5345 remedge(eed);
5346 free_editedge(eed);
5347 eed= NULL;
5350 if(eed) {
5351 eed->v1->f1= 1;
5352 eed->v2->f1= 1;
5356 /* and remove loose selected vertices, that got duplicated accidentally */
5357 for(eve = em->verts.first; eve; eve= nextve) {
5358 nextve= eve->next;
5359 if(eve->f1==0 && (eve->tmp.v || (eve->f & SELECT))) {
5360 BLI_remlink(&em->verts,eve);
5361 free_editvert(eve);
5365 countall(); // apparently always needed when adding stuff, derived mesh
5367 #ifdef WITH_VERSE
5368 if(G.editMesh->vnode) {
5369 sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
5370 sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
5372 #endif
5374 BIF_TransformSetUndo("Rip");
5375 initTransform(TFM_TRANSLATION, 0);
5376 Transform();
5378 G.scene->prop_mode = propmode;
5379 G.scene->proportional = prop;
5382 void shape_propagate(){
5383 EditMesh *em = G.editMesh;
5384 EditVert *ev = NULL;
5385 Mesh* me = (Mesh*)G.obedit->data;
5386 Key* ky = NULL;
5387 KeyBlock* kb = NULL;
5388 Base* base=NULL;
5391 if(me->key){
5392 ky = me->key;
5393 } else {
5394 error("Object Has No Key");
5395 return;
5398 if(ky->block.first){
5399 for(ev = em->verts.first; ev ; ev = ev->next){
5400 if(ev->f & SELECT){
5401 for(kb=ky->block.first;kb;kb = kb->next){
5402 float *data;
5403 data = kb->data;
5404 VECCOPY(data+(ev->keyindex*3),ev->co);
5408 } else {
5409 error("Object Has No Blendshapes");
5410 return;
5413 //TAG Mesh Objects that share this data
5414 for(base = G.scene->base.first; base; base = base->next){
5415 if(base->object && base->object->data == me){
5416 base->object->recalc = OB_RECALC_DATA;
5420 BIF_undo_push("Propagate Blendshape Verts");
5421 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
5422 allqueue(REDRAWVIEW3D, 0);
5423 return;
5426 void shape_copy_from_lerp(KeyBlock* thisBlock, KeyBlock* fromBlock)
5428 EditMesh *em = G.editMesh;
5429 EditVert *ev = NULL;
5430 short mval[2], curval[2], event = 0, finished = 0, canceled = 0, fullcopy=0 ;
5431 float perc = 0;
5432 char str[64];
5433 float *data, *odata;
5435 data = fromBlock->data;
5436 odata = thisBlock->data;
5438 getmouseco_areawin(mval);
5439 curval[0] = mval[0] + 1; curval[1] = mval[1] + 1;
5441 while (finished == 0)
5443 getmouseco_areawin(mval);
5444 if (mval[0] != curval[0] || mval[1] != curval[1])
5447 if(mval[0] > curval[0])
5448 perc += 0.1;
5449 else if(mval[0] < curval[0])
5450 perc -= 0.1;
5452 if(perc < 0) perc = 0;
5453 if(perc > 1) perc = 1;
5455 curval[0] = mval[0];
5456 curval[1] = mval[1];
5458 if(fullcopy == 1){
5459 perc = 1;
5462 for(ev = em->verts.first; ev ; ev = ev->next){
5463 if(ev->f & SELECT){
5464 VecLerpf(ev->co,odata+(ev->keyindex*3),data+(ev->keyindex*3),perc);
5467 sprintf(str,"Blending at %d%c MMB to Copy at 100%c",(int)(perc*100),'%','%');
5468 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
5469 headerprint(str);
5470 force_draw(0);
5472 if(fullcopy == 1){
5473 break;
5476 } else {
5477 PIL_sleep_ms(10);
5480 while(qtest()) {
5481 short val=0;
5482 event= extern_qread(&val);
5483 if(val){
5484 if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)){
5485 finished = 1;
5487 else if (event == MIDDLEMOUSE){
5488 fullcopy = 1;
5490 else if (ELEM3(event,ESCKEY,RIGHTMOUSE,RIGHTMOUSE)){
5491 canceled = 1;
5492 finished = 1;
5497 if(!canceled)
5498 BIF_undo_push("Copy Blendshape Verts");
5499 else
5500 for(ev = em->verts.first; ev ; ev = ev->next){
5501 if(ev->f & SELECT){
5502 VECCOPY(ev->co, odata+(ev->keyindex*3));
5505 return;
5510 void shape_copy_select_from()
5512 Mesh* me = (Mesh*)G.obedit->data;
5513 EditMesh *em = G.editMesh;
5514 EditVert *ev = NULL;
5515 int totverts = 0,curshape = G.obedit->shapenr;
5517 Key* ky = NULL;
5518 KeyBlock *kb = NULL,*thisBlock = NULL;
5519 int maxlen=32, nr=0, a=0;
5520 char *menu;
5522 if(me->key){
5523 ky = me->key;
5524 } else {
5525 error("Object Has No Key");
5526 return;
5529 if(ky->block.first){
5530 for(kb=ky->block.first;kb;kb = kb->next){
5531 maxlen += 40; // Size of a block name
5532 if(a == curshape-1){
5533 thisBlock = kb;
5536 a++;
5538 a=0;
5539 menu = MEM_callocN(maxlen, "Copy Shape Menu Text");
5540 strcpy(menu, "Copy Vert Positions from Shape %t|");
5541 for(kb=ky->block.first;kb;kb = kb->next){
5542 if(a != curshape-1){
5543 sprintf(menu,"%s %s %cx%d|",menu,kb->name,'%',a);
5545 a++;
5547 nr = pupmenu_col(menu, 20);
5548 MEM_freeN(menu);
5549 } else {
5550 error("Object Has No Blendshapes");
5551 return;
5554 a = 0;
5556 for(kb=ky->block.first;kb;kb = kb->next){
5557 if(a == nr){
5559 for(ev = em->verts.first;ev;ev = ev->next){
5560 totverts++;
5563 if(me->totvert != totverts){
5564 error("Shape Has had Verts Added/Removed, please cycle editmode before copying");
5565 return;
5567 shape_copy_from_lerp(thisBlock,kb);
5569 return;
5571 a++;
5573 return;
5576 /* Collection Routines|Currently used by the improved merge code*/
5577 /* buildEdge_collection() creates a list of lists*/
5578 /* these lists are filled with edges that are topologically connected.*/
5579 /* This whole tool needs to be redone, its rather poorly implemented...*/
5581 typedef struct Collection{
5582 struct Collection *next, *prev;
5583 int index;
5584 ListBase collectionbase;
5585 } Collection;
5587 typedef struct CollectedEdge{
5588 struct CollectedEdge *next, *prev;
5589 EditEdge *eed;
5590 } CollectedEdge;
5592 #define MERGELIMIT 0.000001
5594 static void build_edgecollection(ListBase *allcollections)
5596 EditEdge *eed;
5597 Collection *edgecollection, *newcollection;
5598 CollectedEdge *newedge;
5600 int currtag = 1;
5601 short ebalanced = 0;
5602 short collectionfound = 0;
5604 for (eed=G.editMesh->edges.first; eed; eed = eed->next){
5605 eed->tmp.l = 0;
5606 eed->v1->tmp.l = 0;
5607 eed->v2->tmp.l = 0;
5610 /*1st pass*/
5611 for(eed=G.editMesh->edges.first; eed; eed=eed->next){
5612 if(eed->f&SELECT){
5613 eed->v1->tmp.l = currtag;
5614 eed->v2->tmp.l = currtag;
5615 currtag +=1;
5619 /*2nd pass - Brute force. Loop through selected faces until there are no 'unbalanced' edges left (those with both vertices 'tmp.l' tag matching */
5620 while(ebalanced == 0){
5621 ebalanced = 1;
5622 for(eed=G.editMesh->edges.first; eed; eed = eed->next){
5623 if(eed->f&SELECT){
5624 if(eed->v1->tmp.l != eed->v2->tmp.l) /*unbalanced*/{
5625 if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l;
5626 else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l;
5627 ebalanced = 0;
5633 /*3rd pass, set all the edge flags (unnessecary?)*/
5634 for(eed=G.editMesh->edges.first; eed; eed = eed->next){
5635 if(eed->f&SELECT) eed->tmp.l = eed->v1->tmp.l;
5638 for(eed=G.editMesh->edges.first; eed; eed=eed->next){
5639 if(eed->f&SELECT){
5640 if(allcollections->first){
5641 for(edgecollection = allcollections->first; edgecollection; edgecollection=edgecollection->next){
5642 if(edgecollection->index == eed->tmp.l){
5643 newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge");
5644 newedge->eed = eed;
5645 BLI_addtail(&(edgecollection->collectionbase), newedge);
5646 collectionfound = 1;
5647 break;
5649 else collectionfound = 0;
5652 if(allcollections->first == NULL || collectionfound == 0){
5653 newcollection = MEM_mallocN(sizeof(Collection), "element collection");
5654 newcollection->index = eed->tmp.l;
5655 newcollection->collectionbase.first = 0;
5656 newcollection->collectionbase.last = 0;
5658 newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge");
5659 newedge->eed = eed;
5661 BLI_addtail(&(newcollection->collectionbase), newedge);
5662 BLI_addtail(allcollections, newcollection);
5669 static void freecollections(ListBase *allcollections)
5671 struct Collection *curcollection;
5673 for(curcollection = allcollections->first; curcollection; curcollection = curcollection->next)
5674 BLI_freelistN(&(curcollection->collectionbase));
5675 BLI_freelistN(allcollections);
5678 /*Begin UV Edge Collapse Code
5679 Like Edge subdivide, Edge Collapse should handle UV's intelligently, but since UV's are a per-face attribute, normal edge collapse will fail
5680 in areas such as the boundries of 'UV islands'. So for each edge collection we need to build a set of 'welded' UV vertices and edges for it.
5681 The welded UV edges can then be sorted and collapsed.
5683 typedef struct wUV{
5684 struct wUV *next, *prev;
5685 ListBase nodes;
5686 float u, v; /*cached copy of UV coordinates pointed to by nodes*/
5687 EditVert *eve;
5688 int f;
5689 } wUV;
5691 typedef struct wUVNode{
5692 struct wUVNode *next, *prev;
5693 float *u; /*pointer to original tface data*/
5694 float *v; /*pointer to original tface data*/
5695 } wUVNode;
5697 typedef struct wUVEdge{
5698 struct wUVEdge *next, *prev;
5699 float v1uv[2], v2uv[2]; /*nasty.*/
5700 struct wUV *v1, *v2; /*oriented same as editedge*/
5701 EditEdge *eed;
5702 int f;
5703 } wUVEdge;
5705 typedef struct wUVEdgeCollect{ /*used for grouping*/
5706 struct wUVEdgeCollect *next, *prev;
5707 wUVEdge *uved;
5708 int id;
5709 } wUVEdgeCollect;
5711 static void append_weldedUV(EditFace *efa, EditVert *eve, int tfindex, ListBase *uvverts)
5713 wUV *curwvert, *newwvert;
5714 wUVNode *newnode;
5715 int found;
5716 MTFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
5718 found = 0;
5720 for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
5721 if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){
5722 newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
5723 newnode->u = &(tf->uv[tfindex][0]);
5724 newnode->v = &(tf->uv[tfindex][1]);
5725 BLI_addtail(&(curwvert->nodes), newnode);
5726 found = 1;
5727 break;
5731 if(!found){
5732 newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node");
5733 newnode->u = &(tf->uv[tfindex][0]);
5734 newnode->v = &(tf->uv[tfindex][1]);
5736 newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert");
5737 newwvert->u = *(newnode->u);
5738 newwvert->v = *(newnode->v);
5739 newwvert->eve = eve;
5741 BLI_addtail(&(newwvert->nodes), newnode);
5742 BLI_addtail(uvverts, newwvert);
5747 static void build_weldedUVs(ListBase *uvverts)
5749 EditFace *efa;
5750 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
5751 if(efa->v1->f1) append_weldedUV(efa, efa->v1, 0, uvverts);
5752 if(efa->v2->f1) append_weldedUV(efa, efa->v2, 1, uvverts);
5753 if(efa->v3->f1) append_weldedUV(efa, efa->v3, 2, uvverts);
5754 if(efa->v4 && efa->v4->f1) append_weldedUV(efa, efa->v4, 3, uvverts);
5758 static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges)
5760 wUVEdge *curwedge, *newwedge;
5761 int v1tfindex, v2tfindex, found;
5762 MTFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
5764 found = 0;
5766 if(eed->v1 == efa->v1) v1tfindex = 0;
5767 else if(eed->v1 == efa->v2) v1tfindex = 1;
5768 else if(eed->v1 == efa->v3) v1tfindex = 2;
5769 else /* if(eed->v1 == efa->v4) */ v1tfindex = 3;
5771 if(eed->v2 == efa->v1) v2tfindex = 0;
5772 else if(eed->v2 == efa->v2) v2tfindex = 1;
5773 else if(eed->v2 == efa->v3) v2tfindex = 2;
5774 else /* if(eed->v2 == efa->v4) */ v2tfindex = 3;
5776 for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
5777 if(curwedge->eed == eed && curwedge->v1uv[0] == tf->uv[v1tfindex][0] && curwedge->v1uv[1] == tf->uv[v1tfindex][1] && curwedge->v2uv[0] == tf->uv[v2tfindex][0] && curwedge->v2uv[1] == tf->uv[v2tfindex][1]){
5778 found = 1;
5779 break; //do nothing, we don't need another welded uv edge
5783 if(!found){
5784 newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge");
5785 newwedge->v1uv[0] = tf->uv[v1tfindex][0];
5786 newwedge->v1uv[1] = tf->uv[v1tfindex][1];
5787 newwedge->v2uv[0] = tf->uv[v2tfindex][0];
5788 newwedge->v2uv[1] = tf->uv[v2tfindex][1];
5789 newwedge->eed = eed;
5791 BLI_addtail(uvedges, newwedge);
5795 static void build_weldedUVEdges(ListBase *uvedges, ListBase *uvverts)
5797 wUV *curwvert;
5798 wUVEdge *curwedge;
5799 EditFace *efa;
5801 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
5802 if(efa->e1->f1) append_weldedUVEdge(efa, efa->e1, uvedges);
5803 if(efa->e2->f1) append_weldedUVEdge(efa, efa->e2, uvedges);
5804 if(efa->e3->f1) append_weldedUVEdge(efa, efa->e3, uvedges);
5805 if(efa->e4 && efa->e4->f1) append_weldedUVEdge(efa, efa->e4, uvedges);
5809 //link vertices: for each uvedge, search uvverts to populate v1 and v2 pointers
5810 for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){
5811 for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
5812 if(curwedge->eed->v1 == curwvert->eve && curwedge->v1uv[0] == curwvert->u && curwedge->v1uv[1] == curwvert->v){
5813 curwedge->v1 = curwvert;
5814 break;
5817 for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){
5818 if(curwedge->eed->v2 == curwvert->eve && curwedge->v2uv[0] == curwvert->u && curwedge->v2uv[1] == curwvert->v){
5819 curwedge->v2 = curwvert;
5820 break;
5826 static void free_weldedUVs(ListBase *uvverts)
5828 wUV *curwvert;
5829 for(curwvert = uvverts->first; curwvert; curwvert=curwvert->next) BLI_freelistN(&(curwvert->nodes));
5830 BLI_freelistN(uvverts);
5833 static void collapse_edgeuvs(void)
5835 ListBase uvedges, uvverts, allcollections;
5836 wUVEdge *curwedge;
5837 wUVNode *curwnode;
5838 wUVEdgeCollect *collectedwuve, *newcollectedwuve;
5839 Collection *wuvecollection, *newcollection;
5840 int curtag, balanced, collectionfound= 0, vcount;
5841 float avg[2];
5843 if (!CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE))
5844 return;
5846 uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL;
5848 build_weldedUVs(&uvverts);
5849 build_weldedUVEdges(&uvedges, &uvverts);
5851 curtag = 0;
5853 for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
5854 curwedge->v1->f = curtag;
5855 curwedge->v2->f = curtag;
5856 curtag +=1;
5859 balanced = 0;
5860 while(!balanced){
5861 balanced = 1;
5862 for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
5863 if(curwedge->v1->f != curwedge->v2->f){
5864 if(curwedge->v1->f > curwedge->v2->f) curwedge->v1->f = curwedge->v2->f;
5865 else curwedge->v2->f = curwedge->v1->f;
5866 balanced = 0;
5871 for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next) curwedge->f = curwedge->v1->f;
5874 for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){
5875 if(allcollections.first){
5876 for(wuvecollection = allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
5877 if(wuvecollection->index == curwedge->f){
5878 newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge");
5879 newcollectedwuve->uved = curwedge;
5880 BLI_addtail(&(wuvecollection->collectionbase), newcollectedwuve);
5881 collectionfound = 1;
5882 break;
5885 else collectionfound = 0;
5888 if(allcollections.first == NULL || collectionfound == 0){
5889 newcollection = MEM_callocN(sizeof(Collection), "element collection");
5890 newcollection->index = curwedge->f;
5891 newcollection->collectionbase.first = 0;
5892 newcollection->collectionbase.last = 0;
5894 newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge");
5895 newcollectedwuve->uved = curwedge;
5897 BLI_addtail(&(newcollection->collectionbase), newcollectedwuve);
5898 BLI_addtail(&allcollections, newcollection);
5902 for(wuvecollection=allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){
5904 vcount = avg[0] = avg[1] = 0;
5906 for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
5907 avg[0] += collectedwuve->uved->v1uv[0];
5908 avg[1] += collectedwuve->uved->v1uv[1];
5910 avg[0] += collectedwuve->uved->v2uv[0];
5911 avg[1] += collectedwuve->uved->v2uv[1];
5913 vcount +=2;
5917 avg[0] /= vcount; avg[1] /= vcount;
5919 for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){
5920 for(curwnode=collectedwuve->uved->v1->nodes.first; curwnode; curwnode=curwnode->next){
5921 *(curwnode->u) = avg[0];
5922 *(curwnode->v) = avg[1];
5924 for(curwnode=collectedwuve->uved->v2->nodes.first; curwnode; curwnode=curwnode->next){
5925 *(curwnode->u) = avg[0];
5926 *(curwnode->v) = avg[1];
5931 free_weldedUVs(&uvverts);
5932 BLI_freelistN(&uvedges);
5933 freecollections(&allcollections);
5936 /*End UV Edge collapse code*/
5938 static void collapseuvs(EditVert *mergevert)
5940 EditFace *efa;
5941 MTFace *tf;
5942 int uvcount;
5943 float uvav[2];
5945 if (!CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE))
5946 return;
5948 uvcount = 0;
5949 uvav[0] = 0;
5950 uvav[1] = 0;
5952 for(efa = G.editMesh->faces.first; efa; efa=efa->next){
5953 tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
5955 if(efa->v1->f1 && ELEM(mergevert, NULL, efa->v1)) {
5956 uvav[0] += tf->uv[0][0];
5957 uvav[1] += tf->uv[0][1];
5958 uvcount += 1;
5960 if(efa->v2->f1 && ELEM(mergevert, NULL, efa->v2)){
5961 uvav[0] += tf->uv[1][0];
5962 uvav[1] += tf->uv[1][1];
5963 uvcount += 1;
5965 if(efa->v3->f1 && ELEM(mergevert, NULL, efa->v3)){
5966 uvav[0] += tf->uv[2][0];
5967 uvav[1] += tf->uv[2][1];
5968 uvcount += 1;
5970 if(efa->v4 && efa->v4->f1 && ELEM(mergevert, NULL, efa->v4)){
5971 uvav[0] += tf->uv[3][0];
5972 uvav[1] += tf->uv[3][1];
5973 uvcount += 1;
5977 if(uvcount > 0) {
5978 uvav[0] /= uvcount;
5979 uvav[1] /= uvcount;
5981 for(efa = G.editMesh->faces.first; efa; efa=efa->next){
5982 tf = CustomData_em_get(&G.editMesh->fdata, efa->data, CD_MTFACE);
5984 if(efa->v1->f1){
5985 tf->uv[0][0] = uvav[0];
5986 tf->uv[0][1] = uvav[1];
5988 if(efa->v2->f1){
5989 tf->uv[1][0] = uvav[0];
5990 tf->uv[1][1] = uvav[1];
5992 if(efa->v3->f1){
5993 tf->uv[2][0] = uvav[0];
5994 tf->uv[2][1] = uvav[1];
5996 if(efa->v4 && efa->v4->f1){
5997 tf->uv[3][0] = uvav[0];
5998 tf->uv[3][1] = uvav[1];
6004 int collapseEdges(void)
6006 EditVert *eve;
6007 EditEdge *eed;
6009 ListBase allcollections;
6010 CollectedEdge *curredge;
6011 Collection *edgecollection;
6013 int totedges, groupcount, mergecount,vcount;
6014 float avgcount[3];
6016 allcollections.first = 0;
6017 allcollections.last = 0;
6019 mergecount = 0;
6021 if(multires_test()) return 0;
6023 build_edgecollection(&allcollections);
6024 groupcount = BLI_countlist(&allcollections);
6027 for(edgecollection = allcollections.first; edgecollection; edgecollection = edgecollection->next){
6028 totedges = BLI_countlist(&(edgecollection->collectionbase));
6029 mergecount += totedges;
6030 avgcount[0] = 0; avgcount[1] = 0; avgcount[2] = 0;
6032 vcount = 0;
6034 for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
6035 avgcount[0] += ((EditEdge*)curredge->eed)->v1->co[0];
6036 avgcount[1] += ((EditEdge*)curredge->eed)->v1->co[1];
6037 avgcount[2] += ((EditEdge*)curredge->eed)->v1->co[2];
6039 avgcount[0] += ((EditEdge*)curredge->eed)->v2->co[0];
6040 avgcount[1] += ((EditEdge*)curredge->eed)->v2->co[1];
6041 avgcount[2] += ((EditEdge*)curredge->eed)->v2->co[2];
6043 vcount +=2;
6046 avgcount[0] /= vcount; avgcount[1] /=vcount; avgcount[2] /= vcount;
6048 for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
6049 VECCOPY(((EditEdge*)curredge->eed)->v1->co,avgcount);
6050 VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount);
6053 if (CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)) {
6054 /*uv collapse*/
6055 for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
6056 for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
6057 for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){
6058 curredge->eed->v1->f1 = 1;
6059 curredge->eed->v2->f1 = 1;
6060 curredge->eed->f1 = 1;
6062 collapse_edgeuvs();
6066 freecollections(&allcollections);
6067 removedoublesflag(1, MERGELIMIT);
6068 /*get rid of this!*/
6069 countall();
6070 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
6071 allqueue(REDRAWVIEW3D, 0);
6072 return mergecount;
6075 int merge_firstlast(int first, int uvmerge)
6077 EditVert *eve,*mergevert;
6078 EditSelection *ese;
6080 if(multires_test()) return 0;
6082 /* do sanity check in mergemenu in edit.c ?*/
6083 if(first == 0){
6084 ese = G.editMesh->selected.last;
6085 mergevert= (EditVert*)ese->data;
6087 else{
6088 ese = G.editMesh->selected.first;
6089 mergevert = (EditVert*)ese->data;
6092 if(mergevert->f&SELECT){
6093 for (eve=G.editMesh->verts.first; eve; eve=eve->next){
6094 if (eve->f&SELECT)
6095 VECCOPY(eve->co,mergevert->co);
6099 if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)){
6101 for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
6102 for(eve=G.editMesh->verts.first; eve; eve=eve->next){
6103 if(eve->f&SELECT) eve->f1 = 1;
6105 collapseuvs(mergevert);
6108 countall();
6109 return removedoublesflag(1,MERGELIMIT);
6112 int merge_target(int target, int uvmerge)
6114 EditVert *eve;
6116 if(multires_test()) return 0;
6118 if(target) snap_sel_to_curs();
6119 else snap_to_center();
6121 if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)){
6122 for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0;
6123 for(eve=G.editMesh->verts.first; eve; eve=eve->next){
6124 if(eve->f&SELECT) eve->f1 = 1;
6126 collapseuvs(NULL);
6129 countall();
6130 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
6131 allqueue(REDRAWVIEW3D, 0);
6132 return removedoublesflag(1,MERGELIMIT);
6135 #undef MERGELIMIT
6137 typedef struct PathNode{
6138 int u;
6139 int visited;
6140 ListBase edges;
6141 } PathNode;
6143 typedef struct PathEdge{
6144 struct PathEdge *next, *prev;
6145 int v;
6146 float w;
6147 } PathEdge;
6149 void pathselect(void)
6151 EditVert *eve, *s, *t;
6152 EditEdge *eed;
6153 EditSelection *ese;
6154 PathEdge *newpe, *currpe;
6155 PathNode *currpn;
6156 PathNode *Q;
6157 int v, *previous, pathvert, pnindex; /*pnindex redundant?*/
6158 int unbalanced, totnodes;
6159 short physical;
6160 float *cost;
6161 Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/
6163 s = t = NULL;
6165 countall(); /*paranoid?*/
6167 ese = ((EditSelection*)G.editMesh->selected.last);
6168 if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){
6169 physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0");
6171 t = (EditVert*)ese->data;
6172 s = (EditVert*)ese->prev->data;
6174 /*need to find out if t is actually reachable by s....*/
6175 for(eve=G.editMesh->verts.first; eve; eve=eve->next){
6176 eve->f1 = 0;
6179 s->f1 = 1;
6181 unbalanced = 1;
6182 totnodes = 1;
6183 while(unbalanced){
6184 unbalanced = 0;
6185 for(eed=G.editMesh->edges.first; eed; eed=eed->next){
6186 if(!eed->h){
6187 if(eed->v1->f1 && !eed->v2->f1){
6188 eed->v2->f1 = 1;
6189 totnodes++;
6190 unbalanced = 1;
6192 else if(eed->v2->f1 && !eed->v1->f1){
6193 eed->v1->f1 = 1;
6194 totnodes++;
6195 unbalanced = 1;
6203 if(s->f1 && t->f1){ /*t can be reached by s*/
6204 Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes");
6205 totnodes = 0;
6206 for(eve=G.editMesh->verts.first; eve; eve=eve->next){
6207 if(eve->f1){
6208 Q[totnodes].u = totnodes;
6209 Q[totnodes].edges.first = 0;
6210 Q[totnodes].edges.last = 0;
6211 Q[totnodes].visited = 0;
6212 eve->tmp.p = &(Q[totnodes]);
6213 totnodes++;
6215 else eve->tmp.p = NULL;
6218 for(eed=G.editMesh->edges.first; eed; eed=eed->next){
6219 if(!eed->h){
6220 if(eed->v1->f1){
6221 currpn = ((PathNode*)eed->v1->tmp.p);
6223 newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
6224 newpe->v = ((PathNode*)eed->v2->tmp.p)->u;
6225 if(physical){
6226 newpe->w = VecLenf(eed->v1->co, eed->v2->co);
6228 else newpe->w = 1;
6229 newpe->next = 0;
6230 newpe->prev = 0;
6231 BLI_addtail(&(currpn->edges), newpe);
6233 if(eed->v2->f1){
6234 currpn = ((PathNode*)eed->v2->tmp.p);
6235 newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge");
6236 newpe->v = ((PathNode*)eed->v1->tmp.p)->u;
6237 if(physical){
6238 newpe->w = VecLenf(eed->v1->co, eed->v2->co);
6240 else newpe->w = 1;
6241 newpe->next = 0;
6242 newpe->prev = 0;
6243 BLI_addtail(&(currpn->edges), newpe);
6248 heap = BLI_heap_new();
6249 cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs");
6250 previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices");
6252 for(v=0; v < totnodes; v++){
6253 cost[v] = 1000000;
6254 previous[v] = -1; /*array of indices*/
6257 pnindex = ((PathNode*)s->tmp.p)->u;
6258 cost[pnindex] = 0;
6259 BLI_heap_insert(heap, 0.0f, (void*)pnindex);
6261 while( !BLI_heap_empty(heap) ){
6263 pnindex = (int)BLI_heap_popmin(heap);
6264 currpn = &(Q[pnindex]);
6266 if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/
6267 break;
6269 for(currpe=currpn->edges.first; currpe; currpe=currpe->next){
6270 if(!Q[currpe->v].visited){
6271 if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){
6272 cost[currpe->v] = cost[currpn->u] + currpe->w;
6273 previous[currpe->v] = currpn->u;
6274 Q[currpe->v].visited = 1;
6275 BLI_heap_insert(heap, cost[currpe->v], (void*)currpe->v);
6281 pathvert = ((PathNode*)t->tmp.p)->u;
6282 while(pathvert != -1){
6283 for(eve=G.editMesh->verts.first; eve; eve=eve->next){
6284 if(eve->f1){
6285 if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT;
6288 pathvert = previous[pathvert];
6291 for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges));
6292 MEM_freeN(Q);
6293 MEM_freeN(cost);
6294 MEM_freeN(previous);
6295 BLI_heap_free(heap, NULL);
6296 EM_select_flush();
6297 countall();
6298 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
6299 allqueue(REDRAWVIEW3D, 0);
6302 else{
6303 error("Path Selection requires that exactly two vertices be selected");
6304 return;
6308 void region_to_loop(void)
6310 EditEdge *eed;
6311 EditFace *efa;
6313 if(G.totfacesel){
6314 for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
6316 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
6317 if(efa->f&SELECT){
6318 efa->e1->f1++;
6319 efa->e2->f1++;
6320 efa->e3->f1++;
6321 if(efa->e4)
6322 efa->e4->f1++;
6326 EM_clear_flag_all(SELECT);
6328 for(eed=G.editMesh->edges.first; eed; eed=eed->next){
6329 if(eed->f1 == 1) EM_select_edge(eed, 1);
6332 G.scene->selectmode = SCE_SELECT_EDGE;
6333 EM_selectmode_set();
6334 countall();
6335 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
6336 allqueue(REDRAWVIEW3D, 0);
6337 BIF_undo_push("Face Region to Edge Loop");
6342 static int validate_loop(Collection *edgecollection)
6344 EditEdge *eed;
6345 EditFace *efa;
6346 CollectedEdge *curredge;
6348 /*1st test*/
6349 for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
6350 curredge->eed->v1->f1 = 0;
6351 curredge->eed->v2->f1 = 0;
6353 for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
6354 curredge->eed->v1->f1++;
6355 curredge->eed->v2->f1++;
6357 for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
6358 if(curredge->eed->v1->f1 > 2) return(0); else
6359 if(curredge->eed->v2->f1 > 2) return(0);
6362 /*2nd test*/
6363 for(eed = G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
6364 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
6365 efa->e1->f1++;
6366 efa->e2->f1++;
6367 efa->e3->f1++;
6368 if(efa->e4) efa->e4->f1++;
6370 for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
6371 if(curredge->eed->f1 > 2) return(0);
6373 return(1);
6376 static int loop_bisect(Collection *edgecollection){
6378 EditFace *efa, *sf1, *sf2;
6379 EditEdge *eed, *sed;
6380 CollectedEdge *curredge;
6381 int totsf1, totsf2, unbalanced,balancededges;
6383 for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0;
6384 for(efa=G.editMesh->faces.first; efa; efa=efa->next) efa->f1 = 0;
6386 for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next) curredge->eed->f1 = 1;
6388 sf1 = sf2 = NULL;
6389 sed = ((CollectedEdge*)edgecollection->collectionbase.first)->eed;
6391 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
6392 if(sf2) break;
6393 else if(sf1){
6394 if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf2 = efa;
6396 else{
6397 if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf1 = efa;
6401 if(sf1==NULL || sf2==NULL)
6402 return(-1);
6404 if(!(sf1->e1->f1)) sf1->e1->f2 = 1;
6405 if(!(sf1->e2->f1)) sf1->e2->f2 = 1;
6406 if(!(sf1->e3->f1)) sf1->e3->f2 = 1;
6407 if(sf1->e4 && !(sf1->e4->f1)) sf1->e4->f2 = 1;
6408 sf1->f1 = 1;
6409 totsf1 = 1;
6411 if(!(sf2->e1->f1)) sf2->e1->f2 = 2;
6412 if(!(sf2->e2->f1)) sf2->e2->f2 = 2;
6413 if(!(sf2->e3->f1)) sf2->e3->f2 = 2;
6414 if(sf2->e4 && !(sf2->e4->f1)) sf2->e4->f2 = 2;
6415 sf2->f1 = 2;
6416 totsf2 = 1;
6418 /*do sf1*/
6419 unbalanced = 1;
6420 while(unbalanced){
6421 unbalanced = 0;
6422 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
6423 balancededges = 0;
6424 if(efa->f1 == 0){
6425 if(efa->e1->f2 == 1 || efa->e2->f2 == 1 || efa->e3->f2 == 1 || ( (efa->e4) ? efa->e4->f2 == 1 : 0) ){
6426 balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 1;
6427 balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 1;
6428 balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 1;
6429 if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 1;
6430 if(balancededges){
6431 unbalanced = 1;
6432 efa->f1 = 1;
6433 totsf1++;
6440 /*do sf2*/
6441 unbalanced = 1;
6442 while(unbalanced){
6443 unbalanced = 0;
6444 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
6445 balancededges = 0;
6446 if(efa->f1 == 0){
6447 if(efa->e1->f2 == 2 || efa->e2->f2 == 2 || efa->e3->f2 == 2 || ( (efa->e4) ? efa->e4->f2 == 2 : 0) ){
6448 balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 2;
6449 balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 2;
6450 balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 2;
6451 if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 2;
6452 if(balancededges){
6453 unbalanced = 1;
6454 efa->f1 = 2;
6455 totsf2++;
6462 if(totsf1 < totsf2) return(1);
6463 else return(2);
6466 void loop_to_region(void)
6468 EditFace *efa;
6469 ListBase allcollections={NULL,NULL};
6470 Collection *edgecollection;
6471 int testflag;
6473 build_edgecollection(&allcollections);
6475 for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){
6476 if(validate_loop(edgecollection)){
6477 testflag = loop_bisect(edgecollection);
6478 for(efa=G.editMesh->faces.first; efa; efa=efa->next){
6479 if(efa->f1 == testflag){
6480 if(efa->f&SELECT) EM_select_face(efa, 0);
6481 else EM_select_face(efa,1);
6487 for(efa=G.editMesh->faces.first; efa; efa=efa->next){ /*fix this*/
6488 if(efa->f&SELECT) EM_select_face(efa,1);
6491 countall();
6492 freecollections(&allcollections);
6493 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
6494 allqueue(REDRAWVIEW3D, 0);
6495 BIF_undo_push("Edge Loop to Face Region");