Sculpt: Add fast solver option for trim operations

This PR introduces the ability for users to switch between boolean
solvers while using the sculpt *Trim* tools (*Box Trim* & *Lasso Trim*)
much like the mesh boolean modifier and geometry node. Because the
*Exact* solver has performance issues with larger meshes, the *Fast*
solver is set to be the default.

In my very rough timing tests on my laptop on a mesh with **1.7m**
vertices, a *Trim* operation with the *Fast* solver finishes in roughly
20 seconds as opposed to still being in progress after five minutes
with the *Exact* solver.

Addresses part of #84229

Pull Request: https://projects.blender.org/blender/blender/pulls/119699
This commit is contained in:
Sean Kim 2024-03-26 17:25:06 +01:00 committed by Hans Goudey
parent b4b74c8da6
commit 881178895b
2 changed files with 37 additions and 2 deletions

@ -1488,6 +1488,7 @@ class _defs_sculpt:
def trim_box():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("sculpt.trim_box_gesture")
layout.prop(props, "trim_solver", expand=False)
layout.prop(props, "trim_mode", expand=False)
layout.prop(props, "trim_orientation", expand=False)
layout.prop(props, "trim_extrude_mode", expand=False)
@ -1505,6 +1506,7 @@ class _defs_sculpt:
def trim_lasso():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("sculpt.trim_lasso_gesture")
layout.prop(props, "trim_solver", expand=False)
layout.prop(props, "trim_mode", expand=False)
layout.prop(props, "trim_orientation", expand=False)
layout.prop(props, "trim_extrude_mode", expand=False)

@ -32,6 +32,7 @@
#include "bmesh.hh"
#include "tools/bmesh_boolean.hh"
#include "tools/bmesh_intersect.hh"
#include "paint_intern.hh"
#include "sculpt_intern.hh"
@ -90,6 +91,17 @@ static EnumPropertyItem extrude_modes[] = {
{0, nullptr, 0, nullptr, nullptr},
};
enum class SolverMode {
Exact = 0,
Fast = 1,
};
static EnumPropertyItem solver_modes[] = {
{int(SolverMode::Exact), "EXACT", 0, "Exact", "Use the exact boolean solver"},
{int(SolverMode::Fast), "FAST", 0, "Fast", "Use the fast float boolean solver"},
{0, nullptr, 0, nullptr, nullptr},
};
struct TrimOperation {
gesture::Operation op;
@ -102,6 +114,7 @@ struct TrimOperation {
bool use_cursor_depth;
OperationType mode;
SolverMode solver_mode;
OrientationType orientation;
ExtrudeMode extrude_mode;
};
@ -502,8 +515,25 @@ static void apply_trim(gesture::GestureData &gesture_data)
BLI_assert(false);
break;
}
BM_mesh_boolean(
bm, corner_tris, bm_face_isect_pair, nullptr, 2, true, true, false, boolean_mode);
if (trim_operation->solver_mode == SolverMode::Exact) {
BM_mesh_boolean(
bm, corner_tris, bm_face_isect_pair, nullptr, 2, true, true, false, boolean_mode);
}
else {
BM_mesh_intersect(bm,
corner_tris,
bm_face_isect_pair,
nullptr,
false,
false,
true,
true,
false,
false,
boolean_mode,
1e-6f);
}
}
BMeshToMeshParams convert_params{};
@ -573,6 +603,7 @@ static void init_operation(gesture::GestureData &gesture_data, wmOperator &op)
trim_operation->use_cursor_depth = RNA_boolean_get(op.ptr, "use_cursor_depth");
trim_operation->orientation = OrientationType(RNA_enum_get(op.ptr, "trim_orientation"));
trim_operation->extrude_mode = ExtrudeMode(RNA_enum_get(op.ptr, "trim_extrude_mode"));
trim_operation->solver_mode = SolverMode(RNA_enum_get(op.ptr, "trim_solver"));
/* If the cursor was not over the mesh, force the orientation to view. */
if (!gesture_data.ss->gesture_initial_hit) {
@ -606,6 +637,8 @@ static void operator_properties(wmOperatorType *ot)
int(ExtrudeMode::Fixed),
"Extrude Mode",
nullptr);
RNA_def_enum(ot->srna, "trim_solver", solver_modes, int(SolverMode::Fast), "Solver", nullptr);
}
static int gesture_box_exec(bContext *C, wmOperator *op)