Page MenuHome

Geometry Nodes: Improve speed of boolean node, use multi-input sockets
ClosedPublic

Authored by Hans Goudey (HooglyBoogly) on Mar 3 2021, 7:21 AM.

Details

Summary

This commit should significantly improve the performance of the node,
by skipping the conversion to BMesh and back, also skipping realizing
instances for any input mesh instances.

This upgrade allows using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
This will *also* improve performance due to avoiding the overhead of
setting up and allocating memory for many separate operations.

The changes necessary for transforms in mesh_boolean_convert.cc are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using float4x4::itentity().

This patch also fixes a bug where overlapping difference meshes would
make the operation not work. Though I'm not quite sure why.

The way links are updated when you change the operation isn't great
currently, but I would like to address that separately.

Diff Detail

Repository
rB Blender
Branch
geometry-nodes-boolean-direct (branched from master)
Build Status
Buildable 13732
Build 13732: arc lint + arc unit

Event Timeline

Hans Goudey (HooglyBoogly) requested review of this revision.Mar 3 2021, 7:21 AM
Hans Goudey (HooglyBoogly) created this revision.
Hans Goudey (HooglyBoogly) planned changes to this revision.Mar 8 2021, 9:45 PM
  • Merge branch 'master' into geometry-nodes-boolean-direct
  • Some cleanup
  • Improvements, still broken transforms but better
  • Fix transform issues

More progress, working now

Hans Goudey (HooglyBoogly) retitled this revision from WIP: Use multi-input sockets and mesh directly for boolean node to Geometry Nodes: Improve speed of boolean node, use multi-input sockets.Mar 26 2021, 3:03 AM
Hans Goudey (HooglyBoogly) edited the summary of this revision. (Show Details)
  • Simplify logic for target transforms

Generally looks fine to me. But please find and fix the reason that it doesn't work for a Union operation.

source/blender/nodes/geometry/nodes/node_geo_boolean.cc
92

Why is the final argument false here?
I will note that the with the test file 'Boolean Node Upgrade Test.blend', the Union operation does not work. Is this argument the reason?

Hmm, in my testing union is working fine.

source/blender/nodes/geometry/nodes/node_geo_boolean.cc
92

This turns off the first non-multi-input socket in the UI when union is selected to that only the multi-input socket remains.
I used a separate socket only for the difference mode, since AFAIK that's the only mode where the first object is different than the rest.

For the record I'm going to post some performance information I talked about with Howard in chat:

My discovery was the this patch is actually slower when there are multiple input meshes.
This is because boolean has an optimization to avoid calculating self intersections when there are only two input shapes (using two BVH trees rather than a single larger one).
Since realizing the instances is much faster than boolean intersections, realizing instances for each input geometry component avoids that situation and is much faster.

This node is still about 40% faster when there are only two input meshes, and it's the same as the implementation for the modifier, so Howard and I decided it would be best to move forward anyway.
The boolean code can be optimized for more input meshes in the future, and there's already a workaround for situations where it matters anyway-- just realize instances first with a different node.

WITH PATCH APPLIED
Timer 'geo_node_boolean_exec' took 162.446 ms # This just gathers instanced meshes and their transforms from the geometry set
  Timer 'direct_mesh_boolean' took 162.427 ms
    Timer 'meshes_to_imesh' took 1.73373 ms
    Timer 'boolean_mesh' took 157.892 ms
    Timer 'imesh_to_mesh' took 0.800372 ms

WITHOUT PATCH APPLIED
Timer 'geo_node_boolean_exec' took 54.879 ms
  Timer 'geometry_set_realize_instances' took 230 ns # This geometry set's mesh is not an instance, so this doesn't do anything
  Timer 'geometry_set_realize_instances' took 0.233303 ms # This combines the 5 input meshes from the collection into one larger one
  Timer 'mesh_boolean_calc' took 54.591 ms # Then convert to BMesh
    Timer 'boolean_mesh' took 46.4092 ms # And finally call boolean

MODIFIER (for reference)
time end   (__func__): 0.175889  source/blender/modifiers/intern/MOD_boolean.c:716
  Timer 'direct_mesh_boolean' took 175.86 ms # This is doing the same thing as the "with patch applied" results
    Timer 'meshes_to_imesh' took 2.56968 ms 
    Timer 'boolean_mesh' took 170.486 ms
    Timer 'imesh_to_mesh' took 0.784861 ms
This revision was not accepted when it landed; it landed in state Needs Review.Apr 1 2021, 10:01 PM
This revision was automatically updated to reflect the committed changes.

Sorry about the intrusion but it would be awesome if we got to see the fast solver with geometry nodes, the exact solver is not very useful in many situations with complex geometry (at least when realtime feedback is important) - it slows down the viewport too much.

Some other long existing feature request among hard surface artists (related to boolean operations) that I would also like to lift up is that we are missing a way of assigning attributes to the cut out geometry (as well as the boundary loop) - so that one could perform operations like bevel or inset (if we are getting inset that is) on cut out geometry.