7
$\begingroup$

I'd like to use bgl to draw dots points on 2d screen from 3d vertices in scene. I have lines working by using bgl.GL_LINE_LOOP but I couldn't find the full list of bgl.GL_* to loop up for points.

$\endgroup$
  • $\begingroup$ What's the desired radius of these dots? Or do you mean dotted lines? $\endgroup$ – CoDEmanX Dec 28 '14 at 23:08
  • $\begingroup$ Hi, I meant points but wasn't able to find the list of available bgl.GL_* params to look up. Now that you mentioned, what is parameter for dotted lines? $\endgroup$ – Radivarig Dec 28 '14 at 23:22
8
$\begingroup$

short answer:

bgl.glPointSize(5) bgl.glBegin(bgl.GL_POINTS)

less shorter answer:

Open template operator_modal_draw.py

In draw_callback_px(self, context) I call my function

DrawByVertices("points", verts2d, [0.5, 1, 0.1, 0.5])

where verts2d are screen coordinates [(screen.x, screen.y), ..] in my case derived from vector3 like this

from bpy_extras.view3d_utils import location_3d_to_region_2d
#...
verts2d = []
for v in bm.verts:
    new2dCo = location_3d_to_region_2d(context.region, \
                                       context.space_data.region_3d, \
                                       v.co)
    verts2d.append([new2dCo.x,new2dCo.y])

.

def DrawByVertices(mode, verts2d, color):
    bgl.glColor4f(*color)
    bgl.glEnable(bgl.GL_BLEND)

    if mode is "points":
        bgl.glPointSize(5)
        bgl.glBegin(bgl.GL_POINTS)    
    elif mode is "lines":
        bgl.glLineWidth(2)
        bgl.glBegin(bgl.GL_LINE_LOOP)

    for x, y in verts2d:
        bgl.glVertex2f(x, y)

    bgl.glEnd()
    bgl.glDisable(bgl.GL_BLEND)
    #restore defaults
    bgl.glLineWidth(1)
    bgl.glColor4f(0.0, 0.0, 0.0, 1.0)

    return

Result is colored points drawn on screen over 3d vertex coordinates.

$\endgroup$
  • $\begingroup$ Note that the maximum value for point size is driver-specific and never larger than 20 afaik. $\endgroup$ – CoDEmanX Dec 30 '14 at 0:24
6
$\begingroup$

You can use OpenGL's feature for stippled lines to draw dotted / dashed lines:

import bpy
import bgl
import blf


def draw_callback_px(self, context):

    bgl.glPushAttrib(bgl.GL_ENABLE_BIT)
    # glPushAttrib is done to return everything to normal after drawing

    bgl.glLineStipple(1, 0x9999)
    bgl.glEnable(bgl.GL_LINE_STIPPLE)

    font_id = 0  # XXX, need to find out how best to get this.

    # draw some text
    blf.position(font_id, 15, 30, 0)
    blf.size(font_id, 20, 72)
    blf.draw(font_id, "Hello Word " + str(len(self.mouse_path)))

    # 50% alpha, 2 pixel width line
    bgl.glEnable(bgl.GL_BLEND)
    bgl.glColor4f(0.0, 0.0, 0.0, 0.5)
    bgl.glLineWidth(2)

    bgl.glBegin(bgl.GL_LINE_STRIP)
    for x, y in self.mouse_path:
        bgl.glVertex2i(x, y)

    bgl.glEnd()
    bgl.glPopAttrib()

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


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

    def modal(self, context, event):
        context.area.tag_redraw()

        if event.type == 'MOUSEMOVE':
            self.mouse_path.append((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 {'RUNNING_MODAL'}

    def invoke(self, context, event):
        if context.area.type == 'VIEW_3D':
            # 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_PIXEL')

            self.mouse_path = []

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "View3D not found, cannot run operator")
            return {'CANCELLED'}


def register():
    bpy.utils.register_class(ModalDrawOperator)


def unregister():
    bpy.utils.unregister_class(ModalDrawOperator)

if __name__ == "__main__":
    register()

If you want to draw circles in arbitrary size, you'll have to roll your own primitive drawing function for ellipses / circles (basically a regular polygon with as many edges as required to make it look round).

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.