=bmesh: bridge edge loop tool=

rough version of a new bridge tool.

ctrl-e -> bridge (two) edge loops
This commit is contained in:
2011-08-15 23:38:51 +00:00
parent a7a0c17ec5
commit 59e95fa0ff
10 changed files with 218 additions and 5 deletions

View File

@@ -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")

View File

@@ -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);
}
}
}
}

View File

@@ -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);

View File

@@ -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*));

View File

@@ -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

View File

@@ -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; i<BLI_array_count(ee1)/2; i++) {
SWAP(void*, ee1[i], ee1[BLI_array_count(ee1)-i-1]);
SWAP(void*, vv1[i], vv1[BLI_array_count(vv1)-i-1]);
}
}
}
if (cl1) {
float min = 1e32;
for (i=0; i<BLI_array_count(vv1); i++) {
if (len_v3v3(vv1[i]->co, vv2[0]->co) < min) {
min = len_v3v3(vv1[i]->co, vv2[0]->co);
starti = i;
}
}
}
j = 0;
for (i=0; i<BLI_array_count(ee1); i++) {
BMFace *f;
if (j >= 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++;
}
}
}

View File

@@ -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) {

View File

@@ -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", "");
}

View File

@@ -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

View File

@@ -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? */