Don't need help, just curious about boolean modifier

I’m curious about how the boolean modifier works under the hood, and am trying to understand why it works the way it does. Specifically, why it is weird when vertices in the target overlap vertices or even just edges in the mesh with the modifier. I get why coplanar faces would be a problem, but I don’t quite understand some other behavior

E.g.

Here we have a subject cylinder, and a target cylinder which has inset top and bottom faces that exactly march a cross-section of the subject

Line them up and use a bool modifier on ‘subject’, with a target of, well, ‘target’, and the bool modifier produces a nonmanifold result.

Rotate the target slightly, and the bool modifier works as expected.

Obviously the proximal cause is that vertices on the target exactly overlap edges of the subject, but no vertices overlap vertices, and there are no coplanar faces. Intuitively you’d think a boolean modifier would produce nice clean geometry with the arrangement in the middle picture, but obviously it doesn’t.

There are other weird behaviors, obviously, but this seems to be representative, and I’d assume has the same cause. Can someone enlighten me as to why the bool modifier does this sort of thing? I’d really appreciate the education.

1 Like

I don’t have any technical insight to offer here, but I can tell you that there are some known issues with the current boolean modifier. They used to use another third party library called carve for the boolean modifier, but that supposedly caused booleans to fail in other situations and is no longer maintained, so they removed it in favor of using their own code.

A developer named @howardt plans to improve the current boolean modifier:

Maybe he can shed some light on why the current one fails in this situation.

I haven’t looked in detail at the example shown, but I know how the current Boolean modifier works and think I know why you get the behavior shown here.

A boolean modifier has to do two things:

  1. Intersect all the faces of the first object with all faces of the second object and divide those faces with new edges on the affected faces.
  2. For each connected group of faces (delimited by intersection edges) in the newly formed object, decide whether it is Inside or Outside the other object, and then either keep or remove or reverse the normals of the faces, depending on the boolean operation.

The first task has many special cases if there are coplanar faces or overlapping edges or vertices of one object that are on edges or vertices or faces of the other object. The current Boolean modifier handles some of those (vertices on top of other edges or vertices), but not most of them. In the example given above, I can’t tell if any of those non-handled cases occur.

The second task also has special cases with coplanar faces or non-manifold or non-watertight or inconsistent-normal objects. The current Boolean code does the task by taking a test vertex in a group of connected faces to be tested, and shoots a ray on the positive x-axis and counts how many faces of the other object it intersects (odd vs even then determining inside vs outside). When the special cases happen, the code does what it does, which sometimes gives the effect one wants, and sometimes doesn’t. In the example given above, I can’t quite tell whether the target cylinder is watertight (the wireframe suggests it is not; but also, because the inset is meant to exactly match the cross-section of the other, it is likely that numerical effects give a bit of non-determinism about what the ray-casting test does. Also if you rotate one, then you can likely imagine how the test vertex may move inside and outside of the planes on the other object (after all, these are faceted approximations to cylinders, not real cylinders).

The current BMesh Boolean made its programming task earlier by precluding most of the special cases that cause problems by assuming that:

  • The two objects are both manifold, watertight, and have normals that consistently point to the outside.
  • The overlap of the objects is always interpenetrating, not just touching or grazing.

If these assumptions are violated, the code will still do something, but the results will be unpredictable and sometimes nonsensical.

My replacement for Boolean is trying to work without making any of those assumptions. I have it kind of working now, but had a long detour through numerically stability that I am just coming out of. Probably best that I don’t try any more to predict when it will be done.

1 Like

Wow, thank you for the detailed response. I suppose it’s easy to miss how complicated something actually is, when it looks simple.

While what we have works, it’s probably a good thing that it’s being redone/improved, so props to you for taking on the task.

And yeah, time estimation is a trap. It’ll be done when it’s done, and I won’t expect to get to see it a moment sooner. :slight_smile: