Which type of ray cast faster?

I created a script that allows you to view different types of ray_cast in Blender.


After you choose a type and press to view, you will see a square on the location of the “Ray_Cast”
http://blenderartists.org/forum/asset.php?fid=333871&uid=138205&d=1423927457
This works fine, but my goal in making this script was to test the performance of each ray_cast. Objective not yet achieved.
So help me, which one is faster? :confused:


import bpy, bgl
from mathutils import Vector, Matrix, bvhtree
		
def get_viewport():
	view = bgl.Buffer(bgl.GL_INT, 4)
	bgl.glGetIntegerv(bgl.GL_VIEWPORT, view)
	return view


def get_modelview_matrix():
	model_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4, 4])
	bgl.glGetDoublev(bgl.GL_MODELVIEW_MATRIX, model_matrix)
	return model_matrix


def get_projection_matrix():
	proj_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4, 4])
	bgl.glGetDoublev(bgl.GL_PROJECTION_MATRIX, proj_matrix)
	return proj_matrix


def get_depth(x, y):	
	depth = bgl.Buffer(bgl.GL_FLOAT, [0.0])
	bgl.glReadPixels(x, y, 1, 1, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, depth)
	return depth[0]


def UnProject(x, y, z, view_matrix, projection_matrix, viewport):
	world_x = bgl.Buffer(bgl.GL_DOUBLE, 1, [0.0])
	world_y = bgl.Buffer(bgl.GL_DOUBLE, 1, [0.0])
	world_z = bgl.Buffer(bgl.GL_DOUBLE, 1, [0.0])
	bgl.gluUnProject(x, y, z, view_matrix, projection_matrix, viewport, world_x, world_y, world_z)		
	return Vector((world_x[0], world_y[0], world_z[0]))


def region_2d_to_orig_and_view_vector(region, rv3d, coord, clamp=None):
	viewinv = rv3d.view_matrix.inverted()
	persinv = rv3d.perspective_matrix.inverted()


	dx = (2.0 * coord[0] / region.width) - 1.0
	dy = (2.0 * coord[1] / region.height) - 1.0


	if rv3d.is_perspective:
		origin_start = viewinv.translation.copy()


		out = Vector((dx, dy, -0.5))


		w = out.dot(persinv[3].xyz) + persinv[3][3]


		view_vector = ((persinv * out) / w) - origin_start
	else:
		view_vector = -viewinv.col[2].xyz


		origin_start = ((persinv.col[0].xyz * dx) +
						(persinv.col[1].xyz * dy) +
						viewinv.translation)


		if clamp != 0.0:
			if rv3d.view_perspective != 'CAMERA':
				# this value is scaled to the far clip already
				origin_offset = persinv.col[2].xyz
				if clamp is not None:
					if clamp < 0.0:
						origin_offset.negate()
						clamp = -clamp
					if origin_offset.length > clamp:
						origin_offset.length = clamp


				origin_start -= origin_offset


	view_vector.normalize()
	return origin_start, view_vector


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_ray_cast_unproject_bpy(self, context):
	x, y = self.mouse_co
	
	# BPY Matrices
	bpy_viewport = [self.region.x, self.region.y, self.region.width, self.region.height]
	bpy_view_matrix = self.rv3d.view_matrix.transposed()
	bpy_projection_matrix = self.rv3d.window_matrix.transposed()


	# BPY Buffer Matrices
	buffer_bpy_viewport = bgl.Buffer(bgl.GL_INT, 4, bpy_viewport)
	buffer_bpy_view_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4,4],  bpy_view_matrix)
	buffer_bpy_projection_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4,4],  bpy_projection_matrix)
	
	# TESTING BUFFERS
	DEPTH = get_depth(x, y)


	RAY_CAST_W_BPY = UnProject(x, y, DEPTH, buffer_bpy_view_matrix, buffer_bpy_projection_matrix, buffer_bpy_viewport)


	draw_point_bgl(RAY_CAST_W_BPY)


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


	# BGL Buffer Matrices
	buffer_bgl_viewport = get_viewport()
	buffer_bgl_view_matrix = get_modelview_matrix()
	buffer_bgl_projection_matrix = get_projection_matrix()
	
	# TESTING BUFFERS
	DEPTH = get_depth(x, y)


	RAY_CAST_W_BGL = UnProject(x, y, DEPTH, buffer_bgl_view_matrix, buffer_bgl_projection_matrix, buffer_bgl_viewport)


	draw_point_bgl(RAY_CAST_W_BGL)
	
