chiark / gitweb /
Move the OpenGL GUI base code to a seperate class for easier re-use.
authordaid303 <daid303@gmail.com>
Fri, 25 Jan 2013 09:05:55 +0000 (10:05 +0100)
committerdaid303 <daid303@gmail.com>
Fri, 25 Jan 2013 09:05:55 +0000 (10:05 +0100)
Cura/gui/preview3d.py
Cura/gui/projectPlanner.py
Cura/gui/util/opengl.py
Cura/gui/util/openglGui.py
Cura/gui/util/previewTools.py

index c3378da36bc694d94fde80a44b9ad0169f756f02..69b0828a2691ef247e112bf3737d9f3301b05f39 100644 (file)
@@ -40,8 +40,6 @@ class previewPanel(wx.Panel):
                self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DDKSHADOW))
                self.SetMinSize((440,320))
 
-               self.buttonSize = 64
-               self.glButtonList = []
                self.objectList = []
                self.errorList = []
                self.gcode = None
@@ -108,15 +106,15 @@ class previewPanel(wx.Panel):
                self.Bind(wx.EVT_TIMER, self.OnCheckReloadFile, self.checkReloadFileTimer)
                self.checkReloadFileTimer.Start(1000)
 
-               self.infoToolButton   = openglGui.glButton(self, 0, 0,0, self.OnInfoSelect)
-               self.rotateToolButton = openglGui.glButton(self, 1, 0,1, self.OnRotateSelect)
-               self.scaleToolButton  = openglGui.glButton(self, 2, 0,2, self.OnScaleSelect)
+               self.infoToolButton   = openglGui.glButton(self.glCanvas, 0, 'Info', 0,0, self.OnInfoSelect)
+               self.rotateToolButton = openglGui.glButton(self.glCanvas, 1, 'Rotate', 0,1, self.OnRotateSelect)
+               self.scaleToolButton  = openglGui.glButton(self.glCanvas, 2, 'Scale', 0,2, self.OnScaleSelect)
 
-               self.resetRotationButton = openglGui.glButton(self, 4, 1,0, self.OnRotateReset)
-               self.layFlatButton = openglGui.glButton(self, 5, 2,0, self.OnLayFlat)
+               self.resetRotationButton = openglGui.glButton(self.glCanvas, 4, 'Reset rotation', 1,0, self.OnRotateReset)
+               self.layFlatButton = openglGui.glButton(self.glCanvas, 5, 'Lay flat', 2,0, self.OnLayFlat)
 
-               self.resetScaleButton = openglGui.glButton(self, 8, 1,0, self.OnScaleReset)
-               self.scaleMaxButton = openglGui.glButton(self, 9, 2,0, self.OnScaleMax)
+               self.resetScaleButton = openglGui.glButton(self.glCanvas, 8, 'Scale reset', 1,0, self.OnScaleReset)
+               self.scaleMaxButton = openglGui.glButton(self.glCanvas, 9, 'Scale to machine size', 2,0, self.OnScaleMax)
 
                self.infoToolButton.setSelected(True)
                self.returnToModelViewAndUpdateModel()
@@ -443,18 +441,11 @@ class previewPanel(wx.Panel):
                self.updateModelTransform()
                self.glCanvas.updateProfileToControls()
 
-class PreviewGLCanvas(glcanvas.GLCanvas):
+class PreviewGLCanvas(openglGui.glGuiPanel):
        def __init__(self, parent):
-               attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
-               glcanvas.GLCanvas.__init__(self, parent, attribList = attribList)
-               self.parent = parent
-               self.context = glcanvas.GLContext(self)
-               wx.EVT_PAINT(self, self.OnPaint)
-               wx.EVT_SIZE(self, self.OnSize)
-               wx.EVT_ERASE_BACKGROUND(self, self.OnEraseBackground)
-               wx.EVT_MOUSE_EVENTS(self, self.OnMouseEvents)
-               wx.EVT_MOTION(self, self.OnMouseMotion)
+               super(PreviewGLCanvas, self).__init__(parent)
                wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
