[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [56693] trunk/blender/source/blender/bmesh : bridge tool: support for bridging loops with different numbers of vertices.
Campbell Barton
ideasman42 at gmail.com
Sun May 12 05:36:42 CEST 2013
Revision: 56693
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=56693
Author: campbellbarton
Date: 2013-05-12 03:36:41 +0000 (Sun, 12 May 2013)
Log Message:
-----------
bridge tool: support for bridging loops with different numbers of vertices.
Modified Paths:
--------------
trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.c
trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.h
trunk/blender/source/blender/bmesh/operators/bmo_bridge.c
Modified: trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.c 2013-05-11 19:30:08 UTC (rev 56692)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.c 2013-05-12 03:36:41 UTC (rev 56693)
@@ -157,7 +157,8 @@
count++;
}
else {
- BM_edgeloop_free(r_eloops, el_store);
+ BLI_remlink(r_eloops, el_store);
+ BM_edgeloop_free(el_store);
}
}
}
@@ -168,7 +169,8 @@
{
BMEdgeLoopStore *el_store;
while ((el_store = eloops->first)) {
- BM_edgeloop_free(eloops, el_store);
+ BLI_remlink(eloops, el_store);
+ BM_edgeloop_free(el_store);
}
}
@@ -240,10 +242,17 @@
/* -------------------------------------------------------------------- */
/* BM_edgeloop_*** functions */
-void BM_edgeloop_free(ListBase *eloops, BMEdgeLoopStore *el_store)
+BMEdgeLoopStore *BM_edgeloop_copy(BMEdgeLoopStore *el_store)
{
+ BMEdgeLoopStore *el_store_copy = MEM_mallocN(sizeof(*el_store), __func__);
+ *el_store_copy = *el_store;
+ BLI_duplicatelist(&el_store_copy->verts, &el_store->verts);
+ return el_store_copy;
+}
+
+void BM_edgeloop_free(BMEdgeLoopStore *el_store)
+{
BLI_freelistN(&el_store->verts);
- BLI_remlink(eloops, el_store);
MEM_freeN(el_store);
}
@@ -347,3 +356,42 @@
negate_v3(el_store->no);
BLI_reverselist(&el_store->verts);
}
+
+void BM_edgeloop_expand(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, int el_store_len)
+{
+ /* first double until we are more then half as big */
+ while ((el_store->len * 2) < el_store_len) {
+ LinkData *node_curr = el_store->verts.first;
+ while (node_curr) {
+ LinkData *node_curr_copy = MEM_dupallocN(node_curr);
+ BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
+ el_store->len++;
+ node_curr = node_curr_copy->next;
+ }
+ }
+
+ if (el_store->len < el_store_len) {
+ const int step = max_ii(1, el_store->len / (el_store->len % el_store_len));
+ LinkData *node_first = el_store->verts.first;
+ LinkData *node_curr = node_first;
+
+ do {
+ LinkData *node_curr_init = node_curr;
+ LinkData *node_curr_copy;
+ int i = 0;
+ LISTBASE_CIRCULAR_FORWARD_BEGIN (&el_store->verts, node_curr, node_curr_init) {
+ if (i++ < step) {
+ break;
+ }
+ }
+ LISTBASE_CIRCULAR_FORWARD_END (&el_store->verts, node_curr, node_curr_init);
+
+ node_curr_copy = MEM_dupallocN(node_curr);
+ BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
+ el_store->len++;
+ node_curr = node_curr_copy->next;
+ } while (el_store->len < el_store_len);
+ }
+
+ BLI_assert(el_store->len == el_store_len);
+}
Modified: trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.h
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.h 2013-05-11 19:30:08 UTC (rev 56692)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_edgeloop.h 2013-05-12 03:36:41 UTC (rev 56693)
@@ -42,7 +42,8 @@
/* single edgeloop */
-void BM_edgeloop_free(struct ListBase *eloops, struct BMEdgeLoopStore *el_store);
+struct BMEdgeLoopStore *BM_edgeloop_copy(struct BMEdgeLoopStore *el_store);
+void BM_edgeloop_free(struct BMEdgeLoopStore *el_store);
bool BM_edgeloop_is_closed(struct BMEdgeLoopStore *el_store);
int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store);
struct ListBase *BM_edgeloop_verts_get(struct BMEdgeLoopStore *el_store);
@@ -51,6 +52,7 @@
void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store);
void BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store);
void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store);
+void BM_edgeloop_expand(BMesh *bm, struct BMEdgeLoopStore *el_store, int el_store_len);
#define BM_EDGELOOP_NEXT(el_store, elink) \
(elink)->next ? elink->next : (BM_edgeloop_is_closed(el_store) ? BM_edgeloop_verts_get(el_store)->first : NULL)
Modified: trunk/blender/source/blender/bmesh/operators/bmo_bridge.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_bridge.c 2013-05-11 19:30:08 UTC (rev 56692)
+++ trunk/blender/source/blender/bmesh/operators/bmo_bridge.c 2013-05-12 03:36:41 UTC (rev 56693)
@@ -118,7 +118,25 @@
{
LinkData *el_a_first, *el_b_first;
const bool is_closed = BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b);
+ int el_store_a_len, el_store_b_len;
+ bool el_store_b_free = false;
+ el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a);
+ el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b);
+
+ if (el_store_a_len < el_store_b_len) {
+ SWAP(int, el_store_a_len, el_store_b_len);
+ SWAP(struct BMEdgeLoopStore *, el_store_a, el_store_b);
+ }
+
+ if (use_merge) {
+ BLI_assert((el_store_a_len == el_store_a_len));
+ }
+
+ if (el_store_a_len != el_store_b_len) {
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
+ }
+
if (dot_v3v3(BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b)) < 0.0f) {
BM_edgeloop_flip(bm, el_store_b);
}
@@ -139,7 +157,7 @@
/* vote on winding (so new face winding is based on existing connected faces) */
if (bm->totface) {
struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
- int i = 0;
+ int i;
int winding_votes = 0;
int winding_dir = 1;
for (i = 0; i < 2; i++, winding_dir = -winding_dir) {
@@ -160,6 +178,12 @@
}
}
+ if (el_store_a_len > el_store_b_len) {
+ el_store_b = BM_edgeloop_copy(el_store_b);
+ BM_edgeloop_expand(bm, el_store_b, el_store_a_len);
+ el_store_b_free = true;
+ }
+
if (is_closed) {
bm_bridge_best_rotation(el_store_a, el_store_b);
}
@@ -253,44 +277,95 @@
v_b_next = el_b_next->data;
/* get loop data - before making the face */
- bm_vert_loop_pair(bm, v_a, v_b, &l_1, &l_2);
- bm_vert_loop_pair(bm, v_a_next, v_b_next, &l_1_next, &l_2_next);
- /* copy if loop data if its is missing on one ring */
+ if (v_b != v_b_next) {
+ bm_vert_loop_pair(bm, v_a, v_b, &l_1, &l_2);
+ bm_vert_loop_pair(bm, v_a_next, v_b_next, &l_1_next, &l_2_next);
+ }
+ else {
+ /* lazy, could be more clever here */
+ l_1 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_a, 0);
+ l_1_next = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_a_next, 0);
+ l_2 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_b, 0);
+ l_2_next = l_2;
+ }
+
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,
- el_a->data,
- el_b->data,
- el_b_next->data,
- el_a_next->data,
- f_example, true);
- BMO_elem_flag_enable(bm, f, FACE_OUT);
+ if (v_b != v_b_next) {
+ /* copy if loop data if its is missing on one ring */
+ f = BM_face_create_quad_tri(bm, v_a, v_b, v_b_next, v_a_next, f_example, true);
+ BMO_elem_flag_enable(bm, f, FACE_OUT);
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+
+ 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);
+ }
+ else {
+ /* fan-fill a triangle */
+ f = BM_face_create_quad_tri(bm, v_a, v_b, v_a_next, NULL, f_example, true);
+ BMO_elem_flag_enable(bm, f, FACE_OUT);
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+
+ 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_1_next, l_iter);
+ }
+
if (el_a_next == el_a_first) {
break;
}
- 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);
-
el_a = el_a_next;
el_b = el_b_next;
}
}
+
+ if (el_store_a_len != el_store_b_len) {
+ struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
+ int i;
+
+ BMOperator op_sub;
+ /* when we have to bridge betweeen different sized edge-loops,
+ * be clever and post-process for best results */
+ BM_mesh_triangulate(bm, true, true, NULL, NULL);
+
+ /* tag verts on each side so we can restrict rotation of edges to verts on the same side */
+ for (i = 0; i < 2; i++) {
+ LinkData *el;
+ for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
+ BM_elem_flag_set((BMVert *)el->data, BM_ELEM_TAG, i);
+ }
+ }
+
+ BMO_op_initf(bm, &op_sub, 0,
+ "beautify_fill faces=%hf edges=ae use_restrict_tag=%b",
+ BM_ELEM_TAG, true);
+ BMO_op_exec(bm, &op_sub);
+ /* there may also be tagged faces that didnt rotate, mark input */
+ BMO_slot_buffer_flag_enable(bm, op_sub.slots_in, "faces", BM_FACE, FACE_OUT);
+ BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT);
+ BMO_op_finish(bm, &op_sub);
+ }
+
+ if (el_store_b_free) {
+ BM_edgeloop_free(el_store_b);
+ }
}
void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
{
ListBase eloops = {NULL};
LinkData *el_store;
- int eloop_len;
/* merge-bridge support */
const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge");
@@ -310,11 +385,11 @@
BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
"Select at least two edge loops");
goto cleanup;
+ }
- }
- else {
+ if (use_merge) {
bool match = true;
- eloop_len = BM_edgeloop_length_get(eloops.first);
+ const int eloop_len = BM_edgeloop_length_get(eloops.first);
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list