def draw_object_ray_cast(self, context):
	"""Run this function on left mouse, execute the ray cast"""
	# get the context arguments
	x, y = self.mouse_co


	# get the ray from the viewport and mouse
	ray_origin, view_vector = region_2d_to_orig_and_view_vector(self.region, self.rv3d, (x, y))


	ray_target = ray_origin + (view_vector * 1000)
	
	self.obj = context.active_object


	"""Wrapper for ray casting that moves the ray into object space"""


	# get the ray relative to the object
	matrix_inv = self.matrix.inverted()
	ray_origin_obj = matrix_inv * ray_origin
	ray_target_obj = matrix_inv * ray_target


	# cast the ray
	hit, normal, face_index = self.obj.ray_cast(ray_origin_obj, ray_target_obj)
	
	hit_world = self.matrix * hit


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


	ray_origin, view_vector = region_2d_to_orig_and_view_vector(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)
	
def draw_bvhtree_ray_cast(self, context):
	x, y = self.mouse_co


	ray_origin, view_vector = region_2d_to_orig_and_view_vector(self.region, self.rv3d, (x, y))


	# get the ray relative to the object
	matrix_inv = self.matrix.inverted()
	ray_origin_obj = matrix_inv * ray_origin
	ray_target_obj = matrix_inv * view_vector


	# cast the ray
	hit, normal, face_index, distance = self.tree.ray_cast(ray_origin_obj, view_vector)
	
	if hit:
		hit_world = self.matrix * hit
	else:
		hit_world = Vector()


	draw_point_bgl(hit_world)


def show_depth(self, context):
	x, y = self.mouse_co
	depth = get_depth(x, y)
	
	# 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.glVertex2f(*self.mouse_co2)
	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(depth))
	
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
		layout.prop(context.scene, "raycast_type", expand=False)
		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':
			if context.scene.raycast_type in {'0', '1'}:
				self.mouse_co = (event.mouse_x, event.mouse_y)
			elif context.scene.raycast_type in {'2', '3', '4'}:
				self.mouse_co = (event.mouse_region_x, event.mouse_region_y)
			elif context.scene.raycast_type in {'5'}:
				self.mouse_co = (event.mouse_x, event.mouse_y)
				self.mouse_co2 = (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
			draw_handler = [
				draw_ray_cast_unproject_bpy,
				draw_ray_cast_unproject_bgl,
				draw_object_ray_cast,
				draw_scene_ray_cast,
				draw_bvhtree_ray_cast,
				show_depth,
			][int(context.scene.raycast_type)]


			self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_handler, (self, context), 'WINDOW', 'POST_VIEW')
			if context.scene.raycast_type in {'2', '4'}:
				self.obj = context.object
				self.matrix = self.obj.matrix_world.copy()
				if context.scene.raycast_type == '4':
					self.tree = bvhtree.BVHTree.FromObject(self.obj, context.scene)


			self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_handler, (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)
	bpy.types.Scene.raycast_type = bpy.props.EnumProperty(
		name="Ray_Cast type",
		description="Select ray cast type",
		items=[("0","UnProject_Mat_bpy","Ray cast for reading pixel depth"),
			   ("1","UnProject_Mat_bgl","Ray cast for reading pixel depth"),
			   ("2","Object_ray_cast","Ray cast for intersect object geometry"),
			   ("3","Scene_ray_cast","Ray cast for intersect all object geometry in scene"),
			   ("4","BVHTree_ray_cast","Ray cast for intersect all object BVHTree"),
			   ("5","bgl_depth","pixel depth"),
			  ],
			  default='0')


def unregister():
	bpy.utils.unregister_class(PanelTestsRayCast)
	bpy.utils.unregister_class(TestsRayCastOperator)
	del bpy.types.Scene.raycast_type


if __name__ == "__main__":
	register()

Object raycast faster.

Oh I see. Even if the performance difference is very small, using Object.ray_cast or Scene.ray_cast has its advantages. These are more accurate and return more information.
Thanks @Ko1

I have to rectify this. The fastest ray_cast is gluUnProject using matrices called by module “bpy”. The difference is absurd in higth Poly objects.

Once this function takes advantage of own OpenGL drawing, it does not calculate the intersection of BVH, and acts on higth Poly objects in the same way as if they were objects Low Poly.

The performance difference takes into account only its own drawing update OpenGL

I updated the code to add the BVH Tree Raycast. Now this is the fastest raycast.


import bpy, bgl
from mathutils import Vector, Matrix, bvhtree
		
