It seems that blender python exposes very limited functionality of OpenGL. I currently want to draw additional information in every edge of a mesh by using OpenGL. Basically the edge direction is what I am looking for. However, I am not getting very good performance for a mesh consisting of 59,620 edges.
Initially I tried opengl drawing using immediate mode, this was too slow. Next I tried using display list. It is good but not what I expected. I'd have to manually update every the display list when there is a change made(adding, deleting edge/vertex/face). Is there any alternative way to do this? Or is there some way I can just get edges displayed on screen/viewport and display properties for them. That way I don't have to go through checking every edges.
I have a checkbox which when enabled simply generates a display list and adds a draw_handler to the view3d scene which calls this display list.
EDIT: First I create the opengl display list using this piece of code. This code simply goes through every edge and creates an arrow representing the edge direction and finally generates the opengl display list.
def createArrowDisplayList(self, context):
ob = context.object
if ob is None:
return
if bpy.context.active_object.mode != 'EDIT':
return
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)
index = glGenLists(1)
glNewList(index, GL_COMPILE)
glColor3f(0.0,1.0,1.0)
for e in bm.edges:
vecFrom = e.verts[0].co
vecTo = e.verts[1].co
middle = (Vector(vecTo) + Vector(vecFrom)) / 2.0
v = Vector(vecTo) - Vector(vecFrom)
v.normalize()
# if vector is straight pointing up only on z axis ignore it
if abs(v.x) < 0.0001 and abs(v.y) < 0.0001:
continue
vPerp1 = Vector((-v.y, v.x, 0.0))
vPerp2 = Vector((v.y, -v.x, 0.0))
v1 = (vPerp1 - v).normalized()
v2 = (vPerp2 - v).normalized()
SCALER = 1.0
glPushMatrix()
hAngle = degrees(v.xy.angle_signed(Vector((0,1))))
vAngle = -degrees(v.angle(v.xy.to_3d()))
glTranslatef(*middle)
glRotatef(hAngle, 0.0, 0.0, 1.0)
glRotatef(vAngle, 1.0, 0.0, 0.0)
glScalef(SCALER, SCALER, SCALER)
glBegin(GL_TRIANGLES)
glVertex3f( -0.5, -1.0, 0.0 )
glVertex3f( 0.0, 1.0, 0.0 )
glVertex3f( 0.5, -1.0, 0.0 )
glEnd()
glPopMatrix()
"""
glBegin(GL_LINE_STRIP)
glVertex3f(*(middle + v1))
glVertex3f(*(middle))
glVertex3f(*(middle + v2))
glEnd()
"""
glEndList()
return index
And then, I add this method to the draw handler on 3D view. Now the display list needs to be refreshed or generated again manually whenever there is any change made to the underlying mesh
@staticmethod
def draw_callback_px(context, displayListIndex):
wm = context.window_manager
if wm.mesh_layer.bDisplayEdgeDirection == False:
return
ob = context.object
if ob is None:
return
# 50% alpha, 2 pixel width line
#glEnable(GL_BLEND)
glColor4f(1.0, 1.0, 1.0, 0.5)
#glLineWidth(2)
glPushMatrix()
glScalef(*ob.scale)
glTranslatef(*ob.location)
glCallList(displayListIndex)
glPopMatrix()
# restore opengl defaults
glLineWidth(1)
glDisable(GL_BLEND)
glColor4f(0.0, 0.0, 0.0, 1.0)