how one can detect two object contact. with python, for example, I want every sphere becomes the child of the cube it touches. enter image description here


1 Answer 1


Using closest point on mesh

Test code, assumes spheres are named "Sphere[.nnn]" and cubes "Cube[.nnn]" If a hit from the sphere's centre to a point on a cube is less than the sphere's radius, then it parents them.

import bpy
from bpy import context

scene = context.scene
spheres = [o for o in scene.objects if o.name.startswith("Sphere")]
cubes = [o for o in scene.objects if o.name.startswith("Cube")]

for s in spheres:
    o = s.matrix_world.to_translation()
    radius = sum(s.dimensions) / 6 # sphere radius guestimation
    for cube in cubes:
        cmwi = cube.matrix_world.inverted()
        local_pos = cmwi * o
        (hit, loc, norm, face_index) = cube.closest_point_on_mesh(local_pos)
        if hit:
            v2 = cube.matrix_world * loc   
            # distance from global hit to cube
            l = (v2 - o).length
            if l <= radius:
                cube.parent = s
                cube.matrix_parent_inverse = s.matrix_world.inverted()
  • $\begingroup$ Thank you. the cube and the sphere was for example. if I have a more complex form a cube, it will not work. your code gives me an error "need more than 3 values to unpack" on line : (hit, loc, norm, face_index) = cube.closest_point_on_mesh (local_pos) $\endgroup$ Sep 20, 2016 at 15:09
  • $\begingroup$ What version of blender are you using?, closest point on mesh changed to include hit for 2.77 I think. $\endgroup$
    – batFINGER
    Sep 20, 2016 at 15:11
  • $\begingroup$ version of Blender: 2.76 $\endgroup$ Sep 20, 2016 at 15:13
  • $\begingroup$ Change to (loc, norm, face_index) = cube.closest_point_on_mesh(local_pos) and just fudge in hit = True ... or better still upgrade. $\endgroup$
    – batFINGER
    Sep 20, 2016 at 15:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .