diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f48804fa79c..78cd9587737 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1651,6 +1651,10 @@ class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu): layout.operator("mesh.edge_rotate", text="Rotate Edge CW").direction = 'CW' layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").direction = 'CCW' + layout.separator() + + layout.operator("mesh.bridge_edge_loops", text="Bridge Two Edge Loops") + layout.separator() layout.operator("TRANSFORM_OT_edge_slide") diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 5e05c1090d9..c182b74ad6d 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1886,8 +1886,10 @@ static void bmesh_corners_to_loops(Mesh *me, int findex, int loopstart, int numT if (ld->disps) BLI_cellalloc_free(ld->disps); - ld->disps = BLI_cellalloc_malloc(sizeof(float)*3*side*side, "converted loop mdisps"); - memcpy(ld->disps, disps, sizeof(float)*3*side*side); + ld->disps = BLI_cellalloc_calloc(sizeof(float)*3*side*side, "converted loop mdisps"); + if (fd->disps) { + memcpy(ld->disps, disps, sizeof(float)*3*side*side); + } } } } diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 1d177aba6d9..7e881d6097c 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -570,8 +570,9 @@ BMesh *BM_Copy_Mesh(BMesh *bmold) else if (ese->type == BM_FACE) { ele = ftable[BM_GetIndex(ese->data)]; } - - BM_store_selection(bm, ele); + + if (ele) + BM_store_selection(bm, ele); } BLI_array_free(etable); diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index d491562232f..6f57a944966 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -382,6 +382,19 @@ static BMOpDefine def_contextual_create= { BMOP_UNTAN_MULTIRES, }; +/* + + Bridge edge loops with faces +*/ +static BMOpDefine def_bridge_loops= { + "bridge_loops", + {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/ + {BMOP_OPSLOT_ELEMENT_BUF, "faceout"}, /*new faces*/ + {0, /*null-terminating sentinel*/}}, + bmesh_bridge_loops_exec, + 0, +}; + static BMOpDefine def_edgenet_fill= { "edgenet_fill", {{BMOP_OPSLOT_ELEMENT_BUF, "edges"}, /*input edges*/ @@ -1072,6 +1085,7 @@ BMOpDefine *opdefines[] = { &def_bevel, &def_beautify_fill, &def_triangle_fill, + &def_bridge_loops, }; int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*)); diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 1dff6f9b763..7855600591a 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -73,5 +73,6 @@ void bmesh_bevel_exec(BMesh *bm, BMOperator *op); void bmesh_beautify_fill_exec(BMesh *bm, BMOperator *op); void bmesh_triangle_fill_exec(BMesh *bm, BMOperator *op); void bmesh_create_circle_exec(BMesh *bm, BMOperator *op); +void bmesh_bridge_loops_exec(BMesh *bm, BMOperator *op); #endif diff --git a/source/blender/bmesh/operators/connectops.c b/source/blender/bmesh/operators/connectops.c index 7e8f65ce7d5..debb68e577f 100644 --- a/source/blender/bmesh/operators/connectops.c +++ b/source/blender/bmesh/operators/connectops.c @@ -14,6 +14,8 @@ #define VERT_INPUT 1 #define EDGE_OUT 1 #define FACE_NEW 2 +#define EDGE_MARK 4 +#define EDGE_DONE 8 void connectverts_exec(BMesh *bm, BMOperator *op) { @@ -101,3 +103,153 @@ void connectverts_exec(BMesh *bm, BMOperator *op) BLI_array_free(loops); BLI_array_free(verts); } + +static BMVert *get_outer_vert(BMesh *bm, BMEdge *e) +{ + BMIter iter; + BMEdge *e2; + int i; + + i= 0; + BM_ITER(e2, &iter, bm, BM_EDGES_OF_VERT, e->v1) { + if (BMO_TestFlag(bm, e2, EDGE_MARK)) + i++; + } + + if (i==2) + return e->v2; + else + return e->v1; +} + +void bmesh_bridge_loops_exec(BMesh *bm, BMOperator *op) +{ + BMEdge **ee1 = NULL, **ee2 = NULL; + BMVert **vv1 = NULL, **vv2 = NULL; + BLI_array_declare(ee1); + BLI_array_declare(ee2); + BLI_array_declare(vv1); + BLI_array_declare(vv2); + BMOIter siter; + BMIter iter; + BMEdge *e; + int c=0, cl1=0, cl2=0; + + BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) { + BMO_SetFlag(bm, e, EDGE_MARK); + } + + BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) { + if (!BMO_TestFlag(bm, e, EDGE_DONE)) { + BMVert *v, *ov; + BMEdge *e2, *e3, *oe = e; + int i; + + if (c > 2) { + printf("eek! more than two edge loops!\n"); + break; + } + + e2 = e; + v = e->v1; + do { + v = BM_OtherEdgeVert(e2, v); + BM_ITER(e3, &iter, bm, BM_EDGES_OF_VERT, v) { + if (e3 != e2 && BMO_TestFlag(bm, e3, EDGE_MARK)) { + break; + } + } + e2 = e3; + } while (e2 && e2 != e); + + if (!e2) + e2 = e; + + e = e2; + ov = v; + do { + if (c==0) { + BLI_array_append(ee1, e2); + BLI_array_append(vv1, v); + } else { + BLI_array_append(ee2, e2); + BLI_array_append(vv2, v); + } + + BMO_SetFlag(bm, e2, EDGE_DONE); + + v = BM_OtherEdgeVert(e2, v); + BM_ITER(e3, &iter, bm, BM_EDGES_OF_VERT, v) { + if (e3 != e2 && BMO_TestFlag(bm, e3, EDGE_MARK) && !BMO_TestFlag(bm, e3, EDGE_DONE)) { + break; + } + } + e2 = e3; + } while (e2 && e2 != e); + + if (v && !e2) { + if (c==0) { + BLI_array_append(vv1, v); + } else { + BLI_array_append(vv2, v); + } + } + + if (v == ov) { + if (c==0) + cl1 = 1; + else + cl2 = 1; + } + + c++; + } + } + + if (ee1 && ee2) { + int i, j; + BMVert *v1, *v2, *v3, *v4; + int starti=0, lenv1=BLI_array_count(vv1); + + /*handle case of two unclosed loops*/ + if (!cl1 && !cl2) { + v1 = get_outer_vert(bm, ee1[0]); + v2 = BLI_array_count(ee1) > 1 ? get_outer_vert(bm, ee1[1]) : v1; + v3 = get_outer_vert(bm, ee2[0]); + v4 = BLI_array_count(ee2) > 1 ? get_outer_vert(bm, ee2[1]) : v3; +\ + if (len_v3v3(v1->co, v3->co) > len_v3v3(v1->co, v4->co)) { + for (i=0; ico, vv2[0]->co) < min) { + min = len_v3v3(vv1[i]->co, vv2[0]->co); + starti = i; + } + } + } + + j = 0; + for (i=0; i= BLI_array_count(ee2)) + break; + + f = BM_Make_QuadTri(bm, vv1[(i + starti)%lenv1], vv2[i], vv2[i+1], vv1[(i+1 + starti)%lenv1], NULL, 1); + if (!f) { + printf("eek!\n"); + } + + j++; + } + } +} diff --git a/source/blender/bmesh/operators/mesh_conv.c b/source/blender/bmesh/operators/mesh_conv.c index 80dcf6d194e..cc6e93da3e2 100644 --- a/source/blender/bmesh/operators/mesh_conv.c +++ b/source/blender/bmesh/operators/mesh_conv.c @@ -146,7 +146,9 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) { if (me->key) { /*set shape key original index*/ keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); - *keyi = i; + if (keyi) { + *keyi = i; + } for (block=me->key->block.first, j=0; block; block=block->next, j++) { float *co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, @@ -799,6 +801,9 @@ void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) { mvert = me->mvert; while(eve) { keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX); + if (!keyi) { + break; + } if (*keyi >= 0 && *keyi < currkey->totelem) { // valid old vertex if(currkey == actkey) { if(actkey == me->key->refkey) { diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c index 10020136b27..16e8505dbca 100644 --- a/source/blender/editors/mesh/bmesh_tools.c +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -4848,3 +4848,34 @@ void EXPORT_MESH_OT_wavefront(wmOperatorType *ot) RNA_def_boolean(ot->srna, "apply_modifiers", 0, "Apply Modifiers", "Apply Modifiers"); RNA_def_boolean(ot->srna, "relpaths", 0, "Relative Paths", "Use relative paths for textures"); } + +static int bridge_edge_loops(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + + if (!EDBM_CallOpf(em, op, "bridge_loops edges=%he", BM_SELECT)) + return OPERATOR_CANCELLED; + + DAG_id_tag_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_bridge_edge_loops(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Bridge edge loops"; + ot->description= "Make faces between two edge loops"; + ot->idname= "MESH_OT_bridge_edge_loops"; + + /* api callbacks */ + ot->exec= bridge_edge_loops; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "inside", 0, "Inside", ""); +} diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 3b33afa8b49..866a51b2b5d 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -316,5 +316,7 @@ void MESH_OT_loopcut(struct wmOperatorType *ot); void MESH_OT_knifetool(struct wmOperatorType *ot); void MESH_OT_bevel(struct wmOperatorType *ot); +void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot); + #endif // MESH_INTERN_H diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 82d925c4ff3..c0e0714c43e 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -161,6 +161,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_select_next_loop); WM_operatortype_append(EXPORT_MESH_OT_wavefront); + WM_operatortype_append(MESH_OT_bridge_edge_loops); } #if 0 /* UNUSED, remove? */