[Bf-blender-cvs] [ab7608af1bd] master: Apply patch D8816, from Zachary(AFWS) for collection boolean operand.
Howard Trickey
noreply at git.blender.org
Sun Sep 13 23:00:14 CEST 2020
Commit: ab7608af1bd40548cb79a0312f318a32d2fe8596
Author: Howard Trickey
Date: Sun Sep 13 16:57:27 2020 -0400
Branches: master
https://developer.blender.org/rBab7608af1bd40548cb79a0312f318a32d2fe8596
Apply patch D8816, from Zachary(AFWS) for collection boolean operand.
Also added code so that exact solver does the whole collection at once.
This patch allows users to use a collection (as an alternative to Object)
for the boolean modifier operand, and therefore get rid of a long modifier stack.
===================================================================
M source/blender/blenlib/intern/mesh_boolean.cc
M source/blender/blenloader/intern/versioning_290.c
M source/blender/bmesh/tools/bmesh_boolean.cc
M source/blender/bmesh/tools/bmesh_boolean.h
M source/blender/editors/mesh/editmesh_intersect.c
M source/blender/editors/sculpt_paint/paint_mask.c
M source/blender/makesdna/DNA_modifier_types.h
M source/blender/makesrna/intern/rna_modifier.c
M source/blender/modifiers/intern/MOD_boolean.c
===================================================================
diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc
index e92751efe72..a6ab30a3b26 100644
--- a/source/blender/blenlib/intern/mesh_boolean.cc
+++ b/source/blender/blenlib/intern/mesh_boolean.cc
@@ -2068,11 +2068,11 @@ static bool apply_bool_op(BoolOpType bool_optype, const Array<int> &winding)
return true;
}
for (int i = 1; i < nw; ++i) {
- if (winding[i] == 0) {
- return true;
+ if (winding[i] == 1) {
+ return false;
}
}
- return false;
+ return true;
}
default:
return false;
@@ -2398,8 +2398,7 @@ static IMesh gwn_boolean(const IMesh &tm,
IMesh ans;
Vector<Face *> out_faces;
out_faces.reserve(tm.face_size());
- BLI_assert(nshapes == 2); /* TODO: generalize. */
- UNUSED_VARS_NDEBUG(nshapes);
+ Array<int> winding(nshapes, 0);
for (int p : pinfo.index_range()) {
const Patch &patch = pinfo.patch(p);
/* For test triangle, choose one in the middle of patch list
@@ -2421,40 +2420,41 @@ static IMesh gwn_boolean(const IMesh &tm,
if (dbg_level > 0) {
std::cout << "test point = " << test_point_db << "\n";
}
- int other_shape = 1 - shape;
- /* The point_is_inside_shape function has to approximate if the other
- * shape is not PWN. For most operations, even a hint of being inside
- * gives good results, but when shape is the cutter in a Difference
- * operation, we want to be pretty sure that the point is inside other_shape.
- * E.g., T75827.
- */
- bool need_high_confidence = (op == BoolOpType::Difference) && (shape == 1);
- bool inside = point_is_inside_shape(
- tm, shape_fn, test_point_db, other_shape, need_high_confidence);
- if (dbg_level > 0) {
- std::cout << "test point is " << (inside ? "inside\n" : "outside\n");
- }
- bool do_remove;
- bool do_flip;
- switch (op) {
- case BoolOpType::Intersect:
- do_remove = !inside;
- do_flip = false;
- break;
- case BoolOpType::Union:
- do_remove = inside;
- do_flip = false;
- break;
- case BoolOpType::Difference:
- do_remove = (shape == 0) ? inside : !inside;
- do_flip = (shape == 1);
- break;
- default:
- do_remove = false;
- do_flip = false;
- BLI_assert(false);
+ for (int other_shape = 0; other_shape < nshapes; ++other_shape) {
+ if (other_shape == shape) {
+ continue;
+ }
+ /* The point_is_inside_shape function has to approximate if the other
+ * shape is not PWN. For most operations, even a hint of being inside
+ * gives good results, but when shape is a cutter in a Difference
+ * operation, we want to be pretty sure that the point is inside other_shape.
+ * E.g., T75827.
+ */
+ bool need_high_confidence = (op == BoolOpType::Difference) && (shape != 0);
+ bool inside = point_is_inside_shape(
+ tm, shape_fn, test_point_db, other_shape, need_high_confidence);
+ if (dbg_level > 0) {
+ std::cout << "test point is " << (inside ? "inside" : "outside") << " other_shape "
+ << other_shape << "\n";
+ }
+ winding[other_shape] = inside;
}
+ /* Find out the "in the output volume" flag for each of the cases of winding[shape] == 0
+ * and winding[shape] == 1. If the flags are different, this patch should be in the output.
+ * Also, if this is a Difference and the shape isn't the first one, need to flip the normals.
+ */
+ winding[shape] = 0;
+ bool in_output_volume_0 = apply_bool_op(op, winding);
+ winding[shape] = 1;
+ bool in_output_volume_1 = apply_bool_op(op, winding);
+ bool do_remove = in_output_volume_0 == in_output_volume_1;
+ bool do_flip = !do_remove && op == BoolOpType::Difference && shape != 0;
if (dbg_level > 0) {
+ std::cout << "winding = ";
+ for (int i = 0; i < nshapes; ++i) {
+ std::cout << winding[i] << " ";
+ }
+ std::cout << "\niv0=" << in_output_volume_0 << ", iv1=" << in_output_volume_1 << "\n";
std::cout << "result for patch " << p << ": remove=" << do_remove << ", flip=" << do_flip
<< "\n";
}
@@ -3270,13 +3270,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
if (tm_in.face_size() == 0) {
return IMesh(tm_in);
}
- IMesh tm_si;
- if (use_self) {
- tm_si = trimesh_self_intersect(tm_in, arena);
- }
- else {
- tm_si = trimesh_nary_intersect(tm_in, nshapes, shape_fn, use_self, arena);
- }
+ IMesh tm_si = trimesh_nary_intersect(tm_in, nshapes, shape_fn, use_self, arena);
if (dbg_level > 1) {
write_obj_mesh(tm_si, "boolean_tm_si");
std::cout << "\nboolean_tm_input after intersection:\n" << tm_si;
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index b573fb28474..7805dbdcefa 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -526,19 +526,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
-
- /* Initialize solver for Boolean. */
- if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "enum", "solver")) {
- for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
- LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
- if (md->type == eModifierType_Boolean) {
- BooleanModifierData *bmd = (BooleanModifierData *)md;
- bmd->solver = eBooleanModifierSolver_Fast;
- bmd->flag = 0;
- }
- }
- }
- }
}
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
@@ -597,6 +584,20 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ /* Solver and Collections for Boolean. */
+ if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "char", "solver")) {
+ for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+ if (md->type == eModifierType_Boolean) {
+ BooleanModifierData *bmd = (BooleanModifierData *)md;
+ bmd->solver = eBooleanModifierSolver_Fast;
+ bmd->flag = eBooleanModifierFlag_Object;
+ }
+ }
+ }
+ }
+
/* Keep this block, even when empty. */
}
}
diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc
index d2f73dd63ec..56585cb722e 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.cc
+++ b/source/blender/bmesh/tools/bmesh_boolean.cc
@@ -194,6 +194,7 @@ static bool apply_mesh_output_to_bmesh(BMesh *bm, IMesh &m_out)
/* Initially mark all existing faces as "don't keep", except hidden faces.
* Also, save current #BMFace pointers as creating faces will disturb the table. */
Array<BMFace *> old_bmfs(bm->totface);
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
for (int f = 0; f < bm->totface; ++f) {
BMFace *bmf = BM_face_at_index(bm, f);
old_bmfs[f] = bmf;
@@ -331,6 +332,7 @@ static bool bmesh_boolean(BMesh *bm,
const int looptris_tot,
int (*test_fn)(BMFace *f, void *user_data),
void *user_data,
+ int nshapes,
const bool use_self,
const bool use_separate_all,
const BoolOpType boolean_mode)
@@ -339,10 +341,9 @@ static bool bmesh_boolean(BMesh *bm,
IMesh m_triangulated;
IMesh m_in = mesh_from_bm(bm, looptris, looptris_tot, &m_triangulated, &arena);
std::function<int(int)> shape_fn;
- int nshapes;
if (use_self && boolean_mode == BoolOpType::None) {
/* Unary knife operation. Want every face where test_fn doesn't return -1. */
- nshapes = 1;
+ BLI_assert(nshapes == 1);
shape_fn = [bm, test_fn, user_data](int f) {
BMFace *bmf = BM_face_at_index(bm, f);
if (test_fn(bmf, user_data) != -1) {
@@ -352,15 +353,11 @@ static bool bmesh_boolean(BMesh *bm,
};
}
else {
- nshapes = 2;
shape_fn = [bm, test_fn, user_data](int f) {
BMFace *bmf = BM_face_at_index(bm, f);
int test_val = test_fn(bmf, user_data);
- if (test_val == 0) {
- return 0;
- }
- if (test_val == 1) {
- return 1;
+ if (test_val >= 0) {
+ return test_val;
}
return -1;
};
@@ -403,6 +400,7 @@ bool BM_mesh_boolean(BMesh *bm,
const int looptris_tot,
int (*test_fn)(BMFace *f, void *user_data),
void *user_data,
+ const int nshapes,
const bool use_self,
const int boolean_mode)
{
@@ -412,6 +410,7 @@ bool BM_mesh_boolean(BMesh *bm,
looptris_tot,
test_fn,
user_data,
+ nshapes,
use_self,
false,
static_cast<blender::meshintersect::BoolOpType>(boolean_mode));
@@ -430,6 +429,7 @@ bool BM_mesh_boolean_knife(BMesh *bm,
const int looptris_tot,
int (*test_fn)(BMFace *f, void *user_data),
void *user_data,
+ const int nshapes,
const bool use_self,
const bool use_separate_all)
{
@@ -438,6 +438,7 @@ bool BM_mesh_boolean_knife(BMesh *bm,
looptris_tot,
test_fn,
user_data,
+ nshapes,
use_self,
use_separate_all,
blender::meshintersect::BoolOpType::None);
@@ -448,6 +449,7 @@ bool BM_mesh_boolean(BMesh *UNUSED(bm),
const int UNUSED(looptris_tot),
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list