def get_viewport():
	view = bgl.Buffer(bgl.GL_INT, 4)
	bgl.glGetIntegerv(bgl.GL_VIEWPORT, view)
	return view


def get_modelview_matrix():
	model_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4, 4])
	bgl.glGetDoublev(bgl.GL_MODELVIEW_MATRIX, model_matrix)
	return model_matrix


def get_projection_matrix():
	proj_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4, 4])
	bgl.glGetDoublev(bgl.GL_PROJECTION_MATRIX, proj_matrix)
	return proj_matrix


def get_depth(x, y):	
	depth = bgl.Buffer(bgl.GL_FLOAT, [0.0])
	bgl.glReadPixels(x, y, 1, 1, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, depth)
	return depth[0]


def UnProject(x, y, z, view_matrix, projection_matrix, viewport):
	world_x = bgl.Buffer(bgl.GL_DOUBLE, 1, [0.0])
	world_y = bgl.Buffer(bgl.GL_DOUBLE, 1, [0.0])
	world_z = bgl.Buffer(bgl.GL_DOUBLE, 1, [0.0])
	bgl.gluUnProject(x, y, z, view_matrix, projection_matrix, viewport, world_x, world_y, world_z)		
	return Vector((world_x[0], world_y[0], world_z[0]))


def region_2d_to_orig_and_view_vector(region, rv3d, coord, clamp=None):
	viewinv = rv3d.view_matrix.inverted()
	persinv = rv3d.perspective_matrix.inverted()


	dx = (2.0 * coord[0] / region.width) - 1.0
	dy = (2.0 * coord[1] / region.height) - 1.0


	if rv3d.is_perspective:
		origin_start = viewinv.translation.copy()


		out = Vector((dx, dy, -0.5))


		w = out.dot(persinv[3].xyz) + persinv[3][3]


		view_vector = ((persinv * out) / w) - origin_start
	else:
		view_vector = -viewinv.col[2].xyz


		origin_start = ((persinv.col[0].xyz * dx) +
						(persinv.col[1].xyz * dy) +
						viewinv.translation)


		if clamp != 0.0:
			if rv3d.view_perspective != 'CAMERA':
				# this value is scaled to the far clip already
				origin_offset = persinv.col[2].xyz
				if clamp is not None:
					if clamp < 0.0:
						origin_offset.negate()
						clamp = -clamp
					if origin_offset.length > clamp:
						origin_offset.length = clamp


				origin_start -= origin_offset


	view_vector.normalize()
	return origin_start, view_vector


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_ray_cast_unproject_bpy(self, context):
	x, y = self.mouse_co
	
	# BPY Matrices
	bpy_viewport = [self.region.x, self.region.y, self.region.width, self.region.height]
	bpy_view_matrix = self.rv3d.view_matrix.transposed()
	bpy_projection_matrix = self.rv3d.window_matrix.transposed()


	# BPY Buffer Matrices
	buffer_bpy_viewport = bgl.Buffer(bgl.GL_INT, 4, bpy_viewport)
	buffer_bpy_view_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4,4],  bpy_view_matrix)
	buffer_bpy_projection_matrix = bgl.Buffer(bgl.GL_DOUBLE, [4,4],  bpy_projection_matrix)
	
	# TESTING BUFFERS
	DEPTH = get_depth(x, y)


	RAY_CAST_W_BPY = UnProject(x, y, DEPTH, buffer_bpy_view_matrix, buffer_bpy_projection_matrix, buffer_bpy_viewport)


	draw_point_bgl(RAY_CAST_W_BPY)


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


	# BGL Buffer Matrices
	buffer_bgl_viewport = get_viewport()
	buffer_bgl_view_matrix = get_modelview_matrix()
	buffer_bgl_projection_matrix = get_projection_matrix()
	
	# TESTING BUFFERS
	DEPTH = get_depth(x, y)


	RAY_CAST_W_BGL = UnProject(x, y, DEPTH, buffer_bgl_view_matrix, buffer_bgl_projection_matrix, buffer_bgl_viewport)


	draw_point_bgl(RAY_CAST_W_BGL)
	
