One of the common tasks when making a scene in Blender is to control the overlapping of meshes. We can check whether two meshes intersect with each other using the technology of Bounding Volumes.

The “mathutils” module gives us the ability to easily build Bounding Volume Hierarchy Trees (BVH-Trees) for any meshes in the scene, and use them to check for intersections.

For example, let’s add a UV sphere to the scene (shift + a – Mesh – UV Sphere) and a plane (shift + a – Mesh – Plane). For the plane, let’s add some subdivisions in edit mode.

In order to correctly check for intersections with BVH-Tress, the meshes they are built from must be in the same coordinate system.

Let’s calculate the points of both meshes (plane and sphere) in a single coordinate system – World. To do this, we need to multiply the coordinates of each mesh vertex by mesh’s world matrix.

1 2 3 4 5 6 7 8 9 |
mesh_1 = bpy.data.objects['Plane'] m_1 = mesh_1.matrix_world.copy() mesh_1_verts = [m_1 @ vertex.co for vertex in mesh_1.data.vertices] mesh_1_polys = [polygon.vertices for polygon in mesh_1.data.polygons] mesh_2 = bpy.data.objects['Sphere'] m_2 = mesh_2.matrix_world.copy() mesh_2_verts = [m_2 @ vertex.co for vertex in mesh_2.data.vertices] mesh_2_polys = [polygon.vertices for polygon in mesh_2.data.polygons] |

We also generated lists of mesh polygons with the associated vertices.

With these two lists (vertices coordinates and polygon-vertices ratios), we can build a BVH-Tree for each mesh:

1 2 3 4 |
from mathutils.bvhtree import BVHTree mesh_1_bvh_tree = BVHTree.FromPolygons(mesh_1_verts, mesh_1_polys) mesh_2_bvh_tree = BVHTree.FromPolygons(mesh_2_verts, mesh_2_polys) |

Having two generated BVH trees, we can easily find intersections:

1 2 3 |
intersections = mesh_1_bvh_tree.overlap(mesh_2_bvh_tree) # [(4, 133), (1011, 133), (1011, 156), (243, 156), ... ] |

The “overlap” method returns a list of overlapping polygon indices as pairs:

*(“polygon index of mesh 1”, “polygon index of mesh 2”)*

For a simple understanding are the meshes intersect or not, it is enough to check that there is at least one value in the resulting list:

1 2 3 4 5 6 7 |
if intersections: print('MESHES INTERSECTS') print(intersections) else: print('NO INTERSECTIONS') # MESHES INTERSECTS |

For a more detailed intersection check, let’s parse the resulting list into two separate lists, each of which belongs to its own mesh:

1 2 3 4 5 6 7 |
mesh_1_polys_ints = [pair[0] for pair in intersections] # [4, 1011, 1011, 243, ...] mesh_2_polys_ints = [pair[1] for pair in intersections] # [133, 133, 156, 156, ...] |

Now we can select polygons that have intersections on each mesh (in object mode):

1 2 3 4 5 6 7 |
for face in mesh_1.data.polygons: if face.index in mesh_1_polys_ints: face.select = True for face in mesh_2.data.polygons: if face.index in mesh_2_polys_ints: face.select = True |

D