5
$\begingroup$

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

  1. Create a cube at 0,0,0
  2. Move a vertex of the cube from 1,1,1 to 5,5,5
  3. Create an empty called "src" at 2,2,2
  4. 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:

enter image description here

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?

$\endgroup$

1 Answer 1

8
$\begingroup$

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")
$\endgroup$
1
  • 1
    $\begingroup$ Ah, I see. So the "origin" is relative to the object location, but the "direction" is relative to the coordinates given for "origin." The docs and forums keep saying everything is in object local coordinates -- this in't really true for the "direction" and the docs should probably be updated to make that clear. I was thrown off by all the stuff about everything being object local. $\endgroup$ Commented Apr 14, 2016 at 16:17

You must log in to answer this question.

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