+               self.parent = parent
                self.yaw = 30
                self.pitch = 60
                self.zoom = 300
@@ -477,17 +468,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
                self.objColor[2] = profile.getPreferenceColour('model_colour3')
                self.objColor[3] = profile.getPreferenceColour('model_colour4')
 
-       def OnMouseEvents(self,e):
-               if e.ButtonDown() and e.LeftIsDown():
-                       for ctrl in self.parent.glButtonList:
-                               if ctrl.OnMouseDown(e.GetX(), e.GetY()):
-                                       return
-
        def OnMouseMotion(self,e):
-               self.Refresh()
-               for ctrl in self.parent.glButtonList:
-                       if ctrl.OnMouseMotion(e.GetX(), e.GetY()):
-                               return
                if self.parent.objectsMaxV is not None and self.viewport is not None and self.viewMode != 'GCode' and self.viewMode != 'Mixed':
                        p0 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 0, self.modelMatrix, self.projMatrix, self.viewport)
                        p1 = opengl.unproject(e.GetX(), self.viewport[1] + self.viewport[3] - e.GetY(), 1, self.modelMatrix, self.projMatrix, self.viewport)
@@ -553,17 +534,8 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
                if self.zoom > 500:
                        self.zoom = 500
                self.Refresh()
-       
-       def OnEraseBackground(self,event):
-               #Workaround for windows background redraw flicker.
-               pass
-       
-       def OnSize(self,e):
-               self.Refresh()
 
        def OnPaint(self,e):
-               dc = wx.PaintDC(self)
-               self.SetCurrent(self.context)
                opengl.InitGL(self, self.view3D, self.zoom)
                if self.view3D:
                        glTranslate(0,0,-self.zoom)
@@ -585,7 +557,6 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
                glTranslate(-self.parent.machineCenter.x, -self.parent.machineCenter.y, 0)
 
                self.OnDraw()
-               self.SwapBuffers()
 
        def OnDraw(self):
                machineSize = self.parent.machineSize
@@ -774,26 +745,6 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
                        self.parent.tool.OnDraw()
                        glPopMatrix()
 
-               self.drawGui()
-
-               glFlush()
-
-       def drawGui(self):
-               glDisable(GL_DEPTH_TEST)
-               glEnable(GL_BLEND)
-               glDisable(GL_LIGHTING)
-               glColor4ub(255,255,255,255)
-
-               glMatrixMode(GL_PROJECTION)
-               glLoadIdentity()
-               size = self.GetSize()
-               glOrtho(0, size.GetWidth()-1, size.GetHeight()-1, 0, -1000.0, 1000.0)
-               glMatrixMode(GL_MODELVIEW)
-               glLoadIdentity()
-
-               for glButton in self.parent.glButtonList:
-                       glButton.draw()
-
        def drawModel(self, displayList):
                vMin = self.parent.objectsMinV
                vMax = self.parent.objectsMaxV
index e0260881c1af9a7bb75ccdc9e5c0bc7aead96f25..94dc6d84da0d62010778a5bdab2e7945687eda62 100644 (file)
@@ -43,26 +43,15 @@ class ProjectObject(object):
 
                self.parent = parent
                self.filename = filename
-               self.scale = 1.0
-               self.rotate = 0.0
-               self.flipX = False
-               self.flipY = False
-               self.flipZ = False
-               self.swapXZ = False
-               self.swapYZ = False
-               self.extruder = 0
-               self.profile = None
+               self.matrix = numpy.matrix([[1,0,0],[0,1,0],[0,0,1]], numpy.float64)
                
                self.modelDisplayList = None
-               self.modelDirty = False
+               self.modelDirty = True
 
-               self.centerX = -self.getMinimum()[0] + 5
-               self.centerY = -self.getMinimum()[1] + 5
-               
-               self.updateModelTransform()
+               self.centerX = -self.getSize()[0]/2 + 5
+               self.centerY = -self.getSize()[1]/2 + 5
 
-               self.centerX = -self.getMinimum()[0] + 5
-               self.centerY = -self.getMinimum()[1] + 5
+               self.updateModelTransform()
 
        def isSameExceptForPosition(self, other):
                if self.filename != other.filename:
@@ -88,14 +77,8 @@ class ProjectObject(object):
                return True
 
        def updateModelTransform(self):
-               self.mesh.setRotateMirror(self.rotate, self.flipX, self.flipY, self.flipZ, self.swapXZ, self.swapYZ)
-               minZ = self.mesh.getMinimumZ()
-               minV = self.getMinimum()
-               maxV = self.getMaximum()
-               self.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ])
-               minZ = self.mesh.getMinimumZ()
-               self.modelDirty = True
-       
+               self.mesh.processMatrix()
+
        def getMinimum(self):
                return self.mesh.getMinimum()
        def getMaximum(self):
index 0f10077ebe7bd20973096bbef59b86a23cb267cf..1a160571e75edba9acf0a4273208fce2130cbfcf 100644 (file)
@@ -54,10 +54,40 @@ def InitGL(window, view3D, zoom):
 platformMesh = None
 
 def DrawMachine(machineSize):
+       glDisable(GL_LIGHTING)
+       glDisable(GL_CULL_FACE)
+       glEnable(GL_BLEND)
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+
+       sx = machineSize.x
+       sy = machineSize.y
+       for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
+               for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
+                       x1 = sx/2+x * 10
+                       x2 = x1 + 10
+                       y1 = sx/2+y * 10
+                       y2 = y1 + 10
+                       x1 = max(min(x1, sx), 0)
+                       y1 = max(min(y1, sy), 0)
+                       x2 = max(min(x2, sx), 0)
+                       y2 = max(min(y2, sy), 0)
+                       if (x & 1) == (y & 1):
+                               glColor4ub(5, 171, 231, 127)
+                       else:
+                               glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
+                       glBegin(GL_QUADS)
+                       glVertex3f(x1, y1, -0.02)
+                       glVertex3f(x2, y1, -0.02)
+                       glVertex3f(x2, y2, -0.02)
+                       glVertex3f(x1, y2, -0.02)
+                       glEnd()
+
+       glEnable(GL_CULL_FACE)
+
        if profile.getPreference('machine_type') == 'ultimaker':
                glPushMatrix()
                glEnable(GL_LIGHTING)
-               glTranslate(100, 200, -5)
+               glTranslate(100, 200, -1)
                glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
                glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
                glEnable(GL_BLEND)
@@ -73,117 +103,46 @@ def DrawMachine(machineSize):
                if platformMesh:
                        DrawMesh(platformMesh)
                glPopMatrix()
-
-       glDisable(GL_LIGHTING)
-       if False:
-               glColor3f(0.7, 0.7, 0.7)
-               glLineWidth(2)
-               glBegin(GL_LINES)
-               for i in xrange(0, int(machineSize.x), 10):
-                       glVertex3f(i, 0, 0)
-                       glVertex3f(i, machineSize.y, 0)
-               for i in xrange(0, int(machineSize.y), 10):
-                       glVertex3f(0, i, 0)
-                       glVertex3f(machineSize.x, i, 0)
-               glEnd()
-
-               glEnable(GL_LINE_SMOOTH)
-               glEnable(GL_BLEND)
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
-               glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
-
-               glColor3f(0.0, 0.0, 0.0)
-               glLineWidth(4)
-               glBegin(GL_LINE_LOOP)
-               glVertex3f(0, 0, 0)
-               glVertex3f(machineSize.x, 0, 0)
-               glVertex3f(machineSize.x, machineSize.y, 0)
-               glVertex3f(0, machineSize.y, 0)
-               glEnd()
-
-               glLineWidth(2)
-               glBegin(GL_LINE_LOOP)
-               glVertex3f(0, 0, machineSize.z)
-               glVertex3f(machineSize.x, 0, machineSize.z)
-               glVertex3f(machineSize.x, machineSize.y, machineSize.z)
-               glVertex3f(0, machineSize.y, machineSize.z)
-               glEnd()
-               glBegin(GL_LINES)
-               glVertex3f(0, 0, 0)
-               glVertex3f(0, 0, machineSize.z)
-               glVertex3f(machineSize.x, 0, 0)
-               glVertex3f(machineSize.x, 0, machineSize.z)
-               glVertex3f(machineSize.x, machineSize.y, 0)
-               glVertex3f(machineSize.x, machineSize.y, machineSize.z)
-               glVertex3f(0, machineSize.y, 0)
-               glVertex3f(0, machineSize.y, machineSize.z)
-               glEnd()
-       else:
-               glDisable(GL_CULL_FACE)
-               glEnable(GL_BLEND)
+               glDisable(GL_LIGHTING)
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
 
-               sx = machineSize.x
-               sy = machineSize.y
-               for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
-                       for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
-                               x1 = sx/2+x * 10
-                               x2 = x1 + 10
-                               y1 = sx/2+y * 10
-                               y2 = y1 + 10
-                               x1 = max(min(x1, sx), 0)
-                               y1 = max(min(y1, sy), 0)
-                               x2 = max(min(x2, sx), 0)
-                               y2 = max(min(y2, sy), 0)
-                               if (x & 1) == (y & 1):
-                                       glColor4ub(5, 171, 231, 127)
-                               else:
-                                       glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
-                               glBegin(GL_QUADS)
-                               glVertex3f(x1, y1, -0.01)
-                               glVertex3f(x2, y1, -0.01)
-                               glVertex3f(x2, y2, -0.01)
-                               glVertex3f(x1, y2, -0.01)
-                               glEnd()
+       glColor4ub(5, 171, 231, 64)
+       glBegin(GL_QUADS)
+       glVertex3f(0, 0, machineSize.z)
+       glVertex3f(0, machineSize.y, machineSize.z)
+       glVertex3f(machineSize.x, machineSize.y, machineSize.z)
+       glVertex3f(machineSize.x, 0, machineSize.z)
+       glEnd()
+
+       glColor4ub(5, 171, 231, 96)
+       glBegin(GL_QUADS)
+       glVertex3f(0, 0, 0)
+       glVertex3f(0, 0, machineSize.z)
+       glVertex3f(machineSize.x, 0, machineSize.z)
+       glVertex3f(machineSize.x, 0, 0)
+
+       glVertex3f(0, machineSize.y, machineSize.z)
+       glVertex3f(0, machineSize.y, 0)
+       glVertex3f(machineSize.x, machineSize.y, 0)
+       glVertex3f(machineSize.x, machineSize.y, machineSize.z)
+       glEnd()
+
+       glColor4ub(5, 171, 231, 128)
+       glBegin(GL_QUADS)
+       glVertex3f(0, 0, machineSize.z)
+       glVertex3f(0, 0, 0)
+       glVertex3f(0, machineSize.y, 0)
+       glVertex3f(0, machineSize.y, machineSize.z)
 
