Strange object.ray_cast() behavior object.ray_cast() is not behaving as I would expect in Blender 2.77. I understand that it expects object local coordinates, but this problem happens when the object is not translated, rotated, or scaled.

If I edit the shape of the cube mesh without moving the cube, the results of ray_cast() seem plain wrong.

Steps to reproduce


Create a cube at 0,0,0
Move a vertex of the cube from 1,1,1 to 5,5,5
Create an empty called "src" at 2,2,2
Create an empty called "dst" at 2,2,6


Run this python

cb = bpy.data.objects['Cube']
src = bpy.data.objects['src']
dst = bpy.data.objects['dst']
hit, loc, norm, face = cb.ray_cast(src.location, dst.location)
bpy.ops.object.empty_add(location = loc)


This is the result on my system. The new Empty created at the interesection point is selected:



The source and the destination are both at x = 2 and y = 2. The cube has a surface at x = 2 and y = 2. So why on earth is the intersection point at x = 2.22222, y = 2.22222?
Raycast argument Vectors need to be in object's local space.

Ray cast is behaving as expected.  The first parameter is the origin of the ray  src.location and the second is a direction vector, which from a target would be  direction = dst.location - src.location (most commonly normalized)

The vectors also need to be in the local coordinates of the target object being ray-cast onto. Simplest way to calculate another object into target objects local space is multiply the global coord by the target objects matrix world inverted

origin = cb.matrix_world.inverted() * src.matrix_world.translation # use @ for * in 2.8


Test script, using object references as in question.

mw = cb.matrix_world
mwi = mw.inverted()

# src and dst in local space of cb

origin = mwi * src.matrix_world.translation
dest = mwi * dst.matrix_world.translation
direction = (dest - origin).normalized()

hit, loc, norm, face = cb.ray_cast(origin, direction)

if hit:
    print("Hit at ", loc, " (local)")
    bpy.ops.object.empty_add(location = mw * loc)
else:
    print("No HIT")