[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