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"
86 #include "ED_screen.h"
87 #include "ED_transform.h"
89 #include "ED_view3d.h"
91 #include "UI_interface.h"
93 #include "mesh_intern.h"
96 static int extern_qread() {return 0;}
97 static void waitcursor() {}
98 static int pupmenu() {return 0;}
99 static int qtest() {return 0;}
100 #define add_numbut(a, b, c, d, e, f, g) {}
101 static int snap_sel_to_curs() {return 0;}
102 static int snap_to_center() {return 0;}
106 /* local prototypes ---------------*/
107 static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa);
108 int EdgeLoopDelete(EditMesh *em, wmOperator *op);
110 /********* qsort routines *********/
113 typedef struct xvertsort {
118 static int vergxco(const void *v1, const void *v2)
120 const xvertsort *x1=v1, *x2=v2;
122 if( x1->x > x2->x ) return 1;
123 else if( x1->x < x2->x) return -1;
129 struct EditFace *efa;
133 static int vergface(const void *v1, const void *v2)
135 const struct facesort *x1=v1, *x2=v2;
137 if( x1->x > x2->x ) return 1;
138 else if( x1->x < x2->x) return -1;
143 /* *********************************** */
145 void convert_to_triface(EditMesh *em, int direction)
147 EditFace *efa, *efan, *next;
154 if(efa->f & SELECT) {
155 /* choose shortest diagonal for split */
156 fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co);
157 /* this makes sure exact squares get split different in both cases */
158 if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) {
159 efan= EM_face_from_faces(em, efa, NULL, 0, 1, 2, -1);
160 if(efa->f & SELECT) EM_select_face(efan, 1);
161 efan= EM_face_from_faces(em, efa, NULL, 0, 2, 3, -1);
162 if(efa->f & SELECT) EM_select_face(efan, 1);
165 efan= EM_face_from_faces(em, efa, NULL, 0, 1, 3, -1);
166 if(efa->f & SELECT) EM_select_face(efan, 1);
167 efan= EM_face_from_faces(em, efa, NULL, 1, 2, 3, -1);
168 if(efa->f & SELECT) EM_select_face(efan, 1);
171 BLI_remlink(&em->faces, efa);
172 free_editface(em, efa);
178 EM_fgon_flags(em); // redo flags and indices for fgons
183 int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /* return amount */
186 flag - Test with vert->flags
187 automerge - Alternative operation, merge unselected into selected.
188 Used for "Auto Weld" mode. warning.
189 limit - Quick manhattan distance between verts.
192 /* all verts with (flag & 'flag') are being evaluated */
193 EditVert *eve, *v1, *nextve;
194 EditEdge *eed, *e1, *nexted;
195 EditFace *efa, *nextvl;
196 xvertsort *sortblock, *sb, *sb1;
197 struct facesort *vlsortblock, *vsb, *vsb1;
198 int a, b, test, amount;
201 /* flag 128 is cleared, count */
203 /* Normal non weld operation */
204 eve= em->verts.first;
208 if(eve->h==0 && (automerge || (eve->f & flag))) amount++;
211 if(amount==0) return 0;
213 /* allocate memory and qsort */
214 sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub");
215 eve= em->verts.first;
217 if(eve->h==0 && (automerge || (eve->f & flag))) {
218 sb->x= eve->co[0]+eve->co[1]+eve->co[2];
224 qsort(sortblock, amount, sizeof(xvertsort), vergxco);
227 /* test for doubles */
230 for(a=0; a<amount; a++, sb++) {
232 if( (eve->f & 128)==0 ) {
234 for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) {
235 if(sb1->x - sb->x > limit) break;
237 /* when automarge, only allow unselected->selected */
239 if( (v1->f & 128)==0 ) {
240 if ((eve->f & flag)==0 && (v1->f & flag)==1) {
241 if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
242 (float)fabs(v1->co[1]-eve->co[1])<=limit &&
243 (float)fabs(v1->co[2]-eve->co[2])<=limit)
248 } else if( (eve->f & flag)==1 && (v1->f & flag)==0 ) {
249 if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
250 (float)fabs(v1->co[1]-eve->co[1])<=limit &&
251 (float)fabs(v1->co[2]-eve->co[2])<=limit)
262 for(a=0; a<amount; a++, sb++) {
264 if( (eve->f & 128)==0 ) {
266 for(b=a+1; b<amount; b++, sb1++) {
267 /* first test: simpel dist */
268 if(sb1->x - sb->x > limit) break;
271 /* second test: is vertex allowed */
272 if( (v1->f & 128)==0 ) {
273 if( (float)fabs(v1->co[0]-eve->co[0])<=limit &&
274 (float)fabs(v1->co[1]-eve->co[1])<=limit &&
275 (float)fabs(v1->co[2]-eve->co[2])<=limit)
285 MEM_freeN(sortblock);
288 for(eve = em->verts.first; eve; eve=eve->next)
289 if((eve->f & flag) && (eve->f & 128))
290 EM_data_interp_from_verts(em, eve, eve->tmp.v, eve->tmp.v, 0.5f);
292 /* test edges and insert again */
293 eed= em->edges.first;
303 if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
306 if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v;
307 if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v;
308 e1= addedgelist(em, eed->v1, eed->v2, eed);
315 if(e1!=eed) free_editedge(em, eed);
321 /* first count amount of test faces */
322 efa= (struct EditFace *)em->faces.first;
326 if(efa->v1->f & 128) efa->f1= 1;
327 else if(efa->v2->f & 128) efa->f1= 1;
328 else if(efa->v3->f & 128) efa->f1= 1;
329 else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1;
331 if(efa->f1==1) amount++;
335 /* test faces for double vertices, and if needed remove them */
336 efa= (struct EditFace *)em->faces.first;
341 if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v;
342 if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v;
343 if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v;
344 if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v;
347 if(efa->v1==efa->v2) test+=1;
348 if(efa->v2==efa->v3) test+=2;
349 if(efa->v3==efa->v1) test+=4;
350 if(efa->v4==efa->v1) test+=8;
351 if(efa->v3==efa->v4) test+=16;
352 if(efa->v2==efa->v4) test+=32;
356 if(test==1 || test==2) {
361 EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 3, 3);
365 else if(test==8 || test==16) {
370 BLI_remlink(&em->faces, efa);
371 free_editface(em, efa);
376 BLI_remlink(&em->faces, efa);
377 free_editface(em, efa);
383 /* set edge pointers */
384 efa->e1= findedgelist(em, efa->v1, efa->v2);
385 efa->e2= findedgelist(em, efa->v2, efa->v3);
387 efa->e3= findedgelist(em, efa->v3, efa->v1);
391 efa->e3= findedgelist(em, efa->v3, efa->v4);
392 efa->e4= findedgelist(em, efa->v4, efa->v1);
399 /* double faces: sort block */
400 /* count again, now all selected faces */
402 efa= em->faces.first;
405 if(faceselectedOR(efa, 1)) {
413 /* double faces: sort block */
414 vsb= vlsortblock= MEM_mallocN(sizeof(struct facesort)*amount, "sortremovedoub");
415 efa= em->faces.first;
418 if(efa->v4) vsb->x= (uintptr_t) MIN4( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3, (uintptr_t)efa->v4);
419 else vsb->x= (uintptr_t) MIN3( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3);
427 qsort(vlsortblock, amount, sizeof(struct facesort), vergface);
430 for(a=0; a<amount; a++) {
432 if( (efa->f1 & 128)==0 ) {
435 for(b=a+1; b<amount; b++) {
437 /* first test: same pointer? */
438 if(vsb->x != vsb1->x) break;
440 /* second test: is test permitted? */
442 if( (efa->f1 & 128)==0 ) {
443 if( compareface(efa, vsb->efa)) efa->f1 |= 128;
452 MEM_freeN(vlsortblock);
454 /* remove double faces */
455 efa= (struct EditFace *)em->faces.first;
459 BLI_remlink(&em->faces, efa);
460 free_editface(em, efa);
466 /* remove double vertices */
468 eve= (struct EditVert *)em->verts.first;
471 if(automerge || eve->f & flag) {
474 BLI_remlink(&em->verts, eve);
475 free_editvert(em, eve);
481 return a; /* amount */
484 static int removedoublesflag_exec(bContext *C, wmOperator *op)
486 Object *obedit= CTX_data_edit_object(C);
487 Scene *scene = CTX_data_scene(C);
488 EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
491 int cnt = removedoublesflag(em,1,0,scene->toolsettings->doublimit);
495 sprintf(msg, "Removed %d vertices", cnt);
496 BKE_report(op->reports, RPT_INFO, msg);
499 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
500 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
502 BKE_mesh_end_editmesh(obedit->data, em);
503 return OPERATOR_FINISHED;
506 void MESH_OT_remove_doubles(wmOperatorType *ot)
509 ot->name= "Remove Doubles";
510 ot->idname= "MESH_OT_remove_doubles";
513 ot->exec= removedoublesflag_exec;
514 ot->poll= ED_operator_editmesh;
517 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
520 // XXX is this needed?
521 /* called from buttons */
522 static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index)
524 xvertsort *sortblock = userData;
526 sortblock[index].x = x;
529 /* all verts with (flag & 'flag') are sorted */
530 void xsortvert_flag(bContext *C, int flag)
534 xvertsort *sortblock;
538 em_setup_viewcontext(C, &vc);
540 amount = BLI_countlist(&vc.em->verts);
541 sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort");
542 for (i=0,eve= vc.em->verts.first; eve; i++,eve=eve->next)
544 sortblock[i].v1 = eve;
546 mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0);
547 qsort(sortblock, amount, sizeof(xvertsort), vergxco);
549 /* make temporal listbase */
550 tbase.first= tbase.last= 0;
551 for (i=0; i<amount; i++) {
552 eve = sortblock[i].v1;
555 BLI_remlink(&vc.em->verts, eve);
556 BLI_addtail(&tbase, eve);
560 addlisttolist(&vc.em->verts, &tbase);
562 MEM_freeN(sortblock);
566 /* called from buttons */
567 void hashvert_flag(EditMesh *em, int flag)
569 /* switch vertex order using hash table */
571 struct xvertsort *sortblock, *sb, onth, *newsort;
576 eve= em->verts.first;
579 if(eve->f & flag) amount++;
582 if(amount==0) return;
584 /* allocate memory */
585 sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub");
586 eve= em->verts.first;
598 for(a=0; a<amount; a++, sb++) {
599 b= (int)(amount*BLI_drand());
600 if(b>=0 && b<amount) {
601 newsort= sortblock+b;
608 /* make temporal listbase */
609 tbase.first= tbase.last= 0;
613 BLI_remlink(&em->verts, eve);
614 BLI_addtail(&tbase, eve);
618 addlisttolist(&em->verts, &tbase);
620 MEM_freeN(sortblock);
624 /* generic extern called extruder */
625 void extrude_mesh(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op)
627 float nor[3]= {0.0, 0.0, 0.0};
628 short nr, transmode= 0;
630 /* extrude depends on totvertsel etc */
633 if(em->selectmode & SCE_SELECT_VERTEX) {
634 if(em->totvertsel==0) nr= 0;
635 else if(em->totvertsel==1) nr= 4;
636 else if(em->totedgesel==0) nr= 4;
637 else if(em->totfacesel==0)
638 nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
639 else if(em->totfacesel==1)
640 nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
642 nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
644 else if(em->selectmode & SCE_SELECT_EDGE) {
645 if (em->totedgesel==0) nr = 0;
646 else if (em->totedgesel==1) nr = 3;
647 else if(em->totfacesel==0) nr = 3;
648 else if(em->totfacesel==1)
649 nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
651 nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
654 if (em->totfacesel == 0) nr = 0;
655 else if (em->totfacesel == 1) nr = 1;
657 nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
662 if(nr==1) transmode= extrudeflag(obedit, em, SELECT, nor);
663 else if(nr==4) transmode= extrudeflag_verts_indiv(em, SELECT, nor);
664 else if(nr==3) transmode= extrudeflag_edges_indiv(em, SELECT, nor);
665 else transmode= extrudeflag_face_indiv(em, SELECT, nor);
668 BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude");
673 /* We need to force immediate calculation here because
674 * transform may use derived objects (which are now stale).
676 * This shouldn't be necessary, derived queries should be
677 * automatically building this data if invalid. Or something.
679 // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
680 object_handle_update(scene, obedit);
682 /* individual faces? */
683 // BIF_TransformSetUndo("Extrude");
685 // initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
689 // initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
691 Mat4MulVecfl(obedit->obmat, nor);
692 VecSubf(nor, nor, obedit->obmat[3]);
693 // BIF_setSingleAxisConstraint(nor, "along normal");
701 // XXX should be a menu item
702 static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event)
704 Scene *scene= CTX_data_scene(C);
705 Object *obedit= CTX_data_edit_object(C);
706 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
707 int constraint_axis[3] = {0, 0, 1};
709 extrude_mesh(scene, obedit, em, op);
711 BKE_mesh_end_editmesh(obedit->data, em);
713 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
714 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
716 RNA_enum_set(op->ptr, "proportional", 0);
717 RNA_boolean_set(op->ptr, "mirror", 0);
719 /* the following two should only be set when extruding faces */
720 RNA_enum_set(op->ptr, "constraint_orientation", V3D_MANIP_NORMAL);
721 RNA_boolean_set_array(op->ptr, "constraint_axis", constraint_axis);
724 WM_operator_name_call(C, "TFM_OT_translate", WM_OP_INVOKE_REGION_WIN, op->ptr);
726 return OPERATOR_FINISHED;
729 /* extrude without transform */
730 static int mesh_extrude_exec(bContext *C, wmOperator *op)
732 Scene *scene= CTX_data_scene(C);
733 Object *obedit= CTX_data_edit_object(C);
734 EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
736 extrude_mesh(scene, obedit, em, op);
738 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
739 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
741 BKE_mesh_end_editmesh(obedit->data, em);
742 return OPERATOR_FINISHED;
746 void MESH_OT_extrude(wmOperatorType *ot)
750 ot->idname= "MESH_OT_extrude";
753 ot->invoke= mesh_extrude_invoke;
754 ot->exec= mesh_extrude_exec;
755 ot->poll= ED_operator_editmesh;
758 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
760 /* to give to transform */
761 Properties_Proportional(ot);
762 Properties_Constraints(ot);
763 RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", "");
766 static int split_mesh(bContext *C, wmOperator *op)
768 Scene *scene= CTX_data_scene(C);
769 Object *obedit= CTX_data_edit_object(C);
770 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
774 /* make duplicate first */
775 adduplicateflag(em, SELECT);
776 /* old faces have flag 128 set, delete them */
777 delfaceflag(em, 128);
778 recalc_editnormals(em);
782 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
783 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
785 BKE_mesh_end_editmesh(obedit->data, em);
786 return OPERATOR_FINISHED;
789 void MESH_OT_split(wmOperatorType *ot)
793 ot->idname= "MESH_OT_split";
796 ot->exec= split_mesh;
797 ot->poll= ED_operator_editmesh;
800 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
804 static int extrude_repeat_mesh(bContext *C, wmOperator *op)
806 Scene *scene= CTX_data_scene(C);
807 Object *obedit= CTX_data_edit_object(C);
808 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
810 RegionView3D *rv3d = ED_view3d_context_rv3d(C);
812 int steps = RNA_int_get(op->ptr,"steps");
814 float offs = RNA_float_get(op->ptr,"offset");
816 float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0};
820 dvec[0]= rv3d->persinv[2][0];
821 dvec[1]= rv3d->persinv[2][1];
822 dvec[2]= rv3d->persinv[2][2];
828 /* base correction */
829 Mat3CpyMat4(bmat, obedit->obmat);
831 Mat3MulVecfl(tmat, dvec);
833 for(a=0; a<steps; a++) {
834 extrudeflag(obedit, em, SELECT, nor);
835 translateflag(em, SELECT, dvec);
838 recalc_editnormals(em);
842 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
843 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
845 BKE_mesh_end_editmesh(obedit->data, em);
846 return OPERATOR_FINISHED;
849 void MESH_OT_extrude_repeat(wmOperatorType *ot)
852 ot->name= "Extrude Repeat Mesh";
853 ot->idname= "MESH_OT_extrude_repeat";
856 ot->exec= extrude_repeat_mesh;
857 ot->poll= ED_operator_editmesh;
860 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
863 RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX);
864 RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX);
867 /* ************************** spin operator ******************** */
870 static int spin_mesh(bContext *C, wmOperator *op, float *dvec, int steps, float degr, int dupli )
872 Object *obedit= CTX_data_edit_object(C);
873 Scene *scene = CTX_data_scene(C);
874 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
875 EditVert *eve,*nextve;
876 float nor[3]= {0.0f, 0.0f, 0.0f};
877 float si, n[3], q[4], cmat[3][3], imat[3][3], tmat[3][3];
878 float cent[3], bmat[3][3];
882 RNA_float_get_array(op->ptr, "center", cent);
884 /* imat and center and size */
885 Mat3CpyMat4(bmat, obedit->obmat);
888 cent[0]-= obedit->obmat[3][0];
889 cent[1]-= obedit->obmat[3][1];
890 cent[2]-= obedit->obmat[3][2];
891 Mat3MulVecfl(imat, cent);
893 phi= degr*M_PI/360.0;
895 if(scene->toolsettings->editbutflag & B_CLOCKWISE) phi= -phi;
897 RNA_float_get_array(op->ptr, "axis", n);
900 q[0]= (float)cos(phi);
907 Mat3MulMat3(tmat,cmat,bmat);
908 Mat3MulMat3(bmat,imat,tmat);
911 if(scene->toolsettings->editbutflag & B_KEEPORIG)
912 adduplicateflag(em, 1);
914 for(a=0; a<steps; a++) {
915 if(dupli==0) ok= extrudeflag(obedit, em, SELECT, nor);
916 else adduplicateflag(em, SELECT);
921 rotateflag(em, SELECT, cent, bmat);
923 Mat3MulVecfl(bmat,dvec);
924 translateflag(em, SELECT, dvec);
929 /* no vertices or only loose ones selected, remove duplicates */
930 eve= em->verts.first;
933 if(eve->f & SELECT) {
934 BLI_remlink(&em->verts,eve);
935 free_editvert(em, eve);
941 recalc_editnormals(em);
945 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
948 BKE_mesh_end_editmesh(obedit->data, em);
952 static int spin_mesh_exec(bContext *C, wmOperator *op)
954 Scene *scene= CTX_data_scene(C);
955 Object *obedit= CTX_data_edit_object(C);
958 ok= spin_mesh(C, op, NULL, RNA_int_get(op->ptr,"steps"), RNA_float_get(op->ptr,"degrees"), RNA_boolean_get(op->ptr,"dupli"));
960 BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected");
961 return OPERATOR_CANCELLED;
964 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
965 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
967 return OPERATOR_FINISHED;
970 /* get center and axis, in global coords */
971 static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event)
973 Scene *scene = CTX_data_scene(C);
974 View3D *v3d = CTX_wm_view3d(C);
975 RegionView3D *rv3d= ED_view3d_context_rv3d(C);
977 RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
978 RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]);
980 return spin_mesh_exec(C, op);
983 void MESH_OT_spin(wmOperatorType *ot)
987 ot->idname= "MESH_OT_spin";
990 ot->invoke= spin_mesh_invoke;
991 ot->exec= spin_mesh_exec;
992 ot->poll= EM_view3d_poll;
995 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
998 RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX);
999 RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates");
1000 RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f);
1002 RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
1003 RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
1007 static int screw_mesh_exec(bContext *C, wmOperator *op)
1009 Scene *scene= CTX_data_scene(C);
1010 Object *obedit= CTX_data_edit_object(C);
1011 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
1012 EditVert *eve,*v1=0,*v2=0;
1014 float dvec[3], nor[3];
1017 turns= RNA_int_get(op->ptr, "turns");
1018 steps= RNA_int_get(op->ptr, "steps");
1021 for(eve= em->verts.first; eve; eve= eve->next)
1024 /* edges set flags in verts */
1025 for(eed= em->edges.first; eed; eed= eed->next) {
1026 if(eed->v1->f & SELECT) {
1027 if(eed->v2->f & SELECT) {
1028 /* watch: f1 is a byte */
1029 if(eed->v1->f1<2) eed->v1->f1++;
1030 if(eed->v2->f1<2) eed->v2->f1++;
1034 /* find two vertices with eve->f1==1, more or less is wrong */
1035 for(eve= em->verts.first; eve; eve= eve->next) {
1037 if(v1==NULL) v1= eve;
1038 else if(v2==NULL) v2= eve;
1045 if(v1==NULL || v2==NULL) {
1046 BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too");
1047 BKE_mesh_end_editmesh(obedit->data, em);
1048 return OPERATOR_CANCELLED;
1051 /* calculate dvec */
1052 dvec[0]= ( v1->co[0]- v2->co[0] )/steps;
1053 dvec[1]= ( v1->co[1]- v2->co[1] )/steps;
1054 dvec[2]= ( v1->co[2]- v2->co[2] )/steps;
1056 VECCOPY(nor, obedit->obmat[2]);
1058 if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) {
1064 if(spin_mesh(C, op, dvec, turns*steps, 360.0f*turns, 0)) {
1065 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
1066 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1068 BKE_mesh_end_editmesh(obedit->data, em);
1069 return OPERATOR_FINISHED;
1072 BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected");
1073 BKE_mesh_end_editmesh(obedit->data, em);
1074 return OPERATOR_CANCELLED;
1078 /* get center and axis, in global coords */
1079 static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event)
1081 Scene *scene = CTX_data_scene(C);
1082 View3D *v3d = CTX_wm_view3d(C);
1083 RegionView3D *rv3d= ED_view3d_context_rv3d(C);
1085 RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d));
1086 RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]);
1088 return screw_mesh_exec(C, op);
1091 void MESH_OT_screw(wmOperatorType *ot)
1095 ot->idname= "MESH_OT_screw";
1098 ot->invoke= screw_mesh_invoke;
1099 ot->exec= screw_mesh_exec;
1100 ot->poll= EM_view3d_poll;
1103 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1106 RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256);
1107 RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256);
1109 RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX);
1110 RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX);
1113 static void erase_edges(EditMesh *em, ListBase *l)
1115 EditEdge *ed, *nexted;
1117 ed = (EditEdge *) l->first;
1120 if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) {
1122 free_editedge(em, ed);
1128 static void erase_faces(EditMesh *em, ListBase *l)
1130 EditFace *f, *nextf;
1132 f = (EditFace *) l->first;
1136 if( faceselectedOR(f, SELECT) ) {
1138 free_editface(em, f);
1144 static void erase_vertices(EditMesh *em, ListBase *l)
1146 EditVert *v, *nextv;
1148 v = (EditVert *) l->first;
1153 free_editvert(em, v);
1159 void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event)
1161 EditFace *efa, *nextvl;
1162 EditVert *eve,*nextve;
1163 EditEdge *eed,*nexted;
1171 str= "Erase Vertices";
1172 erase_edges(em, &em->edges);
1173 erase_faces(em, &em->faces);
1174 erase_vertices(em, &em->verts);
1177 if(!EdgeLoopDelete(em, op))
1180 str= "Erase Edge Loop";
1183 str= "Erase Edges & Faces";
1184 efa= em->faces.first;
1187 /* delete only faces with 1 or more edges selected */
1189 if(efa->e1->f & SELECT) count++;
1190 if(efa->e2->f & SELECT) count++;
1191 if(efa->e3->f & SELECT) count++;
1192 if(efa->e4 && (efa->e4->f & SELECT)) count++;
1194 BLI_remlink(&em->faces, efa);
1195 free_editface(em, efa);
1199 eed= em->edges.first;
1202 if(eed->f & SELECT) {
1204 free_editedge(em, eed);
1208 efa= em->faces.first;
1212 if( efa->v1->f & SELECT) event++;
1213 if( efa->v2->f & SELECT) event++;
1214 if( efa->v3->f & SELECT) event++;
1215 if(efa->v4 && (efa->v4->f & SELECT)) event++;
1218 BLI_remlink(&em->faces, efa);
1219 free_editface(em, efa);
1227 efa= em->faces.first;
1231 if( efa->e1->f & SELECT) event++;
1232 if( efa->e2->f & SELECT) event++;
1233 if( efa->e3->f & SELECT) event++;
1234 if(efa->e4 && (efa->e4->f & SELECT)) event++;
1237 BLI_remlink(&em->faces, efa);
1238 free_editface(em, efa);
1242 eed= em->edges.first;
1245 if(eed->f & SELECT) {
1247 free_editedge(em, eed);
1251 /* to remove loose vertices: */
1252 eed= em->edges.first;
1254 if( eed->v1->f & SELECT) eed->v1->f-=SELECT;
1255 if( eed->v2->f & SELECT) eed->v2->f-=SELECT;
1258 eve= em->verts.first;
1261 if(eve->f & SELECT) {
1262 BLI_remlink(&em->verts,eve);
1263 free_editvert(em, eve);
1271 delfaceflag(em, SELECT);
1275 if(em->verts.first) free_vertlist(em, &em->verts);
1276 if(em->edges.first) free_edgelist(em, &em->edges);
1277 if(em->faces.first) free_facelist(em, &em->faces);
1278 if(em->selected.first) BLI_freelistN(&(em->selected));
1281 str= "Erase Only Faces";
1282 efa= em->faces.first;
1285 if(efa->f & SELECT) {
1286 BLI_remlink(&em->faces, efa);
1287 free_editface(em, efa);
1293 EM_fgon_flags(em); // redo flags and indices for fgons
1296 /* Note, these values must match delete_mesh() event values */
1297 static EnumPropertyItem prop_mesh_delete_types[] = {
1298 {10,"VERT", 0, "Vertices", ""},
1299 {1, "EDGE", 0, "Edges", ""},
1300 {2, "FACE", 0, "Faces", ""},
1301 {3, "ALL", 0, "All", ""},
1302 {4, "EDGE_FACE",0, "Edges & Faces", ""},
1303 {5, "ONLY_FACE",0, "Only Faces", ""},
1304 {6, "EDGE_LOOP",0, "Edge Loop", ""},
1305 {0, NULL, 0, NULL, NULL}
1308 static int delete_mesh_exec(bContext *C, wmOperator *op)
1310 Scene *scene= CTX_data_scene(C);
1311 Object *obedit= CTX_data_edit_object(C);
1312 EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
1314 delete_mesh(obedit, em, op, RNA_enum_get(op->ptr, "type"));
1316 DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
1317 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
1319 BKE_mesh_end_editmesh(obedit->data, em);
1320 return OPERATOR_FINISHED;
1323 void MESH_OT_delete(wmOperatorType *ot)
1327 ot->idname= "MESH_OT_delete";
1330 ot->invoke= WM_menu_invoke;
1331 ot->exec= delete_mesh_exec;
1333 ot->poll= ED_operator_editmesh;
1336 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1339 RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data");
1344 /*-------------------------------------------------------------------------------*/
1345 /*--------------------------- Edge Based Subdivide ------------------------------*/
1352 /*used by faceloop cut to select only edges valid for edge slide*/
1353 #define DOUBLEOPFILL 16
1355 /* calculates offset for co, based on fractal, sphere or smooth settings */
1356 static void alter_co(float *co, EditEdge *edge, float smooth, float fractal, int beauty, float perc)
1360 if(beauty & B_SMOOTH) {
1361 /* we calculate an offset vector vec1[], to be added to *co */
1362 float len, fac, nor[3], nor1[3], nor2[3];
1364 VecSubf(nor, edge->v1->co, edge->v2->co);
1365 len= 0.5f*Normalize(nor);
1367 VECCOPY(nor1, edge->v1->no);
1368 VECCOPY(nor2, edge->v2->no);
1371 fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
1373 vec1[0]= fac*nor1[0];
1374 vec1[1]= fac*nor1[1];
1375 vec1[2]= fac*nor1[2];
1378 fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
1380 vec1[0]+= fac*nor2[0];
1381 vec1[1]+= fac*nor2[1];
1382 vec1[2]+= fac*nor2[2];
1384 /* falloff for multi subdivide */
1385 smooth *= sqrt(fabs(1.0f - 2.0f*fabs(0.5f-perc)));
1387 vec1[0]*= smooth*len;
1388 vec1[1]*= smooth*len;
1389 vec1[2]*= smooth*len;
1395 else if(beauty & B_SPHERE) { /* subdivide sphere */
1402 if(beauty & B_FRACTAL) {
1403 fac= fractal*VecLenf(edge->v1->co, edge->v2->co);
1404 vec1[0]= fac*(float)(0.5-BLI_drand());
1405 vec1[1]= fac*(float)(0.5-BLI_drand());
1406 vec1[2]= fac*(float)(0.5-BLI_drand());
1407 VecAddf(co, co, vec1);
1411 /* assumes in the edge is the correct interpolated vertices already */
1412 /* percent defines the interpolation, smooth, fractal and beauty are for special options */
1413 /* results in new vertex with correct coordinate, vertex normal and weight group info */
1414 static EditVert *subdivide_edge_addvert(EditMesh *em, EditEdge *edge, float smooth, float fractal, int beauty, float percent)
1419 co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0];
1420 co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1];
1421 co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];
1423 /* offset for smooth or sphere or fractal */
1424 alter_co(co, edge, smooth, fractal, beauty, percent);
1426 /* clip if needed by mirror modifier */
1428 if ( edge->v1->f2 & edge->v2->f2 & 1) {
1431 if ( edge->v1->f2 & edge->v2->f2 & 2) {
1434 if ( edge->v1->f2 & edge->v2->f2 & 4) {
1439 ev = addvertlist(em, co, NULL);
1441 /* vert data (vgroups, ..) */
1442 EM_data_interp_from_verts(em, edge->v1, edge->v2, ev, percent);
1445 ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0];
1446 ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1];
1447 ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2];
1453 static void flipvertarray(EditVert** arr, short size)
1458 for(i=0; i<size/2; i++) {
1460 arr[i] = arr[size-i-1];
1461 arr[size-i-1] = hold;
1465 static void facecopy(EditMesh *em, EditFace *source, EditFace *target)
1467 float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co;
1468 float *v4 = source->v4? source->v4->co: NULL;
1471 CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data);
1473 target->mat_nr = source->mat_nr;
1474 target->flag = source->flag;
1475 target->h = source->h;
1477 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]);
1478 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]);
1479 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]);
1481 InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]);
1483 CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data);
1486 static void fill_quad_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
1488 EditEdge *cedge=NULL;
1489 EditVert *v[4], **verts;
1491 short start=0, end, left, right, vertsize,i;
1498 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
1499 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
1500 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
1501 else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
1503 // Point verts to the array of new verts for cedge
1504 verts = BLI_ghash_lookup(gh, cedge);
1505 //This is the index size of the verts array
1506 vertsize = numcuts+2;
1508 // Is the original v1 the same as the first vert on the selected edge?
1509 // if not, the edge is running the opposite direction in this face so flip
1510 // the array to the correct direction
1512 if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
1515 right = (start+3)%4;
1518 We should have something like this now
1529 where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
1530 and 0,1,2... are the indexes of the new verts stored in verts
1532 We will fill this case like this or this depending on even or odd cuts
1534 |---*---*---| |---*---|
1538 ------------- ---------
1542 if(vertsize % 2 == 0) {
1543 hold = addfacelist(em, verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
1544 hold->e2->f2 |= EDGEINNER;
1545 hold->e4->f2 |= EDGEINNER;
1547 hold = addfacelist(em, verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
1548 hold->e1->f2 |= EDGEINNER;
1549 hold->e3->f2 |= EDGEINNER;
1551 facecopy(em, efa,hold);
1554 for(i=0;i<(vertsize-1)/2;i++) {
1555 hold = addfacelist(em, verts[i],verts[i+1],v[right],NULL,NULL,NULL);
1556 facecopy(em, efa,hold);
1557 if(i+1 != (vertsize-1)/2) {
1558 if(seltype == SUBDIV_SELECT_INNER) {
1559 hold->e2->f2 |= EDGEINNER;
1562 hold = addfacelist(em, verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
1563 facecopy(em, efa,hold);
1564 if(i+1 != (vertsize-1)/2) {
1565 if(seltype == SUBDIV_SELECT_INNER) {
1566 hold->e3->f2 |= EDGEINNER;
1572 static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype)
1574 EditEdge *cedge=NULL;
1575 EditVert *v[3], **verts;
1577 short start=0, end, op, vertsize,i;
1583 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
1584 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
1585 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
1587 // Point verts to the array of new verts for cedge
1588 verts = BLI_ghash_lookup(gh, cedge);
1589 //This is the index size of the verts array
1590 vertsize = numcuts+2;
1592 // Is the original v1 the same as the first vert on the selected edge?
1593 // if not, the edge is running the opposite direction in this face so flip
1594 // the array to the correct direction
1596 if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);}
1601 We should have something like this now
1614 where start,end,op are indexes of EditFace->v1, etc (stored in v)
1615 and 0,1,2... are the indexes of the new verts stored in verts
1617 We will fill this case like this or this depending on even or odd cuts
1631 for(i=0;i<(vertsize-1);i++) {
1632 hold = addfacelist(em, verts[i],verts[i+1],v[op],NULL,NULL,NULL);
1633 if(i+1 != vertsize-1) {
1634 if(seltype == SUBDIV_SELECT_INNER) {
1635 hold->e2->f2 |= EDGEINNER;
1638 facecopy(em, efa,hold);
1642 static void fill_quad_double_op(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1644 EditEdge *cedge[2]={NULL, NULL};
1645 EditVert *v[4], **verts[2];
1647 short start=0, end, left, right, vertsize,i;
1654 if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;}
1655 else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;}
1657 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1658 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1659 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1660 //This is the index size of the verts array
1661 vertsize = numcuts+2;
1663 // Is the original v1 the same as the first vert on the selected edge?
1664 // if not, the edge is running the opposite direction in this face so flip
1665 // the array to the correct direction
1667 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1670 right = (start+3)%4;
1671 if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}
1673 We should have something like this now
1685 We will fill this case like this or this depending on even or odd cuts
1695 for(i=0;i<vertsize-1;i++) {
1696 hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
1697 if(i < vertsize-2) {
1698 hold->e2->f2 |= EDGEINNER;
1699 hold->e2->f2 |= DOUBLEOPFILL;
1701 facecopy(em, efa,hold);
1705 static void fill_quad_double_adj_path(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1707 EditEdge *cedge[2]={NULL, NULL};
1708 EditVert *v[4], **verts[2];
1710 short start=0, start2=0, vertsize,i;
1718 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
1719 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
1720 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;}
1721 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;}
1723 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1724 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1725 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1726 //This is the index size of the verts array
1727 vertsize = numcuts+2;
1729 // Is the original v1 the same as the first vert on the selected edge?
1730 // if not, the edge is running the opposite direction in this face so flip
1731 // the array to the correct direction
1733 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1734 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1736 We should have something like this now
1740 start2 0|---*---*---|
1748 We will fill this case like this or this depending on even or odd cuts
1758 // Make outside tris
1759 hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
1760 /* when ctrl is depressed, only want verts on the cutline selected */
1762 hold->e3->f2 |= EDGEINNER;
1763 facecopy(em, efa,hold);
1764 hold = addfacelist(em, verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
1765 /* when ctrl is depressed, only want verts on the cutline selected */
1767 hold->e1->f2 |= EDGEINNER;
1768 facecopy(em, efa,hold);
1769 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
1770 // hold->e1->h |= EM_FGON;
1774 for(i=0;i<numcuts;i++) {
1775 hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
1776 hold->e2->f2 |= EDGEINNER;
1777 facecopy(em, efa,hold);
1779 //EM_fgon_flags(em);
1783 static void fill_quad_double_adj_fan(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1785 EditEdge *cedge[2]={NULL, NULL};
1786 EditVert *v[4], *op=NULL, **verts[2];
1788 short start=0, start2=0, vertsize,i;
1795 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
1796 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
1797 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
1798 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
1801 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1802 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1803 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1804 //This is the index size of the verts array
1805 vertsize = numcuts+2;
1807 // Is the original v1 the same as the first vert on the selected edge?
1808 // if not, the edge is running the opposite direction in this face so flip
1809 // the array to the correct direction
1811 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1812 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1814 We should have something like this now
1818 start2 0|---*---*---|
1824 end2 3|-----------|op
1826 We will fill this case like this or this (warning horrible ascii art follows)
1836 for(i=0;i<=numcuts;i++) {
1837 hold = addfacelist(em, op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);
1838 hold->e1->f2 |= EDGEINNER;
1839 facecopy(em, efa,hold);
1841 hold = addfacelist(em, op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);
1842 hold->e3->f2 |= EDGEINNER;
1843 facecopy(em, efa,hold);
1847 static void fill_quad_double_adj_inner(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1849 EditEdge *cedge[2]={NULL, NULL};
1850 EditVert *v[4], *op=NULL, **verts[2],**inner;
1852 short start=0, start2=0, vertsize,i;
1860 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;}
1861 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;}
1862 if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;}
1863 if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;}
1866 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1867 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1868 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
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);}
1879 We should have something like this now
1883 start2 0|---*---*---|
1889 end2 3|-----------|op
1891 We will fill this case like this or this (warning horrible ascii art follows)
1902 // Add Inner Vert(s)
1903 inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts");
1905 for(i=0;i<numcuts;i++) {
1906 co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ;
1907 co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ;
1908 co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ;
1909 inner[i] = addvertlist(em, co, NULL);
1910 inner[i]->f2 |= EDGEINNER;
1912 EM_data_interp_from_verts(em, verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f);
1916 hold = addfacelist(em, verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);
1917 hold->e2->f2 |= EDGEINNER;
1918 hold->e3->f2 |= EDGEINNER;
1919 facecopy(em, efa,hold);
1921 hold = addfacelist(em, verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);
1922 hold->e2->f2 |= EDGEINNER;
1923 facecopy(em, efa,hold);
1925 hold = addfacelist(em, op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);
1926 hold->e2->f2 |= EDGEINNER;
1927 facecopy(em, efa,hold);
1929 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
1930 // hold->e1->h |= EM_FGON;
1932 // Add Fill Quads (if # cuts > 1)
1934 for(i=0;i<numcuts-1;i++) {
1935 hold = addfacelist(em, inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);
1936 hold->e1->f2 |= EDGEINNER;
1937 hold->e3->f2 |= EDGEINNER;
1938 facecopy(em, efa,hold);
1940 hold = addfacelist(em, inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);
1941 hold->e2->f2 |= EDGEINNER;
1942 hold->e4->f2 |= EDGEINNER;
1943 facecopy(em, efa,hold);
1945 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
1946 // hold->e1->h |= EM_FGON;
1950 //EM_fgon_flags(em);
1955 static void fill_tri_double(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
1957 EditEdge *cedge[2]={NULL, NULL};
1958 EditVert *v[3], **verts[2];
1960 short start=0, start2=0, vertsize,i;
1966 if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
1967 if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
1968 if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;}
1970 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
1971 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
1972 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
1973 //This is the index size of the verts array
1974 vertsize = numcuts+2;
1976 // Is the original v1 the same as the first vert on the selected edge?
1977 // if not, the edge is running the opposite direction in this face so flip
1978 // the array to the correct direction
1980 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
1981 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
1983 We should have something like this now
1987 start2 0|---*---*---|
1995 We will fill this case like this or this depending on even or odd cuts
2006 hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
2007 hold->e3->f2 |= EDGEINNER;
2008 facecopy(em, efa,hold);
2011 for(i=0;i<numcuts;i++) {
2012 hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
2013 hold->e2->f2 |= EDGEINNER;
2014 facecopy(em, efa,hold);
2018 static void fill_quad_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts)
2020 EditEdge *cedge[3]={0};
2021 EditVert *v[4], **verts[3];
2023 short start=0, start2=0, start3=0, vertsize, i, repeats;
2030 if(!(efa->e1->f & SELECT)) {
2034 start = 1;start2 = 2;start3 = 3;
2036 if(!(efa->e2->f & SELECT)) {
2040 start = 2;start2 = 3;start3 = 0;
2042 if(!(efa->e3->f & SELECT)) {
2046 start = 3;start2 = 0;start3 = 1;
2048 if(!(efa->e4->f & SELECT)) {
2052 start = 0;start2 = 1;start3 = 2;
2054 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2055 verts[0] = BLI_ghash_lookup(gh, cedge[0]);
2056 verts[1] = BLI_ghash_lookup(gh, cedge[1]);
2057 verts[2] = BLI_ghash_lookup(gh, cedge[2]);
2058 //This is the index size of the verts array
2059 vertsize = numcuts+2;
2061 // Is the original v1 the same as the first vert on the selected edge?
2062 // if not, the edge is running the opposite direction in this face so flip
2063 // the array to the correct direction
2065 if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
2066 if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}
2067 if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}
2069 We should have something like this now
2073 start3 0|---*---*---|3
2079 3|-----------|0 start
2081 We will fill this case like this or this depending on even or odd cuts
2082 there are a couple of differences. For odd cuts, there is a tri in the
2083 middle as well as 1 quad at the bottom (not including the extra quads
2086 For even cuts, there is a quad in the middle and 2 quads on the bottom
2088 they are numbered here for clarity
2090 1 outer tris and bottom quads
2109 |---*---*---*---*---|
2117 *-------------------*
2121 *-------------------*
2125 *-------------------*
2129 |-------------------|
2133 // Make outside tris
2134 hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
2135 hold->e3->f2 |= EDGEINNER;
2136 facecopy(em, efa,hold);
2137 hold = addfacelist(em, verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
2138 hold->e3->f2 |= EDGEINNER;
2139 facecopy(em, efa,hold);
2141 hold = addfacelist(em, verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
2142 hold->e2->f2 |= EDGEINNER;
2143 facecopy(em, efa,hold);
2144 //If it is even cuts, add the 2nd lower quad
2145 if(numcuts % 2 == 0) {
2146 hold = addfacelist(em, verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
2147 hold->e2->f2 |= EDGEINNER;
2148 facecopy(em, efa,hold);
2149 // Also Make inner quad
2150 hold = addfacelist(em, verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
2151 hold->e3->f2 |= EDGEINNER;
2152 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
2153 // hold->e3->h |= EM_FGON;
2155 facecopy(em, efa,hold);
2156 repeats = (numcuts / 2) -1;
2159 hold = addfacelist(em, verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
2160 hold->e2->f2 |= EDGEINNER;
2161 //if(scene->toolsettings->editbutflag & B_AUTOFGON) {
2162 // hold->e2->h |= EM_FGON;
2164 facecopy(em, efa,hold);
2165 repeats = ((numcuts+1) / 2)-1;
2168 // cuts for 1 and 2 do not have the repeating quads
2169 if(numcuts < 3) {repeats = 0;}
2170 for(i=0;i<repeats;i++) {
2171 //Make side repeating Quads
2172 hold = addfacelist(em, verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
2173 hold->e2->f2 |= EDGEINNER;
2174 facecopy(em, efa,hold);
2175 hold = addfacelist(em, verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
2176 hold->e4->f2 |= EDGEINNER;
2177 facecopy(em, efa,hold);
2179 // Do repeating bottom quads
2180 for(i=0;i<repeats;i++) {
2181 if(numcuts % 2 == 1) {
2182 hold = addfacelist(em, verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
2184 hold = addfacelist(em, verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
2186 hold->e2->f2 |= EDGEINNER;
2187 facecopy(em, efa,hold);
2189 //EM_fgon_flags(em);
2192 static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float smooth, float fractal, int beauty)
2194 EditVert **verts[4], ***innerverts;
2197 short vertsize, i, j;
2199 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2200 verts[0] = BLI_ghash_lookup(gh, efa->e1);
2201 verts[1] = BLI_ghash_lookup(gh, efa->e2);
2202 verts[2] = BLI_ghash_lookup(gh, efa->e3);
2203 verts[3] = BLI_ghash_lookup(gh, efa->e4);
2205 //This is the index size of the verts array
2206 vertsize = numcuts+2;
2208 // Is the original v1 the same as the first vert on the selected edge?
2209 // if not, the edge is running the opposite direction in this face so flip
2210 // the array to the correct direction
2212 if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
2213 if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
2214 if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
2215 if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
2217 We should have something like this now
2231 // we will fill a 2 dim array of editvert*s to make filling easier
2232 // the innervert order is shown
2243 innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
2244 for(i=0;i<numcuts+2;i++) {
2245 innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
2248 // first row is e1 last row is e3
2249 for(i=0;i<numcuts+2;i++) {
2250 innerverts[0][i] = verts[0][(numcuts+1)-i];
2251 innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i];
2254 for(i=1;i<=numcuts;i++) {
2255 /* we create a fake edge for the next loop */
2256 temp.v2 = innerverts[i][0] = verts[1][i];
2257 temp.v1 = innerverts[i][numcuts+1] = verts[3][i];
2259 for(j=1;j<=numcuts;j++) {
2260 float percent= (float)j/(float)(numcuts+1);
2262 innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, smooth, fractal, beauty, percent);
2266 for(i=0;i<numcuts+1;i++) {
2267 for(j=0;j<numcuts+1;j++) {
2268 hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
2269 hold->e1->f2 = EDGENEW;
2270 hold->e2->f2 = EDGENEW;
2271 hold->e3->f2 = EDGENEW;
2272 hold->e4->f2 = EDGENEW;
2274 if(i != 0) { hold->e1->f2 |= EDGEINNER; }
2275 if(j != 0) { hold->e2->f2 |= EDGEINNER; }
2276 if(i != numcuts) { hold->e3->f2 |= EDGEINNER; }
2277 if(j != numcuts) { hold->e4->f2 |= EDGEINNER; }
2279 facecopy(em, efa,hold);
2282 // Clean up our dynamic multi-dim array
2283 for(i=0;i<numcuts+2;i++) {
2284 MEM_freeN(innerverts[i]);
2286 MEM_freeN(innerverts);
2289 static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float smooth, float fractal, int beauty)
2291 EditVert **verts[3], ***innerverts;
2292 short vertsize, i, j;
2296 // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
2297 verts[0] = BLI_ghash_lookup(gh, efa->e1);
2298 verts[1] = BLI_ghash_lookup(gh, efa->e2);
2299 verts[2] = BLI_ghash_lookup(gh, efa->e3);
2301 //This is the index size of the verts array
2302 vertsize = numcuts+2;
2304 // Is the original v1 the same as the first vert on the selected edge?
2305 // if not, the edge is running the opposite direction in this face so flip
2306 // the array to the correct direction
2308 if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
2309 if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
2310 if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
2312 We should have something like this now
2325 we will fill a 2 dim array of editvert*s to make filling easier
2343 innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
2344 for(i=0;i<numcuts+2;i++) {
2345 innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
2347 //top row is e3 backwards
2348 for(i=0;i<numcuts+2;i++) {
2349 innerverts[0][i] = verts[2][(numcuts+1)-i];
2352 for(i=1;i<=numcuts+1;i++) {
2353 //fake edge, first vert is from e1, last is from e2
2354 temp.v1= innerverts[i][0] = verts[0][i];
2355 temp.v2= innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i];
2357 for(j=1;j<(numcuts+1)-i;j++) {
2358 float percent= (float)j/(float)((numcuts+1)-i);
2360 innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(em, &temp, smooth, fractal, beauty, 1-percent);
2364 // Now fill the verts with happy little tris :)
2365 for(i=0;i<=numcuts+1;i++) {
2366 for(j=0;j<(numcuts+1)-i;j++) {
2367 //We always do the first tri
2368 hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
2369 hold->e1->f2 |= EDGENEW;
2370 hold->e2->f2 |= EDGENEW;
2371 hold->e3->f2 |= EDGENEW;
2372 if(i != 0) { hold->e1->f2 |= EDGEINNER; }
2373 if(j != 0) { hold->e2->f2 |= EDGEINNER; }
2374 if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;}
2376 facecopy(em, efa,hold);
2377 //if there are more to come, we do the 2nd
2378 if(j+1 <= numcuts-i) {
2379 hold = addfacelist(em, innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
2380 facecopy(em, efa,hold);
2381 hold->e1->f2 |= EDGENEW;
2382 hold->e2->f2 |= EDGENEW;
2383 hold->e3->f2 |= EDGENEW;
2388 // Clean up our dynamic multi-dim array
2389 for(i=0;i<numcuts+2;i++) {
2390 MEM_freeN(innerverts[i]);
2392 MEM_freeN(innerverts);
2395 //Next two fill types are for knife exact only and are provided to allow for knifing through vertices
2396 //This means there is no multicut!
2397 static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2)
2401 Depending on which two vertices have been knifed through (v1 and v2), we
2402 triangulate like the patterns below.
2410 if(v1 == 1 && v2 == 3){
2411 hold= addfacelist(em, efa->v1, efa->v2, efa->v3, 0, efa, NULL);
2412 hold->e1->f2 |= EDGENEW;
2413 hold->e2->f2 |= EDGENEW;
2414 hold->e3->f2 |= EDGENEW;
2415 hold->e3->f2 |= EDGEINNER;
2416 facecopy(em, efa, hold);
2418 hold= addfacelist(em, efa->v1, efa->v3, efa->v4, 0, efa, NULL);
2419 hold->e1->f2 |= EDGENEW;
2420 hold->e2->f2 |= EDGENEW;
2421 hold->e3->f2 |= EDGENEW;
2422 hold->e1->f2 |= EDGEINNER;
2423 facecopy(em, efa, hold);
2426 hold= addfacelist(em, efa->v1, efa->v2, efa->v4, 0, efa, NULL);
2427 hold->e1->f2 |= EDGENEW;
2428 hold->e2->f2 |= EDGENEW;
2429 hold->e3->f2 |= EDGENEW;
2430 hold->e2->f2 |= EDGEINNER;
2431 facecopy(em, efa, hold);
2433 hold= addfacelist(em, efa->v2, efa->v3, efa->v4, 0, efa, NULL);
2434 hold->e1->f2 |= EDGENEW;
2435 hold->e2->f2 |= EDGENEW;
2436 hold->e3->f2 |= EDGENEW;
2437 hold->e3->f2 |= EDGEINNER;
2438 facecopy(em, efa, hold);
2442 static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh)
2444 EditEdge *cedge=NULL;
2445 EditVert *v[4], **verts;
2447 short start=0, end, left, right, vertsize;
2454 if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
2455 else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
2456 else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
2457 else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
2459 // Point verts to the array of new verts for cedge
2460 verts = BLI_ghash_lookup(gh, cedge);
2461 //This is the index size of the verts array
2464 // Is the original v1 the same as the first vert on the selected edge?
2465 // if not, the edge is running the opposite direction in this face so flip
2466 // the array to the correct direction
2468 if(verts[0] != v[start]) {flipvertarray(verts,3);}
2471 right = (start+3)%4;
2474 We should have something like this now
2485 where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
2486 and 0,1,2 are the indexes of the new verts stored in verts. We fill like
2487 this, depending on whether its vertex 'left' or vertex 'right' thats
2488 been knifed through...
2498 //triangle is composed of cutvert, end and left
2499 hold = addfacelist(em, verts[1],v[end],v[left],NULL, NULL,NULL);
2500 hold->e1->f2 |= EDGENEW;
2501 hold->e2->f2 |= EDGENEW;
2502 hold->e3->f2 |= EDGENEW;
2503 hold->e3->f2 |= EDGEINNER;
2504 facecopy(em, efa, hold);
2506 //quad is composed of cutvert, left, right and start
2507 hold = addfacelist(em, verts[1],v[left],v[right],v[start], NULL, NULL);
2508 hold->e1->f2 |= EDGENEW;
2509 hold->e2->f2 |= EDGENEW;
2510 hold->e3->f2 |= EDGENEW;
2511 hold->e4->f2 |= EDGENEW;
2512 hold->e1->f2 |= EDGEINNER;
2513 facecopy(em, efa, hold);
2515 else if(v[right]->f1){
2516 //triangle is composed of cutvert, right and start
2517 hold = addfacelist(em, verts[1],v[right],v[start], NULL, NULL, NULL);
2518 hold->e1->f2 |= EDGENEW;
2519 hold->e2->f2 |= EDGENEW;
2520 hold->e3->f2 |= EDGENEW;
2521 hold->e1->f2 |= EDGEINNER;
2522 facecopy(em, efa, hold);
2523 //quad is composed of cutvert, end, left, right
2524 hold = addfacelist(em, verts[1],v[end], v[left], v[right], NULL, NULL);
2525 hold->e1->f2 |= EDGENEW;
2526 hold->e2->f2 |= EDGENEW;
2527 hold->e3->f2 |= EDGENEW;
2528 hold->e4->f2 |= EDGENEW;
2529 hold->e4->f2 |= EDGEINNER;
2530 facecopy(em, efa, hold);
2535 // This function takes an example edge, the current point to create and
2536 // the total # of points to create, then creates the point and return the
2537 // editvert pointer to it.
2538 static EditVert *subdivideedgenum(EditMesh *em, EditEdge *edge, int curpoint, int totpoint, float smooth, float fractal, int beauty)
2543 if (beauty & (B_PERCENTSUBD) && totpoint == 1)
2544 //percent=(float)(edge->tmp.l)/32768.0f;
2545 percent= edge->tmp.fp;
2547 percent= (float)curpoint/(float)(totpoint+1);
2549 ev= subdivide_edge_addvert(em, edge, smooth, fractal, beauty, percent);
2550 ev->f = edge->v1->f;
2555 void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float fractal, int beauty, int numcuts, int seltype)
2558 EditEdge *eed, *cedge, *sort[4];
2559 EditVert *eve, **templist;
2561 float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3];
2562 int i, j, edgecount, touchcount, facetype,hold;
2563 ModifierData *md= obedit->modifiers.first;
2566 //Set faces f1 to 0 cause we need it later
2567 for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0;
2568 for(eve=em->verts.first; eve; eve=eve->next) {
2569 if(!(beauty & B_KNIFE)) /* knife sets this flag for vertex cuts */
2574 for (; md; md=md->next) {
2575 if (md->type==eModifierType_Mirror) {
2576 MirrorModifierData *mmd = (MirrorModifierData*) md;
2578 if(mmd->flag & MOD_MIR_CLIPPING) {
2579 for (eve= em->verts.first; eve; eve= eve->next) {
2583 if (fabs(eve->co[0]) < mmd->tolerance)
2587 if (fabs(eve->co[1]) < mmd->tolerance)
2591 if (fabs(eve->co[2]) < mmd->tolerance)
2600 //Flush vertex flags upward to the edges
2601 for(eed = em->edges.first;eed;eed = eed->next) {
2602 //if(eed->f & flag && eed->v1->f == eed->v2->f) {
2603 // eed->f |= eed->v1->f;
2611 // We store an array of verts for each edge that is subdivided,
2612 // we put this array as a value in a ghash which is keyed by the EditEdge*
2614 // Now for beauty subdivide deselect edges based on length
2615 if(beauty & B_BEAUTY) {
2616 for(ef = em->faces.first;ef;ef = ef->next) {
2620 if(ef->f & SELECT) {
2621 VECCOPY(v1mat, ef->v1->co);
2622 VECCOPY(v2mat, ef->v2->co);
2623 VECCOPY(v3mat, ef->v3->co);
2624 VECCOPY(v4mat, ef->v4->co);
2625 Mat4Mul3Vecfl(obedit->obmat, v1mat);
2626 Mat4Mul3Vecfl(obedit->obmat, v2mat);
2627 Mat4Mul3Vecfl(obedit->obmat, v3mat);
2628 Mat4Mul3Vecfl(obedit->obmat, v4mat);
2630 length[0] = VecLenf(v1mat, v2mat);
2631 length[1] = VecLenf(v2mat, v3mat);
2632 length[2] = VecLenf(v3mat, v4mat);
2633 length[3] = VecLenf(v4mat, v1mat);
2640 // Beauty Short Edges
2641 if(beauty & B_BEAUTY_SHORT) {
2647 } else if(hold == -1) {
2650 if(length[hold] < length[i]) {
2656 sort[hold]->f &= ~SELECT;
2657 sort[hold]->f2 |= EDGENEW;
2663 // Beauty Long Edges
2670 } else if(hold == -1) {
2673 if(length[hold] > length[i]) {
2679 sort[hold]->f &= ~SELECT;
2680 sort[hold]->f2 |= EDGENEW;
2689 gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
2691 // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
2692 if(beauty & B_KNIFE) {
2693 for(eed= em->edges.first;eed;eed=eed->next) {
2694 if( eed->tmp.fp == 0 ) {
2695 EM_select_edge(eed,0);
2699 // So for each edge, if it is selected, we allocate an array of size cuts+2
2700 // so we can have a place for the v1, the new verts and v2
2701 for(eed=em->edges.first;eed;eed = eed->next) {
2703 templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
2704 templist[0] = eed->v1;
2705 for(i=0;i<numcuts;i++) {
2706 // This function creates the new vert and returns it back
2708 templist[i+1] = subdivideedgenum(em, eed, i+1, numcuts, smooth, fractal, beauty);
2709 //while we are here, we can copy edge info from the original edge
2710 cedge = addedgelist(em, templist[i],templist[i+1],eed);
2711 // Also set the edge f2 to EDGENEW so that we can use this info later
2712 cedge->f2 = EDGENEW;
2714 templist[i+1] = eed->v2;
2715 //Do the last edge too
2716 cedge = addedgelist(em, templist[i],templist[i+1],eed);
2717 cedge->f2 = EDGENEW;
2718 // Now that the edge is subdivided, we can put its verts in the ghash
2719 BLI_ghash_insert(gh, eed, templist);
2723 // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
2724 // Now for each face in the mesh we need to figure out How many edges were cut
2725 // and which filling method to use for that face
2726 for(ef = em->faces.first;ef;ef = ef->next) {
2729 if(ef->e1->f & flag) {edgecount++;}
2730 if(ef->e2->f & flag) {edgecount++;}
2731 if(ef->e3->f & flag) {edgecount++;}
2734 if(ef->e4->f & flag) {edgecount++;}
2739 if(beauty & B_KNIFE && numcuts == 1){
2740 /*Test for when knifing through two opposite verts but no edges*/
2742 if(ef->v1->f1) touchcount++;
2743 if(ef->v2->f1) touchcount++;
2744 if(ef->v3->f1) touchcount++;
2745 if(ef->v4->f1) touchcount++;
2746 if(touchcount == 2){
2747 if(ef->v1->f1 && ef->v3->f1){
2749 fill_quad_doublevert(em, ef, 1, 3);
2751 else if(ef->v2->f1 && ef->v4->f1){
2753 fill_quad_doublevert(em, ef, 2, 4);
2760 if(beauty & B_KNIFE && numcuts == 1){
2761 /*Test for when knifing through an edge and one vert*/
2763 if(ef->v1->f1) touchcount++;
2764 if(ef->v2->f1) touchcount++;
2765 if(ef->v3->f1) touchcount++;
2766 if(ef->v4->f1) touchcount++;
2768 if(touchcount == 1){
2769 if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) ||
2770 (ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) ||
2771 (ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) ||
2772 (ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){
2775 fill_quad_singlevert(em, ef, gh);
2779 fill_quad_single(em, ef, gh, numcuts, seltype);
2784 fill_quad_single(em, ef, gh, numcuts, seltype);
2789 fill_quad_single(em, ef, gh, numcuts, seltype);
2792 case 2: ef->f1 = SELECT;
2793 // if there are 2, we check if edge 1 and 3 are either both on or off that way
2794 // we can tell if the selected pair is Adjacent or Opposite of each other
2795 if((ef->e1->f & flag && ef->e3->f & flag) ||
2796 (ef->e2->f & flag && ef->e4->f & flag)) {
2797 fill_quad_double_op(em, ef, gh, numcuts);
2799 switch(0) { // XXX scene->toolsettings->cornertype) {
2800 case 0: fill_quad_double_adj_path(em, ef, gh, numcuts); break;
2801 case 1: fill_quad_double_adj_inner(em, ef, gh, numcuts); break;
2802 case 2: fill_quad_double_adj_fan(em, ef, gh, numcuts); break;
2807 case 3: ef->f1 = SELECT;
2808 fill_quad_triple(em, ef, gh, numcuts);
2810 case 4: ef->f1 = SELECT;
2811 fill_quad_quadruple(em, ef, gh, numcuts, smooth, fractal, beauty);
2817 case 1: ef->f1 = SELECT;
2818 fill_tri_single(em, ef, gh, numcuts, seltype);
2820 case 2: ef->f1 = SELECT;
2821 fill_tri_double(em, ef, gh, numcuts);
2823 case 3: ef->f1 = SELECT;
2824 fill_tri_triple(em, ef, gh, numcuts, smooth, fractal, beauty);
2830 // Delete Old Edges and Faces
2831 for(eed = em->edges.first;eed;eed = eed->next) {
2832 if(BLI_ghash_haskey(gh,eed)) {
2838 free_tagged_edges_faces(em, em->edges.first, em->faces.first);
2840 if(seltype == SUBDIV_SELECT_ORIG && !ctrl) {
2841 /* bugfix: vertex could get flagged as "not-selected"
2842 // solution: clear flags before, not at the same time as setting SELECT flag -dg
2844 for(eed = em->edges.first;eed;eed = eed->next) {
2845 if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) {
2847 EM_select_edge(eed,0);
2850 for(eed = em->edges.first;eed;eed = eed->next) {
2851 if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) {
2853 EM_select_edge(eed,1);
2856 } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| ctrl) {
2857 for(eed = em->edges.first;eed;eed = eed->next) {
2858 if(eed->f2 & EDGEINNER) {
2860 EM_select_edge(eed,1);
2861 if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT;
2862 if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT;
2865 EM_select_edge(eed,0);
2868 } else if(seltype == SUBDIV_SELECT_LOOPCUT){
2869 for(eed = em->edges.first;eed;eed = eed->next) {
2870 if(eed->f2 & DOUBLEOPFILL){
2872 EM_select_edge(eed,1);
2875 EM_select_edge(eed,0);
2879 if(em->selectmode & SCE_SELECT_VERTEX) {
2880 for(eed = em->edges.first;eed;eed = eed->next) {
2881 if(eed->f & SELECT) {
2882 eed->v1->f |= SELECT;
2883 eed->v2->f |= SELECT;
2888 //fix hide flags for edges. First pass, hide edges of hidden faces
2889 for(ef=em->faces.first; ef; ef=ef->next){
2894 if(ef->e4) ef->e4->h |= 1;
2897 //second pass: unhide edges of visible faces adjacent to hidden faces
2898 for(ef=em->faces.first; ef; ef=ef->next){
2903 if(ef->e4) ef->e4->h &= ~1;
2907 // Free the ghash and call MEM_freeN on all the value entries to return
2909 BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
2911 EM_selectmode_flush(em);
2912 for(ef=em->faces.first;ef;ef = ef->next) {
2914 if( (ef->e1->f & SELECT && ef->e2->f & SELECT) &&
2915 (ef->e3->f & SELECT && ef->e4->f & SELECT) ) {
2919 if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) {
2925 recalc_editnormals(em);
2928 static int count_selected_edges(EditEdge *ed)
2933 if( ed->f & SELECT ) totedge++;
2939 /* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */
2940 typedef EditFace *EVPtr;
2941 typedef EVPtr EVPTuple[2];
2943 /** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
2945 arguments: selected edge list, face list.
2946 Edges will also be tagged accordingly (see eed->f2) */
2948 static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa)
2950 EditEdge *e1, *e2, *e3;
2954 /* run through edges, if selected, set pointer edge-> facearray */