Boolean: applying patch D11431 to speed up hole-tolerant raycast.
This patch from Erik Abrahamsson uses a parallel_for to speed up the case where the input is not manifold and the "hole_tolerant" option is set. In a test case on a 24 core (48 thread) machine, this sped up a the boolean part on an object with 221k triangles from 12.06s to 0.46s.
This commit is contained in:
parent
e6a69f7653
commit
a1556fa05c
Notes:
blender-bot
2023-02-14 08:06:35 +01:00
Referenced by issue #94418, No image.previews for some D.images Referenced by issue #93995, Cycles: motion blur only applies on Left view Referenced by issue #93751, Extrude crash Referenced by issue #90540, NoneType object error with entering grease pencil draw mode Referenced by issue #89545, Weight / Vertex paint mode "Show Wireframe" is not working Referenced by issue #89029, Baking to Vertex colors causes Blender shutdown/crash
|
@ -41,6 +41,7 @@
|
|||
# include "BLI_set.hh"
|
||||
# include "BLI_span.hh"
|
||||
# include "BLI_stack.hh"
|
||||
# include "BLI_task.hh"
|
||||
# include "BLI_vector.hh"
|
||||
# include "BLI_vector_set.hh"
|
||||
|
||||
|
@ -48,6 +49,10 @@
|
|||
|
||||
# include "BLI_mesh_boolean.hh"
|
||||
|
||||
# ifdef WITH_TBB
|
||||
# include "tbb/spin_mutex.h"
|
||||
# endif
|
||||
|
||||
// # define PERFDEBUG
|
||||
|
||||
namespace blender::meshintersect {
|
||||
|
@ -2567,47 +2572,58 @@ static IMesh raycast_tris_boolean(const IMesh &tm,
|
|||
BVHTree *tree = raycast_tree(tm);
|
||||
Vector<Face *> out_faces;
|
||||
out_faces.reserve(tm.face_size());
|
||||
Array<float> in_shape(nshapes, 0);
|
||||
Array<int> winding(nshapes, 0);
|
||||
for (int t : tm.face_index_range()) {
|
||||
Face &tri = *tm.face(t);
|
||||
int shape = shape_fn(tri.orig);
|
||||
if (dbg_level > 0) {
|
||||
std::cout << "process triangle " << t << " = " << &tri << "\n";
|
||||
std::cout << "shape = " << shape << "\n";
|
||||
}
|
||||
test_tri_inside_shapes(tm, shape_fn, nshapes, t, tree, in_shape);
|
||||
for (int other_shape = 0; other_shape < nshapes; ++other_shape) {
|
||||
if (other_shape == shape) {
|
||||
continue;
|
||||
}
|
||||
/* The in_shape array has a confidence value for "insideness".
|
||||
* 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.
|
||||
* Also, when the operation is intersection, we also want high confidence.
|
||||
*/
|
||||
bool need_high_confidence = (op == BoolOpType::Difference && shape != 0) ||
|
||||
op == BoolOpType::Intersect;
|
||||
bool inside = in_shape[other_shape] >= (need_high_confidence ? 0.5f : 0.1f);
|
||||
# ifdef WITH_TBB
|
||||
tbb::spin_mutex mtx;
|
||||
# endif
|
||||
const int grainsize = 256;
|
||||
parallel_for(IndexRange(tm.face_size()), grainsize, [&](IndexRange range) {
|
||||
Array<float> in_shape(nshapes, 0);
|
||||
Array<int> winding(nshapes, 0);
|
||||
for (int t : range) {
|
||||
Face &tri = *tm.face(t);
|
||||
int shape = shape_fn(tri.orig);
|
||||
if (dbg_level > 0) {
|
||||
std::cout << "test point is " << (inside ? "inside" : "outside") << " other_shape "
|
||||
<< other_shape << " val = " << in_shape[other_shape] << "\n";
|
||||
std::cout << "process triangle " << t << " = " << &tri << "\n";
|
||||
std::cout << "shape = " << shape << "\n";
|
||||
}
|
||||
winding[other_shape] = inside;
|
||||
}
|
||||
bool do_flip;
|
||||
bool do_remove = raycast_test_remove(op, winding, shape, &do_flip);
|
||||
if (!do_remove) {
|
||||
if (!do_flip) {
|
||||
out_faces.append(&tri);
|
||||
test_tri_inside_shapes(tm, shape_fn, nshapes, t, tree, in_shape);
|
||||
for (int other_shape = 0; other_shape < nshapes; ++other_shape) {
|
||||
if (other_shape == shape) {
|
||||
continue;
|
||||
}
|
||||
/* The in_shape array has a confidence value for "insideness".
|
||||
* 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.
|
||||
* Also, when the operation is intersection, we also want high confidence.
|
||||
*/
|
||||
bool need_high_confidence = (op == BoolOpType::Difference && shape != 0) ||
|
||||
op == BoolOpType::Intersect;
|
||||
bool inside = in_shape[other_shape] >= (need_high_confidence ? 0.5f : 0.1f);
|
||||
if (dbg_level > 0) {
|
||||
std::cout << "test point is " << (inside ? "inside" : "outside") << " other_shape "
|
||||
<< other_shape << " val = " << in_shape[other_shape] << "\n";
|
||||
}
|
||||
winding[other_shape] = inside;
|
||||
}
|
||||
else {
|
||||
raycast_add_flipped(out_faces, tri, arena);
|
||||
bool do_flip;
|
||||
bool do_remove = raycast_test_remove(op, winding, shape, &do_flip);
|
||||
{
|
||||
# ifdef WITH_TBB
|
||||
tbb::spin_mutex::scoped_lock lock(mtx);
|
||||
# endif
|
||||
if (!do_remove) {
|
||||
if (!do_flip) {
|
||||
out_faces.append(&tri);
|
||||
}
|
||||
else {
|
||||
raycast_add_flipped(out_faces, tri, arena);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
BLI_bvhtree_free(tree);
|
||||
ans.set_faces(out_faces);
|
||||
return ans;
|
||||
|
|
Loading…
Reference in New Issue