Snappping the 3D cursor to the surface and find the surface's face it was snapped to

To snap the 3D cursor to the surface of my object, I set the "Cursor Depth" to True in the interface user preferences. How can I know exactly to which face/vertice the cursor was snapped (in code)? Do I need to use object.closest_point_on_mesh?

object.closest_point_on_mesh(bpy.context.scene.cursor_location)


Or maybe this data is stored somewhere? Isn't is the whole purpose of Cursor Depth? Also, how can I know which object was it snapped to, in the case of multiple objects in the scene? Thanks!

• As far as I know Cursor Depth uses the opengl depth buffer for approximate distance. It is not aware of any object geometry or mesh topology, since it may not even be a mesh object it was "snapped to". Oct 20, 2017 at 17:09
• I'd go for scene ray cast , as shown in my answer, you could (with depth picking on) loop thru and compare globalized object.closest_point_on_mesh to cursor loc for scene mesh objects. Oct 20, 2017 at 19:44

Using Scene.ray_cast

Can shoot a ray into the scene using Scene.ray_cast from the cursor location, in the direction of the converted view matrix's z axis. Test code, prints the ray hit (if hit) of each 3d view in the context screen.

import bpy
from mathutils import Vector
context = bpy.context
screen = context.screen
scene = context.scene
areas3d = [a for a in screen.areas if a.type == 'VIEW_3D']
for a in areas3d:
r3d = a.spaces.active.region_3d
vm = r3d.view_matrix.transposed().to_3x3().to_4x4()
norm = vm * Vector((0, 0, 1))
norm.normalize()
ray = scene.ray_cast(scene.cursor_location, norm)
hit, loc, norm, face, obj, matrix = ray
if hit:
print("hit object", obj, "on face:", face)