from __future__ import absolute_import
from __future__ import division
-import numpy
-from ctypes import c_void_p
+import wx
import OpenGL
OpenGL.ERROR_CHECKING = False
self._zoom = 100
self._objectList = []
self._objectShader = None
+ self._focusObj = None
+ self._selectedObj = None
self._objColors = [None,None,None,None]
- self._tmpVertex = None
+ self._mouseX = -1
+ self._mouseY = -1
self.updateProfileToControls()
def loadScene(self, fileList):
for obj in meshLoader.loadMeshes(filename):
self._objectList.append(obj)
+ def _deleteObject(self, obj):
+ if obj == self._selectedObj:
+ self._selectedObj = None
+ if obj == self._focusObj:
+ self._focusObj = None
+ self._objectList.remove(obj)
+ for m in obj._meshList:
+ if m.vbo is not None:
+ self.glReleaseList.append(m.vbo)
+
def updateProfileToControls(self):
self._objColors[0] = profile.getPreferenceColour('model_colour')
self._objColors[1] = profile.getPreferenceColour('model_colour2')
self._objColors[2] = profile.getPreferenceColour('model_colour3')
self._objColors[3] = profile.getPreferenceColour('model_colour4')
+ def OnKeyChar(self, keyCode):
+ if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
+ if self._selectedObj is not None:
+ self._deleteObject(self._selectedObj)
+ self.Refresh()
+
+ def OnMouseDown(self,e):
+ if self._focusObj is not None:
+ self._selectedObj = self._focusObj
+
def OnMouseMotion(self,e):
if e.Dragging() and e.LeftIsDown():
- self._yaw += e.GetX() - self.oldX
- self._pitch -= e.GetY() - self.oldY
+ self._yaw += e.GetX() - self._mouseX
+ self._pitch -= e.GetY() - self._mouseY
if self._pitch > 170:
self._pitch = 170
if self._pitch < 10:
self._pitch = 10
if e.Dragging() and e.RightIsDown():
- self._zoom += e.GetY() - self.oldY
+ self._zoom += e.GetY() - self._mouseY
if self._zoom < 1:
self._zoom = 1
if self._zoom > 500:
self._zoom = 500
- self.oldX = e.GetX()
- self.oldY = e.GetY()
+ self._mouseX = e.GetX()
+ self._mouseY = e.GetY()
def _init3DView(self):
# set viewing projection
size = self.GetSize()
glViewport(0, 0, size.GetWidth(), size.GetHeight())
+ glLoadIdentity()
glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
def OnPaint(self,e):
if self._objectShader is None:
- self._objectShader = opengl.GLShader("""
+ self._objectShader = opengl.GLShader(self, """
uniform float cameraDistance;
varying float light_amount;
void main(void)
{
- gl_FragColor = gl_Color * light_amount;
+ gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
}
""")
self._init3DView()
glRotate(-self._pitch, 1,0,0)
glRotate(self._yaw, 0,0,1)
glTranslate(0,0,-15)
- glColor3f(self._objColors[0][0], self._objColors[0][1], self._objColors[0][2])
+ glClearColor(1,1,1,1)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
+
+ for n in xrange(0, len(self._objectList)):
+ obj = self._objectList[n]
+ glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
+ self._renderObject(obj)
+
+ if self._mouseX > -1:
+ n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
+ if n < len(self._objectList):
+ self._focusObj = self._objectList[n]
+ else:
+ self._focusObj = None
+
+ self._init3DView()
+ glTranslate(0,0,-self._zoom)
+ glRotate(-self._pitch, 1,0,0)
+ glRotate(self._yaw, 0,0,1)
+ glTranslate(0,0,-15)
self._objectShader.bind()
self._objectShader.setUniform('cameraDistance', self._zoom)
- if self._tmpVertex is None:
- for obj in self._objectList:
- for m in obj._meshList:
- self._tmpVertex = opengl.GLVBO(m.vertexes, m.normal)
-
- self._tmpVertex.render()
+ for obj in self._objectList:
+ col = self._objColors[0]
+ if self._selectedObj == obj:
+ col = map(lambda n: n * 1.3, col)
+ elif self._focusObj == obj:
+ col = map(lambda n: n * 1.2, col)
+ elif self._focusObj is not None or self._selectedObj is not None:
+ col = map(lambda n: n * 0.8, col)
+ glColor4f(col[0], col[1], col[2], col[3])
+ self._renderObject(obj)
self._objectShader.unbind()
+
+ def _renderObject(self, obj):
+ glPushMatrix()
+ offset = (obj.getMinimum() + obj.getMaximum()) / 2
+ glTranslate(-offset[0], -offset[1], -obj.getMinimum()[2])
+ for m in obj._meshList:
+ if m.vbo is None:
+ m.vbo = opengl.GLVBO(self, m.vertexes, m.normal)
+ m.vbo.render()
+ glPopMatrix()
platformMesh = None
class GLShader(object):
- def __init__(self, vertexProgram, fragmentProgram):
+ def __init__(self, owner, vertexProgram, fragmentProgram):
+ self._owner = owner
try:
self._vertexProgram = shaders.compileShader(vertexProgram, GL_VERTEX_SHADER)
self._fragmentProgram = shaders.compileShader(fragmentProgram, GL_FRAGMENT_SHADER)
def unbind(self):
shaders.glUseProgram(0)
- def delete(self):
- shaders.glDeleteShader(self._vertexProgram)
- shaders.glDeleteShader(self._fragmentProgram)
- glDeleteProgram(self._program)
+ def release(self):
+ if self._program != None:
+ shaders.glDeleteShader(self._vertexProgram)
+ shaders.glDeleteShader(self._fragmentProgram)
+ glDeleteProgram(self._program)
+ self._program = None
def setUniform(self, name, value):
- glUniform1f(glGetUniformLocation(self._program, name), value)
+ if self._program is not None:
+ glUniform1f(glGetUniformLocation(self._program, name), value)
+
+ def __del__(self):
+ if self._program is not None and bool(glDeleteProgram):
+ print "OpenGL shader was not properly cleaned, trying to clean it up now."
+ self._owner.glReleaseList.append(self)
class GLVBO(object):
- def __init__(self, vertexArray, normalArray):
+ def __init__(self, owner, vertexArray, normalArray):
self._buffer = glGenBuffers(1)
self._size = len(vertexArray)
+ self._owner = owner
glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
glBufferData(GL_ARRAY_BUFFER, numpy.concatenate((vertexArray, normalArray), 1), GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
def render(self):
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
- #glVertexPointer(3, GL_FLOAT, 0, m.vertexes)
- #glNormalPointer(GL_FLOAT, 0, m.normal)
glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
glVertexPointer(3, GL_FLOAT, 2*3*4, c_void_p(0))
glNormalPointer(GL_FLOAT, 2*3*4, c_void_p(3 * 4))
self._buffer = None
def __del__(self):
- if self._buffer is not None:
- print "OpenGL buffer was not properly cleaned, trying to clean it up now."
- glDeleteBuffers(self._buffer, 1)
+ if self._buffer is not None and bool(glDeleteBuffers):
+ self._owner.glReleaseList.append(self)
def DrawMachine(machineSize):
glDisable(GL_LIGHTING)
self._glRobotTexture = None
self._buttonSize = 64
+ self.glReleaseList = []
+
wx.EVT_PAINT(self, self._OnGuiPaint)
wx.EVT_SIZE(self, self._OnSize)
wx.EVT_ERASE_BACKGROUND(self, self._OnEraseBackground)
- wx.EVT_LEFT_DOWN(self, self._OnGuiMouseLeftDown)
- wx.EVT_LEFT_UP(self, self._OnGuiMouseLeftUp)
+ wx.EVT_LEFT_DOWN(self, self._OnGuiMouseDown)
+ wx.EVT_LEFT_UP(self, self._OnGuiMouseUp)
+ wx.EVT_RIGHT_DOWN(self, self._OnGuiMouseDown)
+ wx.EVT_RIGHT_UP(self, self._OnGuiMouseUp)
+ wx.EVT_MIDDLE_DOWN(self, self._OnGuiMouseDown)
+ wx.EVT_MIDDLE_UP(self, self._OnGuiMouseUp)
wx.EVT_MOTION(self, self._OnGuiMouseMotion)
- wx.EVT_CHAR(self, self.OnKeyChar)
+ wx.EVT_CHAR(self, self._OnGuiKeyChar)
wx.EVT_KILL_FOCUS(self, self.OnFocusLost)
- def OnKeyChar(self, e):
+ def _OnGuiKeyChar(self, e):
if self._focus is not None:
self._focus.OnKeyChar(e.GetKeyCode())
self.Refresh()
+ else:
+ self.OnKeyChar(e.GetKeyCode())
def OnFocusLost(self, e):
self._focus = None
self.Refresh()
- def _OnGuiMouseLeftDown(self,e):
+ def _OnGuiMouseDown(self,e):
self.SetFocus()
if self._container.OnMouseDown(e.GetX(), e.GetY()):
self.Refresh()
return
- self.OnMouseLeftDown(e)
- def _OnGuiMouseLeftUp(self, e):
+ self.OnMouseDown(e)
+
+ def _OnGuiMouseUp(self, e):
if self._container.OnMouseUp(e.GetX(), e.GetY()):
self.Refresh()
return
- self.OnMouseLeftUp(e)
+ self.OnMouseUp(e)
def _OnGuiMouseMotion(self,e):
self.Refresh()
dc = wx.PaintDC(self)
try:
self.SetCurrent(self._context)
+ for obj in self.glReleaseList:
+ obj.release()
+ del self.glReleaseList[:]
self.OnPaint(e)
self._drawGui()
glFlush()
self._container.updateLayout()
self.Refresh()
- def OnMouseLeftDown(self,e):
+ def OnMouseDown(self,e):
pass
- def OnMouseLeftUp(self,e):
+ def OnMouseUp(self,e):
pass
def OnMouseMotion(self, e):
pass
+ def OnKeyChar(self, keyCode):
+ pass
def OnPaint(self, e):
pass