[Bf-blender-cvs] [1b93b09f6d2] newboolean: Fixed Newboolean bug: how face sides were tracked.

Howard Trickey noreply at git.blender.org
Mon Apr 20 23:40:38 CEST 2020


Commit: 1b93b09f6d2eb32df0cf60fed746ea95bc6d3687
Author: Howard Trickey
Date:   Mon Apr 20 17:38:09 2020 -0400
Branches: newboolean
https://developer.blender.org/rB1b93b09f6d2eb32df0cf60fed746ea95bc6d3687

Fixed Newboolean bug: how face sides were tracked.

Also, being more paranoid about new BMesh elements changing
positions in their tables after creating new elements, so
copying them all first.

===================================================================

M	source/blender/bmesh/tools/bmesh_boolean.c

===================================================================

diff --git a/source/blender/bmesh/tools/bmesh_boolean.c b/source/blender/bmesh/tools/bmesh_boolean.c
index ac79d2eedeb..bc95444178b 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.c
+++ b/source/blender/bmesh/tools/bmesh_boolean.c
@@ -29,7 +29,6 @@
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_utildefines.h"
 #include "BLI_alloca.h"
 #include "BLI_bitmap.h"
 #include "BLI_delaunay_2d.h"
@@ -148,10 +147,10 @@ typedef struct MeshAdd {
   int totvert;
   int totedge;
   int totface;
-  int vindex_start;   /* Add this to position in verts to get index of new vert. */
-  int eindex_start;   /* Add this to position in edges to get index of new edge. */
-  int findex_start;   /* Add this to position in faces to get index of new face. */
-  IMesh *im;          /* Underlying IMesh. */
+  int vindex_start; /* Add this to position in verts to get index of new vert. */
+  int eindex_start; /* Add this to position in edges to get index of new edge. */
+  int findex_start; /* Add this to position in faces to get index of new face. */
+  IMesh *im;        /* Underlying IMesh. */
 } MeshAdd;
 
 /* MeshDelete holds an incremental deletion to an IMesh.
@@ -239,18 +238,18 @@ typedef struct PartPartIntersect {
   int b_index;
 } PartPartIntersect;
 
+/* Bit to set in face_side per face flag inside BoolState. */
+#define SIDE_A 1
+#define SIDE_B 2
+#define BOTH_SIDES_OPP_NORMALS 4
+
 typedef struct BoolState {
   MemArena *mem_arena;
   IMesh im;
-  int boolean_mode;
   double eps;
-  int (*test_fn)(void *elem, void *user_data);
-  void *test_fn_user_data;
+  uchar *face_side;
 } BoolState;
 
-/* test_fn results used to distinguish parts of mesh. */
-enum { TEST_NONE = -1, TEST_B = 0, TEST_A = 1, TEST_ALL = 2 };
-
 /* Decoration to shut up gnu 'unused function' warning. */
 #ifdef __GNUC__
 #  define ATTU __attribute__((unused))
@@ -277,6 +276,7 @@ ATTU static void dump_meshchange(const MeshChange *change, const char *label);
 ATTU static void dump_cdt_input(const CDT_input *cdt, const char *label);
 ATTU static void dump_cdt_result(const CDT_result *cdt, const char *label, const char *prefix);
 ATTU static void dump_bm(struct BMesh *bm, const char *msg);
+ATTU bool analyze_bmesh_for_boolean(BMesh *bm, bool verbose, int side, uchar *face_side);
 #endif
 
 #ifdef PERFDEBUG
