Simple 3D Collision Detection with Python Scripting in Blender

by Paul Balzer on 8. Juni 2016

3 Comments

If you are looking for a very simple way to check, if two objects touch each other in Blender, maybe this might be a solution. The field of collision detection is very popular in game development and these guys have a lot of special algorithms for fast and/or exact collision between circles & circles, rectangles & circles, triangles & circles and so on…

Most of these are based on the Seperating Axis Theorem, which is simply the mathematical solution of the question: Is it possible to look ‘between’ the two objects from any direction? If so, they are not colliding. Things get much simpler, if you just check the bounding boxes of two objects. In case of a cube, the bounding box is exactly the object itself. To check if two cubes touch each other, you have to check a collision between two bounding boxes. To make it even easier, one of the boxes is axis aligned (not rotated). We are talking about AABB (axis aligned bounding box) 3D collision check in Python. For visualization, we are using Blender. In Blender, you can run Python scripts.

Collision Check in Blender

The setup is the following:

boxes

Python Script to Check Collision of 3D Bounding Boxes

Remember: One of them need to be axis aligned!

import bpy
from mathutils import Vector

def get_BoundBox(object_name):
    """
    returns the corners of the bounding box of an object in world coordinates
    #  ________ 
    # |\       |\
    # |_\______|_\
    # \ |      \ |
    #  \|_______\|
    # 
    """
    bpy.context.scene.update()
    ob = bpy.context.scene.objects[object_name]
    bbox_corners = [ob.matrix_world * Vector(corner) for corner in ob.bound_box]

    return bbox_corners



def check_Collision(box1, box2):
    """
    Check Collision of 2 Bounding Boxes
    box1 & box2 muss Liste mit Vector sein,
    welche die Eckpunkte der Bounding Box
    enthält
    #  ________ 
    # |\       |\
    # |_\______|_\
    # \ |      \ |
    #  \|_______\|
    # 
    #
    """
    print('\nKollisionscheck mit:')

    x_max = max([e[0] for e in box1])
    x_min = min([e[0] for e in box1])
    y_max = max([e[1] for e in box1])
    y_min = min([e[1] for e in box1])
    z_max = max([e[2] for e in box1])
    z_min = min([e[2] for e in box1])
    print('Box1 min %.2f, %.2f, %.2f' % (x_min, y_min, z_min))
    print('Box1 max %.2f, %.2f, %.2f' % (x_max, y_max, z_max))    
    
    x_max2 = max([e[0] for e in box2])
    x_min2 = min([e[0] for e in box2])
    y_max2 = max([e[1] for e in box2])
    y_min2 = min([e[1] for e in box2])
    z_max2 = max([e[2] for e in box2])
    z_min2 = min([e[2] for e in box2])
    print('Box2 min %.2f, %.2f, %.2f' % (x_min2, y_min2, z_min2))
    print('Box2 max %.2f, %.2f, %.2f' % (x_max2, y_max2, z_max2))        
    
    
    isColliding = ((x_max >= x_min2 and x_max <= x_max2) \
                    or (x_min <= x_max2 and x_min >= x_min2)) \
                    and ((y_max >= y_min2 and y_max <= y_max2) \
                    or (y_min <= y_max2 and y_min >= y_min2)) \
                    and ((z_max >= z_min2 and z_max <= z_max2) \
                    or (z_min <= z_max2 and z_min >= z_min2))

    if isColliding:
        print('Kollision!')
        
    return isColliding

# MAIN
# Check Collision of Objects named 'Cube1' and 'Cube2' in Scene
collision = check_Collision(get_BoundBox('Cube1'), get_BoundBox('Cube2'))

BoxCollision_Blender

3 Comments

  1. The collision check in the code above seems wrong. I tested this in blender.
    One corrected version would be:
    isColliding = ((x_max >= x_min2 and x_min = y_min2 and y_min = z_min2 and z_min <= z_max2))
    Also this is just an axis-aligned bounding box collision test.
    A oriented bounding box test is more demanding but missing here.

    1. Sorry, something went wrong with the formating when copy & pasting code.
      Here is the hopefully corrected version:
      isColliding = ((x_max1 > = x_min2 and x_min1 = y_min2 and y_min1 = z_min2 and z_min1 < = z_max2))

      1. isColliding = ((x_max1 > x_min2 and x_min1 < x_max2)
        and (y_max1 > y_min2 and y_min1 < y_max2)
        and (z_max1 > z_min2 and z_min1 < z_max2))

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.