-               glEnable(GL_CULL_FACE)
-
-               glColor4ub(5, 171, 231, 64)
-               glBegin(GL_QUADS)
-               glVertex3f(0, 0, machineSize.z)
-               glVertex3f(0, machineSize.y, machineSize.z)
-               glVertex3f(machineSize.x, machineSize.y, machineSize.z)
-               glVertex3f(machineSize.x, 0, machineSize.z)
-               glEnd()
-
-               glColor4ub(5, 171, 231, 96)
-               glBegin(GL_QUADS)
-               glVertex3f(0, 0, 0)
-               glVertex3f(0, 0, machineSize.z)
-               glVertex3f(machineSize.x, 0, machineSize.z)
-               glVertex3f(machineSize.x, 0, 0)
-
-               glVertex3f(0, machineSize.y, machineSize.z)
-               glVertex3f(0, machineSize.y, 0)
-               glVertex3f(machineSize.x, machineSize.y, 0)
-               glVertex3f(machineSize.x, machineSize.y, machineSize.z)
-               glEnd()
-
-               glColor4ub(5, 171, 231, 128)
-               glBegin(GL_QUADS)
-               glVertex3f(0, 0, machineSize.z)
-               glVertex3f(0, 0, 0)
-               glVertex3f(0, machineSize.y, 0)
-               glVertex3f(0, machineSize.y, machineSize.z)
-
-               glVertex3f(machineSize.x, 0, 0)
-               glVertex3f(machineSize.x, 0, machineSize.z)
-               glVertex3f(machineSize.x, machineSize.y, machineSize.z)
-               glVertex3f(machineSize.x, machineSize.y, 0)
-               glEnd()
-
-               glDisable(GL_BLEND)
+       glVertex3f(machineSize.x, 0, 0)
+       glVertex3f(machineSize.x, 0, machineSize.z)
+       glVertex3f(machineSize.x, machineSize.y, machineSize.z)
+       glVertex3f(machineSize.x, machineSize.y, 0)
+       glEnd()
+
+       glDisable(GL_BLEND)
 
+       #Draw the X/Y/Z indicator
        glPushMatrix()
        glTranslate(5, 5, 2)
        glLineWidth(2)
@@ -234,10 +193,10 @@ def glDrawStringCenter(s):
        glRasterPos2f(0, 0)
        width = 0
        for c in s:
-               width += glutBitmapWidth(GLUT_BITMAP_HELVETICA_18, ord(c))
+               width += glutBitmapWidth(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
        glBitmap(0,0,0,0, -width/2, 0, None)
        for c in s:
-               glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, ord(c))
+               glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
 
 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
        npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
index 8ce9df40e444c3b84be0f9ef89b565a81c0a3250..ce362d5ded46287da9cae25cc34e09b78c358ad5 100644 (file)
@@ -1,6 +1,8 @@
 from __future__ import absolute_import
 from __future__ import division
 
+import wx
+from wx import glcanvas
 import OpenGL
 OpenGL.ERROR_CHECKING = False
 from OpenGL.GL import *
@@ -9,14 +11,82 @@ from Cura.gui.util import opengl
 
 glButtonsTexture = None
 
+class glGuiPanel(glcanvas.GLCanvas):
+       def __init__(self, parent):
+               attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 24, glcanvas.WX_GL_STENCIL_SIZE, 8)
+               glcanvas.GLCanvas.__init__(self, parent, attribList = attribList)
+               self._parent = parent
+               self._context = glcanvas.GLContext(self)
+               self._glGuiControlList = []
+               self._buttonSize = 64
+
+               wx.EVT_PAINT(self, self._OnGuiPaint)
+               wx.EVT_SIZE(self, self._OnSize)
+               wx.EVT_ERASE_BACKGROUND(self, self._OnEraseBackground)
+               wx.EVT_MOUSE_EVENTS(self, self._OnGuiMouseEvents)
+               wx.EVT_MOTION(self, self._OnGuiMouseMotion)
+
+       def _OnGuiMouseEvents(self,e):
+               if e.ButtonDown() and e.LeftIsDown():
+                       for ctrl in self._glGuiControlList:
+                               if ctrl.OnMouseDown(e.GetX(), e.GetY()):
+                                       return
+
+       def _OnGuiMouseMotion(self,e):
+               self.Refresh()
+               for ctrl in self._glGuiControlList:
+                       if ctrl.OnMouseMotion(e.GetX(), e.GetY()):
+                               return
+               self.OnMouseMotion(e)
+
+       def _OnGuiPaint(self, e):
+               dc = wx.PaintDC(self)
+               self.SetCurrent(self._context)
+               self.OnPaint(e)
+               self._drawGui()
+               glFlush()
+               self.SwapBuffers()
+
+       def _drawGui(self):
+               glDisable(GL_DEPTH_TEST)
+               glEnable(GL_BLEND)
+               glDisable(GL_LIGHTING)
+               glColor4ub(255,255,255,255)
+
+               glMatrixMode(GL_PROJECTION)
+               glLoadIdentity()
+               size = self.GetSize()
+               glOrtho(0, size.GetWidth()-1, size.GetHeight()-1, 0, -1000.0, 1000.0)
+               glMatrixMode(GL_MODELVIEW)
+               glLoadIdentity()
+
+               for glButton in self._glGuiControlList:
+                       glButton.draw()
+
+       def _OnEraseBackground(self,event):
+               #Workaround for windows background redraw flicker.
+               pass
+
+       def _OnSize(self,e):
+               self.Refresh()
+
+       def OnMouseEvents(self,e):
+               pass
+
+       def OnMouseMotion(self, e):
+               pass
+       def OnPaint(self, e):
+               pass
+
 class glButton(object):