@@ -810,7 +810,9 @@ static bool isect_tri_tri_epsilon_v3_db_ex(const double t_a0[3],
 
 /* TODO: move these into math_geom.c. */
 /* What is interpolation factor that gives closest point on line to a given point? */
-static double line_interp_factor_v3_db(const double point[3], const double line_co1[3], const double line_co2[3])
+static double line_interp_factor_v3_db(const double point[3],
+                                       const double line_co1[3],
+                                       const double line_co2[3])
 {
   double h[3], seg_dir[3], seg_len_squared;
 
@@ -831,11 +833,11 @@ static double line_interp_factor_v3_db(const double point[3], const double line_
  * \note Similar logic to isect_ray_plane_v3.
  */
 static int isect_seg_plane_normalized_epsilon_v3_db(const double seg_co1[3],
-             const double seg_co2[3],
-             const double plane[4],
-             double epsilon,
-             double r_isect[3],
-             double *r_lambda)
+                                                    const double seg_co2[3],
+                                                    const double plane[4],
+                                                    double epsilon,
+                                                    double r_isect[3],
+                                                    double *r_lambda)
 {
   double h[3], plane_co[3], seg_dir[3], side1, side2;
   double dot, lambda;
@@ -884,7 +886,7 @@ static void init_imesh_from_bmesh(IMesh *im, BMesh *bm)
   im->bm = bm;
   im->me = NULL;
   BM_mesh_elem_table_ensure(bm, BM_VERT | BM_EDGE | BM_FACE);
-  BM_mesh_elem_index_ensure(bm, BM_VERT| BM_EDGE | BM_FACE | BM_LOOP);
+  BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE | BM_FACE | BM_LOOP);
   im->co_tree = make_im_co_tree(im);
 }
 
@@ -1202,21 +1204,6 @@ static void imesh_face_calc_tesselation(IMesh *im, int f, int (*r_index)[3])
   }
 }
 
-static int imesh_test_face(const IMesh *im, int (*test_fn)(void *, void *), void *user_data, int f)
-{
-  if (im->bm) {
-    BMFace *bmf = BM_face_at_index(im->bm, f);
-    if (bmf) {
-      return test_fn(bmf, user_data);
-    }
-    return 0;
-  }
-  else {
-    /* TODO */
-    return 0;
-  }
-}
-
 static int resolve_merge(int v, const IntIntMap *vert_merge_map)
 {
   int vmapped = v;
@@ -1228,14 +1215,28 @@ static int resolve_merge(int v, const IntIntMap *vert_merge_map)
   return vmapped;
 }
 
+/* Trying this instead of trying to keep the tables up to date.
+ * I keep having this bug where strange BMVerts are being used
+ * and I hope this will fix it.
+ */
+#define USE_BM_ELEM_COPY
+
+/* To store state of side (side a / side b / opp normals) we will
+ * use these hflag tags in BMFaces. Note that the modifier currently
+ * uses BM_ELEM_DRAW for side a / side b; we'll overwrite that as
+ * modifier code doesn't use it again after this routine returns.
+ */
+#define SIDE_A_TAG BM_ELEM_TAG
+#define SIDE_B_TAG BM_ELEM_DRAW
+#define BOTH_SIDES_OPP_NORMALS_TAG (1 << 6)
+#define ALL_SIDE_TAGS (SIDE_A_TAG | SIDE_B_TAG | BOTH_SIDES_OPP_NORMALS_TAG)
+
 /* Apply the change to the BMesh. Ensure that indices are valid afterwards.
- * Also, fill in r_both_side_faces with (new) indices of faces that have examples from
- * both sides of the boolean operation (because they came from coplanar face intersections).
+ * Also reallocate bs->face_side and set it appropriately,
+ * including marking those faces that have examples on both sides but have opposite
+ * normals with the flag that says that.
  */
