How to make the raycast ignore an object?

Here is an example of how to use the Scene.ray_cast function. However, I want to ignore an object (eg cube). How to make this possible?

import bpy, bgl
from bpy_extras import view3d_utils
from mathutils import Vector, Matrix


def draw_point_bgl(coords):
    # VIEWING BGL
    bgl.glEnable(bgl.GL_BLEND)
    bgl.glColor4f(1.0, 0.5, 0.5, 1.0)
    bgl.glPointSize(50)    
    bgl.glBegin(bgl.GL_POINTS)
    bgl.glVertex3f(*coords)
    bgl.glEnd()
    bgl.glDisable(bgl.GL_BLEND)


    # restore opengl defaults
    bgl.glDepthRange(0,1)
    bgl.glPointSize(1)
    bgl.glLineWidth(1)
    bgl.glDisable(bgl.GL_BLEND)
    bgl.glColor4f(0.0, 0.0, 0.0, 1.0)


    bpy.context.area.header_text_set(str(coords))


def draw_scene_ray_cast(self, context):
    x, y = self.mouse_co

    view_vector = view3d_utils.region_2d_to_vector_3d(self.region, self.rv3d, (x, y))
    ray_origin = view3d_utils.region_2d_to_origin_3d(self.region, self.rv3d, (x, y))

    ray_target = ray_origin + (view_vector * 1000)
    
    scene = context.scene

    # cast the ray
    result, object, matrix, location, normal = scene.ray_cast(ray_origin, ray_target)

    draw_point_bgl(location)

class PanelTestsRayCast(bpy.types.Panel):
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Test RayCast"
    bl_label = "Test RayCast"

    def draw(self, context):
        layout = self.layout
        TheCol = layout.column(align = True)
        TheCol.operator("view3d.test_ray_cast")
        
class TestsRayCastOperator(bpy.types.Operator):
    """using mouse events"""
    bl_idname = "view3d.test_ray_cast"
    bl_label = "Show RayCast"
    
    def modal(self, context, event):
        if context.area:
            context.area.tag_redraw()
        
        if event.type == 'MOUSEMOVE':
            self.mouse_co = (event.mouse_region_x, event.mouse_region_y)
             
        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            context.area.header_text_set()
            return {'FINISHED'}

        return {'PASS_THROUGH'} 

    def invoke(self, context, event):        
        if context.space_data.type == 'VIEW_3D':
            self.rv3d = context.region_data
            self.region = context.region
            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_scene_ray_cast, (self, context), 'WINDOW', 'POST_VIEW')
            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "Active space must be a View3d")
            return {'CANCELLED'}

def register():
    bpy.utils.register_class(PanelTestsRayCast)
    bpy.utils.register_class(TestsRayCastOperator)

def unregister():
    bpy.utils.unregister_class(PanelTestsRayCast)
    bpy.utils.unregister_class(TestsRayCastOperator)

if __name__ == "__main__":
    register()

Attachments


Cast another ray from hit location, or slightly further along the ray vector (I’m not sure if it would hit the very same coordinate again if you don’t add a minimal offset).

I thought that too. But as my goal is that the face of the object to be ignored overlaps the face of another object (coplanar), this solution would ignore the face of the other object also :frowning:

You can use ray_cast on objects too. http://www.blender.org/api/blender_python_api_2_75_release/bpy.types.Object.html?highlight=ray_cast#bpy.types.Object.ray_cast

So you just cast on objects you are interested in and pick the object yielding the minimum value.

See Text Editor -> Templates -> Python -> Operator Modal View3d Raycast

I also thought this solution. But the problem is that I would have to test the ray_cast on all objects, which would slow the script. (It must be all objects.)

Another solution that I thought would be to create another scene with all the other objects. But I have not tested this option and I think it would consume a lot of memory in some cases.

Does Scene.ray_cast() respect Object.hide? Maybe hiding them temporarily helps.

1 Like

When the object is hidden, the Scene.raycast ignores it. But for what I intend to do, the object needs to be visible in some way.

But if you hide it, cast the ray, unhide it, then the user wouldn’t notice.

1 Like

You’re right. I don’t know why I didn’t think about this. :smiley:
Thank @CoDEmanX.