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
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
48 #include "MEM_guardedalloc.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"
64 #include "BLI_ghash.h"
65 #include "BLI_linklist.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_customdata.h"
70 #include "BKE_global.h"
71 #include "BKE_library.h"
73 #include "BKE_object.h"
74 #include "BKE_utildefines.h"
77 #include "BKE_verse.h"
80 #include "BIF_cursors.h"
81 #include "BIF_editmesh.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"
94 #include "BIF_verse.h"
97 #include "BDR_drawobject.h"
98 #include "BDR_editobject.h"
100 #include "BSE_view.h"
101 #include "BSE_edit.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
{
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;
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;
150 /* *********************************** */
152 void convert_to_triface(int direction
)
154 EditMesh
*em
= G
.editMesh
;
155 EditFace
*efa
, *efan
, *next
;
158 if(multires_test()) return;
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);
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
);
188 EM_fgon_flags(); // redo flags and indices for fgons
191 if(G
.editMesh
->vnode
)
192 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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
;
208 int a
, b
, test
, amount
;
210 if(multires_test()) return 0;
212 /* flag 128 is cleared, count */
213 eve
= em
->verts
.first
;
217 if(eve
->h
==0 && (eve
->f
& flag
)) amount
++;
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
;
226 if(eve
->h
==0 && (eve
->f
& flag
)) {
227 sb
->x
= eve
->co
[0]+eve
->co
[1]+eve
->co
[2];
233 qsort(sortblock
, amount
, sizeof(xvertsort
), vergxco
);
235 /* test for doubles */
237 for(a
=0; a
<amount
; a
++) {
239 if( (eve
->f
& 128)==0 ) {
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 */
248 if( (v1
->f
& 128)==0 ) {
250 dist
= (float)fabs(v1
->co
[0]-eve
->co
[0]);
252 dist
= (float)fabs(v1
->co
[1]-eve
->co
[1]);
254 dist
= (float)fabs(v1
->co
[2]-eve
->co
[2]);
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
;
284 if( (eed
->v1
->f
& 128) || (eed
->v2
->f
& 128) ) {
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
);
292 if(e1
!=eed
) free_editedge(eed
);
298 /* first count amount of test faces */
299 efa
= (struct EditFace
*)em
->faces
.first
;
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
++;
312 /* test faces for double vertices, and if needed remove them */
313 efa
= (struct EditFace
*)em
->faces
.first
;
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
;
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;
333 if(test
==1 || test
==2) {
338 EM_data_interp_from_faces(efa
, NULL
, efa
, 0, 2, 3, 3);
342 else if(test
==8 || test
==16) {
347 BLI_remlink(&em
->faces
, efa
);
353 BLI_remlink(&em
->faces
, efa
);
360 /* set edge pointers */
361 efa
->e1
= findedgelist(efa
->v1
, efa
->v2
);
362 efa
->e2
= findedgelist(efa
->v2
, efa
->v3
);
364 efa
->e3
= findedgelist(efa
->v3
, efa
->v1
);
368 efa
->e3
= findedgelist(efa
->v3
, efa
->v4
);
369 efa
->e4
= findedgelist(efa
->v4
, efa
->v1
);
376 /* double faces: sort block */
377 /* count again, now all selected faces */
379 efa
= em
->faces
.first
;
382 if(faceselectedOR(efa
, 1)) {
390 /* double faces: sort block */
391 vsb
= vlsortblock
= MEM_mallocN(sizeof(struct facesort
)*amount
, "sortremovedoub");
392 efa
= em
->faces
.first
;
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
);
404 qsort(vlsortblock
, amount
, sizeof(struct facesort
), vergface
);
407 for(a
=0; a
<amount
; a
++) {
409 if( (efa
->f1
& 128)==0 ) {
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? */
419 if( (efa
->f1
& 128)==0 ) {
420 if( compareface(efa
, vsb
->efa
)) efa
->f1
|= 128;
429 MEM_freeN(vlsortblock
);
431 /* remove double faces */
432 efa
= (struct EditFace
*)em
->faces
.first
;
436 BLI_remlink(&em
->faces
, efa
);
443 /* remove double vertices */
445 eve
= (struct EditVert
*)em
->verts
.first
;
451 BLI_remlink(&em
->verts
, eve
);
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
);
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 */
480 xvertsort
*sortblock
;
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
)
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
;
499 BLI_remlink(&em
->verts
, eve
);
500 BLI_addtail(&tbase
, eve
);
504 addlisttolist(&em
->verts
, &tbase
);
506 MEM_freeN(sortblock
);
509 if(G
.editMesh
->vnode
)
510 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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
;
523 struct xvertsort
*sortblock
, *sb
, onth
, *newsort
;
527 if(multires_test()) return;
530 eve
= em
->verts
.first
;
533 if(eve
->f
& flag
) amount
++;
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
;
552 for(a
=0; a
<amount
; a
++, sb
++) {
553 b
= (int)(amount
*BLI_drand());
554 if(b
>=0 && b
<amount
) {
555 newsort
= sortblock
+b
;
562 /* make temporal listbase */
563 tbase
.first
= tbase
.last
= 0;
567 BLI_remlink(&em
->verts
, eve
);
568 BLI_addtail(&tbase
, eve
);
572 addlisttolist(&em
->verts
, &tbase
);
574 MEM_freeN(sortblock
);
576 if(G
.editMesh
->vnode
)
577 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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;
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");
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");
610 nr
= pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
613 if (G
.totfacesel
== 0) nr
= 0;
614 else if (G
.totfacesel
== 1) nr
= 1;
616 nr
= pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
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
);
627 error("No valid selection");
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");
645 initTransform(TFM_SHRINKFATTEN
, CTX_NO_PET
);
649 initTransform(TFM_TRANSLATION
, CTX_NO_PET
);
651 Mat4MulVecfl(G
.obedit
->obmat
, nor
);
652 VecSubf(nor
, nor
, G
.obedit
->obmat
[3]);
653 BIF_setSingleAxisConstraint(nor
, NULL
);
661 void split_mesh(void)
665 if(multires_test()) return;
667 if(okee(" Split ")==0) return;
671 /* make duplicate first */
672 adduplicateflag(SELECT
);
673 /* old faces have flag 128 set, delete them */
675 recalc_editnormals();
680 allqueue(REDRAWVIEW3D
, 0);
681 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
684 if(G
.editMesh
->vnode
)
685 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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};
698 if(multires_test()) return;
701 dvec
[0]= G
.vd
->persinv
[2][0];
702 dvec
[1]= G
.vd
->persinv
[2][1];
703 dvec
[2]= G
.vd
->persinv
[2][2];
709 /* base correction */
710 Mat3CpyMat4(bmat
, G
.obedit
->obmat
);
712 Mat3MulVecfl(tmat
, dvec
);
714 for(a
=0; a
<steps
; a
++) {
715 extrudeflag(SELECT
, nor
);
716 translateflag(SELECT
, dvec
);
719 recalc_editnormals();
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];
741 if(multires_test()) return;
743 /* imat and center and size */
744 Mat3CpyMat4(bmat
, G
.obedit
->obmat
);
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;
756 if(G
.scene
->toolsettings
->editbutflag
& B_CLOCKWISE
) phi
= -phi
;
759 n
[0]= G
.vd
->viewinv
[1][0];
760 n
[1]= G
.vd
->viewinv
[1][1];
761 n
[2]= G
.vd
->viewinv
[1][2];
763 n
[0]= G
.vd
->viewinv
[2][0];
764 n
[1]= G
.vd
->viewinv
[2][1];
765 n
[2]= G
.vd
->viewinv
[2][2];
769 q
[0]= (float)cos(phi
);
776 Mat3MulMat3(tmat
,cmat
,bmat
);
777 Mat3MulMat3(bmat
,imat
,tmat
);
779 if(mode
==0) if(G
.scene
->toolsettings
->editbutflag
& B_KEEPORIG
) adduplicateflag(1);
782 for(a
=0;a
<steps
;a
++) {
783 if(mode
==0) ok
= extrudeflag(SELECT
, nor
);
784 else adduplicateflag(SELECT
);
786 error("No valid vertices are selected");
789 rotateflag(SELECT
, cent
, bmat
);
791 Mat3MulVecfl(bmat
,dvec
);
792 translateflag(SELECT
, dvec
);
797 /* no vertices or only loose ones selected, remove duplicates */
798 eve
= em
->verts
.first
;
801 if(eve
->f
& SELECT
) {
802 BLI_remlink(&em
->verts
,eve
);
808 recalc_editnormals();
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;
824 float dvec
[3], nor
[3];
827 if(multires_test()) return;
830 eve
= em
->verts
.first
;
835 /* edges set flags in verts */
836 eed
= em
->edges
.first
;
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
++;
847 /* find two vertices with eve->f1==1, more or less is wrong */
848 eve
= em
->verts
.first
;
852 else if(v2
==0) v2
= eve
;
861 error("You have to select a string of connected vertices too");
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) {
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
;
891 if( (ed
->v1
->f
& SELECT
) || (ed
->v2
->f
& SELECT
) ) {
899 static void erase_faces(ListBase
*l
)
903 f
= (EditFace
*) l
->first
;
907 if( faceselectedOR(f
, SELECT
) ) {
915 static void erase_vertices(ListBase
*l
)
919 v
= (EditVert
*) l
->first
;
930 void delete_mesh(void)
932 EditMesh
*em
= G
.editMesh
;
933 EditFace
*efa
, *nextvl
;
934 EditVert
*eve
,*nextve
;
935 EditEdge
*eed
,*nexted
;
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");
947 str
= "Erase Vertices";
948 erase_edges(&em
->edges
);
949 erase_faces(&em
->faces
);
950 erase_vertices(&em
->verts
);
953 if(!EdgeLoopDelete())
956 str
= "Erase Edge Loop";
959 str
= "Erase Edges & Faces";
960 efa
= em
->faces
.first
;
963 /* delete only faces with 1 or more edges selected */
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
++;
970 BLI_remlink(&em
->faces
, efa
);
975 eed
= em
->edges
.first
;
978 if(eed
->f
& SELECT
) {
984 efa
= em
->faces
.first
;
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
++;
994 BLI_remlink(&em
->faces
, efa
);
1003 efa
= em
->faces
.first
;
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
++;
1013 BLI_remlink(&em
->faces
, efa
);
1018 eed
= em
->edges
.first
;
1021 if(eed
->f
& SELECT
) {
1027 /* to remove loose vertices: */
1028 eed
= em
->edges
.first
;
1030 if( eed
->v1
->f
& SELECT
) eed
->v1
->f
-=SELECT
;
1031 if( eed
->v2
->f
& SELECT
) eed
->v2
->f
-=SELECT
;
1034 eve
= em
->verts
.first
;
1037 if(eve
->f
& SELECT
) {
1038 BLI_remlink(&em
->verts
,eve
);
1047 delfaceflag(SELECT
);
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
));
1057 str
= "Erase Only Faces";
1058 efa
= em
->faces
.first
;
1061 if(efa
->f
& SELECT
) {
1062 BLI_remlink(&em
->faces
, efa
);
1069 EM_fgon_flags(); // redo flags and indices for fgons
1072 allqueue(REDRAWVIEW3D
, 0);
1073 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
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
;
1084 EditEdge
*eed
,*e1
,*nexted
;
1085 EditFace
*efa
,*nextvl
, *efan
;
1088 if(G
.obedit
==0 || (G
.obedit
->type
!=OB_MESH
)) return;
1089 if(multires_test()) return;
1093 /* copy all selected vertices */
1094 eve
= em
->verts
.first
;
1096 if(eve
->f
& SELECT
) {
1097 v1
= BLI_addfillvert(eve
->co
);
1100 v1
->xs
= 0; // used for counting edges
1104 /* copy all selected edges */
1105 eed
= em
->edges
.first
;
1107 if( (eed
->v1
->f
& SELECT
) && (eed
->v2
->f
& SELECT
) ) {
1108 e1
= BLI_addfilledge(eed
->v1
->tmp
.v
, eed
->v2
->tmp
.v
);
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
;
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
--;
1131 if(ok
) { /* there are faces selected */
1132 eed
= filledgebase
.first
;
1135 if(eed
->v1
->xs
<2 || eed
->v2
->xs
<2) {
1136 BLI_remlink(&filledgebase
,eed
);
1142 if(BLI_edgefill(0, (G
.obedit
&& G
.obedit
->actcol
)?(G
.obedit
->actcol
-1):0)) {
1143 efa
= fillfacebase
.first
;
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);
1158 allqueue(REDRAWVIEW3D
, 0);
1159 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
1162 if(G
.editMesh
->vnode
)
1163 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
1166 BIF_undo_push("Fill");
1169 /*-------------------------------------------------------------------------------*/
1170 /*--------------------------- Edge Based Subdivide ------------------------------*/
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
)
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
);
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];
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];
1218 if(rad
> 0.0) { /* subdivide sphere */
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
)
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
);
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];
1264 static void flipvertarray(EditVert
** arr
, short size
)
1269 for(i
=0; i
<size
/2; 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
;
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]);
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
;
1303 short start
=0, end
, left
, right
, vertsize
,i
;
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);}
1327 right
= (start
+3)%4;
1330 We should have something like this now
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 |---*---*---| |---*---|
1350 ------------- ---------
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
;
1359 hold
= addfacelist(verts
[(vertsize
-1)/2],v
[left
],v
[right
],NULL
, NULL
,NULL
);
1360 hold
->e1
->f2
|= EDGEINNER
;
1361 hold
->e3
->f2
|= EDGEINNER
;
1366 for(i
=0;i
<(vertsize
-1)/2;i
++) {
1367 hold
= addfacelist(verts
[i
],verts
[i
+1],v
[right
],NULL
,NULL
,NULL
);
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
);
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
;
1389 short start
=0, end
, op
, vertsize
,i
;
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);}
1413 We should have something like this now
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
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
;
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];
1459 short start
=0, end
, left
, right
, vertsize
,i
;
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);}
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
1497 We will fill this case like this or this depending on even or odd cuts
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
;
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];
1522 short start
=0, start2
=0, vertsize
,i
;
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
1551 start2 0|---*---*---|
1559 We will fill this case like this or this depending on even or odd cuts
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
;
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
;
1580 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1581 // hold->e1->h |= EM_FGON;
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
;
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];
1599 short start
=0, start2
=0, vertsize
,i
;
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
1629 start2 0|---*---*---|
1635 end2 3|-----------|op
1637 We will fill this case like this or this (warning horrible ascii art follows)
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
;
1652 hold
= addfacelist(op
,verts
[0][i
],verts
[0][i
+1],NULL
,NULL
,NULL
);
1653 hold
->e3
->f2
|= EDGEINNER
;
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
;
1663 short start
=0, start2
=0, vertsize
,i
;
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
1694 start2 0|---*---*---|
1700 end2 3|-----------|op
1702 We will fill this case like this or this (warning horrible ascii art follows)
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
);
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
;
1732 hold
= addfacelist(verts
[0][0],verts
[0][1],inner
[numcuts
-1],op
,NULL
,NULL
);
1733 hold
->e2
->f2
|= EDGEINNER
;
1736 hold
= addfacelist(op
,inner
[numcuts
-1],verts
[1][numcuts
],verts
[1][numcuts
+1],NULL
,NULL
);
1737 hold
->e2
->f2
|= EDGEINNER
;
1740 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1741 // hold->e1->h |= EM_FGON;
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
;
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
;
1756 //if(G.scene->toolsettings->editbutflag & B_AUTOFGON) {
1757 // hold->e1->h |= EM_FGON;
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];
1771 short start
=0, start2
=0, vertsize
,i
;
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
1798 start2 0|---*---*---|
1806 We will fill this case like this or this depending on even or odd cuts
1817 hold
= addfacelist(verts
[0][vertsize
-2],verts
[0][vertsize
-1],verts
[1][1],NULL
,NULL
,NULL
);
1818 hold
->e3
->f2
|= EDGEINNER
;
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
;
1829 static void fill_quad_triple(EditFace
*efa
, struct GHash
*gh
, int numcuts
)
1831 EditEdge
*cedge
[3]={0};
1832 EditVert
*v
[4], **verts
[3];
1834 short start
=0, start2
=0, start3
=0, vertsize
, i
, repeats
;
1841 if(!(efa
->e1
->f
& SELECT
)) {
1845 start
= 1;start2
= 2;start3
= 3;
1847 if(!(efa
->e2
->f
& SELECT
)) {
1851 start
= 2;start2
= 3;start3
= 0;
1853 if(!(efa
->e3
->f
& SELECT
)) {
1857 start
= 3;start2
= 0;start3
= 1;
1859 if(!(efa
->e4
->f
& SELECT
)) {
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
1884 start3 0|---*---*---|3
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
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
1920 |---*---*---*---*---|
1928 *-------------------*
1932 *-------------------*
1936 *-------------------*
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
;
1948 hold
= addfacelist(verts
[1][vertsize
-2],verts
[1][vertsize
-1],verts
[2][1],NULL
,NULL
,NULL
);
1949 hold
->e3
->f2
|= EDGEINNER
;
1952 hold
= addfacelist(verts
[0][0],verts
[0][1],verts
[2][vertsize
-2],verts
[2][vertsize
-1],NULL
,NULL
);
1953 hold
->e2
->f2
|= EDGEINNER
;
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
;
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;
1967 repeats
= (numcuts
/ 2) -1;
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;
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
;
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
;
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
);
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
;
2003 static void fill_quad_quadruple(EditFace
*efa
, struct GHash
*gh
, int numcuts
, float rad
, int beauty
)
2005 EditVert
**verts
[4], ***innerverts
;
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
2042 // we will fill a 2 dim array of editvert*s to make filling easier
2043 // the innervert order is shown
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
);
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
; }
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
;
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
2136 we will fill a 2 dim array of editvert*s to make filling easier
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
;}
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
);
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
){
2211 Depending on which two vertices have been knifed through (v1 and v2), we
2212 triangulate like the patterns below.
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
);
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
;
2257 short start
=0, end
, left
, right
, vertsize
;
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
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);}
2281 right
= (start
+3)%4;
2284 We should have something like this now
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...
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
)
2353 if (beauty
& (B_PERCENTSUBD
) && totpoint
== 1)
2354 //percent=(float)(edge->tmp.l)/32768.0f;
2355 percent
= edge
->tmp
.fp
;
2357 percent
= (float)curpoint
/(float)(totpoint
+1);
2359 ev
= subdivide_edge_addvert(edge
, rad
, beauty
, percent
);
2360 ev
->f
= edge
->v1
->f
;
2365 void esubdivideflag(int flag
, float rad
, int beauty
, int numcuts
, int seltype
)
2367 EditMesh
*em
= G
.editMesh
;
2369 EditEdge
*eed
, *cedge
, *sort
[4];
2370 EditVert
**templist
;
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
) {
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;
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
) {
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
);
2423 // Beauty Short Edges
2424 if(beauty
& B_BEAUTY_SHORT
) {
2430 } else if(hold
== -1) {
2433 if(length
[hold
] < length
[i
]) {
2438 sort
[hold
]->f
&= ~SELECT
;
2439 sort
[hold
]->f2
|= EDGENEW
;
2444 // Beauty Long Edges
2451 } else if(hold
== -1) {
2454 if(length
[hold
] > length
[i
]) {
2459 sort
[hold
]->f
&= ~SELECT
;
2460 sort
[hold
]->f2
|= EDGENEW
;
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
) {
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
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
) {
2508 if(ef
->e1
->f
& flag
) {edgecount
++;}
2509 if(ef
->e2
->f
& flag
) {edgecount
++;}
2510 if(ef
->e3
->f
& flag
) {edgecount
++;}
2513 if(ef
->e4
->f
& flag
) {edgecount
++;}
2518 if(beauty
& B_KNIFE
&& numcuts
== 1){
2519 /*Test for when knifing through two opposite verts but no edges*/
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
){
2528 fill_quad_doublevert(ef
, 1, 3);
2530 else if(ef
->v2
->f1
&& ef
->v4
->f1
){
2532 fill_quad_doublevert(ef
, 2, 4);
2539 if(beauty
& B_KNIFE
&& numcuts
== 1){
2540 /*Test for when knifing through an edge and one vert*/
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
)) ){
2554 fill_quad_singlevert(ef
, gh
);
2558 fill_quad_single(ef
, gh
, numcuts
, seltype
);
2563 fill_quad_single(ef
, gh
, numcuts
, seltype
);
2568 fill_quad_single(ef
, gh
, numcuts
, seltype
);
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
);
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;
2586 case 3: ef
->f1
= SELECT
;
2587 fill_quad_triple(ef
, gh
, numcuts
);
2589 case 4: ef
->f1
= SELECT
;
2590 fill_quad_quadruple(ef
, gh
, numcuts
, rad
, beauty
);
2596 case 1: ef
->f1
= SELECT
;
2597 fill_tri_single(ef
, gh
, numcuts
, seltype
);
2599 case 2: ef
->f1
= SELECT
;
2600 fill_tri_double(ef
, gh
, numcuts
);
2602 case 3: ef
->f1
= SELECT
;
2603 fill_tri_triple(ef
, gh
, numcuts
, rad
, beauty
);
2609 // Delete Old Edges and Faces
2610 for(eed
= em
->edges
.first
;eed
;eed
= eed
->next
) {
2611 if(BLI_ghash_haskey(gh
,eed
)) {
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
) {
2623 EM_select_edge(eed
,1);
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
) {
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
;
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
){
2646 EM_select_edge(eed
,1);
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
){
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
){
2677 if(ef
->e4
) ef
->e4
->h
&= ~1;
2681 // Free the ghash and call MEM_freeN on all the value entries to return
2683 BLI_ghash_free(gh
, NULL
, (GHashValFreeFP
)MEM_freeN
);
2685 EM_selectmode_flush();
2686 for(ef
=em
->faces
.first
;ef
;ef
= ef
->next
) {
2688 if( (ef
->e1
->f
& SELECT
&& ef
->e2
->f
& SELECT
) &&
2689 (ef
->e3
->f
& SELECT
&& ef
->e4
->f
& SELECT
) ) {
2693 if( (ef
->e1
->f
& SELECT
&& ef
->e2
->f
& SELECT
) && ef
->e3
->f
& SELECT
) {
2699 recalc_editnormals();
2701 allqueue(REDRAWVIEW3D
, 0);
2702 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
2705 static int count_selected_edges(EditEdge
*ed
)
2710 if( ed
->f
& SELECT
) 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)
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
;
2731 /* run through edges, if selected, set pointer edge-> facearray */
2735 if( eed
->f
& SELECT
) {
2736 eed
->tmp
.p
= (EditVert
*) (&efaa
[i
]);
2739 else eed
->tmp
.p
= NULL
;
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
2753 if(efa
->v4
==0 && (efa
->f
& SELECT
)) { /* if selected triangle */
2757 if(e1
->f2
<3 && e1
->tmp
.p
) {
2759 evp
= (EVPtr
*) e1
->tmp
.p
;
2760 evp
[(int)e1
->f2
] = efa
;
2764 if(e2
->f2
<3 && e2
->tmp
.p
) {
2766 evp
= (EVPtr
*) e2
->tmp
.p
;
2767 evp
[(int)e2
->f2
]= efa
;
2771 if(e3
->f2
<3 && e3
->tmp
.p
) {
2773 evp
= (EVPtr
*) e3
->tmp
.p
;
2774 evp
[(int)e3
->f2
]= efa
;
2780 /* set to 3 to make sure these are not flipped or joined */
2784 if (efa
->e4
) efa
->e4
->f2
= 3;
2793 /* returns vertices of two adjacent triangles forming a quad
2794 - can be righthand or lefthand
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
) {
2816 else if VTEST(efa
, 2, efa1
) {
2822 else if VTEST(efa
, 3, efa1
) {
2829 if VTEST(efa1
, 1, efa
) {
2835 else if VTEST(efa1
, 2, efa
) {
2841 else if VTEST(efa1
, 3, efa
) {
2851 /* Helper functions for edge/quad edit features*/
2852 static void untag_edges(EditFace
*f
)
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
;
2870 BLI_remlink(&em
->faces
, efa
);
2874 /* avoid deleting edges that are still in use */
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
;
2898 // void **efaar, **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");
2926 ok
= collect_quadedges(efaar
, em
->edges
.first
, em
->faces
.first
);
2931 eed
= em
->edges
.first
;
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 */
2943 if(efa
->e1
->f1
|| efa
->e2
->f1
|| efa
->e3
->f1
) ok
= 0;
2944 if(efa
->fgonf
) ok
= 0;
2946 if(efa
->e1
->f1
|| efa
->e2
->f1
|| efa
->e3
->f1
) ok
= 0;
2947 if(efa
->fgonf
) ok
= 0;
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
) ) {
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
);
2997 if(dia2
.v1
==eed
->v1
&& dia2
.v2
==eed
->v2
) {
3004 w
= EM_face_from_faces(efaa
[0], efaa
[1],
3005 vindex
[0], vindex
[1], 4+vindex
[2], -1);
3009 w
= EM_face_from_faces(efaa
[0], efaa
[1],
3010 vindex
[0], 4+vindex
[2], 4+vindex
[3], -1);
3016 else if(fac1
< fac2
) {
3017 if(dia1
.v1
==eed
->v1
&& dia1
.v2
==eed
->v2
) {
3025 w
= EM_face_from_faces(efaa
[0], efaa
[1],
3026 vindex
[1], 4+vindex
[2], 4+vindex
[3], -1);
3030 w
= EM_face_from_faces(efaa
[0], efaa
[1],
3031 vindex
[0], 4+vindex
[1], 4+vindex
[3], -1);
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
3056 allqueue(REDRAWVIEW3D
, 0);
3057 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
3059 if(G
.editMesh
->vnode
)
3060 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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
);
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;
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
));
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*/
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*/
3146 fe1
[0] = eed
->v1
->f1
;
3147 fe1
[1] = eed
->v2
->f1
;
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*/
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*/
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
;
3171 if(flag
& B_JOINTRIA_VCOL
){
3172 if(!col1
|| !col2
) attrok
|= B_JOINTRIA_VCOL
;
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;
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;
3201 /*Bitflags for edges.*/
3203 #define T2QCOMPLEX 2
3205 void join_triangles(void)
3207 EditMesh
*em
=G
.editMesh
;
3208 EditVert
*v1
, *v2
, *v3
, *v4
, *eve
;
3209 EditEdge
*eed
, **edsortblock
= NULL
, **edb
= NULL
;
3211 EVPTuple
*efaar
= 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*/
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
;
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
);
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 */
3253 efaa
= (EVPtr
*) eed
->tmp
.p
;
3259 for(eed
=em
->edges
.first
; eed
; eed
=eed
->next
){
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
) ){
3269 efaa
[0]->f1
= 1; //mark for join
3270 efaa
[1]->f1
= 1; //mark for join
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*/
3297 measure
= measure_facepair(v1
, v2
, v3
, v4
, limit
);
3298 if(measure
< limit
){
3300 eed
->f1
|= T2QCOMPLEX
;
3301 eed
->crease
= measure
; /*we dont mark edges for join yet*/
3309 /*Quicksort the complex edges according to their weighting*/
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
){
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.*/
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);
3351 /*free data and cleanup*/
3353 for(eed
=em
->edges
.first
, i
= 0; eed
; eed
=eed
->next
, i
++) eed
->crease
= creases
[i
];
3356 for(eed
=em
->edges
.first
; eed
; eed
=eed
->next
){
3357 if(eed
->f1
& T2QDELETE
) eed
->f1
= 1;
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();
3366 allqueue(REDRAWVIEW3D
, 0);
3367 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
3369 if(G
.editMesh
->vnode
)
3370 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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
;
3386 //void **efaar, **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
;
3412 if(eed
->f2
==2) { /* points to 2 faces */
3414 efaa
= (EVPtr
*) eed
->tmp
.p
;
3416 /* don't do it if flagged */
3420 if(efa
->e1
->f1
|| efa
->e2
->f1
|| efa
->e3
->f1
) ok
= 0;
3422 if(efa
->e1
->f1
|| efa
->e2
->f1
|| efa
->e3
->f1
) ok
= 0;
3426 givequadverts(efaa
[0], efaa
[1], &v1
, &v2
, &v3
, &v4
, vindex
);
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]);
3458 } /* endif test convex */
3465 /* clear tagged edges and faces: */
3466 free_tagged_edges_faces(em
->edges
.first
, em
->faces
.first
);
3470 allqueue(REDRAWVIEW3D
, 0);
3471 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
3473 if(G
.editMesh
->vnode
)
3474 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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 */
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 */
3498 face
[facecount
] = efa
;
3507 /* how many edges does each face have */
3508 if(face
[0]->e4
) fac1
= 4;
3511 if(face
[1]->e4
) fac2
= 4;
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 */
3522 for(i
=0; i
<fac1
; i
++)
3523 for(j
=0; j
<fac2
; j
++)
3524 if (edges
[0][i
] == edges
[1][j
])
3530 /* coplaner faces only please */
3531 if(Inpf(face
[0]->n
,face
[1]->n
) <= 0.000001)
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 */
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
)
3550 if((p3
+1)%fac2
== 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 */
3560 for(srchedge
= em
->edges
.first
;srchedge
;srchedge
= srchedge
->next
)
3561 if(srchedge
->h
&& ((srchedge
->v1
->f
& SELECT
) || (srchedge
->v2
->f
& SELECT
)))
3564 hiddenedges
= MEM_mallocN(sizeof(EditVert
*)*numhidden
+1, "RotateEdgeHiddenVerts");
3566 error("Malloc Was not happy!");
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) {
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) {
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) {
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
;
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
)
3647 MEM_freeN(hiddenedges
);
3649 /* get rid of the old edge and faces*/
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
)
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
) {
3669 if(eed
->f
& SELECT
) edgeCount
++;
3673 /* more selected edges, check faces */
3674 for(efa
= G
.editMesh
->faces
.first
; efa
; efa
= efa
->next
) {
3675 if(efa
->f
& SELECT
) {
3679 if(efa
->e4
) efa
->e4
->f1
++;
3683 for(eed
= G
.editMesh
->edges
.first
; eed
; eed
= eed
->next
) {
3684 if(eed
->f1
==2) edgeCount
++;
3687 for(eed
= G
.editMesh
->edges
.first
; eed
; eed
= eed
->next
) {
3689 edge_rotate(eed
,dir
);
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
);
3705 else error("Select one edge or two adjacent faces");
3708 /* flush selected vertices (again) to edges/faces */
3711 allqueue(REDRAWVIEW3D
, 0);
3712 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
3715 if(G
.editMesh
->vnode
)
3716 sync_all_versefaces_with_editfaces((VNode
*)G
.editMesh
->vnode
);
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
;
3740 if (ac
== 1 || ac
== -1) {
3741 midvec
[0] = midvec
[1] = midvec
[2] = 0;
3745 fac
= (float)sqrt((ac2
+ 2*ac
+ 1)/(1 - ac2
) + 1);
3746 VecAddf(mid
, n_c
, n_a
);
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];
3769 s_b
= (float)sqrt(1 - (s_b
* s_b
));
3771 s_a
= (float)sqrt(1 - (s_a
* s_a
));
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
;
3782 VecAddf(Pos1
, v2
, c
);
3783 VecAddf(Pos2
, v3
, b
);
3785 VecAddf(Dir
, Pos1
, Pos2
);
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
);
3800 Crossf(o_c
, o_a
, no
);
3803 if (Inpf(c
, o_c
) <= 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
)
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
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
);
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
);
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
);
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
);
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
);
3852 VecAddf(vec
, v1
, v4
);
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
);
3863 VecAddf(vec
, v3
, v4
);
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
);
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
)) {
3889 VecAddf(vec
, o_v1
, o_v2
);
3890 VecAddf(vec
, vec
, o_v3
);
3891 VecMulf(vec
, 1.0f
/3.0f
);
3898 static void bevel_shrink_faces(float d
, int flag
)
3900 EditMesh
*em
= G
.editMesh
;
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
;
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
);
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
);
3939 static void bevel_shrink_draw(float d
, int flag
)
3941 EditMesh
*em
= G
.editMesh
;
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
;
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
);
3955 bevel_displace_vec(vec
, v2
, v3
, v1
, d
, no
);
3957 bevel_displace_vec(vec
, v3
, v1
, v2
, d
, no
);
3960 fix_bevel_tri_wrap(v1
, v2
, v3
, fv1
, fv2
, fv3
, no
);
3975 VECCOPY(v4
, efa
->v4
->co
);
3976 bevel_displace_vec(vec
, v4
, v1
, v2
, d
, no
);
3978 bevel_displace_vec(vec
, v1
, v2
, v3
, d
, no
);
3980 bevel_displace_vec(vec
, v2
, v3
, v4
, d
, no
);
3982 bevel_displace_vec(vec
, v3
, v4
, v1
, d
, no
);
3985 fix_bevel_quad_wrap(v1
, v2
, v3
, v4
, fv1
, fv2
, fv3
, fv4
, d
, no
);
4008 static void bevel_mesh(float bsize
, int allfaces
)
4010 EditMesh
*em
= G
.editMesh
;
4012 /* Enables debug printfs and assigns material indices: */
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];
4023 float limit
= 0.001f
;
4025 if(multires_test()) return;
4029 removedoublesflag(1, limit
);
4031 /* tag all original faces */
4032 efa
= em
->faces
.first
;
4035 if (faceselectedAND(efa
, 1)||allfaces
) {
4040 if (efa
->v4
) efa
->v4
->f
|= 128;
4045 if (efa
->v4
) efa
->v4
->f
&= ~64;
4051 fprintf(stderr
,"bevel_mesh: split\n");
4054 efa
= em
->faces
.first
;
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
;
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
,
4080 addedgelist(efa
->e2
->v1
->tmp
.v
,
4083 addedgelist(efa
->e3
->v1
->tmp
.v
,
4086 if (efa
->e4
) addedgelist(efa
->e4
->v1
->tmp
.v
,
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
);
4100 addfacelist(v1
, v2
, v3
, 0, efa
,NULL
);
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
;
4120 if (faceselectedAND(efa
, 1)||allfaces
) {
4127 fprintf(stderr
,"bevel_mesh: make edge quads\n");
4130 /* find edges that are on each other and make quads between them */
4132 eed
= em
->edges
.first
;
4134 eed
->f2
= eed
->f1
= 0;
4135 if ( ((eed
->v1
->f
& eed
->v2
->f
) & 1) || allfaces
)
4136 eed
->f1
|= 4; /* original edges */
4141 eed
= em
->edges
.first
;
4143 if ( ((eed
->f1
& 2)==0) && (eed
->f1
& 4) ) {
4144 eed2
= em
->edges
.first
;
4146 if ( (eed2
!= eed
) && ((eed2
->f1
& 2)==0) && (eed
->f1
& 4) ) {
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
) ) ) )
4159 fprintf(stderr
, "bevel_mesh: edge quad\n");
4162 eed
->f1
|= 2; /* these edges are finished */
4166 efa
= em
->faces
.first
; /* search example face (for mat_nr, ME_SMOOTH, ...) */
4168 if ( (efa
->e1
== eed
) ||
4171 (efa
->e4
&& (efa
->e4
== eed
)) ) {
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) {
4184 if (VecCompare(eed
->v1
->co
, eed2
->v2
->co
, limit
)) {
4185 efa
= addfacelist(neweve
[0], neweve
[1], neweve
[2], neweve
[3], example
,NULL
);
4187 efa
= addfacelist(neweve
[0], neweve
[2], neweve
[3], neweve
[1], example
,NULL
);
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
);
4198 } else fprintf(stderr
,"bevel_mesh: error creating face\n");
4203 if (eed2
) eed2
= eed2
->next
;
4209 eed
= em
->edges
.first
;
4211 eed
->f2
= eed
->f1
= 0;
4220 fprintf(stderr
,"bevel_mesh: find clusters\n");
4223 /* Look for vertex clusters */
4225 eve
= em
->verts
.first
;
4227 eve
->f
&= ~(64|128);
4232 /* eve->f: 128: first vertex in a list (->tmp.v) */
4233 /* 64: vertex is in a list */
4235 eve
= em
->verts
.first
;
4237 eve2
= em
->verts
.first
;
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"); */
4247 } else if ((eve
->f
& 64) == 0) {
4248 /* fprintf(stderr," *\n"); */
4249 if (eve3
) eve3
->tmp
.v
= eve2
;
4257 if (eve3
) eve3
->tmp
.v
= NULL
;
4264 fprintf(stderr
,"bevel_mesh: shrink faces\n");
4267 bevel_shrink_faces(bsize
, 2);
4270 fprintf(stderr
,"bevel_mesh: fill clusters\n");
4273 /* Make former vertex clusters faces */
4275 eve
= em
->verts
.first
;
4281 eve
= em
->verts
.first
;
4297 efa
= em
->faces
.first
; /* search example face */
4299 if ( (efa
->v1
== neweve
[0]) ||
4300 (efa
->v2
== neweve
[0]) ||
4301 (efa
->v3
== neweve
[0]) ||
4302 (efa
->v4
&& (efa
->v4
== neweve
[0])) ) {
4306 if (efa
) efa
= efa
->next
;
4309 fprintf(stderr
,"bevel_mesh: Making %d-gon\n", a
);
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
);
4323 eed
= em
->edges
.first
;
4327 if ((neweve
[b
]==eed
->v1
) || (neweve
[b
]==eed
->v2
)) c
++;
4329 if(exist_face(eed
->v1
, eed
->v2
, eve2
, 0)==0) {
4330 efa
= addfacelist(eed
->v1
, eed
->v2
, eve2
, 0, example
,NULL
);
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
);
4353 if(exist_face(neweve
[0], neweve
[1], neweve
[2], 0)==0)
4354 efa
= addfacelist(neweve
[0], neweve
[1], neweve
[2], 0, example
, NULL
);
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
);
4370 eve
= em
->verts
.first
;
4373 eve
->f
&= ~(128|64);
4378 recalc_editnormals();
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 */
4392 static void bevel_mesh_recurs(float bsize
, short recurs
, int allfaces
)
4398 for (nr
=0; nr
<recurs
; nr
++) {
4399 bevel_mesh(d
, allfaces
);
4400 if (nr
==0) d
/= 3; else d
/= 2;
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))
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;
4445 if (G
.qual
& LR_CTRLKEY
)
4446 drawd
= (float) floor(drawd
* 10.0f
)/10.0f
;
4447 if (G
.qual
& LR_SHIFTKEY
)
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 */
4457 /* make a copy, for safety */
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 */
4470 sprintf(str
, "Bevel Size: %.4f LMB to confirm, RMB to cancel, SPACE to input directly.", drawd
);
4473 /* this also verifies other area/windows for clean swap */
4474 screen_swapbuffers();
4478 glDrawBuffer(GL_FRONT
);
4480 BIF_ThemeColor(TH_WIRE
);
4483 glBegin(GL_LINE_STRIP
);
4490 bglFlush(); // flush display for frontbuffer
4491 glDrawBuffer(GL_BACK
);
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
)
4503 else if (val
&& event
==SPACEKEY
) {
4504 if (fbutton(&d
, 0.000, 10.000, 10, 0, "Width:")!=0) {
4510 /* On any other keyboard event, recalc */
4517 SetBlenderCursor(BC_WAITCURSOR
);
4518 bevel_mesh_recurs(drawd
/fac
, recurs
, 1);
4520 SetBlenderCursor(SYSCURSOR
);
4521 BIF_undo_push("Bevel");
4525 /* *********** END BEVEL *********/
4527 typedef struct SlideVert
{
4532 int EdgeLoopDelete(void) {
4533 if(!EdgeSlide(1, 1)) {
4537 removedoublesflag(1,0.001);
4539 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
4543 int EdgeSlide(short immediate
, float imperc
)
4545 EditMesh
*em
= G
.editMesh
;
4547 EditEdge
*eed
,*first
=NULL
,*last
=NULL
, *temp
= NULL
;
4548 EditVert
*ev
, *nearest
;
4549 LinkNode
*edgelist
= NULL
, *vertlist
=NULL
, *look
;
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;
4556 short event
, draw
=1;
4557 short mval
[2], mvalo
[2];
4561 view3d_get_object_project_mat(curarea
, G
.obedit
, projectMat
, viewMat
);
4563 mvalo
[0] = -1; mvalo
[1] = -1;
4566 // Get number of selected edges and clear some flags
4567 for(eed
=em
->edges
.first
;eed
;eed
=eed
->next
) {
4570 if(eed
->f
& SELECT
) numsel
++;
4573 for(ev
=em
->verts
.first
;ev
;ev
=ev
->next
) {
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
) {
4581 if(efa
->e1
->f
& SELECT
) {
4584 if(efa
->e1
->f1
> 2) {
4585 error("3+ face edge");
4589 if(efa
->e2
->f
& SELECT
) {
4592 if(efa
->e2
->f1
> 2) {
4593 error("3+ face edge");
4597 if(efa
->e3
->f
& SELECT
) {
4600 if(efa
->e3
->f1
> 2) {
4601 error("3+ face edge");
4605 if(efa
->e4
&& efa
->e4
->f
& SELECT
) {
4608 if(efa
->e4
->f1
> 2) {
4609 error("3+ face edge");
4613 // Make sure loop is not 2 edges of same face
4615 error("loop crosses itself");
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");
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
4635 BLI_linklist_prepend(&edgelist
,eed
);
4641 if(editedge_getSharedVert(eed
, last
)) {
4642 BLI_linklist_append(&edgelist
,eed
);
4646 } else if(editedge_getSharedVert(eed
, first
)) {
4647 BLI_linklist_prepend(&edgelist
,eed
);
4654 if(eed
->next
== NULL
&& numadded
!= numsel
) {
4655 eed
=em
->edges
.first
;
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");
4667 // Put the verts in order in a linklist
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
);
4680 BLI_linklist_append(&vertlist
,eed
->v2
);
4684 //This is the case that we only have 1 edge
4685 BLI_linklist_append(&vertlist
,eed
->v1
);
4689 // for all the entries
4690 if(eed
->v1
->f1
!= 1) {
4691 BLI_linklist_append(&vertlist
,eed
->v1
);
4693 } else if(eed
->v2
->f1
!= 1) {
4694 BLI_linklist_append(&vertlist
,eed
->v2
);
4700 // populate the SlideVerts
4702 vertgh
= BLI_ghash_new(BLI_ghashutil_ptrhash
, BLI_ghashutil_ptrcmp
);
4708 tempsv
= (struct SlideVert
*)MEM_mallocN(sizeof(struct SlideVert
),"SlideVert");
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
) {
4723 if(eed
->f
& SELECT
) {
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
)) {
4735 } else if (!(tempsv
->down
)) {
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
) {
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
) {
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
) {
4764 tempsv
->up
= efa
->e3
;
4765 } else if (!(tempsv
->down
)) {
4766 tempsv
->down
= efa
->e3
;
4770 if(editedge_containsVert(efa
->e4
, ev
) && efa
->e4
!= eed
) {
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
);
4790 BLI_ghash_insert(vertgh
,ev
,tempsv
);
4795 // make sure the UPs nad DOWNs are 'faceloops'
4796 // Also find the nearest slidevert to the cursor
4797 getmouseco_areawin(mval
);
4802 if(look
->next
!= NULL
) {
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
);
4816 if(G
.f
& G_DRAW_EDGELEN
) {
4817 if(!(tempsv
->up
->f
& SELECT
)) {
4818 tempsv
->up
->f
|= SELECT
;
4819 tempsv
->up
->f2
|= 16;
4821 tempsv
->up
->f2
|= ~16;
4823 if(!(tempsv
->down
->f
& SELECT
)) {
4824 tempsv
->down
->f
|= SELECT
;
4825 tempsv
->down
->f2
|= 16;
4827 tempsv
->down
->f2
|= ~16;
4832 float tempdist
, co
[2];
4834 if(!sharesFace(tempsv
->up
,sv
->up
)) {
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));
4846 vertdist
= tempdist
;
4847 nearest
= (EditVert
*)look
->link
;
4848 } else if ( tempdist
< vertdist
) {
4849 vertdist
= tempdist
;
4850 nearest
= (EditVert
*)look
->link
;
4859 // we should have enough info now to slide
4865 /* For the % calculation */
4869 EditVert
*centerVert
, *upVert
, *downVert
;
4873 getmouseco_areawin(mval
);
4875 if (!immediate
&& (mval
[0] == mvalo
[0] && mval
[1] == mvalo
[1])) {
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
));
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;}
4911 VecLerpf(ev
->co
, editedge_getOtherVert(tempsv
->down
,ev
)->co
, editedge_getOtherVert(tempsv
->up
,ev
)->co
, fabs(newlen
));
4913 VecLerpf(ev
->co
, editedge_getOtherVert(tempsv
->up
,ev
)->co
, editedge_getOtherVert(tempsv
->down
,ev
)->co
, fabs(newlen
));
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
);
4930 mymultmatrix(G
.obedit
->obmat
);
4932 glColor3ub(0, 255, 0);
4934 glVertex3fv(upVert
->co
);
4935 glVertex3fv(downVert
->co
);
4939 // draw start edge for non-prop
4942 glColor3ub(255,0,255);
4944 glVertex3fv(upVert
->co
);
4946 glVertex3fv(downVert
->co
);
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 */
4961 len
= rc
[0]*rc
[0]+ rc
[1]*rc
[1];
4962 if (len
==0) {len
= 0.0001;}
4964 if ((G
.qual
& LR_SHIFTKEY
)==0) {
4966 labda
= ( rc
[0]*((mval
[0]-v2
[0])) + rc
[1]*((mval
[1]-v2
[1])) )/len
;
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;
4986 } else if (G
.qual
== LR_CTRLKEY
) {
4992 sprintf(str
, "(P)ercentage: %f", perc
);
4994 len
= VecLenf(upVert
->co
,downVert
->co
)*((perc
+1)/2);
4996 len
= VecLenf(upVert
->co
,downVert
->co
) - len
;
4998 sprintf(str
, "Non (P)rop Length: %f, Press (F) to flip control side", len
);
5004 screen_swapbuffers();
5009 event
= extern_qread(&val
); // extern_qread stores important events for the mainloop to handle
5011 /* val==0 on key-release event */
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
5019 } else if(ELEM3(event
, PADENTER
, LEFTMOUSE
, RETKEY
)) {
5020 draw
= 0; // End looping now
5021 } else if(event
==MIDDLEMOUSE
) {
5024 } else if(event
==PKEY
) {
5025 (prop
== 1) ? (prop
= 0):(prop
= 1);
5027 } else if(event
==FKEY
) {
5028 (flip
== 1) ? (flip
= 0):(flip
= 1);
5030 } else if(ELEM(event
, RIGHTARROWKEY
, WHEELUPMOUSE
)) { // Scroll through Control Edges
5033 if(nearest
== (EditVert
*)look
->link
) {
5034 if(look
->next
== NULL
) {
5035 nearest
= (EditVert
*)vertlist
->link
;
5037 nearest
= (EditVert
*)look
->next
->link
;
5044 } else if(ELEM(event
, LEFTARROWKEY
, WHEELDOWNMOUSE
)) { // Scroll through Control Edges
5048 if(look
->next
->link
== nearest
) {
5049 nearest
= (EditVert
*)look
->link
;
5054 if((EditVert
*)vertlist
->link
== nearest
) {
5055 nearest
= look
->link
;
5068 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
5072 if(G
.f
& G_DRAW_EDGELEN
) {
5075 tempsv
= BLI_ghash_lookup(vertgh
,(EditVert
*)look
->link
);
5076 if(tempsv
!= NULL
) {
5077 tempsv
->up
->f
&= !SELECT
;
5078 tempsv
->down
->f
&= !SELECT
;
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
);
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
);
5107 /* -------------------- More tools ------------------ */
5109 void mesh_set_smooth_faces(short event
)
5111 EditMesh
*em
= G
.editMesh
;
5114 if(G
.obedit
==0) return;
5116 if(G
.obedit
->type
!= OB_MESH
) return;
5118 efa
= em
->faces
.first
;
5120 if(efa
->f
& SELECT
) {
5121 if(event
==1) efa
->flag
|= ME_SMOOTH
;
5122 else if(event
==0) efa
->flag
&= ~ME_SMOOTH
;
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
);
5159 sefa
->e3
= addedgelist(sefa
->v3
, sefa
->v4
, sefa
->e3
);
5160 sefa
->e4
= addedgelist(sefa
->v4
, sefa
->v1
, sefa
->e4
);
5163 sefa
->e3
= addedgelist(sefa
->v3
, sefa
->v1
, sefa
->e3
);
5167 /* based on mouse cursor position, it defines how is being ripped */
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
) {
5194 if(efa
->v4
&& faceselectedOR(efa
, SELECT
) ) {
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
++;
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]) );
5214 error("Can't perform ripping with faces selected this way");
5218 error("No proper selection or faces included");
5223 /* duplicate vertices, new vertices get selected */
5224 for(eve
= em
->verts
.last
; eve
; eve
= eve
->prev
) {
5226 if(eve
->f
& SELECT
) {
5227 eve
->tmp
.v
= addvertlist(eve
->co
, eve
);
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 */
5242 mindist
= 1000000.0f
;
5243 if(sefa
->e1
->v1
->tmp
.v
|| sefa
->e1
->v2
->tmp
.v
) {
5244 dist
= mesh_rip_edgedist(projectMat
,
5246 sefa
->e1
->v2
->co
, mval
);
5252 if(sefa
->e2
->v1
->tmp
.v
|| sefa
->e2
->v2
->tmp
.v
) {
5253 dist
= mesh_rip_edgedist(projectMat
,
5255 sefa
->e2
->v2
->co
, mval
);
5261 if(sefa
->e3
->v1
->tmp
.v
|| sefa
->e3
->v2
->tmp
.v
) {
5262 dist
= mesh_rip_edgedist(projectMat
,
5264 sefa
->e3
->v2
->co
, mval
);
5270 if(sefa
->e4
&& (sefa
->e4
->v1
->tmp
.v
|| sefa
->e4
->v2
->tmp
.v
)) {
5271 dist
= mesh_rip_edgedist(projectMat
,
5273 sefa
->e4
->v2
->co
, mval
);
5281 if(seed
==NULL
) { // never happens?
5282 error("No proper edge found to start");
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
) {
5291 if((eed
->v1
->tmp
.v
) || (eed
->v2
->tmp
.v
)) {
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
) {
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 */
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 */
5322 mesh_rip_setface(efa
);
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
) {
5337 if(efa
->e4
) efa
->e4
->f1
= 1;
5340 for(eed
= em
->edges
.last
; eed
; eed
= seed
) {
5343 if(eed
->v1
->tmp
.v
|| eed
->v2
->tmp
.v
||
5344 (eed
->v1
->f
& SELECT
) || (eed
->v2
->f
& SELECT
)) {
5356 /* and remove loose selected vertices, that got duplicated accidentally */
5357 for(eve
= em
->verts
.first
; eve
; eve
= nextve
) {
5359 if(eve
->f1
==0 && (eve
->tmp
.v
|| (eve
->f
& SELECT
))) {
5360 BLI_remlink(&em
->verts
,eve
);
5365 countall(); // apparently always needed when adding stuff, derived mesh
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
);
5374 BIF_TransformSetUndo("Rip");
5375 initTransform(TFM_TRANSLATION
, 0);
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
;
5387 KeyBlock
* kb
= NULL
;
5394 error("Object Has No Key");
5398 if(ky
->block
.first
){
5399 for(ev
= em
->verts
.first
; ev
; ev
= ev
->next
){
5401 for(kb
=ky
->block
.first
;kb
;kb
= kb
->next
){
5404 VECCOPY(data
+(ev
->keyindex
*3),ev
->co
);
5409 error("Object Has No Blendshapes");
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);
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 ;
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])
5449 else if(mval
[0] < curval
[0])
5452 if(perc
< 0) perc
= 0;
5453 if(perc
> 1) perc
= 1;
5455 curval
[0] = mval
[0];
5456 curval
[1] = mval
[1];
5462 for(ev
= em
->verts
.first
; ev
; ev
= ev
->next
){
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
);
5482 event
= extern_qread(&val
);
5484 if(ELEM3(event
, PADENTER
, LEFTMOUSE
, RETKEY
)){
5487 else if (event
== MIDDLEMOUSE
){
5490 else if (ELEM3(event
,ESCKEY
,RIGHTMOUSE
,RIGHTMOUSE
)){
5498 BIF_undo_push("Copy Blendshape Verts");
5500 for(ev
= em
->verts
.first
; ev
; ev
= ev
->next
){
5502 VECCOPY(ev
->co
, odata
+(ev
->keyindex
*3));
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
;
5518 KeyBlock
*kb
= NULL
,*thisBlock
= NULL
;
5519 int maxlen
=32, nr
=0, a
=0;
5525 error("Object Has No Key");
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){
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
);
5547 nr
= pupmenu_col(menu
, 20);
5550 error("Object Has No Blendshapes");
5556 for(kb
=ky
->block
.first
;kb
;kb
= kb
->next
){
5559 for(ev
= em
->verts
.first
;ev
;ev
= ev
->next
){
5563 if(me
->totvert
!= totverts
){
5564 error("Shape Has had Verts Added/Removed, please cycle editmode before copying");
5567 shape_copy_from_lerp(thisBlock
,kb
);
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
;
5584 ListBase collectionbase
;
5587 typedef struct CollectedEdge
{
5588 struct CollectedEdge
*next
, *prev
;
5592 #define MERGELIMIT 0.000001
5594 static void build_edgecollection(ListBase
*allcollections
)
5597 Collection
*edgecollection
, *newcollection
;
5598 CollectedEdge
*newedge
;
5601 short ebalanced
= 0;
5602 short collectionfound
= 0;
5604 for (eed
=G
.editMesh
->edges
.first
; eed
; eed
= eed
->next
){
5611 for(eed
=G
.editMesh
->edges
.first
; eed
; eed
=eed
->next
){
5613 eed
->v1
->tmp
.l
= currtag
;
5614 eed
->v2
->tmp
.l
= currtag
;
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){
5622 for(eed
=G
.editMesh
->edges
.first
; eed
; eed
= eed
->next
){
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
;
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
){
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");
5645 BLI_addtail(&(edgecollection
->collectionbase
), newedge
);
5646 collectionfound
= 1;
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");
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.
5684 struct wUV
*next
, *prev
;
5686 float u
, v
; /*cached copy of UV coordinates pointed to by nodes*/
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*/
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*/
5705 typedef struct wUVEdgeCollect
{ /*used for grouping*/
5706 struct wUVEdgeCollect
*next
, *prev
;
5711 static void append_weldedUV(EditFace
*efa
, EditVert
*eve
, int tfindex
, ListBase
*uvverts
)
5713 wUV
*curwvert
, *newwvert
;
5716 MTFace
*tf
= CustomData_em_get(&G
.editMesh
->fdata
, efa
->data
, CD_MTFACE
);
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
);
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
)
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
);
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]){
5779 break; //do nothing, we don't need another welded uv edge
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
)
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
;
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
;
5826 static void free_weldedUVs(ListBase
*uvverts
)
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
;
5838 wUVEdgeCollect
*collectedwuve
, *newcollectedwuve
;
5839 Collection
*wuvecollection
, *newcollection
;
5840 int curtag
, balanced
, collectionfound
= 0, vcount
;
5843 if (!CustomData_has_layer(&G
.editMesh
->fdata
, CD_MTFACE
))
5846 uvverts
.first
= uvverts
.last
= uvedges
.first
= uvedges
.last
= allcollections
.first
= allcollections
.last
= NULL
;
5848 build_weldedUVs(&uvverts
);
5849 build_weldedUVEdges(&uvedges
, &uvverts
);
5853 for(curwedge
=uvedges
.first
; curwedge
; curwedge
=curwedge
->next
){
5854 curwedge
->v1
->f
= curtag
;
5855 curwedge
->v2
->f
= curtag
;
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
;
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;
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];
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
)
5945 if (!CustomData_has_layer(&G
.editMesh
->fdata
, CD_MTFACE
))
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];
5960 if(efa
->v2
->f1
&& ELEM(mergevert
, NULL
, efa
->v2
)){
5961 uvav
[0] += tf
->uv
[1][0];
5962 uvav
[1] += tf
->uv
[1][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];
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];
5981 for(efa
= G
.editMesh
->faces
.first
; efa
; efa
=efa
->next
){
5982 tf
= CustomData_em_get(&G
.editMesh
->fdata
, efa
->data
, CD_MTFACE
);
5985 tf
->uv
[0][0] = uvav
[0];
5986 tf
->uv
[0][1] = uvav
[1];
5989 tf
->uv
[1][0] = uvav
[0];
5990 tf
->uv
[1][1] = uvav
[1];
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)
6009 ListBase allcollections
;
6010 CollectedEdge
*curredge
;
6011 Collection
*edgecollection
;
6013 int totedges
, groupcount
, mergecount
,vcount
;
6016 allcollections
.first
= 0;
6017 allcollections
.last
= 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;
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];
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
)) {
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;
6066 freecollections(&allcollections
);
6067 removedoublesflag(1, MERGELIMIT
);
6068 /*get rid of this!*/
6070 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
6071 allqueue(REDRAWVIEW3D
, 0);
6075 int merge_firstlast(int first
, int uvmerge
)
6077 EditVert
*eve
,*mergevert
;
6080 if(multires_test()) return 0;
6082 /* do sanity check in mergemenu in edit.c ?*/
6084 ese
= G
.editMesh
->selected
.last
;
6085 mergevert
= (EditVert
*)ese
->data
;
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
){
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
);
6109 return removedoublesflag(1,MERGELIMIT
);
6112 int merge_target(int target
, int uvmerge
)
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;
6130 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
6131 allqueue(REDRAWVIEW3D
, 0);
6132 return removedoublesflag(1,MERGELIMIT
);
6137 typedef struct PathNode
{
6143 typedef struct PathEdge
{
6144 struct PathEdge
*next
, *prev
;
6149 void pathselect(void)
6151 EditVert
*eve
, *s
, *t
;
6154 PathEdge
*newpe
, *currpe
;
6157 int v
, *previous
, pathvert
, pnindex
; /*pnindex redundant?*/
6158 int unbalanced
, totnodes
;
6161 Heap
*heap
; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/
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
){
6185 for(eed
=G
.editMesh
->edges
.first
; eed
; eed
=eed
->next
){
6187 if(eed
->v1
->f1
&& !eed
->v2
->f1
){
6192 else if(eed
->v2
->f1
&& !eed
->v1
->f1
){
6203 if(s
->f1
&& t
->f1
){ /*t can be reached by s*/
6204 Q
= MEM_callocN(sizeof(PathNode
)*totnodes
, "Path Select Nodes");
6206 for(eve
=G
.editMesh
->verts
.first
; eve
; eve
=eve
->next
){
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
]);
6215 else eve
->tmp
.p
= NULL
;
6218 for(eed
=G
.editMesh
->edges
.first
; eed
; eed
=eed
->next
){
6221 currpn
= ((PathNode
*)eed
->v1
->tmp
.p
);
6223 newpe
= MEM_mallocN(sizeof(PathEdge
), "Path Edge");
6224 newpe
->v
= ((PathNode
*)eed
->v2
->tmp
.p
)->u
;
6226 newpe
->w
= VecLenf(eed
->v1
->co
, eed
->v2
->co
);
6231 BLI_addtail(&(currpn
->edges
), newpe
);
6234 currpn
= ((PathNode
*)eed
->v2
->tmp
.p
);
6235 newpe
= MEM_mallocN(sizeof(PathEdge
), "Path Edge");
6236 newpe
->v
= ((PathNode
*)eed
->v1
->tmp
.p
)->u
;
6238 newpe
->w
= VecLenf(eed
->v1
->co
, eed
->v2
->co
);
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
++){
6254 previous
[v
] = -1; /*array of indices*/
6257 pnindex
= ((PathNode
*)s
->tmp
.p
)->u
;
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....*/
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
){
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
));
6294 MEM_freeN(previous
);
6295 BLI_heap_free(heap
, NULL
);
6298 DAG_object_flush_update(G
.scene
, G
.obedit
, OB_RECALC_DATA
);
6299 allqueue(REDRAWVIEW3D
, 0);
6303 error("Path Selection requires that exactly two vertices be selected");
6308 void region_to_loop(void)
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
){
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();
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
)
6346 CollectedEdge
*curredge
;
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);
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
){
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);
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;
6389 sed
= ((CollectedEdge
*)edgecollection
->collectionbase
.first
)->eed
;
6391 for(efa
=G
.editMesh
->faces
.first
; efa
; efa
=efa
->next
){
6394 if(efa
->e1
== sed
|| efa
->e2
== sed
|| efa
->e3
== sed
|| ( (efa
->e4
) ? efa
->e4
== sed
: 0) ) sf2
= efa
;
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
)
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;
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;
6422 for(efa
=G
.editMesh
->faces
.first
; efa
; efa
=efa
->next
){
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;
6444 for(efa
=G
.editMesh
->faces
.first
; efa
; efa
=efa
->next
){
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;
6462 if(totsf1
< totsf2
) return(1);
6466 void loop_to_region(void)
6469 ListBase allcollections
={NULL
,NULL
};
6470 Collection
*edgecollection
;
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);
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");