-static void apply_meshchange_to_bmesh(BoolState *bs,
-                                      BMesh *bm,
-                                      MeshChange *change,
-                                      IntSet *r_both_side_faces)
+static void apply_meshchange_to_bmesh(BoolState *bs, BMesh *bm, MeshChange *change)
 {
   int bm_tot_v, bm_tot_e, bm_tot_f, tot_new_v, tot_new_e, tot_new_f;
   int i, v, e, f, v1, v2;
@@ -1248,8 +1249,11 @@ static void apply_meshchange_to_bmesh(BoolState *bs,
   BMEdge **new_bmes, **face_bmes;
   BMEdge *bme, *bme_eg;
   BMFace *bmf, *bmf_eg;
-  LinkNode *both_side_bmfaces, *opp_normals_flags, *ln, *ln2;
-  bool both_sides, opp_normals;
+#ifdef USE_BM_ELEM_COPY
+  BMFace **new_bmfs;
+#endif
+  int fside;
+
   MeshAdd *meshadd = &change->add;
   MeshDelete *meshdelete = &change->delete;
   IntIntMap *vert_merge_map = &change->vert_merge_map;
@@ -1269,10 +1273,18 @@ static void apply_meshchange_to_bmesh(BoolState *bs,
 #endif
 
   /* Create new BMVerts. */
+  BM_mesh_elem_table_ensure(bm, BM_VERT);
   bm_tot_v = bm->totvert;
   tot_new_v = meshadd_totvert(meshadd);
+#ifdef USE_BM_ELEM_COPY
+  new_bmvs = MEM_mallocN((size_t)(bm_tot_v + tot_new_v) * sizeof(BMVert *), __func__);
+  BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)new_bmvs, bm_tot_v);
+#endif
   if (tot_new_v > 0) {
+#ifndef USE_BM_ELEM_COPY
     new_bmvs = BLI_array_alloca(new_bmvs, (size_t)tot_new_v);
+#endif
+    BLI_assert(meshadd->vindex_start == bm_tot_v);
     for (v = meshadd->vindex_start; v < meshadd->vindex_start + tot_new_v; v++) {
       newvert = meshadd_get_newvert(meshadd, v);
       BLI_assert(newvert != NULL);
@@ -1284,21 +1296,34 @@ static void apply_meshchange_to_bmesh(BoolState *bs,
         /* BM_mesh_validate(bm); */
       }
 #endif
+#ifdef USE_BM_ELEM_COPY
+      new_bmvs[v] = bmv;
+#else
       new_bmvs[v - meshadd->vindex_start] = bmv;
+#endif
     }
   }
 
+#ifndef USE_BM_ELEM_COPY
   /* Adding verts has made the vertex table dirty.
    * It is probably still ok, but just in case...
    * TODO: find a way to avoid regenerating this table, maybe.
    */
   BM_mesh_elem_table_ensure(bm, BM_VERT);
+#endif
 
   /* Now the edges. */
   bm_tot_e = bm->totedge;
   tot_new_e = meshadd_totedge(meshadd);
+#ifdef USE_BM_ELEM_COPY
+  new_bmes = MEM_mallocN((size_t)(bm_tot_e + tot_new_e) * sizeof(BMEdge *), __func__);
+  BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)new_bmes, bm_tot_e);
+#endif
   if (tot_new_e > 0) {
+#ifndef USE_BM_ELEM_COPY
     new_bmes = BLI_array_alloca(new_bmes, (size_t)tot_new_e);
+#endif
+    BLI_assert(meshadd->eindex_start == bm_tot_e);
     for (e = meshadd->eindex_start; e < meshadd->eindex_start + tot_new_e; e++) {
       newedge = meshadd_get_newedge(meshadd, e);
       BLI_assert(newedge != NULL);
@@ -1307,7 +1332,11 @@ static void apply_meshchange_to_bmesh(BoolState *bs,
          * though it may be technically dirty, all of the example indices
          * will still be OK since they should be from original edges. */
         BLI_assert(newedge->example < meshadd->eindex_start);
+#ifdef USE_BM_ELEM_COPY
+        bme_eg = new_bmes[newedge->example];
+#else
         bme_eg = bm->etable[newedge->example];
+#endif
         BLI_assert(bme_eg != NULL && bme_eg->head.htype == BM_EDGE);
       }
       else {
@@ -1315,6 +1344,12 @@ static void apply_meshchange_to_bmesh(BoolState *bs,
       }
       v1 = newedge->v1;
       v2 = newedge->v2;
+#ifdef USE_BM_ELEM_COPY
+      if (v1 < bm_tot_v) {
+        v1 = resolve_merge(v1, vert_merge_map);
+      }
+      bmv1 = new_bmvs[v1];
+#else
       if (v1 < bm_tot_v) {
         v1 = resolve_merge(v1, vert_merge_map);
         bmv1 = BM_vert_at_index(bm, v1);
@@ -1322,7 +1357,14 @@ static void apply_meshchange_to_bmesh(BoolState *bs,
       else {
         bmv1 = new_bmvs[v1 - meshadd->vindex_start];
       }
+#endif
       BLI_assert(bmv1 != NULL);
+#ifdef USE_BM_ELEM_COPY
+      if (v2 < bm_tot_v) {
+        v2 = resolve_merge(v2, vert_merge_map);
+      }
+      bmv2 = new_bmvs[v2];
+#else
       if (v2 < bm_tot_v) {
         v2 = resolve_merge(v2, vert_merge_map);
         bmv2 = BM_vert_at_index(bm, v2);
@@ -1330,7 +1372,9 @@ static void apply_meshchange_to_bmesh(BoolState *bs,
       else {
         bmv2 = new_bmvs[v2 - meshadd->vindex_start];
       }
+#endif
       BLI_assert(bmv2 != NULL);
+      BLI_assert(v1 != v2 && bmv1 != bmv2);
       bme = BM_ed

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list