[Bf-blender-cvs] [9d2be27] dyntopo_holes: basic bridge support
Campbell Barton
noreply at git.blender.org
Sat Oct 4 12:05:32 CEST 2014
Commit: 9d2be27f1757883b74028610a99b0823cb2165a2
Author: Campbell Barton
Date: Sat Oct 4 11:47:54 2014 +0200
Branches: dyntopo_holes
https://developer.blender.org/rB9d2be27f1757883b74028610a99b0823cb2165a2
basic bridge support
===================================================================
M source/blender/blenkernel/intern/pbvh_bmesh.c
===================================================================
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index e84ec99..d16a99a 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -25,6 +25,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_alloca.h"
+#include "BLI_array.h"
#include "BLI_buffer.h"
#include "BLI_ghash.h"
#include "BLI_heap.h"
@@ -1201,6 +1203,167 @@ static bool bm_vert_ordered_fan_walk(BMVert *v, BLI_Buffer *buf)
return true;
}
+static void bm_varray_center(
+ const BMVert **varr, const int varr_num,
+ float r_center[3])
+{
+ int i;
+
+ zero_v3(r_center);
+ for (i = 0; i < varr_num; i++) {
+ add_v3_v3(r_center, varr[i]->co);
+ }
+ mul_v3_fl(r_center, 1.0f / (float)varr_num);
+}
+
+static void bm_varray_normal(
+ const BMVert **varr, int varr_num,
+ float r_normal[3])
+{
+ const BMVert *v_prev = varr[varr_num - 1];
+ const BMVert *v_curr = varr[0];
+ int i;
+
+ zero_v3(r_normal);
+
+ /* Newell's Method */
+ for (i = 0; i < varr_num; v_prev = v_curr, v_curr = varr[++i]) {
+ add_newell_cross_v3_v3v3(r_normal, v_prev->co, v_curr->co);
+ }
+
+ normalize_v3(r_normal);
+}
+
+static void bm_varray_dirs_2d(
+ const BMVert **varr, int varr_num,
+ float axis_mat[3][3], const float center[3],
+ float (*r_dirs)[2])
+{
+ float center_2d[2];
+ int i;
+
+ mul_v2_m3v3(center_2d, axis_mat, center);
+
+ for (i = 0; i < varr_num; i++) {
+ mul_v2_m3v3(r_dirs[i], axis_mat, varr[i]->co);
+ sub_v2_v2(r_dirs[i], center_2d);
+ normalize_v2(r_dirs[i]);
+ }
+}
+
+static void pbvh_bridge_loops(
+ PBVH *bvh,
+ BMVert **eloop_a, int eloop_a_len,
+ BMVert **eloop_b, int eloop_b_len,
+ BMFace *f_adj)
+{
+ /* all edges will have a face, since we didnt remove the center fan yet */
+ const int ni = BM_ELEM_CD_GET_INT(f_adj, bvh->cd_face_node_offset);
+ float (*eloop_a_dirs)[2] = BLI_array_alloca(eloop_a_dirs, eloop_a_len);
+ float (*eloop_b_dirs)[2] = BLI_array_alloca(eloop_b_dirs, eloop_b_len);
+ float eloop_a_cent[3], eloop_a_normal[3];
+ float eloop_b_cent[3], eloop_b_normal[3];
+ float axis[3];
+ float axis_mat[3][3];
+ int a_offset = 0;
+ int b_offset = 0;
+ int a_step_base;
+ int b_step_base;
+
+ BLI_assert(eloop_a_len >= eloop_b_len);
+
+ bm_varray_center((const BMVert **)eloop_a, eloop_a_len, eloop_a_cent);
+ bm_varray_center((const BMVert **)eloop_b, eloop_b_len, eloop_b_cent);
+
+ bm_varray_normal((const BMVert **)eloop_a, eloop_a_len, eloop_a_normal);
+ bm_varray_normal((const BMVert **)eloop_b, eloop_b_len, eloop_b_normal);
+
+ if (dot_v3v3(eloop_a_normal, eloop_b_normal) < 0.0f) {
+ BLI_array_reverse(eloop_b, eloop_b_len);
+ negate_v3(eloop_b_normal);
+ }
+
+ add_v3_v3v3(axis, eloop_a_normal, eloop_b_normal);
+ normalize_v3(axis);
+
+ axis_dominant_v3_to_m3(axis_mat, axis);
+
+ bm_varray_dirs_2d((const BMVert **)eloop_a, eloop_a_len, axis_mat, eloop_a_cent, eloop_a_dirs);
+ bm_varray_dirs_2d((const BMVert **)eloop_b, eloop_b_len, axis_mat, eloop_b_cent, eloop_b_dirs);
+
+ /* find closest angle on the smaller loop */
+ {
+ float t_best;
+ int i;
+
+ a_offset = 0;
+
+ t_best = -1.0f;
+ for (i = 0; i < eloop_b_len; i++) {
+ float t = dot_v2v2(eloop_a_dirs[a_offset], eloop_b_dirs[i]);
+ if (t > t_best) {
+ t_best = t;
+ b_offset = i;
+ }
+ }
+ }
+
+ a_step_base = 0;
+ b_step_base = 0;
+
+ do {
+ BMFace *f_new;
+ BMVert *v_tri[3];
+ BMEdge *e_tri[3];
+ /* Step (false == a, true == b) */
+ bool step_side;
+
+ const int a_curr = ((a_step_base + a_offset)) % eloop_a_len;
+ const int b_curr = ((b_step_base + b_offset)) % eloop_b_len;
+ const int a_next = ((a_step_base + a_offset) + 1) % eloop_a_len;
+ const int b_next = ((b_step_base + b_offset) + 1) % eloop_b_len;
+
+ if ((a_step_base != eloop_a_len) && (b_step_base == eloop_b_len)) {
+ step_side = false;
+ }
+ else if ((a_step_base == eloop_a_len) && (b_step_base != eloop_b_len)) {
+ step_side = true;
+ }
+ else {
+ if (dot_v2v2(eloop_a_dirs[a_curr], eloop_b_dirs[b_next]) <
+ dot_v2v2(eloop_a_dirs[a_next], eloop_b_dirs[b_curr]))
+ {
+ step_side = false;
+ }
+ else {
+ step_side = true;
+ }
+ }
+
+ if (step_side == false) {
+ v_tri[0] = eloop_b[b_curr];
+ v_tri[1] = eloop_a[a_curr];
+ v_tri[2] = eloop_a[a_next];
+ a_step_base += 1;
+ }
+ else {
+ v_tri[0] = eloop_a[a_curr];
+ v_tri[2] = eloop_b[b_curr];
+ v_tri[1] = eloop_b[b_next];
+ b_step_base += 1;
+ }
+ BLI_assert(a_step_base <= eloop_a_len);
+ BLI_assert(b_step_base <= eloop_b_len);
+
+ if (!BM_face_exists(v_tri, 3, NULL)) {
+ bm_edges_from_tri(bvh->bm, v_tri, e_tri);
+ f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj, bvh->cd_face_node_offset);
+ (void)f_new;
+ }
+ } while ((a_step_base != eloop_a_len) ||
+ (b_step_base != eloop_b_len));
+}
+
static void pbvh_bmesh_collapse_close_verts(EdgeQueueContext *eq_ctx,
PBVH *bvh)
{
@@ -1235,26 +1398,28 @@ static void pbvh_bmesh_collapse_close_verts(EdgeQueueContext *eq_ctx,
continue;
}
- if (!bm_vert_ordered_fan_walk(v1, &edge_verts_v1))
+ /* Regarding the check for '< 3' verts, this should NOT happen,
+ * but have a guard here to prevent crashing for now */
+ if (!bm_vert_ordered_fan_walk(v1, &edge_verts_v1) || (edge_verts_v1.count < 3))
continue;
- if (!bm_vert_ordered_fan_walk(v2, &edge_verts_v2))
- continue;
-
- /* this should NOT happen, but have a guard here to prevent crashing for now */
- if (edge_verts_v1.count < 3 || edge_verts_v2.count < 3) {
+ if (!bm_vert_ordered_fan_walk(v2, &edge_verts_v2) || (edge_verts_v2.count < 3))
continue;
- }
/* Note, maybe this should be done after deletion of the vertices? */
-#if 0
- if (edge_verts_v2.count > edge_verts_v1.count) {
- pbvh_bridge_loops(bvh, &edge_verts_v1, &edge_verts_v2, deleted_verts);
+ if (edge_verts_v2.count < edge_verts_v1.count) {
+ pbvh_bridge_loops(
+ bvh,
+ edge_verts_v1.data, edge_verts_v1.count,
+ edge_verts_v2.data, edge_verts_v2.count,
+ BM_vert_find_first_loop(v1)->f);
}
else {
- pbvh_bridge_loops(bvh, &edge_verts_v2, &edge_verts_v1, deleted_verts);
+ pbvh_bridge_loops(
+ bvh,
+ edge_verts_v2.data, edge_verts_v2.count,
+ edge_verts_v1.data, edge_verts_v1.count,
+ BM_vert_find_first_loop(v2)->f);
}
-#endif
-
/* Remove the faces (would use 'BM_FACES_OF_VERT' except we can't look on data we remove) */
while ((l = BM_vert_find_first_loop(v1))) {
More information about the Bf-blender-cvs
mailing list