Commit d603348b authored by sumpfralle's avatar sumpfralle

moved some opengl functions to OpenGLTools

moved some ODE functions to ode_objects
added an EmergencyDialog class for displaying dependency problems via the builtin Tk interface


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@261 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 55510618
from pycam.Geometry.Point import Point from pycam.Geometry.Point import Point
import OpenGL.GL as GL import OpenGL.GL as GL
import OpenGL.GLU as GLU import OpenGL.GLU as GLU
import OpenGL.GLUT as GLUT
import math import math
# the length of the distance vector does not matter - it will be normalized and multiplied later anyway # the length of the distance vector does not matter - it will be normalized and multiplied later anyway
...@@ -174,3 +175,151 @@ class Camera: ...@@ -174,3 +175,151 @@ class Camera:
return (factors_x, factors_y) return (factors_x, factors_y)
def keep_gl_mode(func):
def wrapper(*args, **kwargs):
prev_mode = GL.glGetIntegerv(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.glGetIntegerv(GL.GL_MATRIX_MODE)
GL.glPushMatrix()
func(*args, **kwargs)
final_matrix_mode = GL.glGetIntegerv(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.glPushMatrix()
GL.glTranslatef(x, y, z)
if p == 'xy':
GL.glRotatef(90, 1, 0, 0)
pass
elif p == 'yz':
GL.glRotatef(90, 0, 1, 0)
GL.glRotatef(90, 0, 0, 1)
elif p == 'xz':
GL.glRotatef(90, 0, 1, 0)
GL.glRotatef(90, 0, 0, 1)
GL.glRotatef(45, 0, 1, 0)
GL.glScalef(scale, scale, scale)
for c in str(s):
GLUT.glutStrokeCharacter(GLUT.GLUT_STROKE_ROMAN, ord(c))
GL.glPopMatrix()
@keep_gl_mode
@keep_matrix
def draw_axes(settings):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
#GL.glTranslatef(0, 0, -2)
size_x = abs(settings.get("maxx"))
size_y = abs(settings.get("maxy"))
size_z = abs(settings.get("maxz"))
size = 1.5 * max(max(size_x, size_y), size_z)
# the divider is just based on playing with numbers
scale = size/1500.0
string_distance = 1.1 * size
GL.glBegin(GL.GL_LINES)
GL.glColor3f(1, 0, 0)
GL.glVertex3f(0, 0, 0)
GL.glVertex3f(size, 0, 0)
GL.glEnd()
draw_string(string_distance, 0, 0, 'xy', "X", scale=scale)
GL.glBegin(GL.GL_LINES)
GL.glColor3f(0, 1, 0)
GL.glVertex3f(0, 0, 0)
GL.glVertex3f(0, size, 0)
GL.glEnd()
draw_string(0, string_distance, 0, 'yz', "Y", scale=scale)
GL.glBegin(GL.GL_LINES)
GL.glColor3f(0, 0, 1)
GL.glVertex3f(0, 0, 0)
GL.glVertex3f(0, 0, size)
GL.glEnd()
draw_string(0, 0, string_distance, 'xz', "Z", scale=scale)
@keep_matrix
def draw_bounding_box(minx, miny, minz, maxx, maxy, maxz, color):
p1 = [minx, miny, minz]
p2 = [minx, maxy, minz]
p3 = [maxx, maxy, minz]
p4 = [maxx, miny, minz]
p5 = [minx, miny, maxz]
p6 = [minx, maxy, maxz]
p7 = [maxx, maxy, maxz]
p8 = [maxx, miny, maxz]
# lower rectangle
GL.glBegin(GL.GL_LINES)
GL.glColor3f(*color)
# all combinations of neighbouring corners
for corner_pair in [(p1, p2), (p1, p5), (p1, p4), (p2, p3),
(p2, p6), (p3, p4), (p3, p7), (p4, p8), (p5, p6),
(p6, p7), (p7, p8), (p8, p5)]:
GL.glVertex3f(*(corner_pair[0]))
GL.glVertex3f(*(corner_pair[1]))
GL.glEnd()
@keep_gl_mode
@keep_matrix
def draw_cutter(cutter, color):
if not cutter is None:
GL.glColor3f(*color)
cutter.to_OpenGL()
@keep_gl_mode
@keep_matrix
def draw_complete_model_view(settings):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
# axes
if settings.get("show_axes"):
draw_axes(settings)
# stock model
if settings.get("show_bounding_box"):
draw_bounding_box(float(settings.get("minx")), float(settings.get("miny")),
float(settings.get("minz")), float(settings.get("maxx")),
float(settings.get("maxy")), float(settings.get("maxz")),
settings.get("color_bounding_box"))
# draw the model
if settings.get("show_model"):
GL.glColor3f(*settings.get("color_model"))
settings.get("model").to_OpenGL()
# draw the toolpath
if settings.get("show_toolpath"):
for toolpath_obj in settings.get("toolpath"):
if toolpath_obj.visible:
draw_toolpath(toolpath_obj.get_path(),
settings.get("color_toolpath_cut"),
settings.get("color_toolpath_return"))
# draw the drill
if settings.get("show_drill_progress"):
draw_cutter(settings.get("cutter"), settings.get("color_cutter"))
@keep_gl_mode
@keep_matrix
def draw_toolpath(toolpath, color_forward, color_backward):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
if toolpath:
last = None
for path in toolpath:
if last:
GL.glColor3f(*color_backward)
GL.glBegin(GL.GL_LINES)
GL.glVertex3f(last.x, last.y, last.z)
last = path.points[0]
GL.glVertex3f(last.x, last.y, last.z)
GL.glEnd()
GL.glColor3f(*color_forward)
GL.glBegin(GL.GL_LINE_STRIP)
for point in path.points:
GL.glVertex3f(point.x, point.y, point.z)
GL.glEnd()
last = path.points[-1]
...@@ -10,6 +10,7 @@ import pycam.PathGenerators ...@@ -10,6 +10,7 @@ import pycam.PathGenerators
import pycam.PathProcessors import pycam.PathProcessors
import pycam.Geometry.utils as utils import pycam.Geometry.utils as utils
import pycam.Gui.OpenGLTools as ogl_tools import pycam.Gui.OpenGLTools as ogl_tools
import pycam.Gui.ode_objects as ode_objects
import OpenGL.GL as GL import OpenGL.GL as GL
import OpenGL.GLU as GLU import OpenGL.GLU as GLU
import OpenGL.GLUT as GLUT import OpenGL.GLUT as GLUT
...@@ -347,7 +348,7 @@ class GLView: ...@@ -347,7 +348,7 @@ class GLView:
def _paint_raw(self, widget=None): def _paint_raw(self, widget=None):
# draw the model # draw the model
GuiCommon.draw_complete_model_view(self.settings) ogl_tools.draw_complete_model_view(self.settings)
# update the dimension display # update the dimension display
s = self.settings s = self.settings
dimension_bar = self.gui.get_object("view3ddimension") dimension_bar = self.gui.get_object("view3ddimension")
...@@ -512,7 +513,7 @@ class ProjectGui: ...@@ -512,7 +513,7 @@ class ProjectGui:
for name in COLORS.keys(): for name in COLORS.keys():
self.settings.set(name, COLORS[name]) self.settings.set(name, COLORS[name])
# set the availability of ODE # set the availability of ODE
if GuiCommon.is_ode_available(): if ode_objects.is_ode_available():
self.settings.set("enable_ode", True) self.settings.set("enable_ode", True)
self.gui.get_object("SettingEnableODE").set_sensitive(True) self.gui.get_object("SettingEnableODE").set_sensitive(True)
self.gui.get_object("MaterialAllowanceControl").set_sensitive(True) self.gui.get_object("MaterialAllowanceControl").set_sensitive(True)
...@@ -684,7 +685,7 @@ class ProjectGui: ...@@ -684,7 +685,7 @@ class ProjectGui:
def get_physics(self, cutter): def get_physics(self, cutter):
if self.settings.get("enable_ode"): if self.settings.get("enable_ode"):
self._physics_cache = GuiCommon.generate_physics(self.settings, cutter, self._physics_cache) self._physics_cache = ode_objects.generate_physics(self.settings, cutter, self._physics_cache)
else: else:
self._physics_cache = None self._physics_cache = None
return self._physics_cache return self._physics_cache
......
...@@ -16,7 +16,7 @@ from pycam.PathProcessors import * ...@@ -16,7 +16,7 @@ from pycam.PathProcessors import *
from pycam.Geometry.utils import * from pycam.Geometry.utils import *
from pycam.Importers import * from pycam.Importers import *
from pycam.Exporters import * from pycam.Exporters import *
import pycam.Gui.common as GuiCommon import pycam.Gui.OpenGLTools as ogl_tools
import pycam.Gui.Settings import pycam.Gui.Settings
import time import time
...@@ -53,22 +53,6 @@ class OpenglWidget(Tk.Opengl): ...@@ -53,22 +53,6 @@ class OpenglWidget(Tk.Opengl):
self.master.resetView() self.master.resetView()
class SimpleGui(Tk.Frame): class SimpleGui(Tk.Frame):
def draw_string(self, x, y, z, p, s, scale=.01):
GL.glPushMatrix()
GL.glTranslatef(x,y,z)
if p == 'xy':
pass
elif p == 'yz':
GL.glRotatef(90, 0, 1, 0)
GL.glRotatef(90, 0, 0, 1)
elif p == 'xz':
GL.glRotatef(90, 0, 1, 0)
GL.glRotatef(90, 0, 0, 1)
GL.glRotatef(-90, 0, 1, 0)
GL.glScalef(scale,scale,scale)
for c in str(s):
GLUT.glutStrokeCharacter(GLUT.GLUT_STROKE_ROMAN, ord(c))
GL.glPopMatrix()
def load_model(self, model): def load_model(self, model):
self.model = model self.model = model
...@@ -88,19 +72,19 @@ class SimpleGui(Tk.Frame): ...@@ -88,19 +72,19 @@ class SimpleGui(Tk.Frame):
GL.glVertex3f(0,0,0) GL.glVertex3f(0,0,0)
GL.glVertex3f(size,0,0) GL.glVertex3f(size,0,0)
GL.glEnd() GL.glEnd()
GuiCommon.draw_string(size,0,0,'xy',"X") ogl_tools.draw_string(size,0,0,'xy',"X")
GL.glBegin(GL.GL_LINES) GL.glBegin(GL.GL_LINES)
GL.glColor3f(0,1,0) GL.glColor3f(0,1,0)
GL.glVertex3f(0,0,0) GL.glVertex3f(0,0,0)
GL.glVertex3f(0,size,0) GL.glVertex3f(0,size,0)
GL.glEnd() GL.glEnd()
GuiCommon.draw_string(0,size,0,'yz',"Y") ogl_tools.draw_string(0,size,0,'yz',"Y")
GL.glBegin(GL.GL_LINES) GL.glBegin(GL.GL_LINES)
GL.glColor3f(0,0,1) GL.glColor3f(0,0,1)
GL.glVertex3f(0,0,0) GL.glVertex3f(0,0,0)
GL.glVertex3f(0,0,size) GL.glVertex3f(0,0,size)
GL.glEnd() GL.glEnd()
GuiCommon.draw_string(0,0,size,'xz',"Z") ogl_tools.draw_string(0,0,size,'xz',"Z")
if True: if True:
# stock model # stock model
......
import OpenGL.GL as GL import Tkinter
import OpenGL.GLUT as GLUT
# "ode" is imported later, if required # "ode" is imported later, if required
#import ode_objects #import ode_objects
import random import random
...@@ -18,165 +17,6 @@ MODEL_TRANSFORMATIONS = { ...@@ -18,165 +17,6 @@ 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)),
} }
_ode_override_state = None
def keep_gl_mode(func):
def wrapper(*args, **kwargs):
prev_mode = GL.glGetIntegerv(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.glGetIntegerv(GL.GL_MATRIX_MODE)
GL.glPushMatrix()
func(*args, **kwargs)
final_matrix_mode = GL.glGetIntegerv(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.glPushMatrix()
GL.glTranslatef(x, y, z)
if p == 'xy':
GL.glRotatef(90, 1, 0, 0)
pass
elif p == 'yz':
GL.glRotatef(90, 0, 1, 0)
GL.glRotatef(90, 0, 0, 1)
elif p == 'xz':
GL.glRotatef(90, 0, 1, 0)
GL.glRotatef(90, 0, 0, 1)
GL.glRotatef(45, 0, 1, 0)
GL.glScalef(scale, scale, scale)
for c in str(s):
GLUT.glutStrokeCharacter(GLUT.GLUT_STROKE_ROMAN, ord(c))
GL.glPopMatrix()
@keep_gl_mode
@keep_matrix
def draw_axes(settings):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
#GL.glTranslatef(0, 0, -2)
size_x = abs(settings.get("maxx"))
size_y = abs(settings.get("maxy"))
size_z = abs(settings.get("maxz"))
size = 1.5 * max(max(size_x, size_y), size_z)
# the divider is just based on playing with numbers
scale = size/1500.0
string_distance = 1.1 * size
GL.glBegin(GL.GL_LINES)
GL.glColor3f(1, 0, 0)
GL.glVertex3f(0, 0, 0)
GL.glVertex3f(size, 0, 0)
GL.glEnd()
draw_string(string_distance, 0, 0, 'xy', "X", scale=scale)
GL.glBegin(GL.GL_LINES)
GL.glColor3f(0, 1, 0)
GL.glVertex3f(0, 0, 0)
GL.glVertex3f(0, size, 0)
GL.glEnd()
draw_string(0, string_distance, 0, 'yz', "Y", scale=scale)
GL.glBegin(GL.GL_LINES)
GL.glColor3f(0, 0, 1)
GL.glVertex3f(0, 0, 0)
GL.glVertex3f(0, 0, size)
GL.glEnd()
draw_string(0, 0, string_distance, 'xz', "Z", scale=scale)
@keep_matrix
def draw_bounding_box(minx, miny, minz, maxx, maxy, maxz, color):
p1 = [minx, miny, minz]
p2 = [minx, maxy, minz]
p3 = [maxx, maxy, minz]
p4 = [maxx, miny, minz]
p5 = [minx, miny, maxz]
p6 = [minx, maxy, maxz]
p7 = [maxx, maxy, maxz]
p8 = [maxx, miny, maxz]
# lower rectangle
GL.glBegin(GL.GL_LINES)
GL.glColor3f(*color)
# all combinations of neighbouring corners
for corner_pair in [(p1, p2), (p1, p5), (p1, p4), (p2, p3),
(p2, p6), (p3, p4), (p3, p7), (p4, p8), (p5, p6),
(p6, p7), (p7, p8), (p8, p5)]:
GL.glVertex3f(*(corner_pair[0]))
GL.glVertex3f(*(corner_pair[1]))
GL.glEnd()
@keep_gl_mode
@keep_matrix
def draw_cutter(cutter, color):
if not cutter is None:
GL.glColor3f(*color)
cutter.to_OpenGL()
@keep_gl_mode
@keep_matrix
def draw_complete_model_view(settings):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
# axes
if settings.get("show_axes"):
draw_axes(settings)
# stock model
if settings.get("show_bounding_box"):
draw_bounding_box(float(settings.get("minx")), float(settings.get("miny")),
float(settings.get("minz")), float(settings.get("maxx")),
float(settings.get("maxy")), float(settings.get("maxz")),
settings.get("color_bounding_box"))
# draw the model
if settings.get("show_model"):
GL.glColor3f(*settings.get("color_model"))
settings.get("model").to_OpenGL()
# draw the toolpath
if settings.get("show_toolpath"):
for toolpath_obj in settings.get("toolpath"):
if toolpath_obj.visible:
draw_toolpath(toolpath_obj.get_path(),
settings.get("color_toolpath_cut"),
settings.get("color_toolpath_return"))
# draw the drill
if settings.get("show_drill_progress"):
draw_cutter(settings.get("cutter"), settings.get("color_cutter"))
@keep_gl_mode
@keep_matrix
def draw_toolpath(toolpath, color_forward, color_backward):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
if toolpath:
last = None
for path in toolpath:
if last:
GL.glColor3f(*color_backward)
GL.glBegin(GL.GL_LINES)
GL.glVertex3f(last.x, last.y, last.z)
last = path.points[0]
GL.glVertex3f(last.x, last.y, last.z)
GL.glEnd()
GL.glColor3f(*color_forward)
GL.glBegin(GL.GL_LINE_STRIP)
for point in path.points:
GL.glVertex3f(point.x, point.y, point.z)
GL.glEnd()
last = path.points[-1]
@keep_gl_mode
def rotate_view(scale, rotation=None):
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GL.glScalef(scale, scale, scale)
if rotation:
for one_rot in rotation:
GL.glRotatef(*one_rot)
def transform_model(model, direction="normal"): def transform_model(model, direction="normal"):
model.transform(MODEL_TRANSFORMATIONS[direction]) model.transform(MODEL_TRANSFORMATIONS[direction])
...@@ -189,30 +29,38 @@ def scale_model(model, scale): ...@@ -189,30 +29,38 @@ def scale_model(model, scale):
matrix = ((scale, 0, 0, 0), (0, scale, 0, 0), (0, 0, scale, 0)) matrix = ((scale, 0, 0, 0), (0, scale, 0, 0), (0, 0, scale, 0))
model.transform(matrix) model.transform(matrix)
def generate_physics(settings, cutter, physics=None):
import ode_objects
if physics is None:
physics = ode_objects.PhysicalWorld()
physics.reset()
physics.add_mesh((0, 0, 0), settings.get("model").triangles())
shape_info = cutter.get_shape("ODE", additional_distance=settings.get("material_allowance"))
physics.set_drill(shape_info[0], (0.0, 0.0, 0.0))
return physics
def is_ode_available(): class EmergencyDialog(Tkinter.Frame):
global _ode_override_state """ This graphical message window requires no external dependencies.
if not _ode_override_state is None: The Tk interface package is part of the main python distribution.
return _ode_override_state Use this class for displaying dependency errors (especially on Windows).
else: """
try:
import ode
return True
except ImportError:
return False
def override_ode_availability(state): def __init__(self, title, message):
global _ode_override_state try:
_ode_override_state = state root = Tkinter.Tk()
except Tkinter.TclError, err_msg:
print >>sys.stderr, "Warning: Failed to create error dialog window (%s). Probably you are running PyCAM from a terminal." % str(err_msg)
print >>sys.stderr, "%s: %s" % (title, message)
return
root.title(title)
root.bind("<Return>", self.finish)
root.bind("<Escape>", self.finish)
root.minsize(300, 100)
Tkinter.Frame.__init__(self, root, width=400)
self.pack()
# add text output as label
message = Tkinter.Message(self, text=message, width=200)
message["width"] = 200
message.pack()
# add the "close" button
close = Tkinter.Button(root, text="Close")
close["command"] = self.finish
close.pack(side=Tkinter.BOTTOM)
self.mainloop()
def finish(self, *args):
self.quit()
class ToolPathList(list): class ToolPathList(list):
......
import ode try:
import ode
except ImportError:
ode = None
ShapeCylinder = lambda radius, height: ode.GeomCylinder(None, radius, height) ShapeCylinder = lambda radius, height: ode.GeomCylinder(None, radius, height)
ShapeCapsule = lambda radius, height: ode.GeomCapsule(None, radius, height - (2 * radius)) ShapeCapsule = lambda radius, height: ode.GeomCapsule(None, radius, height - (2 * radius))
_ode_override_state = None
def generate_physics(settings, cutter, physics=None):
if physics is None:
physics = PhysicalWorld()
physics.reset()
physics.add_mesh((0, 0, 0), settings.get("model").triangles())
shape_info = cutter.get_shape("ODE", additional_distance=settings.get("material_allowance"))
physics.set_drill(shape_info[0], (0.0, 0.0, 0.0))
return physics
def is_ode_available():
global _ode_override_state
if not _ode_override_state is None:
return _ode_override_state
else:
if ode is None:
return False
else:
return True
def override_ode_availability(state):
global _ode_override_state
_ode_override_state = state
def convert_triangles_to_vertices_faces(triangles): def convert_triangles_to_vertices_faces(triangles):
corners = [] corners = []
......
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