def draw_object_ray_cast(self, context):
	"""Run this function on left mouse, execute the ray cast"""
	# get the context arguments
	x, y = self.mouse_co


	# get the ray from the viewport and mouse
	ray_origin, view_vector = region_2d_to_orig_and_view_vector(self.region, self.rv3d, (x, y))


	ray_target = ray_origin + (view_vector * 1000)
	
	self.obj = context.active_object


	"""Wrapper for ray casting that moves the ray into object space"""


	# get the ray relative to the object
	matrix_inv = self.matrix.inverted()
	ray_origin_obj = matrix_inv * ray_origin
	ray_target_obj = matrix_inv * ray_target


	# cast the ray
	hit, normal, face_index = self.obj.ray_cast(ray_origin_obj, ray_target_obj)
	
	hit_world = self.matrix * hit


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


	ray_origin, view_vector = region_2d_to_orig_and_view_vector(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)
	
def draw_bvhtree_ray_cast(self, context):
	x, y = self.mouse_co


	ray_origin, view_vector = region_2d_to_orig_and_view_vector(self.region, self.rv3d, (x, y))


	# get the ray relative to the object
	matrix_inv = self.matrix.inverted()
	ray_origin_obj = matrix_inv * ray_origin
	ray_target_obj = matrix_inv * view_vector


	# cast the ray
	hit, normal, face_index, distance = self.tree.ray_cast(ray_origin_obj, view_vector)
	
	if hit:
		hit_world = self.matrix * hit
	else:
		hit_world = Vector()


	draw_point_bgl(hit_world)


def show_depth(self, context):
	x, y = self.mouse_co
	depth = get_depth(x, y)
	
	# 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.glVertex2f(*self.mouse_co2)
	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(depth))
	
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
		layout.prop(context.scene, "raycast_type", expand=False)
		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':
			if context.scene.raycast_type in {'0', '1'}:
				self.mouse_co = (event.mouse_x, event.mouse_y)
			elif context.scene.raycast_type in {'2', '3', '4'}:
				self.mouse_co = (event.mouse_region_x, event.mouse_region_y)
			elif context.scene.raycast_type in {'5'}:
				self.mouse_co = (event.mouse_x, event.mouse_y)
				self.mouse_co2 = (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
			draw_handler = [
				draw_ray_cast_unproject_bpy,
				draw_ray_cast_unproject_bgl,
				draw_object_ray_cast,
				draw_scene_ray_cast,
				draw_bvhtree_ray_cast,
				show_depth,
			][int(context.scene.raycast_type)]


			self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_handler, (self, context), 'WINDOW', 'POST_VIEW')
			if context.scene.raycast_type in {'2', '4'}:
				self.obj = context.object
				self.matrix = self.obj.matrix_world.copy()
				if context.scene.raycast_type == '4':
					self.tree = bvhtree.BVHTree.FromObject(self.obj, context.scene)


			self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_handler, (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)
	bpy.types.Scene.raycast_type = bpy.props.EnumProperty(
		name="Ray_Cast type",
		description="Select ray cast type",
		items=[("0","UnProject_Mat_bpy","Ray cast for reading pixel depth"),
			   ("1","UnProject_Mat_bgl","Ray cast for reading pixel depth"),
			   ("2","Object_ray_cast","Ray cast for intersect object geometry"),
			   ("3","Scene_ray_cast","Ray cast for intersect all object geometry in scene"),
			   ("4","BVHTree_ray_cast","Ray cast for intersect all object BVHTree"),
			   ("5","bgl_depth","pixel depth"),
			  ],
			  default='0')


def unregister():
	bpy.utils.unregister_class(PanelTestsRayCast)
	bpy.utils.unregister_class(TestsRayCastOperator)
	del bpy.types.Scene.raycast_type


if __name__ == "__main__":
	register()

As a side note: You can do this…


            self.region = context.region
            if context.scene.raycast_type == '0':
                self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_ray_cast_unproject_bpy, (self, context), 'WINDOW', 'POST_VIEW')
            if context.scene.raycast_type == '1':
                self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_ray_cast_unproject_bgl, (self, context), 'WINDOW', 'POST_VIEW')
            if context.scene.raycast_type == '2':
                self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_object_ray_cast, (self, context), 'WINDOW', 'POST_VIEW')
            if context.scene.raycast_type == '3':
                self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_scene_ray_cast, (self, context), 'WINDOW', 'POST_VIEW')

… more elegent like this:

            self.region = context.region
            draw_handler = [
                draw_ray_cast_unproject_bpy,
                draw_ray_cast_unproject_bgl,
                draw_object_ray_cast,
                draw_scene_ray_cast
            ][int(context.scene.raycast_type)]
            
            self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_handler, (self, context), 'WINDOW', 'POST_VIEW')



Thank you @CoDEmanX, edited :slight_smile: