=bmesh: bridge edge loop tool=
rough version of a new bridge tool. ctrl-e -> bridge (two) edge loops
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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", "");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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? */
|
||||
|
||||
Reference in New Issue
Block a user