bmesh tool: support for merged-bridge (like bridge, collapsing), with a
factor to blend between loops.
This commit is contained in:
@@ -422,6 +422,8 @@ static BMOpDefine bmo_bridge_loops_def = {
|
||||
"bridge_loops",
|
||||
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */
|
||||
{BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */
|
||||
{BMO_OP_SLOT_BOOL, "use_merge"},
|
||||
{BMO_OP_SLOT_FLT, "merge_factor"},
|
||||
{0, /* null-terminating sentinel */}},
|
||||
bmo_bridge_loops_exec,
|
||||
0,
|
||||
|
||||
@@ -223,6 +223,10 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
|
||||
BMEdge *e, *nexte;
|
||||
int c = 0, cl1 = 0, cl2 = 0;
|
||||
|
||||
/* merge-bridge support */
|
||||
const int use_merge = BMO_slot_bool_get(op, "use_merge");
|
||||
const float merge_factor = BMO_slot_float_get(op, "merge_factor");
|
||||
|
||||
BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK);
|
||||
|
||||
BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) {
|
||||
@@ -423,59 +427,99 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate the bridge quads */
|
||||
for (i = 0; i < BLI_array_count(ee1) && i < BLI_array_count(ee2); i++) {
|
||||
BMFace *f;
|
||||
/* merge loops of bridge faces */
|
||||
if (use_merge) {
|
||||
/* at the moment these will be the same */
|
||||
const int vert_len = mini(BLI_array_count(vv1), BLI_array_count(vv2));
|
||||
const int edge_len = mini(BLI_array_count(ee1), BLI_array_count(ee2));
|
||||
|
||||
BMLoop *l_1 = NULL;
|
||||
BMLoop *l_2 = NULL;
|
||||
BMLoop *l_1_next = NULL;
|
||||
BMLoop *l_2_next = NULL;
|
||||
BMLoop *l_iter;
|
||||
BMFace *f_example;
|
||||
|
||||
int i1, i1next, i2, i2next;
|
||||
|
||||
i1 = clamp_index(i * dir1 + starti, lenv1);
|
||||
i1next = clamp_index((i + 1) * dir1 + starti, lenv1);
|
||||
i2 = i;
|
||||
i2next = clamp_index(i + 1, lenv2);
|
||||
|
||||
if (vv1[i1] == vv1[i1next]) {
|
||||
continue;
|
||||
if (merge_factor <= 0.0f) {
|
||||
/* 2 --> 1 */
|
||||
for (i = 0; i < vert_len; i++) {
|
||||
BM_vert_splice(bm, vv2[i], vv1[i]);
|
||||
}
|
||||
for (i = 0; i < edge_len; i++) {
|
||||
BM_edge_splice(bm, ee2[i], ee1[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (wdir < 0) {
|
||||
SWAP(int, i1, i1next);
|
||||
SWAP(int, i2, i2next);
|
||||
}
|
||||
|
||||
/* get loop data - before making the face */
|
||||
bm_vert_loop_pair(bm, vv1[i1], vv2[i2], &l_1, &l_2);
|
||||
bm_vert_loop_pair(bm, vv1[i1next], vv2[i2next], &l_1_next, &l_2_next);
|
||||
/* copy if loop data if its is missing on one ring */
|
||||
if (l_1 && l_1_next == NULL) l_1_next = l_1;
|
||||
if (l_1_next && l_1 == NULL) l_1 = l_1_next;
|
||||
if (l_2 && l_2_next == NULL) l_2_next = l_2;
|
||||
if (l_2_next && l_2 == NULL) l_2 = l_2_next;
|
||||
f_example = l_1 ? l_1->f : (l_2 ? l_2->f : NULL);
|
||||
|
||||
f = BM_face_create_quad_tri(bm,
|
||||
vv1[i1],
|
||||
vv2[i2],
|
||||
vv2[i2next],
|
||||
vv1[i1next],
|
||||
f_example, TRUE);
|
||||
if (!f || f->len != 4) {
|
||||
fprintf(stderr, "%s: in bridge! (bmesh internal error)\n", __func__);
|
||||
else if (merge_factor >= 1.0f) {
|
||||
/* 1 --> 2 */
|
||||
for (i = 0; i < vert_len; i++) {
|
||||
BM_vert_splice(bm, vv1[i], vv2[i]);
|
||||
}
|
||||
for (i = 0; i < edge_len; i++) {
|
||||
BM_edge_splice(bm, ee1[i], ee2[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
l_iter = BM_FACE_FIRST_LOOP(f);
|
||||
/* mid factor, be tricky */
|
||||
/* 1 --> 2 */
|
||||
for (i = 0; i < vert_len; i++) {
|
||||
BM_data_interp_from_verts(bm, vv1[i], vv2[i], vv2[i], merge_factor);
|
||||
interp_v3_v3v3(vv2[i]->co, vv1[i]->co, vv2[i]->co, merge_factor);
|
||||
BM_vert_splice(bm, vv1[i], vv2[i]);
|
||||
}
|
||||
for (i = 0; i < edge_len; i++) {
|
||||
//BM_data_interp_from_edge(bm, vv1[i], vv2[i], vv2[i], merge_factor);
|
||||
BM_edge_splice(bm, ee1[i], ee2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Generate the bridge quads */
|
||||
for (i = 0; i < BLI_array_count(ee1) && i < BLI_array_count(ee2); i++) {
|
||||
BMFace *f;
|
||||
|
||||
if (l_1) BM_elem_attrs_copy(bm, bm, l_1, l_iter); l_iter = l_iter->next;
|
||||
if (l_2) BM_elem_attrs_copy(bm, bm, l_2, l_iter); l_iter = l_iter->next;
|
||||
if (l_2_next) BM_elem_attrs_copy(bm, bm, l_2_next, l_iter); l_iter = l_iter->next;
|
||||
if (l_1_next) BM_elem_attrs_copy(bm, bm, l_1_next, l_iter);
|
||||
BMLoop *l_1 = NULL;
|
||||
BMLoop *l_2 = NULL;
|
||||
BMLoop *l_1_next = NULL;
|
||||
BMLoop *l_2_next = NULL;
|
||||
BMLoop *l_iter;
|
||||
BMFace *f_example;
|
||||
|
||||
int i1, i1next, i2, i2next;
|
||||
|
||||
i1 = clamp_index(i * dir1 + starti, lenv1);
|
||||
i1next = clamp_index((i + 1) * dir1 + starti, lenv1);
|
||||
i2 = i;
|
||||
i2next = clamp_index(i + 1, lenv2);
|
||||
|
||||
if (vv1[i1] == vv1[i1next]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wdir < 0) {
|
||||
SWAP(int, i1, i1next);
|
||||
SWAP(int, i2, i2next);
|
||||
}
|
||||
|
||||
/* get loop data - before making the face */
|
||||
bm_vert_loop_pair(bm, vv1[i1], vv2[i2], &l_1, &l_2);
|
||||
bm_vert_loop_pair(bm, vv1[i1next], vv2[i2next], &l_1_next, &l_2_next);
|
||||
/* copy if loop data if its is missing on one ring */
|
||||
if (l_1 && l_1_next == NULL) l_1_next = l_1;
|
||||
if (l_1_next && l_1 == NULL) l_1 = l_1_next;
|
||||
if (l_2 && l_2_next == NULL) l_2_next = l_2;
|
||||
if (l_2_next && l_2 == NULL) l_2 = l_2_next;
|
||||
f_example = l_1 ? l_1->f : (l_2 ? l_2->f : NULL);
|
||||
|
||||
f = BM_face_create_quad_tri(bm,
|
||||
vv1[i1],
|
||||
vv2[i2],
|
||||
vv2[i2next],
|
||||
vv1[i1next],
|
||||
f_example, TRUE);
|
||||
if (!f || f->len != 4) {
|
||||
fprintf(stderr, "%s: in bridge! (bmesh internal error)\n", __func__);
|
||||
}
|
||||
else {
|
||||
l_iter = BM_FACE_FIRST_LOOP(f);
|
||||
|
||||
if (l_1) BM_elem_attrs_copy(bm, bm, l_1, l_iter); l_iter = l_iter->next;
|
||||
if (l_2) BM_elem_attrs_copy(bm, bm, l_2, l_iter); l_iter = l_iter->next;
|
||||
if (l_2_next) BM_elem_attrs_copy(bm, bm, l_2_next, l_iter); l_iter = l_iter->next;
|
||||
if (l_1_next) BM_elem_attrs_copy(bm, bm, l_1_next, l_iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4804,8 +4804,12 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op)
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
BMEditMesh *em = BMEdit_FromObject(obedit);
|
||||
|
||||
if (!EDBM_op_callf(em, op, "bridge_loops edges=%he", BM_ELEM_SELECT))
|
||||
if (!EDBM_op_callf(em, op,
|
||||
"bridge_loops edges=%he use_merge=%b merge_factor=%f",
|
||||
BM_ELEM_SELECT, RNA_boolean_get(op->ptr, "use_merge"), RNA_float_get(op->ptr, "merge_factor")))
|
||||
{
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
EDBM_update_generic(C, em, TRUE);
|
||||
|
||||
@@ -4827,6 +4831,9 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_boolean(ot->srna, "inside", 0, "Inside", "");
|
||||
|
||||
RNA_def_boolean(ot->srna, "use_merge", FALSE, "Merge", "Merge rather than creating faces");
|
||||
RNA_def_float(ot->srna, "merge_factor", 0.5f, 0.0f, 1.0f, "Merge Factor", "", 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
||||
Reference in New Issue
Block a user