0
$\begingroup$

So i found a script for an Collision Detection @ https://www.cbcity.de/simple-3d-collision-detection-with-python-scripting-in-blender But it seems outdated as i get some Errors , any ideas on how to make this run again?

$\endgroup$
2
  • $\begingroup$ so if i want to check the collision between two pointclouds is there an easy way to assign multiple objects with bounding boxes? $\endgroup$
    – Schmid
    Feb 10 at 11:37
  • $\begingroup$ The script does just work for 2 cubes. I don’t think that there is an easy way - but there might be built-in functions which can do that. I know there is such a functionality in UPBGE - so you can easily detect collisions between objects - but I don’t whether vanilla Blender has this too. $\endgroup$
    – Chris
    Feb 10 at 11:41

2 Answers 2

0
$\begingroup$

Check this out:

import bpy
from mathutils import Vector
 
def get_BoundBox(object_name):
    """
    returns the corners of the bounding box of an object in world coordinates
    #  ________ 
    # |\       |\
    # |_\______|_\
    # \ |      \ |
    #  \|_______\|
    # 
    """
    
    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'))
$\endgroup$
0
$\begingroup$

This creates bounding boxes from objects and then returns True if the bounding boxes are touching using the BVHTree overlap method. Otherwise, it'll return False.

import bpy
from mathutils import Vector
from mathutils.bvhtree import BVHTree

def worldBoundingBox(obj):
    """returns the corners of the bounding box of an object in world coordinates"""
    return [obj.matrix_world @ Vector(corner) for corner in obj.bound_box]

def objectsOverlap(obj1, obj2):
    """returns True if the object's bounding boxes are overlapping"""
    vert1 = worldBoundingBox(obj1)
    vert2 = worldBoundingBox(obj2)
    faces = [(0, 1, 2, 3), (4, 7, 6, 5), (0, 4, 5, 1), (1, 5, 6, 2), (2, 6, 7, 3), (4, 0, 3, 7)]

    bvh1 = BVHTree.FromPolygons(vert1, faces)
    bvh2 = BVHTree.FromPolygons(vert2, faces)

    return bool(bvh1.overlap(bvh2))

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.