-       def __init__(self, parent, imageID, x, y, callback):
+       def __init__(self, parent, imageID, tooltip, x, y, callback):
+               self._tooltip = tooltip
                self._parent = parent
                self._imageID = imageID
                self._x = x
                self._y = y
                self._callback = callback
-               self._parent.glButtonList.append(self)
+               self._parent._glGuiControlList.append(self)
                self._selected = False
                self._focus = False
                self._hidden = False
@@ -39,7 +109,7 @@ class glButton(object):
 
                cx = (self._imageID % 4) / 4
                cy = int(self._imageID / 4) / 4
-               bs = self._parent.buttonSize
+               bs = self._parent._buttonSize
 
                glPushMatrix()
                glTranslatef(self._x * bs * 1.3 + bs * 0.8, self._y * bs * 1.3 + bs * 0.8, 0)
@@ -51,6 +121,7 @@ class glButton(object):
                elif self._focus:
                        scale = 0.9
                glScalef(bs * scale, bs * scale, bs * scale)
+               glColor4ub(255,255,255,255)
                glBegin(GL_QUADS)
                glTexCoord2f(cx+0.25, cy)
                glVertex2f( 0.5,-0.5)
@@ -62,12 +133,16 @@ class glButton(object):
                glVertex2f( 0.5, 0.5)
                glEnd()
                glDisable(GL_TEXTURE_2D)
+               if self._focus:
+                       glColor4ub(0,0,0,255)
+                       glTranslatef(0, -0.55, 0)
+                       opengl.glDrawStringCenter(self._tooltip)
                glPopMatrix()
 
        def _checkHit(self, x, y):
                if self._hidden:
                        return False
-               bs = self._parent.buttonSize
+               bs = self._parent._buttonSize
                return -bs * 0.5 <= x - (self._x * bs * 1.3 + bs * 0.8) <= bs * 0.5 and -bs * 0.5 <= y - (self._y * bs * 1.3 + bs * 0.8) <= bs * 0.5
 
        def OnMouseMotion(self, x, y):
index 131e9c2d97a6974bf4226a97700b5898b9bca953..0de3bf67922cbe7323f93842698c4aeb0f4f24ef 100644 (file)
@@ -365,6 +365,21 @@ class toolScale(object):
                glEnable(GL_BLEND)
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
 
+               glColor3ub(0,0,0)
+               size = self.parent.getObjectSize()
+               radius = self.parent.getObjectBoundaryCircle() * max(scaleX, scaleY, scaleZ)
+               glPushMatrix()
+               glTranslate(0,0,size[2]/2 + 5)
+               glRotate(-self.parent.yaw, 0,0,1)
+               if self.parent.pitch < 80:
+                       glTranslate(0, radius + 5,0)
+               elif self.parent.pitch < 100:
+                       glTranslate(0, (radius + 5) * (90 - self.parent.pitch) / 10,0)
+               else:
+                       glTranslate(0,-(radius + 5),0)
+               opengl.glDrawStringCenter("%dx%dx%d" % (size[0] * scaleX, size[1] * scaleY, size[2] * scaleZ))
+               glPopMatrix()
+
                glLineWidth(1)
                glBegin(GL_LINES)
                glColor3ub(128,0,0)