The bgl module allows us to obtain various information displayed in 3D Blender view. For example, I made a script that gets the 3D coordinate where the mouse cursor hits a object:

import bpy
import bgl

"""Functions for the mouse_coords_to_3D_view"""
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

"""Function mouse_coords_to_3D_view"""
def mouse_coords_to_3D_view(x, y):    
    depth = bgl.Buffer(bgl.GL_FLOAT, [0.0])
    bgl.glReadPixels(x, y, 1, 1, bgl.GL_DEPTH_COMPONENT, bgl.GL_FLOAT, depth)
    #if (depth[0] != 1.0):
    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])
    view1 = get_viewport()
    model = get_modelview_matrix()
    proj = get_projection_matrix ()   
    bgl.gluUnProject(x, y, depth[0], 
                     model, proj,
                     world_x, world_y, world_z)
    return world_x[0], world_y[0], world_z[0]

"""drawing point OpenGL in mouse_coords_to_3D_view"""
def draw_callback_px(self, context):
    # mouse coordinates relative to 3d view
    x, y = self.mouse_path

    # mouse coordinates relative to Blender interface
    view = get_viewport()
    gmx = view[0] + x
    gmy = view[1] + y

    # draw 3d mouse OpenGL point in the 3D View
    mouse3d = mouse_coords_to_3D_view(gmx, gmy)        
    bgl.glColor4f(1.0, 0.8, 0.0, 1.0)

    context.area.header_text_set("hit: %.2f %.2f %.2f" % mouse3d)

class ModalDrawOperator(bpy.types.Operator):
    """Draw a point with the mouse"""
    bl_idname = "view3d.modal_operator"
    bl_label = "Simple Modal View3D Operator"   

    def modal(self, context, event):

        if event.type == 'MOUSEMOVE':
            self.mouse_path = (event.mouse_region_x, event.mouse_region_y)            

        elif event.type == 'LEFTMOUSE':
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'FINISHED'}

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
            return {'CANCELLED'}

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        # the arguments we pass the the callback
        args = (self, context)
        # Add the region OpenGL drawing callback
        # draw in view space with 'POST_VIEW' and 'PRE_VIEW'
        self._handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback_px, args, 'WINDOW', 'POST_VIEW')
        self.mouse_path = []
        #self.wx = bpy.context.window.width
        #self.wy = bpy.context.window.height
        return {'RUNNING_MODAL'}

def register():

def unregister():

if __name__ == "__main__":

But now I want to get a list with the 2D vertices in screen. How can I get it without having to convert 3D to 2D? If anyone knows, please tell me. Can be the Vertices index too

  • 2
    $\begingroup$ What do you mean when you say 2D vertices in screen? Do you mean going into Orthographic mode and then get the coordinates for the visible vertices? Or are you after a x/y-axis, z/y-axis, x/z-axis 2D? $\endgroup$
    – Humilton
    Feb 16, 2015 at 22:02
  • 2
    $\begingroup$ You must convert 3d -> 2d, The 2d locations aren't stored anywhere. $\endgroup$
    – ideasman42
    Feb 16, 2015 at 22:26
  • $\begingroup$ 2D like the mouse coords. (x and y). $\endgroup$
    – Mano-Wii
    Feb 16, 2015 at 22:28
  • $\begingroup$ @Mano-Wii In what space? View? Oxy plane? $\endgroup$ Feb 16, 2015 at 22:30
  • $\begingroup$ @someonewithpc, In the Viewport space. Integer values relative to the screen pixels. As is done in OpenGL $\endgroup$
    – Mano-Wii
    Feb 16, 2015 at 22:34


Browse other questions tagged .