3 * ***** BEGIN GPL LICENSE BLOCK *****
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * The Original Code is Copyright (C) 2004 by Blender Foundation.
20 * All rights reserved.
22 * The Original Code is: all of this file.
24 * Contributor(s): Johnny Matthews, Geoffrey Bantle.
26 * ***** END GPL LICENSE BLOCK *****
31 editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise in mods.c
40 #include "MEM_guardedalloc.h"
43 #include "BLO_sys_types.h" // for intptr_t support
45 #include "DNA_mesh_types.h"
46 #include "DNA_material_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "DNA_modifier_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_screen_types.h"
52 #include "DNA_view3d_types.h"
53 #include "DNA_key_types.h"
54 #include "DNA_windowmanager_types.h"
56 #include "RNA_types.h"
57 #include "RNA_define.h"
58 #include "RNA_access.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_context.h"
69 #include "BKE_customdata.h"
70 #include "BKE_depsgraph.h"
71 #include "BKE_global.h"
72 #include "BKE_library.h"
74 #include "BKE_object.h"
75 #include "BKE_utildefines.h"
76 #include "BKE_bmesh.h"
77 #include "BKE_report.h"
80 #include "BIF_glutil.h"
88 #include "ED_view3d.h"
90 #include "ED_screen.h"
91 #include "BIF_transform.h"
93 #include "UI_interface.h"
95 #include "mesh_intern.h"
99 static int extern_qread() {return 0;}
100 static void waitcursor() {}
101 static int pupmenu() {return 0;}
102 static int qtest() {return 0;}
103 #define add_numbut(a, b, c, d, e, f, g) {}
104 static int snap_sel_to_curs() {return 0;}
105 static int snap_to_center() {return 0;}
109 /* local prototypes ---------------*/
110 static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa);
111 int EdgeLoopDelete(EditMesh *em, wmOperator *op);
113 /********* qsort routines *********/
116 typedef struct xvertsort {
121 static int vergxco(const void *v1, const void *v2)
123 const xvertsort *x1=v1, *x2=v2;
125 if( x1->x > x2->x ) return 1;
126 else if( x1->x < x2->x) return -1;
132 struct EditFace *efa;
136 static int vergface(const void *v1, const void *v2)
138 const struct facesort *x1=v1, *x2=v2;
140 if( x1->x > x2->x ) return 1;
141 else if( x1->x < x2->x) return -1;
146 /* *********************************** */
148 void convert_to_triface(EditMesh *em, int direction)
150 EditFace *efa, *efan, *next;
157 if(efa->f & SELECT) {
158 /* choose shortest diagonal for split */
159 fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co);
160 /* this makes sure exact squares get split different in both cases */
161 if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
162 efan= EM_face_from_faces(em, efa, NULL, 0, 1, 2, -1);
163 if(efa->f & SELECT) EM_select_face(efan, 1);
164 efan= EM_face_from_faces(em, efa, NULL, 0, 2, 3, -1);
165 if(efa->f & SELECT) EM_select_face(efan, 1);
168 efan= EM_face_from_faces(em, efa, NULL, 0, 1, 3, -1);
169 if(efa->f & SELECT) EM_select_face(efan, 1);
170 efan= EM_face_from_faces(em, efa, NULL, 1, 2, 3, -1);
171 if(efa->f & SELECT) EM_select_face(efan, 1);
174 BLI_remlink(&em->faces, efa);
175 free_editface(em, efa);
181 EM_fgon_flags(em); // redo flags and indices for fgons
186 int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /* return amount */
189 flag - Test with vert->flags
190 automerge - Alternative operation, merge unselected into selected.
191 Used for "Auto Weld" mode. warning.
192 limit - Quick manhattan distance between verts.
195 /* all verts with (flag & 'flag') are being evaluated */
196 EditVert *eve, *v1, *nextve;
197 EditEdge *eed, *e1, *nexted;
198 EditFace *efa, *nextvl;
199 xvertsort *sortblock, *sb, *sb1;
200 struct facesort *vlsortblock, *vsb, *vsb1;
201 int a, b, test, amount;
204 /* flag 128 is cleared, count */
206 /* Normal non weld operation */
207 eve= em->verts.first;
211 if(eve->h==0 && (automerge || (eve->f & flag))) amount++;
214 if(amount==0) return 0;
216 /* allocate memory and qsort */
217 sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
218 eve= em->verts.first;
220 if(eve->h==0 && (automerge || (eve->f & flag))) {
221 sb->x= eve->co[0]+eve->co[1]+eve->co[2];
227 qsort(sortblock, amount, sizeof(xvertsort), vergxco);
230 /* test for doubles */
233 for(a=0; a<amount; a++, sb++) {
235 if( (eve->f & 128)==0 ) {
237 for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) {
238 if(sb1->x - sb->x > limit) break;
240 /* when automarge, only allow unselected->selected */
242 if( (v1->f & 128)==0 ) {
243 if ((eve->f & flag)==0 && (v1->f & flag)==1) {
244 if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
245 (float)fabs(v1->co[1]-eve->co[1])<=limit &&
246 (float)fabs(v1->co[2]-eve->co[2])<=limit)
251 } else if( (eve->f & flag)==1 && (v1->f & flag)==0 ) {
252 if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
253 (float)fabs(v1->co[1]-eve->co[1])<=limit &&
254 (float)fabs(v1->co[2]-eve->co[2])<=limit)
265 for(a=0; a<amount; a++, sb++) {
267 if( (eve->f & 128)==0 ) {
269 for(b=a+1; b<amount; b++, sb1++) {
270 /* first test: simpel dist */
271 if(sb1->x - sb->x > limit) break;
274 /* second test: is vertex allowed */
275 if( (v1->f & 128)==0 ) {
276 if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
277 (float)fabs(v1->co[1]-eve->co[1])<=limit &&
278 (float)fabs(v1->co[2]-eve->co[2])<=limit)
288 MEM_freeN(sortblock);
291 for(eve = em->verts.first; eve; eve=eve->next)
292 if((eve->f & flag) && (eve->f & 128))
293 EM_data_interp_from_verts(em, eve, eve->tmp.v, eve->tmp.v, 0.5f);
295 /* test edges and insert again */
296 eed= em->edges.first;
306 if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
309 if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v;
310 if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v;
311 e1= addedgelist(em, eed->v1, eed->v2, eed);
318 if(e1!=eed) free_editedge(em, eed);
324 /* first count amount of test faces */
325 efa= (struct EditFace *)em->faces.first;
329 if(efa->v1->f & 128) efa->f1= 1;
330 else if(efa->v2->f & 128) efa->f1= 1;
331 else if(efa->v3->f & 128) efa->f1= 1;
332 else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1;
334 if(efa->f1==1) amount++;
338 /* test faces for double vertices, and if needed remove them */
339 efa= (struct EditFace *)em->faces.first;
344 if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v;
345 if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v;
346 if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v;
347 if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v;
350 if(efa->v1==efa->v2) test+=1;
351 if(efa->v2==efa->v3) test+=2;
352 if(efa->v3==efa->v1) test+=4;
353 if(efa->v4==efa->v1) test+=8;
354 if(efa->v3==efa->v4) test+=16;
355 if(efa->v2==efa->v4) test+=32;
359 if(test==1 || test==2) {
364 EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 3, 3);
368 else if(test==8 || test==16) {
373 BLI_remlink(&em->faces, efa);
374 free_editface(em, efa);
379 BLI_remlink(&em->faces, efa);
380 free_editface(em, efa);
386 /* set edge pointers */
387 efa->e1= findedgelist(em, efa->v1, efa->v2);
388 efa->e2= findedgelist(em, efa->v2, efa->v3);
390 efa->e3= findedgelist(em, efa->v3, efa->v1);
394 efa->e3= findedgelist(em, efa->v3, efa->v4);
395 efa->e4= findedgelist(em, efa->v4, efa->v1);
402 /* double faces: sort block */
403 /* count again, now all selected faces */
405 efa= em->faces.first;
408 if(faceselectedOR(efa, 1)) {
416 /* double faces: sort block */
417 vsb= vlsortblock= MEM_mallocN(sizeof(struct facesort)*amount, "sortremovedoub");
418 efa= em->faces.first;
421 if(efa->v4) vsb->x= (uintptr_t) MIN4( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3, (uintptr_t)efa->v4);
422 else vsb->x= (uintptr_t) MIN3( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3);
430 qsort(vlsortblock, amount, sizeof(struct facesort), vergface);
433 for(a=0; a<amount; a++) {
435 if( (efa->f1 & 128)==0 ) {
438 for(b=a+1; b<amount; b++) {
440 /* first test: same pointer? */
441 if(vsb->x != vsb1->x) break;
443 /* second test: is test permitted? */
445 if( (efa->f1 & 128)==0 ) {
446 if( compareface(efa, vsb->efa)) efa->f1 |= 128;
455 MEM_freeN(vlsortblock);
457 /* remove double faces */
458 efa= (struct EditFace *)em->faces.first;
462 BLI_remlink(&em->faces, efa);
463 free_editface(em, efa);
469 /* remove double vertices */
471 eve= (struct EditVert *)em->verts.first;
474 if(automerge || eve->f & flag) {
477 BLI_remlink(&em->verts, eve);
478 free_editvert(em, eve);
484 return a; /* amount */
487 static int removedoublesflag_exec(bContext *C, wmOperator *op)
489 Object *obedit= CTX_data_edit_object(C);
490 Scene *scene = CTX_data_scene(C);
491 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
494 int cnt = removedoublesflag(em,1,0,scene->toolsettings->doublimit);
498 sprintf(msg, "Removed %d vertices", cnt);
499 BKE_report(op->reports, RPT_INFO, msg);
502 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
504 return OPERATOR_FINISHED;
507 void MESH_OT_removedoublesflag(wmOperatorType *ot)
510 ot->name= "Remove Doubles";
511 ot->idname= "MESH_OT_removedoublesflag";
514 ot->exec= removedoublesflag_exec;
515 ot->poll= ED_operator_editmesh;
518 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
521 // XXX is this needed?
522 /* called from buttons */
523 static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index)
525 xvertsort *sortblock = userData;
527 sortblock[index].x = x;
530 /* all verts with (flag & 'flag') are sorted */
531 void xsortvert_flag(bContext *C, int flag)
535 xvertsort *sortblock;
539 em_setup_viewcontext(C, &vc);
541 amount = BLI_countlist(&vc.em->verts);
542 sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort");
543 for (i=0,eve= vc.em->verts.first; eve; i++,eve=eve->next)
545 sortblock[i].v1 = eve;
547 mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0);
548 qsort(sortblock, amount, sizeof(xvertsort), vergxco);
550 /* make temporal listbase */
551 tbase.first= tbase.last= 0;
552 for (i=0; i<amount; i++) {
553 eve = sortblock[i].v1;
556 BLI_remlink(&vc.em->verts, eve);
557 BLI_addtail(&tbase, eve);
561 addlisttolist(&vc.em->verts, &tbase);
563 MEM_freeN(sortblock);
567 /* called from buttons */
568 void hashvert_flag(EditMesh *em, int flag)
570 /* switch vertex order using hash table */
572 struct xvertsort *sortblock, *sb, onth, *newsort;
577 eve= em->verts.first;
580 if(eve->f & flag) amount++;
583 if(amount==0) return;
585 /* allocate memory */
586 sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub");
587 eve= em->verts.first;
599 for(a=0; a<amount; a++, sb++) {
600 b= (int)(amount*BLI_drand());
601 if(b>=0 && b<amount) {
602 newsort= sortblock+b;
609 /* make temporal listbase */
610 tbase.first= tbase.last= 0;
614 BLI_remlink(&em->verts, eve);
615 BLI_addtail(&tbase, eve);
619 addlisttolist(&em->verts, &tbase);
621 MEM_freeN(sortblock);
625 /* generic extern called extruder */
626 void extrude_mesh(Object *obedit, EditMesh *em, wmOperator *op)
628 Scene *scene= NULL; // XXX CTX!
629 float nor[3]= {0.0, 0.0, 0.0};
630 short nr, transmode= 0;
632 if(em->selectmode & SCE_SELECT_VERTEX) {
633 if(em->totvertsel==0) nr= 0;
634 else if(em->totvertsel==1) nr= 4;
635 else if(em->totedgesel==0) nr= 4;
636 else if(em->totfacesel==0)
637 nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
638 else if(em->totfacesel==1)
639 nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
641 nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
643 else if(em->selectmode & SCE_SELECT_EDGE) {
644 if (em->totedgesel==0) nr = 0;
647 /*else if (em->totedgesel==1) nr = 3;
648 else if(em->totfacesel==0) nr = 3;
649 else if(em->totfacesel==1)
650 nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
652 nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
656 if (em->totfacesel == 0) nr = 0;
657 else if (em->totfacesel == 1) nr = 1;
659 nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
664 if(nr==1) transmode= extrudeflag(obedit, em, SELECT, nor);
665 else if(nr==4) transmode= extrudeflag_verts_indiv(em, SELECT, nor);
666 else if(nr==3) transmode= extrudeflag_edges_indiv(em, SELECT, nor);
667 else transmode= extrudeflag_face_indiv(em, SELECT, nor);
670 BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
675 /* We need to force immediate calculation here because
676 * transform may use derived objects (which are now stale).
678 * This shouldn't be necessary, derived queries should be
679 * automatically building this data if invalid. Or something.
681 // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
682 object_handle_update(scene, obedit);
684 /* individual faces? */
685 // BIF_TransformSetUndo("Extrude");
687 // initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
691 // initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
693 Mat4MulVecfl(obedit->obmat, nor);
694 VecSubf(nor, nor, obedit->obmat[3]);
695 // BIF_setSingleAxisConstraint(nor, "along normal");
703 // XXX should be a menu item
704 static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
706 Object *obedit= CTX_data_edit_object(C);
707 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
709 extrude_mesh(obedit,em, op);
711 RNA_int_set(op->ptr, "mode", TFM_TRANSLATION);
712 WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
714 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
716 return OPERATOR_FINISHED;
719 /* extrude without transform */
720 static int mesh_extrude_exec(bContext *C, wmOperator *op)
722 Object *obedit= CTX_data_edit_object(C);
723 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
725 extrude_mesh(obedit,em, op);
727 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
729 return OPERATOR_FINISHED;
733 void MESH_OT_extrude(wmOperatorType *ot)
736 ot->name= "Extrude Mesh";
737 ot->idname= "MESH_OT_extrude";
740 ot->invoke= mesh_extrude_invoke;
741 ot->exec= mesh_extrude_exec;
742 ot->poll= ED_operator_editmesh;
745 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
747 /* to give to transform */
748 RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
751 static int split_mesh(bContext *C, wmOperator *op)
753 Object *obedit= CTX_data_edit_object(C);
754 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
758 /* make duplicate first */
759 adduplicateflag(em, SELECT);
760 /* old faces have flag 128 set, delete them */
761 delfaceflag(em, 128);
762 recalc_editnormals(em);
766 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
768 // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
769 return OPERATOR_FINISHED;
772 void MESH_OT_split_mesh(wmOperatorType *ot)
775 ot->name= "Split Mesh";
776 ot->idname= "MESH_OT_split_mesh";
779 ot->exec= split_mesh;
780 ot->poll= ED_operator_editmesh;
783 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
787 static int extrude_repeat_mesh(bContext *C, wmOperator *op)
789 Object *obedit= CTX_data_edit_object(C);
790 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
792 RegionView3D *rv3d = CTX_wm_region_view3d(C);
794 int steps = RNA_int_get(op->ptr,"steps");
796 float offs = RNA_float_get(op->ptr,"offset");
798 float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
802 dvec[0]= rv3d->persinv[2][0];
803 dvec[1]= rv3d->persinv[2][1];
804 dvec[2]= rv3d->persinv[2][2];
810 /* base correction */
811 Mat3CpyMat4(bmat, obedit->obmat);
813 Mat3MulVecfl(tmat, dvec);
815 for(a=0; a<steps; a++) {
816 extrudeflag(obedit, em, SELECT, nor);
817 translateflag(em, SELECT, dvec);
820 recalc_editnormals(em);
824 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
826 // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
827 return OPERATOR_FINISHED;
830 void MESH_OT_extrude_repeat(wmOperatorType *ot)
833 ot->name= "Extrude Repeat Mesh";
834 ot->idname= "MESH_OT_extrude_repeat";
837 ot->exec= extrude_repeat_mesh;
838 ot->poll= ED_operator_editmesh;
841 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
844 RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
845 RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
848 /* ************************** spin operator ******************** */
850 static int spin_mesh(bContext *C, float *dvec, int steps, float degr, int dupli )
852 Object *obedit= CTX_data_edit_object(C);
853 View3D *v3d = CTX_wm_view3d(C);
854 Scene *scene = CTX_data_scene(C);
855 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
856 RegionView3D *rv3d= CTX_wm_region_view3d(C);
857 EditVert *eve,*nextve;
858 float nor[3]= {0.0f, 0.0f, 0.0f};
859 float *curs, si, n[3], q[4], cmat[3][3], imat[3][3], tmat[3][3];
860 float cent[3], bmat[3][3];
864 /* imat and center and size */
865 Mat3CpyMat4(bmat, obedit->obmat);
868 curs= give_cursor(scene, v3d);
870 cent[0]-= obedit->obmat[3][0];
871 cent[1]-= obedit->obmat[3][1];
872 cent[2]-= obedit->obmat[3][2];
873 Mat3MulVecfl(imat, cent);
875 phi= degr*M_PI/360.0;
877 if(scene->toolsettings->editbutflag & B_CLOCKWISE) phi= -phi;
880 n[0]= rv3d->viewinv[1][0];
881 n[1]= rv3d->viewinv[1][1];
882 n[2]= rv3d->viewinv[1][2];
884 n[0]= rv3d->viewinv[2][0];
885 n[1]= rv3d->viewinv[2][1];
886 n[2]= rv3d->viewinv[2][2];
890 q[0]= (float)cos(phi);
897 Mat3MulMat3(tmat,cmat,bmat);
898 Mat3MulMat3(bmat,imat,tmat);
901 if(scene->toolsettings->editbutflag & B_KEEPORIG)
902 adduplicateflag(em, 1);
904 for(a=0; a<steps; a++) {
905 if(dupli==0) ok= extrudeflag(obedit, em, SELECT, nor);
906 else adduplicateflag(em, SELECT);
911 rotateflag(em, SELECT, cent, bmat);
913 Mat3MulVecfl(bmat,dvec);
914 translateflag(em, SELECT, dvec);
919 /* no vertices or only loose ones selected, remove duplicates */
920 eve= em->verts.first;
923 if(eve->f & SELECT) {
924 BLI_remlink(&em->verts,eve);
925 free_editvert(em, eve);
931 recalc_editnormals(em);
935 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
941 static int spin_mesh_exec(bContext *C, wmOperator *op)
943 Object *obedit= CTX_data_edit_object(C);
946 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
948 ok= spin_mesh(C, NULL, RNA_int_get(op->ptr,"steps"), RNA_float_get(op->ptr,"degrees"), RNA_boolean_get(op->ptr,"dupli"));
950 BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected");
951 return OPERATOR_CANCELLED;
953 return OPERATOR_FINISHED;
956 void MESH_OT_spin(wmOperatorType *ot)
960 ot->idname= "MESH_OT_spin";
963 ot->exec= spin_mesh_exec;
964 ot->poll= ED_operator_editmesh;
967 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
970 RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX);
971 RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
972 RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f);
975 static int screw_mesh_exec(bContext *C, wmOperator *op)
977 Object *obedit= CTX_data_edit_object(C);
978 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
979 EditVert *eve,*v1=0,*v2=0;
981 float dvec[3], nor[3];
984 turns= RNA_int_get(op->ptr, "turns");
985 steps= RNA_int_get(op->ptr, "steps");
988 for(eve= em->verts.first; eve; eve= eve->next)
991 /* edges set flags in verts */
992 for(eed= em->edges.first; eed; eed= eed->next) {
993 if(eed->v1->f & SELECT) {
994 if(eed->v2->f & SELECT) {
995 /* watch: f1 is a byte */
996 if(eed->v1->f1<2) eed->v1->f1++;
997 if(eed->v2->f1<2) eed->v2->f1++;
1001 /* find two vertices with eve->f1==1, more or less is wrong */
1002 for(eve= em->verts.first; eve; eve= eve->next) {
1004 if(v1==NULL) v1= eve;
1005 else if(v2==NULL) v2= eve;
1012 if(v1==NULL || v2==NULL) {
1013 BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too");
1014 return OPERATOR_CANCELLED;
1017 /* calculate dvec */
1018 dvec[0]= ( v1->co[0]- v2->co[0] )/steps;
1019 dvec[1]= ( v1->co[1]- v2->co[1] )/steps;
1020 dvec[2]= ( v1->co[2]- v2->co[2] )/steps;
1022 VECCOPY(nor, obedit->obmat[2]);
1024 if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) {
1030 if(spin_mesh(C, dvec, turns*steps, 360.0f*turns, 0)) {
1031 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1033 return OPERATOR_FINISHED;
1036 BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected");
1037 return OPERATOR_CANCELLED;
1041 void MESH_OT_screw(wmOperatorType *ot)
1045 ot->idname= "MESH_OT_screw";
1048 ot->exec= screw_mesh_exec;
1049 ot->poll= ED_operator_editmesh;
1052 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1055 RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256);
1056 RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256);
1059 static void erase_edges(EditMesh *em, ListBase *l)
1061 EditEdge *ed, *nexted;
1063 ed = (EditEdge *) l->first;
1066 if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) {
1068 free_editedge(em, ed);
1074 static void erase_faces(EditMesh *em, ListBase *l)
1076 EditFace *f, *nextf;
1078 f = (EditFace *) l->first;
1082 if( faceselectedOR(f, SELECT) ) {
1084 free_editface(em, f);
1090 static void erase_vertices(EditMesh *em, ListBase *l)
1092 EditVert *v, *nextv;
1094 v = (EditVert *) l->first;
1099 free_editvert(em, v);
1105 /* Note, these values must match delete_mesh() event values */
1106 static EnumPropertyItem prop_mesh_delete_types[] = {
1107 {10,"VERT", "Vertices", ""},
1108 {1, "EDGE", "Edges", ""},
1109 {2, "FACE", "Faces", ""},
1110 {3, "ALL", "All", ""},
1111 {4, "EDGE_FACE","Edges & Faces", ""},
1112 {5, "ONLY_FACE","Only Faces", ""},
1113 {6, "EDGE_LOOP","Edge Loop", ""},
1114 {7, "COLLAPSE","Collapse", ""},
1115 {0, NULL, NULL, NULL}
1118 static int delete_mesh_exec(bContext *C, wmOperator *op)
1120 Object *obedit= CTX_data_edit_object(C);
1121 EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
1122 EditFace *efa, *nextvl;
1123 EditVert *eve,*nextve;
1124 EditEdge *eed,*nexted;
1127 int event = RNA_enum_get(op->ptr, "type");
1132 str= "Erase Vertices";
1133 erase_edges(em, &em->edges);
1134 erase_faces(em, &em->faces);
1135 erase_vertices(em, &em->verts);
1138 BMesh *bm = editmesh_to_bmesh(em);
1143 BMO_Init_Op(&bmop, BMOP_DISSOLVE_VERTS);
1144 BMO_HeaderFlag_To_Slot(bm, &bmop, BMOP_DISVERTS_VERTIN,
1145 BM_SELECT, BM_VERT);
1146 BMO_Exec_Op(bm, &bmop);
1148 BMO_Finish_Op(bm, &bmop);
1150 if (BMO_GetError(bm, &errmsg, NULL)) {
1151 BKE_report(op->reports, RPT_ERROR, errmsg);
1153 return OPERATOR_CANCELLED;
1156 em2 = bmesh_to_editmesh(bm);
1157 set_editMesh(em, em2);
1162 if(!EdgeLoopDelete(em, op))
1165 str= "Erase Edge Loop";
1168 str= "Erase Edges & Faces";
1169 efa= em->faces.first;
1172 /* delete only faces with 1 or more edges selected */
1174 if(efa->e1->f & SELECT) count++;
1175 if(efa->e2->f & SELECT) count++;
1176 if(efa->e3->f & SELECT) count++;
1177 if(efa->e4 && (efa->e4->f & SELECT)) count++;
1179 BLI_remlink(&em->faces, efa);
1180 free_editface(em, efa);
1184 eed= em->edges.first;
1187 if(eed->f & SELECT) {
1189 free_editedge(em, eed);
1193 efa= em->faces.first;
1197 if( efa->v1->f & SELECT) event++;
1198 if( efa->v2->f & SELECT) event++;
1199 if( efa->v3->f & SELECT) event++;
1200 if(efa->v4 && (efa->v4->f & SELECT)) event++;
1203 BLI_remlink(&em->faces, efa);
1204 free_editface(em, efa);
1212 efa= em->faces.first;
1216 if( efa->e1->f & SELECT) event++;
1217 if( efa->e2->f & SELECT) event++;
1218 if( efa->e3->f & SELECT) event++;
1219 if(efa->e4 && (efa->e4->f & SELECT)) event++;
1222 BLI_remlink(&em->faces, efa);
1223 free_editface(em, efa);
1227 eed= em->edges.first;
1230 if(eed->f & SELECT) {
1232 free_editedge(em, eed);
1236 /* to remove loose vertices: */
1237 eed= em->edges.first;
1239 if( eed->v1->f & SELECT) eed->v1->f-=SELECT;
1240 if( eed->v2->f & SELECT) eed->v2->f-=SELECT;
1243 eve= em->verts.first;
1246 if(eve->f & SELECT) {
1247 BLI_remlink(&em->verts,eve);
1248 free_editvert(em, eve);
1256 delfaceflag(em, SELECT);
1260 if(em->verts.first) free_vertlist(em, &em->verts);
1261 if(em->edges.first) free_edgelist(em, &em->edges);
1262 if(em->faces.first) free_facelist(em, &em->faces);
1263 if(em->selected.first) BLI_freelistN(&(em->selected));
1266 str= "Erase Only Faces";
1267 efa= em->faces.first;
1270 if(efa->f & SELECT) {
1271 BLI_remlink(&em->faces, efa);
1272 free_editface(em, efa);
1278 EM_fgon_flags(em); // redo flags and indices for fgons
1280 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1282 return OPERATOR_FINISHED;
1285 void MESH_OT_delete(wmOperatorType *ot)
1289 ot->idname= "MESH_OT_delete";
1292 ot->invoke= WM_menu_invoke;
1293 ot->exec= delete_mesh_exec;
1295 ot->poll= ED_operator_editmesh;
1298 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1301 RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
1306 /*-------------------------------------------------------------------------------*/
1307 /*--------------------------- Edge Based Subdivide ------------------------------*/
1314 /*used by faceloop cut to select only edges valid for edge slide*/
1315 #define DOUBLEOPFILL 16
1317 /* calculates offset for co, based on fractal, sphere or smooth settings */
1318 static void alter_co(float *co, EditEdge *edge, float rad, int beauty, float perc)
1322 if(beauty & B_SMOOTH) {
1323 /* we calculate an offset vector vec1[], to be added to *co */
1324 float len, fac, nor[3], nor1[3], nor2[3];
1326 VecSubf(nor, edge->v1->co, edge->v2->co);
1327 len= 0.5f*Normalize(nor);
1329 VECCOPY(nor1, edge->v1->no);
1330 VECCOPY(nor2, edge->v2->no);
1333 fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
1335 vec1[0]= fac*nor1[0];
1336 vec1[1]= fac*nor1[1];
1337 vec1[2]= fac*nor1[2];
1340 fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
1342 vec1[0]+= fac*nor2[0];
1343 vec1[1]+= fac*nor2[1];
1344 vec1[2]+= fac*nor2[2];
1355 if(rad > 0.0) { /* subdivide sphere */
1361 else if(rad< 0.0) { /* fractal subdivide */
1362 fac= rad* VecLenf(edge->v1->co, edge->v2->co);
1363 vec1[0]= fac*(float)(0.5-BLI_drand());
1364 vec1[1]= fac*(float)(0.5-BLI_drand());
1365 vec1[2]= fac*(float)(0.5-BLI_drand());
1366 VecAddf(co, co, vec1);
1372 /* assumes in the edge is the correct interpolated vertices already */
1373 /* percent defines the interpolation, rad and beauty are for special options */
1374 /* results in new vertex with correct coordinate, vertex normal and weight group info */
1375 static EditVert *subdivide_edge_addvert(EditMesh *em, EditEdge *edge, float rad, int beauty, float percent)
1380 co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0];
1381 co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1];
1382 co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];
1384 /* offset for smooth or sphere or fractal */
1385 alter_co(co, edge, rad, beauty, percent);
1387 /* clip if needed by mirror modifier */
1389 if ( edge->v1->f2 & edge->v2->f2 & 1) {
1392 if ( edge->v1->f2 & edge->v2->f2 & 2) {
1395 if ( edge->v1->f2 & edge->v2->f2 & 4) {
1400 ev = addvertlist(em, co, NULL);
1402 /* vert data (vgroups, ..) */
1403 EM_data_interp_from_verts(em, edge->v1, edge->v2, ev, percent);
1406 ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0];
1407 ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1];
1408 ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2];
1414 static void flipvertarray(EditVert** arr, short size)
1419 for(i=0; i<size/2; i++) {
1421 arr[i] = arr[size-i-1];
1422 arr[size-i-1] = hold;
1426 static void facecopy(EditMesh *em, EditFace *source, EditFace *target)
1428 float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co;
1429 float *v4 = source->v4? source->v4->co: NULL;
1432 CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data);
1434 target->mat_nr = source->mat_nr;
1435 target->flag = source->flag;
1436 target->h = source->h;
1438 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]);
1439 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]);
1440 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]);
1442 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]);
1444 CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data);
1447 static void fill_quad_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
1449 EditEdge *cedge=NULL;
1450 EditVert *v[4], **verts;
1452 short start=0, end, left, right, vertsize,i;
1459 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
1460 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
1461 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
1462 else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
1464 // Point verts to the array of new verts for cedge
1465 verts = BLI_ghash_lookup(gh, cedge);
1466 //This is the index size of the verts array
1467 vertsize = numcuts+2;
1469 // Is the original v1 the same as the first vert on the selected edge?
1470 // if not, the edge is running the opposite direction in this face so flip
1471 // the array to the correct direction
1473 if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
1476 right = (start+3)%4;
1479 We should have something like this now
1490 where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
1491 and 0,1,2... are the indexes of the new verts stored in verts
1493 We will fill this case like this or this depending on even or odd cuts
1495 |---*---*---| |---*---|
1499 ------------- ---------
1503 if(vertsize % 2 == 0) {
1504 hold = addfacelist(em, verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
1505 hold->e2->f2 |= EDGEINNER;
1506 hold->e4->f2 |= EDGEINNER;
1508 hold = addfacelist(em, verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
1509 hold->e1->f2 |= EDGEINNER;
1510 hold->e3->f2 |= EDGEINNER;
1512 facecopy(em, efa,hold);
1515 for(i=0;i<(vertsize-1)/2;i++) {
1516 hold = addfacelist(em, verts[i],verts[i+1],v[right],NULL,NULL,NULL);
1517 facecopy(em, efa,hold);
1518 if(i+1 != (vertsize-1)/2) {
1519 if(seltype == SUBDIV_SELECT_INNER) {
1520 hold->e2->f2 |= EDGEINNER;
1523 hold = addfacelist(em, verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
1524 facecopy(em, efa,hold);
1525 if(i+1 != (vertsize-1)/2) {
1526 if(seltype == SUBDIV_SELECT_INNER) {
1527 hold->e3->f2 |= EDGEINNER;
1533 static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
1535 EditEdge *cedge=NULL;
1536 EditVert *v[3], **verts;
1538 short start=0, end, op, vertsize,i;
1544 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
1545 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
1546 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
1548 // Point verts to the array of new verts for cedge
1549 verts = BLI_ghash_lookup(gh, cedge);
1550 //This is the index size of the verts array
1551 vertsize = numcuts+2;
1553 // Is the original v1 the same as the first vert on the selected edge?
1554 // if not, the edge is running the opposite direction in this face so flip
1555 // the array to the correct direction
1557 if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
1562 We should have something like this now
1575 where start,end,op are indexes of EditFace->v1, etc (stored in v)
1576 and 0,1,2... are the indexes of the new verts stored in verts
1578 We will fill this case like this or this depending on even or odd cuts
1592 for(i=0;i<(vertsize-1);i++) {
1593 hold = addfacelist(em, verts[i],verts[i+1],v[op],NULL,NULL,NULL);
1594 if(i+1 != vertsize-1) {
1595 if(seltype == SUBDIV_SELECT_INNER) {
1596 hold->e2->f2 |= EDGEINNER;
1599 facecopy(em, efa,hold);
1603 static void fill_quad_double_op(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1605 EditEdge *cedge[2]={NULL, NULL};
1606 EditVert *v[4], **verts[2];
1608 short start=0, end, left, right, vertsize,i;
1615 if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;}
1616 else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;}
1618 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1619 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1620 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1621 //This is the index size of the verts array
1622 vertsize = numcuts+2;
1624 // Is the original v1 the same as the first vert on the selected edge?
1625 // if not, the edge is running the opposite direction in this face so flip
1626 // the array to the correct direction
1628 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1631 right = (start+3)%4;
1632 if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}
1634 We should have something like this now
1646 We will fill this case like this or this depending on even or odd cuts
1656 for(i=0;i<vertsize-1;i++) {
1657 hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
1658 if(i < vertsize-2) {
1659 hold->e2->f2 |= EDGEINNER;
1660 hold->e2->f2 |= DOUBLEOPFILL;
1662 facecopy(em, efa,hold);
1666 static void fill_quad_double_adj_path(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1668 EditEdge *cedge[2]={NULL, NULL};
1669 EditVert *v[4], **verts[2];
1671 short start=0, start2=0, vertsize,i;
1679 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
1680 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
1681 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;}
1682 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;}
1684 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1685 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1686 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1687 //This is the index size of the verts array
1688 vertsize = numcuts+2;
1690 // Is the original v1 the same as the first vert on the selected edge?
1691 // if not, the edge is running the opposite direction in this face so flip
1692 // the array to the correct direction
1694 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1695 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1697 We should have something like this now
1701 start2 0|---*---*---|
1709 We will fill this case like this or this depending on even or odd cuts
1719 // Make outside tris
1720 hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
1721 /* when ctrl is depressed, only want verts on the cutline selected */
1723 hold->e3->f2 |= EDGEINNER;
1724 facecopy(em, efa,hold);
1725 hold = addfacelist(em, verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
1726 /* when ctrl is depressed, only want verts on the cutline selected */
1728 hold->e1->f2 |= EDGEINNER;
1729 facecopy(em, efa,hold);
1730 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
1731 // hold->e1->h |= EM_FGON;
1735 for(i=0;i<numcuts;i++) {
1736 hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
1737 hold->e2->f2 |= EDGEINNER;
1738 facecopy(em, efa,hold);
1740 //EM_fgon_flags(em);
1744 static void fill_quad_double_adj_fan(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1746 EditEdge *cedge[2]={NULL, NULL};
1747 EditVert *v[4], *op=NULL, **verts[2];
1749 short start=0, start2=0, vertsize,i;
1756 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
1757 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
1758 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
1759 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
1762 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1763 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1764 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1765 //This is the index size of the verts array
1766 vertsize = numcuts+2;
1768 // Is the original v1 the same as the first vert on the selected edge?
1769 // if not, the edge is running the opposite direction in this face so flip
1770 // the array to the correct direction
1772 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1773 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1775 We should have something like this now
1779 start2 0|---*---*---|
1785 end2 3|-----------|op
1787 We will fill this case like this or this (warning horrible ascii art follows)
1797 for(i=0;i<=numcuts;i++) {
1798 hold = addfacelist(em, op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);
1799 hold->e1->f2 |= EDGEINNER;
1800 facecopy(em, efa,hold);
1802 hold = addfacelist(em, op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);
1803 hold->e3->f2 |= EDGEINNER;
1804 facecopy(em, efa,hold);
1808 static void fill_quad_double_adj_inner(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1810 EditEdge *cedge[2]={NULL, NULL};
1811 EditVert *v[4], *op=NULL, **verts[2],**inner;
1813 short start=0, start2=0, vertsize,i;
1821 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
1822 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
1823 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
1824 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
1827 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1828 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1829 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1830 //This is the index size of the verts array
1831 vertsize = numcuts+2;
1833 // Is the original v1 the same as the first vert on the selected edge?
1834 // if not, the edge is running the opposite direction in this face so flip
1835 // the array to the correct direction
1837 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1838 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1840 We should have something like this now
1844 start2 0|---*---*---|
1850 end2 3|-----------|op
1852 We will fill this case like this or this (warning horrible ascii art follows)
1863 // Add Inner Vert(s)
1864 inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts");
1866 for(i=0;i<numcuts;i++) {
1867 co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ;
1868 co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ;
1869 co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ;
1870 inner[i] = addvertlist(em, co, NULL);
1871 inner[i]->f2 |= EDGEINNER;
1873 EM_data_interp_from_verts(em, verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f);
1877 hold = addfacelist(em, verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);
1878 hold->e2->f2 |= EDGEINNER;
1879 hold->e3->f2 |= EDGEINNER;
1880 facecopy(em, efa,hold);
1882 hold = addfacelist(em, verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);
1883 hold->e2->f2 |= EDGEINNER;
1884 facecopy(em, efa,hold);
1886 hold = addfacelist(em, op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);
1887 hold->e2->f2 |= EDGEINNER;
1888 facecopy(em, efa,hold);
1890 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
1891 // hold->e1->h |= EM_FGON;
1893 // Add Fill Quads (if # cuts > 1)
1895 for(i=0;i<numcuts-1;i++) {
1896 hold = addfacelist(em, inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);
1897 hold->e1->f2 |= EDGEINNER;
1898 hold->e3->f2 |= EDGEINNER;
1899 facecopy(em, efa,hold);
1901 hold = addfacelist(em, inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);
1902 hold->e2->f2 |= EDGEINNER;
1903 hold->e4->f2 |= EDGEINNER;
1904 facecopy(em, efa,hold);
1906 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
1907 // hold->e1->h |= EM_FGON;
1911 //EM_fgon_flags(em);
1916 static void fill_tri_double(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1918 EditEdge *cedge[2]={NULL, NULL};
1919 EditVert *v[3], **verts[2];
1921 short start=0, start2=0, vertsize,i;
1927 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
1928 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
1929 if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;}
1931 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1932 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1933 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1934 //This is the index size of the verts array
1935 vertsize = numcuts+2;
1937 // Is the original v1 the same as the first vert on the selected edge?
1938 // if not, the edge is running the opposite direction in this face so flip
1939 // the array to the correct direction
1941 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1942 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1944 We should have something like this now
1948 start2 0|---*---*---|
1956 We will fill this case like this or this depending on even or odd cuts
1967 hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
1968 hold->e3->f2 |= EDGEINNER;
1969 facecopy(em, efa,hold);
1972 for(i=0;i<numcuts;i++) {
1973 hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
1974 hold->e2->f2 |= EDGEINNER;
1975 facecopy(em, efa,hold);
1979 static void fill_quad_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1981 EditEdge *cedge[3]={0};
1982 EditVert *v[4], **verts[3];
1984 short start=0, start2=0, start3=0, vertsize, i, repeats;
1991 if(!(efa->e1->f & SELECT)) {
1995 start = 1;start2 = 2;start3 = 3;
1997 if(!(efa->e2->f & SELECT)) {
2001 start = 2;start2 = 3;start3 = 0;
2003 if(!(efa->e3->f & SELECT)) {
2007 start = 3;start2 = 0;start3 = 1;
2009 if(!(efa->e4->f & SELECT)) {
2013 start = 0;start2 = 1;start3 = 2;
2015 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2016 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
2017 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
2018 verts[2] = BLI_ghash_lookup(gh, cedge[2]);
2019 //This is the index size of the verts array
2020 vertsize = numcuts+2;
2022 // Is the original v1 the same as the first vert on the selected edge?
2023 // if not, the edge is running the opposite direction in this face so flip
2024 // the array to the correct direction
2026 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
2027 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
2028 if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}
2030 We should have something like this now
2034 start3 0|---*---*---|3
2040 3|-----------|0 start
2042 We will fill this case like this or this depending on even or odd cuts
2043 there are a couple of differences. For odd cuts, there is a tri in the
2044 middle as well as 1 quad at the bottom (not including the extra quads
2047 For even cuts, there is a quad in the middle and 2 quads on the bottom
2049 they are numbered here for clarity
2051 1 outer tris and bottom quads
2070 |---*---*---*---*---|
2078 *-------------------*
2082 *-------------------*
2086 *-------------------*
2090 |-------------------|
2094 // Make outside tris
2095 hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
2096 hold->e3->f2 |= EDGEINNER;
2097 facecopy(em, efa,hold);
2098 hold = addfacelist(em, verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
2099 hold->e3->f2 |= EDGEINNER;
2100 facecopy(em, efa,hold);
2102 hold = addfacelist(em, verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
2103 hold->e2->f2 |= EDGEINNER;
2104 facecopy(em, efa,hold);
2105 //If it is even cuts, add the 2nd lower quad
2106 if(numcuts % 2 == 0) {
2107 hold = addfacelist(em, verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
2108 hold->e2->f2 |= EDGEINNER;
2109 facecopy(em, efa,hold);
2110 // Also Make inner quad
2111 hold = addfacelist(em, verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
2112 hold->e3->f2 |= EDGEINNER;
2113 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
2114 // hold->e3->h |= EM_FGON;
2116 facecopy(em, efa,hold);
2117 repeats = (numcuts / 2) -1;
2120 hold = addfacelist(em, verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
2121 hold->e2->f2 |= EDGEINNER;
2122 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
2123 // hold->e2->h |= EM_FGON;
2125 facecopy(em, efa,hold);
2126 repeats = ((numcuts+1) / 2)-1;
2129 // cuts for 1 and 2 do not have the repeating quads
2130 if(numcuts < 3) {repeats = 0;}
2131 for(i=0;i<repeats;i++) {
2132 //Make side repeating Quads
2133 hold = addfacelist(em, verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
2134 hold->e2->f2 |= EDGEINNER;
2135 facecopy(em, efa,hold);
2136 hold = addfacelist(em, verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
2137 hold->e4->f2 |= EDGEINNER;
2138 facecopy(em, efa,hold);
2140 // Do repeating bottom quads
2141 for(i=0;i<repeats;i++) {
2142 if(numcuts % 2 == 1) {
2143 hold = addfacelist(em, verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
2145 hold = addfacelist(em, verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
2147 hold->e2->f2 |= EDGEINNER;
2148 facecopy(em, efa,hold);
2150 //EM_fgon_flags(em);
2153 static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
2155 EditVert **verts[4], ***innerverts;
2158 short vertsize, i, j;
2160 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2161 verts[0] = BLI_ghash_lookup(gh, efa->e1);
2162 verts[1] = BLI_ghash_lookup(gh, efa->e2);
2163 verts[2] = BLI_ghash_lookup(gh, efa->e3);
2164 verts[3] = BLI_ghash_lookup(gh, efa->e4);
2166 //This is the index size of the verts array
2167 vertsize = numcuts+2;
2169 // Is the original v1 the same as the first vert on the selected edge?
2170 // if not, the edge is running the opposite direction in this face so flip
2171 // the array to the correct direction
2173 if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
2174 if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
2175 if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
2176 if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
2178 We should have something like this now
2192 // we will fill a 2 dim array of editvert*s to make filling easier
2193 // the innervert order is shown
2204 innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
2205 for(i=0;i<numcuts+2;i++) {
2206 innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
2209 // first row is e1 last row is e3
2210 for(i=0;i<numcuts+2;i++) {
2211 innerverts[0][i] = verts[0][(numcuts+1)-i];
2212 innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i];
2215 for(i=1;i<=numcuts;i++) {
2216 /* we create a fake edge for the next loop */
2217 temp.v2 = innerverts[i][0] = verts[1][i];
2218 temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
2220 for(j=1;j<=numcuts;j++) {
2221 float percent= (float)j/(float)(numcuts+1);
2223 innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, rad, beauty, percent);
2227 for(i=0;i<numcuts+1;i++) {
2228 for(j=0;j<numcuts+1;j++) {
2229 hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
2230 hold->e1->f2 = EDGENEW;
2231 hold->e2->f2 = EDGENEW;
2232 hold->e3->f2 = EDGENEW;
2233 hold->e4->f2 = EDGENEW;
2235 if(i != 0) { hold->e1->f2 |= EDGEINNER; }
2236 if(j != 0) { hold->e2->f2 |= EDGEINNER; }
2237 if(i != numcuts) { hold->e3->f2 |= EDGEINNER; }
2238 if(j != numcuts) { hold->e4->f2 |= EDGEINNER; }
2240 facecopy(em, efa,hold);
2243 // Clean up our dynamic multi-dim array
2244 for(i=0;i<numcuts+2;i++) {
2245 MEM_freeN(innerverts[i]);
2247 MEM_freeN(innerverts);
2250 static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty)
2252 EditVert **verts[3], ***innerverts;
2253 short vertsize, i, j;
2257 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2258 verts[0] = BLI_ghash_lookup(gh, efa->e1);
2259 verts[1] = BLI_ghash_lookup(gh, efa->e2);
2260 verts[2] = BLI_ghash_lookup(gh, efa->e3);
2262 //This is the index size of the verts array
2263 vertsize = numcuts+2;
2265 // Is the original v1 the same as the first vert on the selected edge?
2266 // if not, the edge is running the opposite direction in this face so flip
2267 // the array to the correct direction
2269 if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
2270 if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
2271 if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
2273 We should have something like this now
2286 we will fill a 2 dim array of editvert*s to make filling easier
2304 innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
2305 for(i=0;i<numcuts+2;i++) {
2306 innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
2308 //top row is e3 backwards
2309 for(i=0;i<numcuts+2;i++) {
2310 innerverts[0][i] = verts[2][(numcuts+1)-i];
2313 for(i=1;i<=numcuts+1;i++) {
2314 //fake edge, first vert is from e1, last is from e2
2315 temp.v1= innerverts[i][0] = verts[0][i];
2316 temp.v2= innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i];
2318 for(j=1;j<(numcuts+1)-i;j++) {
2319 float percent= (float)j/(float)((numcuts+1)-i);
2321 innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(em, &temp, rad, beauty, 1-percent);
2325 // Now fill the verts with happy little tris :)
2326 for(i=0;i<=numcuts+1;i++) {
2327 for(j=0;j<(numcuts+1)-i;j++) {
2328 //We always do the first tri
2329 hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
2330 hold->e1->f2 |= EDGENEW;
2331 hold->e2->f2 |= EDGENEW;
2332 hold->e3->f2 |= EDGENEW;
2333 if(i != 0) { hold->e1->f2 |= EDGEINNER; }
2334 if(j != 0) { hold->e2->f2 |= EDGEINNER; }
2335 if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;}
2337 facecopy(em, efa,hold);
2338 //if there are more to come, we do the 2nd
2339 if(j+1 <= numcuts-i) {
2340 hold = addfacelist(em, innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
2341 facecopy(em, efa,hold);
2342 hold->e1->f2 |= EDGENEW;
2343 hold->e2->f2 |= EDGENEW;
2344 hold->e3->f2 |= EDGENEW;
2349 // Clean up our dynamic multi-dim array
2350 for(i=0;i<numcuts+2;i++) {
2351 MEM_freeN(innerverts[i]);
2353 MEM_freeN(innerverts);
2356 //Next two fill types are for knife exact only and are provided to allow for knifing through vertices
2357 //This means there is no multicut!
2358 static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2)
2362 Depending on which two vertices have been knifed through (v1 and v2), we
2363 triangulate like the patterns below.
2371 if(v1 == 1 && v2 == 3){
2372 hold= addfacelist(em, efa->v1, efa->v2, efa->v3, 0, efa, NULL);
2373 hold->e1->f2 |= EDGENEW;
2374 hold->e2->f2 |= EDGENEW;
2375 hold->e3->f2 |= EDGENEW;
2376 hold->e3->f2 |= EDGEINNER;
2377 facecopy(em, efa, hold);
2379 hold= addfacelist(em, efa->v1, efa->v3, efa->v4, 0, efa, NULL);
2380 hold->e1->f2 |= EDGENEW;
2381 hold->e2->f2 |= EDGENEW;
2382 hold->e3->f2 |= EDGENEW;
2383 hold->e1->f2 |= EDGEINNER;
2384 facecopy(em, efa, hold);
2387 hold= addfacelist(em, efa->v1, efa->v2, efa->v4, 0, efa, NULL);
2388 hold->e1->f2 |= EDGENEW;
2389 hold->e2->f2 |= EDGENEW;
2390 hold->e3->f2 |= EDGENEW;
2391 hold->e2->f2 |= EDGEINNER;
2392 facecopy(em, efa, hold);
2394 hold= addfacelist(em, efa->v2, efa->v3, efa->v4, 0, efa, NULL);
2395 hold->e1->f2 |= EDGENEW;
2396 hold->e2->f2 |= EDGENEW;
2397 hold->e3->f2 |= EDGENEW;
2398 hold->e3->f2 |= EDGEINNER;
2399 facecopy(em, efa, hold);
2403 static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh)
2405 EditEdge *cedge=NULL;
2406 EditVert *v[4], **verts;
2408 short start=0, end, left, right, vertsize;
2415 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
2416 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
2417 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
2418 else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
2420 // Point verts to the array of new verts for cedge
2421 verts = BLI_ghash_lookup(gh, cedge);
2422 //This is the index size of the verts array
2425 // Is the original v1 the same as the first vert on the selected edge?
2426 // if not, the edge is running the opposite direction in this face so flip
2427 // the array to the correct direction
2429 if(verts[0] != v[start]) {flipvertarray(verts,3);}
2432 right = (start+3)%4;
2435 We should have something like this now
2446 where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
2447 and 0,1,2 are the indexes of the new verts stored in verts. We fill like
2448 this, depending on whether its vertex 'left' or vertex 'right' thats
2449 been knifed through...
2459 //triangle is composed of cutvert, end and left
2460 hold = addfacelist(em, verts[1],v[end],v[left],NULL, NULL,NULL);
2461 hold->e1->f2 |= EDGENEW;
2462 hold->e2->f2 |= EDGENEW;
2463 hold->e3->f2 |= EDGENEW;
2464 hold->e3->f2 |= EDGEINNER;
2465 facecopy(em, efa, hold);
2467 //quad is composed of cutvert, left, right and start
2468 hold = addfacelist(em, verts[1],v[left],v[right],v[start], NULL, NULL);
2469 hold->e1->f2 |= EDGENEW;
2470 hold->e2->f2 |= EDGENEW;
2471 hold->e3->f2 |= EDGENEW;
2472 hold->e4->f2 |= EDGENEW;
2473 hold->e1->f2 |= EDGEINNER;
2474 facecopy(em, efa, hold);
2476 else if(v[right]->f1){
2477 //triangle is composed of cutvert, right and start
2478 hold = addfacelist(em, verts[1],v[right],v[start], NULL, NULL, NULL);
2479 hold->e1->f2 |= EDGENEW;
2480 hold->e2->f2 |= EDGENEW;
2481 hold->e3->f2 |= EDGENEW;
2482 hold->e1->f2 |= EDGEINNER;
2483 facecopy(em, efa, hold);
2484 //quad is composed of cutvert, end, left, right
2485 hold = addfacelist(em, verts[1],v[end], v[left], v[right], NULL, NULL);
2486 hold->e1->f2 |= EDGENEW;
2487 hold->e2->f2 |= EDGENEW;
2488 hold->e3->f2 |= EDGENEW;
2489 hold->e4->f2 |= EDGENEW;
2490 hold->e4->f2 |= EDGEINNER;
2491 facecopy(em, efa, hold);
2496 // This function takes an example edge, the current point to create and
2497 // the total # of points to create, then creates the point and return the
2498 // editvert pointer to it.
2499 static EditVert *subdivideedgenum(EditMesh *em, EditEdge *edge, int curpoint, int totpoint, float rad, int beauty)
2504 if (beauty & (B_PERCENTSUBD) && totpoint == 1)
2505 //percent=(float)(edge->tmp.l)/32768.0f;
2506 percent= edge->tmp.fp;
2508 percent= (float)curpoint/(float)(totpoint+1);
2510 ev= subdivide_edge_addvert(em, edge, rad, beauty, percent);
2511 ev->f = edge->v1->f;
2516 void esubdivideflag(Object *obedit, EditMesh *em, int flag, float rad, int beauty, int numcuts, int seltype)
2519 EditEdge *eed, *cedge, *sort[4];
2520 EditVert *eve, **templist;
2522 float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3];
2523 int i, j, edgecount, touchcount, facetype,hold;
2524 ModifierData *md= obedit->modifiers.first;
2527 //Set faces f1 to 0 cause we need it later
2528 for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0;
2529 for(eve=em->verts.first; eve; eve=eve->next) {
2530 if(!(beauty & B_KNIFE)) /* knife sets this flag for vertex cuts */
2535 for (; md; md=md->next) {
2536 if (md->type==eModifierType_Mirror) {
2537 MirrorModifierData *mmd = (MirrorModifierData*) md;
2539 if(mmd->flag & MOD_MIR_CLIPPING) {
2540 for (eve= em->verts.first; eve; eve= eve->next) {
2544 if (fabs(eve->co[0]) < mmd->tolerance)
2548 if (fabs(eve->co[1]) < mmd->tolerance)
2552 if (fabs(eve->co[2]) < mmd->tolerance)
2561 //Flush vertex flags upward to the edges
2562 for(eed = em->edges.first;eed;eed = eed->next) {
2563 //if(eed->f & flag && eed->v1->f == eed->v2->f) {
2564 // eed->f |= eed->v1->f;
2572 // We store an array of verts for each edge that is subdivided,
2573 // we put this array as a value in a ghash which is keyed by the EditEdge*
2575 // Now for beauty subdivide deselect edges based on length
2576 if(beauty & B_BEAUTY) {
2577 for(ef = em->faces.first;ef;ef = ef->next) {
2581 if(ef->f & SELECT) {
2582 VECCOPY(v1mat, ef->v1->co);
2583 VECCOPY(v2mat, ef->v2->co);
2584 VECCOPY(v3mat, ef->v3->co);
2585 VECCOPY(v4mat, ef->v4->co);
2586 Mat4Mul3Vecfl(obedit->obmat, v1mat);
2587 Mat4Mul3Vecfl(obedit->obmat, v2mat);
2588 Mat4Mul3Vecfl(obedit->obmat, v3mat);
2589 Mat4Mul3Vecfl(obedit->obmat, v4mat);
2591 length[0] = VecLenf(v1mat, v2mat);
2592 length[1] = VecLenf(v2mat, v3mat);
2593 length[2] = VecLenf(v3mat, v4mat);
2594 length[3] = VecLenf(v4mat, v1mat);
2601 // Beauty Short Edges
2602 if(beauty & B_BEAUTY_SHORT) {
2608 } else if(hold == -1) {
2611 if(length[hold] < length[i]) {
2616 sort[hold]->f &= ~SELECT;
2617 sort[hold]->f2 |= EDGENEW;
2622 // Beauty Long Edges
2629 } else if(hold == -1) {
2632 if(length[hold] > length[i]) {
2637 sort[hold]->f &= ~SELECT;
2638 sort[hold]->f2 |= EDGENEW;
2646 gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
2648 // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
2649 if(beauty & B_KNIFE) {
2650 for(eed= em->edges.first;eed;eed=eed->next) {
2651 if( eed->tmp.fp == 0 ) {
2652 EM_select_edge(eed,0);
2656 // So for each edge, if it is selected, we allocate an array of size cuts+2
2657 // so we can have a place for the v1, the new verts and v2
2658 for(eed=em->edges.first;eed;eed = eed->next) {
2660 templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
2661 templist[0] = eed->v1;
2662 for(i=0;i<numcuts;i++) {
2663 // This function creates the new vert and returns it back
2665 templist[i+1] = subdivideedgenum(em, eed, i+1, numcuts, rad, beauty);
2666 //while we are here, we can copy edge info from the original edge
2667 cedge = addedgelist(em, templist[i],templist[i+1],eed);
2668 // Also set the edge f2 to EDGENEW so that we can use this info later
2669 cedge->f2 = EDGENEW;
2671 templist[i+1] = eed->v2;
2672 //Do the last edge too
2673 cedge = addedgelist(em, templist[i],templist[i+1],eed);
2674 cedge->f2 = EDGENEW;
2675 // Now that the edge is subdivided, we can put its verts in the ghash
2676 BLI_ghash_insert(gh, eed, templist);
2680 // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
2681 // Now for each face in the mesh we need to figure out How many edges were cut
2682 // and which filling method to use for that face
2683 for(ef = em->faces.first;ef;ef = ef->next) {
2686 if(ef->e1->f & flag) {edgecount++;}
2687 if(ef->e2->f & flag) {edgecount++;}
2688 if(ef->e3->f & flag) {edgecount++;}
2691 if(ef->e4->f & flag) {edgecount++;}
2696 if(beauty & B_KNIFE && numcuts == 1){
2697 /*Test for when knifing through two opposite verts but no edges*/
2699 if(ef->v1->f1) touchcount++;
2700 if(ef->v2->f1) touchcount++;
2701 if(ef->v3->f1) touchcount++;
2702 if(ef->v4->f1) touchcount++;
2703 if(touchcount == 2){
2704 if(ef->v1->f1 && ef->v3->f1){
2706 fill_quad_doublevert(em, ef, 1, 3);
2708 else if(ef->v2->f1 && ef->v4->f1){
2710 fill_quad_doublevert(em, ef, 2, 4);
2717 if(beauty & B_KNIFE && numcuts == 1){
2718 /*Test for when knifing through an edge and one vert*/
2720 if(ef->v1->f1) touchcount++;
2721 if(ef->v2->f1) touchcount++;
2722 if(ef->v3->f1) touchcount++;
2723 if(ef->v4->f1) touchcount++;
2725 if(touchcount == 1){
2726 if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) ||
2727 (ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) ||
2728 (ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) ||
2729 (ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){
2732 fill_quad_singlevert(em, ef, gh);
2736 fill_quad_single(em, ef, gh, numcuts, seltype);
2741 fill_quad_single(em, ef, gh, numcuts, seltype);
2746 fill_quad_single(em, ef, gh, numcuts, seltype);
2749 case 2: ef->f1 = SELECT;
2750 // if there are 2, we check if edge 1 and 3 are either both on or off that way
2751 // we can tell if the selected pair is Adjacent or Opposite of each other
2752 if((ef->e1->f & flag && ef->e3->f & flag) ||
2753 (ef->e2->f & flag && ef->e4->f & flag)) {
2754 fill_quad_double_op(em, ef, gh, numcuts);
2756 switch(0) { // XXX scene->toolsettings->cornertype) {
2757 case 0: fill_quad_double_adj_path(em, ef, gh, numcuts); break;
2758 case 1: fill_quad_double_adj_inner(em, ef, gh, numcuts); break;
2759 case 2: fill_quad_double_adj_fan(em, ef, gh, numcuts); break;
2764 case 3: ef->f1 = SELECT;
2765 fill_quad_triple(em, ef, gh, numcuts);
2767 case 4: ef->f1 = SELECT;
2768 fill_quad_quadruple(em, ef, gh, numcuts, rad, beauty);
2774 case 1: ef->f1 = SELECT;
2775 fill_tri_single(em, ef, gh, numcuts, seltype);
2777 case 2: ef->f1 = SELECT;
2778 fill_tri_double(em, ef, gh, numcuts);
2780 case 3: ef->f1 = SELECT;
2781 fill_tri_triple(em, ef, gh, numcuts, rad, beauty);
2787 // Delete Old Edges and Faces
2788 for(eed = em->edges.first;eed;eed = eed->next) {
2789 if(BLI_ghash_haskey(gh,eed)) {
2795 free_tagged_edges_faces(em, em->edges.first, em->faces.first);
2797 if(seltype == SUBDIV_SELECT_ORIG && !ctrl) {
2798 /* bugfix: vertex could get flagged as "not-selected"
2799 // solution: clear flags before, not at the same time as setting SELECT flag -dg
2801 for(eed = em->edges.first;eed;eed = eed->next) {
2802 if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) {
2804 EM_select_edge(eed,0);
2807 for(eed = em->edges.first;eed;eed = eed->next) {
2808 if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) {
2810 EM_select_edge(eed,1);
2813 } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| ctrl) {
2814 for(eed = em->edges.first;eed;eed = eed->next) {
2815 if(eed->f2 & EDGEINNER) {
2817 EM_select_edge(eed,1);
2818 if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT;
2819 if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT;
2822 EM_select_edge(eed,0);
2825 } else if(seltype == SUBDIV_SELECT_LOOPCUT){
2826 for(eed = em->edges.first;eed;eed = eed->next) {
2827 if(eed->f2 & DOUBLEOPFILL){
2829 EM_select_edge(eed,1);
2832 EM_select_edge(eed,0);
2836 if(em->selectmode & SCE_SELECT_VERTEX) {
2837 for(eed = em->edges.first;eed;eed = eed->next) {
2838 if(eed->f & SELECT) {
2839 eed->v1->f |= SELECT;
2840 eed->v2->f |= SELECT;
2845 //fix hide flags for edges. First pass, hide edges of hidden faces
2846 for(ef=em->faces.first; ef; ef=ef->next){
2851 if(ef->e4) ef->e4->h |= 1;
2854 //second pass: unhide edges of visible faces adjacent to hidden faces
2855 for(ef=em->faces.first; ef; ef=ef->next){
2860 if(ef->e4) ef->e4->h &= ~1;
2864 // Free the ghash and call MEM_freeN on all the value entries to return
2866 BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
2868 EM_selectmode_flush(em);
2869 for(ef=em->faces.first;ef;ef = ef->next) {
2871 if( (ef->e1->f & SELECT && ef->e2->f & SELECT) &&
2872 (ef->e3->f & SELECT && ef->e4->f & SELECT) ) {
2876 if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) {
2882 recalc_editnormals(em);
2883 // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
2886 static int count_selected_edges(EditEdge *ed)
2891 if( ed->f & SELECT ) totedge++;
2897 /* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */
2898 typedef EditFace *EVPtr;
2899 typedef EVPtr EVPTuple[2];
2901 /** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
2903 arguments: selected edge list, face list.
2904 Edges will also be tagged accordingly (see eed->f2) */
2906 static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
2908 EditEdge *e1, *e2, *e3;
2912 /* run through edges, if selected, set pointer edge-> facearray */
2916 if( eed->f & SELECT ) {
2917 eed->tmp.p = (EditVert *) (&efaa[i]);
2920 else eed->tmp.p = NULL;