Commit b7ac1bf9 authored by sumpfralle's avatar sumpfralle

r648@erker: lars | 2010-02-12 20:02:30 +0100

 fixed some inconsistencies of the opengl code


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@113 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent df858550
#!/usr/bin/env python #!/usr/bin/env python
import OpenGL.GL as GL import OpenGL.GL as GL
import OpenGL.GLU as GLU
import OpenGL.GLUT as GLUT import OpenGL.GLUT as GLUT
import pycam.Importers.STLImporter import pycam.Importers.STLImporter
import pycam.Exporters.STLExporter import pycam.Exporters.STLExporter
...@@ -34,6 +35,9 @@ def gtkgl_functionwrapper(function): ...@@ -34,6 +35,9 @@ def gtkgl_functionwrapper(function):
glcontext=self.area.get_gl_context() glcontext=self.area.get_gl_context()
if not gldrawable.gl_begin(glcontext): if not gldrawable.gl_begin(glcontext):
return return
if not self.initialized:
self.glsetup()
self.initialized = True
function(self, *args, **kwords) function(self, *args, **kwords)
gldrawable.gl_end() gldrawable.gl_end()
return decorated # TODO: make this a well behaved decorator (keeping name, docstring etc) return decorated # TODO: make this a well behaved decorator (keeping name, docstring etc)
...@@ -47,7 +51,9 @@ class GLView: ...@@ -47,7 +51,9 @@ class GLView:
import gtk.gtkgl import gtk.gtkgl
except ImportError: except ImportError:
return return
self.mouse = { "start_pos": None, "button": None } self.initialized = False
self.busy = False
self.mouse = {"start_pos": None, "button": None, "timestamp": 0}
self.enabled = True self.enabled = True
self.settings = settings self.settings = settings
self.gui = gui self.gui = gui
...@@ -67,9 +73,9 @@ class GLView: ...@@ -67,9 +73,9 @@ class GLView:
self.area = gtk.gtkgl.DrawingArea(glconfig) self.area = gtk.gtkgl.DrawingArea(glconfig)
self.area.set_size_request(400, 400) self.area.set_size_request(400, 400)
# first run; might also be important when doing other fancy gtk/gdk stuff # first run; might also be important when doing other fancy gtk/gdk stuff
self.area.connect_after('realize', self._realize) self.area.connect_after('realize', self.init_view)
# called when a part of the screen is uncovered # called when a part of the screen is uncovered
self.area.connect('expose_event', self._expose_event) self.area.connect('expose_event', self.paint)
# resize window # resize window
self.area.connect('configure_event', self._resize_window) self.area.connect('configure_event', self._resize_window)
# catch mouse events # catch mouse events
...@@ -81,25 +87,41 @@ class GLView: ...@@ -81,25 +87,41 @@ class GLView:
self.container.show() self.container.show()
self.window.show() self.window.show()
def check_busy(func):
def busy_wrapper(self, *args, **kwargs):
if self.busy:
return
self.busy = True
func(self, *args, **kwargs)
self.busy = False
return busy_wrapper
def glsetup(self): def glsetup(self):
if self.initialized:
return
GLUT.glutInit() GLUT.glutInit()
GL.glShadeModel(GL.GL_FLAT) GL.glShadeModel(GL.GL_FLAT)
GL.glClearColor(0., 0., 0., 0.)
GL.glClearDepth(1.)
GL.glEnable(GL.GL_DEPTH_TEST)
GL.glDepthFunc(GL.GL_LEQUAL)
GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST)
GL.glMatrixMode(GL.GL_MODELVIEW) GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, (0.1, 0.1, 0.1, 1.0)) GL.glMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, (0.1, 0.1, 0.1, 1.0))
GL.glMaterial(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, (0.1, 0.1, 0.1, 1.0)) GL.glMaterial(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, (0.1, 0.1, 0.1, 1.0))
GL.glMaterial(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, (0.5)) GL.glMaterial(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, (0.5))
GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL)
def _gl_clear(self): GL.glMatrixMode(GL.GL_PROJECTION)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT) self.store_view_setting()
def _gl_finish(self):
self.area.get_gl_drawable().swap_buffers()
def destroy(self, widget=None): def destroy(self, widget=None):
self.area.destroy() self.area.destroy()
self.window.destroy() self.window.destroy()
@check_busy
@gtkgl_functionwrapper
def mouse_handler(self, widget, event): def mouse_handler(self, widget, event):
last_timestamp = self.mouse["timestamp"]
x, y, state = event.x, event.y, event.state x, y, state = event.x, event.y, event.state
if self.mouse["button"] is None: if self.mouse["button"] is None:
if (state == BUTTON_ZOOM) or (state == BUTTON_ROTATE) or (state == BUTTON_MOVE): if (state == BUTTON_ZOOM) or (state == BUTTON_ROTATE) or (state == BUTTON_MOVE):
...@@ -115,57 +137,122 @@ class GLView: ...@@ -115,57 +137,122 @@ class GLView:
else: else:
return return
else: else:
if time.time() - last_timestamp < 0.5:
return
# a button was pressed before # a button was pressed before
if self.mouse["button"] == state: if self.mouse["button"] == state:
if state == BUTTON_ZOOM: if state == BUTTON_ZOOM:
# the start button is still active: update the view # the start button is still active: update the view
current_scale = self.settings.get("scale") current_scale = self.settings.get("scale")
diff = x - self.mouse["start_pos"][0] diff = 0.2 * (x - self.mouse["start_pos"][0])
if -10 <= diff <= 10: if -1 <= diff <= 1:
return new_scale = current_scale
elif diff > 0: elif diff > 0:
change = +math.log(diff/10) new_scale = current_scale * (1 + diff)
else: else:
change = -math.log(-diff/10) new_scale = current_scale / (1 - diff)
new_scale = current_scale + change
print "%f -> %f" % (current_scale, new_scale) print "%f -> %f" % (current_scale, new_scale)
GL.glMatrixMode(GL.GL_MODELVIEW) self.scale_view(new_scale)
GL.glLoadIdentity()
GL.glScalef(new_scale, new_scale, new_scale)
else: else:
# button was released # button was released
self.mouse["button"] = None self.mouse["button"] = None
self.mouse["timestamp"] = time.time()
def store_view_setting(self):
prev_mode = GL.glGetDoublev(GL.GL_MATRIX_MODE)
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glPushMatrix()
self.projection_matrix = GL.glGetDoublev(GL.GL_PROJECTION_MATRIX)[:]
GL.glPopMatrix()
GL.glMatrixMode(prev_mode)
def restore_view_setting(self):
prev_mode = GL.glGetDoublev(GL.GL_MATRIX_MODE)
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
#print "Loaded %s" % str(self.projection_matrix)
GL.glLoadMatrixf(self.projection_matrix[:])
GL.glMatrixMode(prev_mode)
def gtkgl_refresh(func):
def refresh_wrapper(self, *args, **kwargs):
prev_mode = GL.glGetDoublev(GL.GL_MATRIX_MODE)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
self._paint()
func(self, *args, **kwargs)
self.restore_view_setting()
GL.glMatrixMode(prev_mode)
GL.glFlush()
self.area.get_gl_drawable().swap_buffers()
return refresh_wrapper
def gtkgl_redraw(func):
def redraw_wrapper(self, *args, **kwargs):
prev_mode = GL.glGetDoublev(GL.GL_MATRIX_MODE)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
self._paint()
func(self, *args, **kwargs)
self.store_view_setting()
GL.glMatrixMode(prev_mode)
GL.glFlush()
self.area.get_gl_drawable().swap_buffers()
return redraw_wrapper
@gtkgl_functionwrapper @gtkgl_functionwrapper
@gtkgl_redraw
def scale_view(self, zoom):
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadMatrixf(self.projection_matrix)
mult = [[zoom, 0, 0, 0], [0, zoom, 0, 0], [0, 0, zoom, 0], [0, 0, 0, 1]]
GL.glMultMatrixf(mult)
@check_busy
@gtkgl_functionwrapper
@gtkgl_redraw
def rotate_view(self, widget, data=None): def rotate_view(self, widget, data=None):
self._gl_clear()
GuiCommon.rotate_view(self.settings.get("scale"), data) GuiCommon.rotate_view(self.settings.get("scale"), data)
self.paint()
self._gl_finish()
def reset_view(self): def reset_view(self):
self.rotate_view(self.area, GuiCommon.VIEW_ROTATIONS["reset"]) self.rotate_view(self.area, GuiCommon.VIEW_ROTATIONS["reset"])
@check_busy
@gtkgl_functionwrapper @gtkgl_functionwrapper
def _realize(self, widget): @gtkgl_refresh
self.glsetup() def _resize_window(self, widget, data=None):
GL.glViewport(0, 0, self.container.allocation.width, self.container.allocation.height - 50)
def _expose_event(self, widget, event):
self.paint()
@check_busy
@gtkgl_functionwrapper @gtkgl_functionwrapper
def _resize_window(self, widget, data=None): @gtkgl_refresh
GL.glViewport(0, 0, widget.allocation.width, widget.allocation.height) def paint(self, widget=None, data=None):
# the decorators take core for redraw
pass
def paint(self):
self._gl_clear()
self._paint()
self._gl_finish()
@gtkgl_functionwrapper
def _paint(self, widget=None): def _paint(self, widget=None):
GuiCommon.draw_complete_model_view(self.settings) GuiCommon.draw_complete_model_view(self.settings)
@gtkgl_functionwrapper
def init_view(self, widget=None):
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT)
GL.glLoadIdentity()
self._paint()
s = self.settings
scale = s.get("scale")
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glScalef(scale, scale, scale)
GL.glTranslatef((s.get("maxx") + s.get("minx"))/2, (s.get("maxy") + s.get("miny"))/2, (s.get("maxz") + s.get("minz"))/2)
GL.glFlush()
GL.glPushMatrix()
self.store_view_setting()
GL.glPopMatrix()
self.area.get_gl_drawable().swap_buffers()
class VisualThread(threading.Thread): class VisualThread(threading.Thread):
...@@ -277,7 +364,6 @@ class ProjectGui: ...@@ -277,7 +364,6 @@ class ProjectGui:
self.gui.get_object("GenerateToolPathButton").connect("clicked", self.generate_toolpath) self.gui.get_object("GenerateToolPathButton").connect("clicked", self.generate_toolpath)
self.gui.get_object("SaveToolPathButton").connect("clicked", self.save_toolpath) self.gui.get_object("SaveToolPathButton").connect("clicked", self.save_toolpath)
self.gui.get_object("Toggle3dView").connect("toggled", self.toggle_3d_view) self.gui.get_object("Toggle3dView").connect("toggled", self.toggle_3d_view)
self.toggle_3d_view(True)
def gui_activity_guard(func): def gui_activity_guard(func):
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
...@@ -423,7 +509,7 @@ class ProjectGui: ...@@ -423,7 +509,7 @@ class ProjectGui:
if callable(filename): if callable(filename):
filename = filename() filename = filename()
self.model = pycam.Importers.STLImporter.ImportModel(filename) self.model = pycam.Importers.STLImporter.ImportModel(filename)
self.toggle_3d_view(value=True) self.toggle_3d_view(True)
self.reload_model() self.reload_model()
@gui_activity_guard @gui_activity_guard
......
...@@ -26,8 +26,26 @@ MODEL_TRANSFORMATIONS = { ...@@ -26,8 +26,26 @@ MODEL_TRANSFORMATIONS = {
"y_swap_z": ((1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0)), "y_swap_z": ((1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0)),
} }
def draw_string(x, y, z, p, s, scale=.01): def keep_gl_mode(func):
def wrapper(*args, **kwargs):
prev_mode = GL.glGetDoublev(GL.GL_MATRIX_MODE)
func(*args, **kwargs)
GL.glMatrixMode(prev_mode)
return wrapper
def keep_matrix(func):
def wrapper(*args, **kwargs):
pushed_matrix_mode = GL.glGetDoublev(GL.GL_MATRIX_MODE)
GL.glPushMatrix() GL.glPushMatrix()
func(*args, **kwargs)
final_matrix_mode = GL.glGetDoublev(GL.GL_MATRIX_MODE)
GL.glMatrixMode(pushed_matrix_mode)
GL.glPopMatrix()
GL.glMatrixMode(final_matrix_mode)
return wrapper
@keep_matrix
def draw_string(x, y, z, p, s, scale=.01):
GL.glTranslatef(x, y, z) GL.glTranslatef(x, y, z)
if p == 'xy': if p == 'xy':
pass pass
...@@ -41,9 +59,17 @@ def draw_string(x, y, z, p, s, scale=.01): ...@@ -41,9 +59,17 @@ def draw_string(x, y, z, p, s, scale=.01):
GL.glScalef(scale, scale, scale) GL.glScalef(scale, scale, scale)
for c in str(s): for c in str(s):
GLUT.glutStrokeCharacter(GLUT.GLUT_STROKE_ROMAN, ord(c)) GLUT.glutStrokeCharacter(GLUT.GLUT_STROKE_ROMAN, ord(c))
GL.glPopMatrix()
def draw_axes(size): @keep_gl_mode
@keep_matrix
def draw_axes(settings):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GL.glTranslatef(0, 0, -2)
if settings.get("unit") == "mm":
size = 100
else:
size = 5
GL.glBegin(GL.GL_LINES) GL.glBegin(GL.GL_LINES)
GL.glColor3f(1, 0, 0) GL.glColor3f(1, 0, 0)
GL.glVertex3f(0, 0, 0) GL.glVertex3f(0, 0, 0)
...@@ -63,6 +89,7 @@ def draw_axes(size): ...@@ -63,6 +89,7 @@ def draw_axes(size):
GL.glEnd() GL.glEnd()
draw_string(0, 0, size, 'xz', "Z") draw_string(0, 0, size, 'xz', "Z")
@keep_matrix
def draw_bounding_box(minx, miny, minz, maxx, maxy, maxz): def draw_bounding_box(minx, miny, minz, maxx, maxy, maxz):
color = [0.3, 0.3, 0.3] color = [0.3, 0.3, 0.3]
p1 = [minx, miny, minz] p1 = [minx, miny, minz]
...@@ -84,14 +111,13 @@ def draw_bounding_box(minx, miny, minz, maxx, maxy, maxz): ...@@ -84,14 +111,13 @@ def draw_bounding_box(minx, miny, minz, maxx, maxy, maxz):
GL.glVertex3f(*(corner_pair[1])) GL.glVertex3f(*(corner_pair[1]))
GL.glEnd() GL.glEnd()
@keep_gl_mode
@keep_matrix
def draw_complete_model_view(settings): def draw_complete_model_view(settings):
GL.glTranslatef(0, 0, -2) GL.glMatrixMode(GL.GL_MODELVIEW)
if settings.get("unit") == "mm": GL.glLoadIdentity()
size = 100
else:
size = 5
# axes # axes
draw_axes(size) draw_axes(settings)
# stock model # stock model
draw_bounding_box(float(settings.get("minx")), float(settings.get("miny")), draw_bounding_box(float(settings.get("minx")), float(settings.get("miny")),
float(settings.get("minz")), float(settings.get("maxx")), float(settings.get("minz")), float(settings.get("maxx")),
...@@ -102,7 +128,11 @@ def draw_complete_model_view(settings): ...@@ -102,7 +128,11 @@ def draw_complete_model_view(settings):
# draw the toolpath # draw the toolpath
draw_toolpath(settings.get("toolpath")) draw_toolpath(settings.get("toolpath"))
@keep_gl_mode
@keep_matrix
def draw_toolpath(toolpath): def draw_toolpath(toolpath):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
if toolpath: if toolpath:
last = None last = None
for path in toolpath: for path in toolpath:
...@@ -120,8 +150,9 @@ def draw_toolpath(toolpath): ...@@ -120,8 +150,9 @@ def draw_toolpath(toolpath):
GL.glEnd() GL.glEnd()
last = path.points[-1] last = path.points[-1]
@keep_gl_mode
def rotate_view(scale, rotation=None): def rotate_view(scale, rotation=None):
GL.glMatrixMode(GL.GL_MODELVIEW) GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity() GL.glLoadIdentity()
GL.glScalef(scale, scale, scale) GL.glScalef(scale, scale, scale)
if rotation: if rotation:
......
...@@ -132,6 +132,7 @@ ...@@ -132,6 +132,7 @@
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">False</property>
<property name="position">0</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment