Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/bmesh/operators/bmo_connect.c')
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c199
1 files changed, 123 insertions, 76 deletions
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index 7418be3565c..6943dcb3e5d 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -39,6 +39,7 @@
#define FACE_NEW 2
#define EDGE_MARK 4
#define EDGE_DONE 8
+#define FACE_OUT 16
void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
{
@@ -223,6 +224,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) {
@@ -370,39 +375,36 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
}
}
- /* Find the shortest distance from a vert in vv1 to vv2[0]. Use that
- * vertex in vv1 as a starting point in the first loop, while starting
- * from vv2[0] in the second loop. This is a simplistic attempt to get
- * a better edge-to-edge match between the two loops. */
+ /* Find the smallest sum of distances from verts in vv1 to verts in vv2,
+ * finding a starting point in the first loop, to start with vv2[0] in the
+ * second loop. This is a simplistic attempt to get a better edge-to-edge
+ * match between two loops. */
if (cl1) {
- int previ, nexti;
float min = 1e32;
- /* BMESH_TODO: Would be nice to do a more thorough analysis of all
- * the vertices in both loops to find a more accurate match for the
- * starting point and winding direction of the bridge generation. */
-
- 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);
+ for (i = 0; i < lenv1; i++) {
+ float len;
+
+ /* compute summed length between vertices in forward direction */
+ len = 0.0f;
+ for (j = 0; j < lenv2; j++)
+ len += len_v3v3(vv1[clamp_index(i+j, lenv1)]->co, vv2[j]->co);
+
+ if (len < min) {
+ min = len;
starti = i;
}
- }
- /* Reverse iteration order for the first loop if the distance of
- * the (starti - 1) vert from vv1 is a better match for vv2[1] than
- * the (starti + 1) vert.
- *
- * This is not always going to be right, but it will work better in
- * the average case.
- */
- previ = clamp_index(starti - 1, lenv1);
- nexti = clamp_index(starti + 1, lenv1);
-
- /* avoid sqrt for comparison */
- if (len_squared_v3v3(vv1[nexti]->co, vv2[1]->co) > len_squared_v3v3(vv1[previ]->co, vv2[1]->co)) {
- /* reverse direction for reading vv1 (1 is forward, -1 is backward) */
- dir1 = -1;
+ /* compute summed length between vertices in backward direction */
+ len = 0.0f;
+ for (j = 0; j < lenv2; j++)
+ len += len_v3v3(vv1[clamp_index(i-j, lenv1)]->co, vv2[j]->co);
+
+ if (len < min) {
+ min = len;
+ starti = i;
+ dir1 = -1;
+ }
}
}
@@ -426,63 +428,108 @@ 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;
-
- 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);
+ /* merge loops of bridge faces */
+ if (use_merge) {
+ const int vert_len = mini(BLI_array_count(vv1), BLI_array_count(vv2)) - ((cl1 || cl2) ? 1 : 0);
+ const int edge_len = mini(BLI_array_count(ee1), BLI_array_count(ee2));
+
+ 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]);
+ }
}
-
- /* 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_elem_flag_merge(vv1[i], vv2[i]);
+ BM_vert_splice(bm, vv1[i], vv2[i]);
+ }
+ for (i = 0; i < edge_len; i++) {
+ BM_data_interp_from_edges(bm, ee1[i], ee2[i], ee2[i], merge_factor);
+ BM_elem_flag_merge(ee1[i], ee2[i]);
+ 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;
+
+ 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 (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);
+ 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 {
+ BMO_elem_flag_enable(bm, f, FACE_OUT);
+
+ 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);
+ }
}
}
}
+ BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_OUT);
+
cleanup:
BLI_array_free(ee1);
BLI_array_free(ee2);