Commit 77ac4453 authored by Guillaume Seguin's avatar Guillaume Seguin

Rework gcview to make it cleaner, better and faster

parent bf64e797
#!/usr/bin/python
# This file is part of the Printrun suite.
#
# Printrun is free software: you can redistribute it and/or modify
......@@ -16,43 +17,39 @@
import os
import math
import stltool
import wx
from wx import glcanvas
import time
import threading
import gcoder
import pyglet
pyglet.options['shadow_window'] = False
pyglet.options['debug_gl'] = False
from pyglet.gl import *
pyglet.options['debug_gl'] = True
import stltool
import threading
from pyglet.gl import *
from pyglet import gl
from pyglet.graphics.vertexbuffer import create_buffer
from printrun.libtatlin import actors
class GLPanel(wx.Panel):
class wxGLPanel(wx.Panel):
'''A simple class for using OpenGL with wxPython.'''
def __init__(self, parent, id, pos = wx.DefaultPosition,
size = wx.DefaultSize, style = 0):
# Forcing a no full repaint to stop flickering
style = style | wx.NO_FULL_REPAINT_ON_RESIZE
#call super function
super(GLPanel, self).__init__(parent, id, pos, size, style)
super(wxGLPanel, self).__init__(parent, id, pos, size, style)
#init gl canvas data
self.GLinitialized = False
attribList = (glcanvas.WX_GL_RGBA, # RGBA
glcanvas.WX_GL_DOUBLEBUFFER, # Double Buffered
glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit
# Create the canvas
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.canvas = glcanvas.GLCanvas(self, attribList = attribList)
self.sizer.Add(self.canvas, 1, wx.EXPAND)
self.SetSizer(self.sizer)
#self.sizer.Fit(self)
self.Layout()
self.sizer.Fit(self)
# bind events
self.canvas.Bind(wx.EVT_ERASE_BACKGROUND, self.processEraseBackgroundEvent)
......@@ -89,12 +86,12 @@ class GLPanel(wx.Panel):
self.OnReshape(size.width, size.height)
self.canvas.Refresh(False)
event.Skip()
#wx.CallAfter(self.Refresh)
def processPaintEvent(self, event):
'''Process the drawing event.'''
self.canvas.SetCurrent()
# This is a 'perfect' time to initialize OpenGL ... only if we need to
if not self.GLinitialized:
self.OnInitGL()
self.GLinitialized = True
......@@ -104,7 +101,7 @@ class GLPanel(wx.Panel):
def Destroy(self):
#clean up the pyglet OpenGL context
#self.pygletcontext.destroy()
self.pygletcontext.destroy()
#call the super method
super(wx.Panel, self).Destroy()
......@@ -116,51 +113,23 @@ class GLPanel(wx.Panel):
#create a pyglet context for this panel
self.pmat = (GLdouble * 16)()
self.mvmat = (GLdouble * 16)()
self.pygletcontext = Context(current_context)
self.pygletcontext = gl.Context(gl.current_context)
self.pygletcontext.set_current()
self.dist = 1000
self.vpmat = None
#normal gl init
glClearColor(0, 0, 0, 1)
glColor3f(1, 0, 0)
glClearColor(0.98, 0.98, 0.78, 1)
glClearDepth(1.0) # set depth value to 1
glDepthFunc(GL_LEQUAL)
glEnable(GL_COLOR_MATERIAL)
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
# Uncomment this line for a wireframe view
#glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
# Simple light setup. On Windows GL_LIGHT0 is enabled by default,
# but this is not the case on Linux or Mac, so remember to always
# include it.
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_LIGHT1)
# Define a simple function to create ctypes arrays of floats:
def vec(*args):
return (GLfloat * len(args))(*args)
glLightfv(GL_LIGHT0, GL_POSITION, vec(.5, .5, 1, 0))
glLightfv(GL_LIGHT0, GL_SPECULAR, vec(.5, .5, 1, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, vec(1, 1, 1, 1))
glLightfv(GL_LIGHT1, GL_POSITION, vec(1, 0, .5, 0))
glLightfv(GL_LIGHT1, GL_DIFFUSE, vec(.5, .5, .5, 1))
glLightfv(GL_LIGHT1, GL_SPECULAR, vec(1, 1, 1, 1))
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.5, 0, 0.3, 1))
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vec(1, 1, 1, 1))
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vec(0, 0.1, 0, 0.9))
#create objects to draw
#self.create_objects()
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
self.OnReshape(*self.GetClientSize())
def OnReshape(self, width, height):
'''Reshape the OpenGL viewport based on the dimensions of the window.'''
if not self.GLinitialized:
self.OnInitGL()
self.GLinitialized = True
self.pmat = (GLdouble * 16)()
self.mvmat = (GLdouble * 16)()
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
......@@ -170,8 +139,6 @@ class GLPanel(wx.Panel):
#pyglet stuff
self.vpmat = (GLint * 4)(0, 0, *list(self.GetClientSize()))
glGetDoublev(GL_PROJECTION_MATRIX, self.pmat)
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
#glMatrixMode(GL_PROJECTION)
# Wrap text to the width of the window
if self.GLinitialized:
......@@ -180,13 +147,9 @@ class GLPanel(wx.Panel):
def OnDraw(self, *args, **kwargs):
"""Draw the window."""
#clear the context
self.canvas.SetCurrent()
self.pygletcontext.set_current()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
#draw objects
self.draw_objects()
#update screen
self.SwapBuffers()
#==========================================================================
......@@ -204,262 +167,8 @@ class GLPanel(wx.Panel):
'''called in the middle of ondraw after the buffer has been cleared'''
pass
def _dist(dist):
"""return axis length, or 0 if None"""
if dist is None:
return 0
else:
return float(dist)
class gcpoint(object):
"""gcode point
stub for first line"""
def __init__(self, x = 0, y = 0, z = 0, e = 0):
self.x = x
self.y = y
self.z = z
self.e = e
self.length = 0
class gcline(object):
"""gcode move line
Once initialised, it knows its position, length and extrusion ratio
Returns lines into gcview batch()
"""
def __init__(self, x = None, y = None, z = None, e = None, f = None, prev_gcline = None, orgline = False):
if prev_gcline is None:
self.prev_gcline = gcpoint()
else:
self.prev_gcline = prev_gcline
if x is None:
self.x = self.prev_gcline.x
else:
self.x = float(x)
if y is None:
self.y = self.prev_gcline.y
else:
self.y = float(y)
if z is None:
self.z = self.prev_gcline.z
else:
self.z = float(z)
if e is None:
self.e = self.prev_gcline.e
else:
self.e = float(e)
self.f = f
self.orgline = orgline
self.calc_delta()
self.calc_len()
def __str__(self):
return u"line from %s,%s,%s to %s,%s,%s with extrusion ratio %s and feedrate %s\n%s" % (
self.prev_gcline.x,
self.prev_gcline.y,
self.prev_gcline.z,
self.x,
self.y,
self.z,
self.extrusion_ratio,
self.f,
self.orgline,
)
def calc_delta(self, prev_gcline = None):
if prev_gcline is None:
prev_gcline = self.prev_gcline
if self.prev_gcline is not None:
self.dx = self.x - prev_gcline.x
self.dy = self.y - prev_gcline.y
self.dz = self.z - prev_gcline.z
self.de = self.e - prev_gcline.e
else:
self.dx = self.x
self.dy = self.y
self.dz = self.z
self.de = self.e
def calc_len(self):
if self.dz != 0:
self.length = math.sqrt(self.dx**2 + self.dy**2 + self.dz**2)
else:
self.length = math.sqrt(self.dx**2 + self.dy**2)
if self.de:
self.extrusion_ratio = self.length / self.de
else:
self.extrusion_ratio = 0
def glline(self):
return [
self.prev_gcline.x,
self.prev_gcline.y,
self.prev_gcline.z,
self.x,
self.y,
self.z,
]
def glcolor(self, upper_limit = None, lower_limit = 0, max_feedrate = 0):
if self.extrusion_ratio == 0:
return [255, 255, 255, 0, 0, 0]
else:
blue_color = 0
green_color = 0
if upper_limit is not None:
if self.extrusion_ratio <= lower_limit:
blue_color = 0
else:
blue_color = int ((self.extrusion_ratio - lower_limit) / (upper_limit - lower_limit) * 255)
else:
blue_color = 0
if max_feedrate > 0 and self.f > 0:
green_color = int((self.f/max_feedrate) * 255)
if green_color > 255:
green_color = 255
if green_color < 0:
green_color = 0
if blue_color > 255:
blue_color = 255
if blue_color < 0:
blue_color = 0
return[255, green_color, blue_color, 128, green_color, blue_color/4]
def float_from_line(axe, line):
return float(line.split(axe)[1].split(" ")[0])
class gcThreadRenderer(threading.Thread):
def __init__(self, gcview, lines):
threading.Thread.__init__(self)
self.gcview = gcview
self.lines = lines
print "q init"
def run(self):
for line in self.lines:
layer_name = line.z
if line.z not in self.gcview.layers:
self.gcview.layers[line.z] = pyglet.graphics.Batch()
self.gcview.layerlist = self.gcview.layers.keys()
self.gcview.layerlist.sort()
self.gcview.layers[line.z].add(2, GL_LINES, None, ("v3f", line.glline()), ("c3B", line.glcolor(self.gcview.upper_limit, self.gcview.lower_limit, self.gcview.max_feedrate)))
self.gcview.t2 = time.time()
print "Rendered lines in %fs" % (self.gcview.t2-self.gcview.t1)
class gcview(object):
"""gcode visualiser
Holds opengl objects for all layers
"""
def __init__(self, lines, batch, w = 0.5, h = 0.5):
if len(lines) == 0:
return
print "Loading %s lines" % (len(lines))
#End pos of previous mode
self.prev = gcpoint()
# Correction for G92 moves
self.delta = [0, 0, 0, 0]
self.layers = {}
self.t0 = time.time()
self.lastf = 0
lines = [self.transform(i) for i in lines]
lines = [i for i in lines if i is not None]
self.t1 = time.time()
print "transformed %s lines in %fs" % (len(lines), self.t1- self.t0)
self.upper_limit = 0
self.lower_limit = None
self.max_feedrate = 0
for line in lines:
if line.extrusion_ratio and line.length > 0.005: #lines shorter than 0.003 can have large extrusion ratio
if line.extrusion_ratio > self.upper_limit:
self.upper_limit = line.extrusion_ratio
if self.lower_limit is None or line.extrusion_ratio < self.lower_limit:
self.lower_limit = line.extrusion_ratio
if line.f > self.max_feedrate:
self.max_feedrate = line.f
#print upper_limit, lower_limit
#self.render_gl(lines)
q = gcThreadRenderer(self, lines)
q.setDaemon(True)
q.start()
def transform(self, line):
"""transforms line of gcode into gcline object (or None if its not move)
Tracks coordinates across resets in self.delta
"""
orgline = line
line = line.split(";")[0]
cur = [None, None, None, None, None]
if len(line) > 0:
if "G92" in line:
#Recalculate delta on G92 (reset)
if("X" in line):
try:
self.delta[0] = float_from_line("X", line) + self.prev.x
except:
self.delta[0] = 0
if("Y" in line):
try:
self.delta[1] = float_from_line("Y", line) + self.prev.y
except:
self.delta[1] = 0
if("Z" in line):
try:
self.delta[2] = float_from_line("Z", line) + self.prev.z
except:
self.delta[2] = 0
if("E" in line):
try:
self.delta[3] = float_from_line("E", line) + self.prev.e
except:
self.delta[3] = 0
return None
if "G1" in line or "G0" in line:
#Create new gcline
if("X" in line):
cur[0] = float_from_line("X", line) + self.delta[0]
if("Y" in line):
cur[1] = float_from_line("Y", line) + self.delta[1]
if("Z" in line):
cur[2] = float_from_line("Z", line) + self.delta[2]
if("E" in line):
cur[3] = float_from_line("E", line) + self.delta[3]
if "F" in line:
cur[4] = float_from_line("F", line)
if cur == [None, None, None, None, None]:
return None
else:
#print cur
if cur[4] is None:
cur[4] = self.lastf
else:
self.lastf = cur[4]
r = gcline(x = cur[0], y = cur[1], z = cur[2], e = cur[3], f = cur[4], prev_gcline = self.prev, orgline = orgline)
self.prev = r
return r
return None
def delete(self):
#for i in self.vlists:
# i.delete()
#self.vlists = []
pass
def trackball(p1x, p1y, p2x, p2y, r):
TRACKBALLSIZE = r
#float a[3]; /* Axis of rotation */
#float phi; /* how much to rotate about axis */
#float p1[3], p2[3], d[3];
......@@ -537,15 +246,15 @@ def mulquat(q1, rq):
q1[3] * rq[3] - q1[0] * rq[0] - q1[1] * rq[1] - q1[2] * rq[2]]
class TestGlPanel(GLPanel):
class GcodeViewPanel(wxGLPanel):
def __init__(self, parent, size, id = wx.ID_ANY):
super(TestGlPanel, self).__init__(parent, id, wx.DefaultPosition, size, 0)
def __init__(self, parent, id = wx.ID_ANY):
super(GcodeViewPanel, self).__init__(parent, id, wx.DefaultPosition, wx.DefaultSize, 0)
self.batches = []
self.rot = 0
self.canvas.Bind(wx.EVT_MOUSE_EVENTS, self.move)
self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.double)
self.initialized = 1
self.initialized = 0
self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.wheel)
self.parent = parent
self.initpos = None
......@@ -553,64 +262,67 @@ class TestGlPanel(GLPanel):
self.bedsize = [200, 200]
self.transv = [0, 0, -self.dist]
self.basequat = [0, 0, 0, 1]
wx.CallAfter(self.forceresize)
self.mousepos = [0, 0]
def create_objects(self):
'''create opengl objects when opengl is initialized'''
for obj in self.parent.objects:
if obj.model and obj.model.loaded and not obj.model.initialized:
obj.model.init()
def update_object_resize(self):
'''called when the window recieves only if opengl is initialized'''
pass
def draw_objects(self):
'''called in the middle of ondraw after the buffer has been cleared'''
if self.vpmat is None:
return
self.create_objects()
#glLoadIdentity()
#print list(self.pmat)
if self.rot == 1:
glLoadIdentity()
glMultMatrixd(self.mvmat)
else:
glLoadIdentity()
glTranslatef(*self.transv)
glPushMatrix()
glTranslatef(-self.parent.platform.width/2, -self.parent.platform.depth/2, 0)
for obj in self.parent.objects:
if not obj.model or not obj.model.loaded or not obj.model.initialized:
continue
glPushMatrix()
glTranslatef(*(obj.offsets))
glRotatef(obj.rot, 0.0, 0.0, 1.0)
glScalef(*obj.scale)
obj.model.display()
glPopMatrix()
glPopMatrix()
def double(self, event):
p = event.GetPositionTuple()
sz = self.GetClientSize()
v = map(lambda m, w, b: b * m / w, p, sz, self.bedsize)
v[1] = self.bedsize[1] - v[1]
v += [300]
print v
self.add_file("../prusa/metric-prusa/x-end-idler.stl", v)
def forceresize(self):
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1))
threading.Thread(target = self.update).start()
self.initialized = 0
def move_shape(self, delta):
"""moves shape (selected in l, which is list ListBox of shapes)
by an offset specified in tuple delta.
Positive numbers move to (rigt, down)"""
name = self.parent.l.GetSelection()
if name == wx.NOT_FOUND:
return False
name = self.parent.l.GetString(name)
model = self.parent.models[name]
model.offsets = [
model.offsets[0] + delta[0],
model.offsets[1] + delta[1],
model.offsets[2]
]
self.Refresh()
return True
print "Double-click at "+str(v)+" in "
print self
def move(self, event):
"""react to mouse actions:
no mouse: show red mousedrop
LMB: move active object,
with shift rotate viewport
RMB: nothing
with shift move viewport
LMB: rotate viewport
RMB: move viewport
"""
if event.Dragging() and event.LeftIsDown():
if self.initpos == None:
self.initpos = event.GetPositionTuple()
else:
if not event.ShiftDown():
currentpos = event.GetPositionTuple()
delta = (
(currentpos[0] - self.initpos[0]),
-(currentpos[1] - self.initpos[1])
)
self.move_shape(delta)
self.initpos = None
return
#print self.initpos
p1 = self.initpos
self.initpos = None
......@@ -642,7 +354,7 @@ class TestGlPanel(GLPanel):
if self.initpos is not None:
self.initpos = None
elif event.Dragging() and event.RightIsDown() and event.ShiftDown():
elif event.Dragging() and event.RightIsDown():
if self.initpos is None:
self.initpos = event.GetPositionTuple()
else:
......@@ -659,51 +371,35 @@ class TestGlPanel(GLPanel):
glLoadIdentity()
glTranslatef(self.transv[0], self.transv[1], 0)
glTranslatef(0, 0, self.transv[2])
if(self.rot):
if self.rot:
glMultMatrixd(build_rotmatrix(self.basequat))
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
self.rot = 1
self.initpos = None
else:
#mouse is moving without a button press
p = event.GetPositionTuple()
sz = self.GetClientSize()
v = map(lambda m, w, b: b * m / w, p, sz, self.bedsize)
v[1] = self.bedsize[1] - v[1]
self.mousepos = v
def rotate_shape(self, angle):
"""rotates acive shape
positive angle is clockwise
"""
name = self.parent.l.GetSelection()
if name == wx.NOT_FOUND:
return False
name = self.parent.l.GetString(name)
model = self.parent.models[name]
model.rot += angle
return
wx.CallAfter(self.Refresh)
def wheel(self, event):
"""react to mouse wheel actions:
rotate object
with shift zoom viewport
without shift: set max layer
with shift: zoom viewport
"""
z = event.GetWheelRotation()
angle = 10
if not event.ShiftDown():
i = self.parent.l.GetSelection()
if i < 0:
try:
self.parent.setlayerindex(z)
except:
pass
if event.ShiftDown():
if not self.parent.model:
return
if z > 0:
self.rotate_shape(angle / 2)
max_layers = self.parent.model.max_layers
current_layer = self.parent.model.num_layers_to_draw
new_layer = min(max_layers, current_layer + 1)
self.parent.model.num_layers_to_draw = new_layer
else:
self.rotate_shape(-angle / 2)
current_layer = self.parent.model.num_layers_to_draw
new_layer = max(1, current_layer - 1)
self.parent.model.num_layers_to_draw = new_layer
wx.CallAfter(self.Refresh)
return
if z > 0:
self.transv[2] += angle
......@@ -712,10 +408,11 @@ class TestGlPanel(GLPanel):
glLoadIdentity()
glTranslatef(*self.transv)
if(self.rot):
if self.rot:
glMultMatrixd(build_rotmatrix(self.basequat))
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
self.rot = 1
wx.CallAfter(self.Refresh)
def keypress(self, event):
"""gets keypress events and moves/rotates acive shape"""
......@@ -745,268 +442,69 @@ class TestGlPanel(GLPanel):
if keycode == 93:
self.rotate_shape(angle)
event.Skip()
def update(self):
while(1):
dt = 0.05
time.sleep(0.05)
try:
wx.CallAfter(self.Refresh)
except:
return
def anim(self, obj):
g = 50 * 9.8
v = 20
dt = 0.05
basepos = obj.offsets[2]
obj.offsets[2] += obj.animoffset
while obj.offsets[2] > -1:
time.sleep(dt)
obj.offsets[2] -= v * dt
v += g * dt
if(obj.offsets[2] < 0):
obj.scale[2] *= 1 - 3 * dt
#return
v = v / 4
while obj.offsets[2] < basepos:
time.sleep(dt)
obj.offsets[2] += v * dt
v -= g * dt
obj.scale[2] *= 1 + 5 * dt
obj.scale[2] = 1.0
def create_objects(self):
'''create opengl objects when opengl is initialized'''
self.initialized = 1
wx.CallAfter(self.Refresh)
def drawmodel(self, m, n):
batch = pyglet.graphics.Batch()
stl = stlview(m.facets, batch = batch)
m.batch = batch
m.animoffset = 300
#print m
#threading.Thread(target = self.anim, args = (m, )).start()
wx.CallAfter(self.Refresh)
def update_object_resize(self):
'''called when the window recieves only if opengl is initialized'''
pass
class GCObject(object):
def draw_objects(self):
'''called in the middle of ondraw after the buffer has been cleared'''
if self.vpmat is None:
return
if not self.initialized:
self.create_objects()
#glLoadIdentity()
#print list(self.pmat)
if self.rot == 1:
glLoadIdentity()
glMultMatrixd(self.mvmat)
else:
glLoadIdentity()
glTranslatef(*self.transv)
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.2, 0.2, 0.2, 1))
glBegin(GL_LINES)
glNormal3f(0, 0, 1)
rows = 10
cols = 10
zheight = 50
for i in xrange(-rows, rows + 1):
if i % 5 == 0:
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.6, 0.6, 0.6, 1))
else:
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.2, 0.2, 0.2, 1))
glVertex3f(10 * -cols, 10 * i, 0)
glVertex3f(10 * cols, 10 * i, 0)
for i in xrange(-cols, cols + 1):
if i % 5 == 0:
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.6, 0.6, 0.6, 1))
else:
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.2, 0.2, 0.2, 1))
glVertex3f(10 * i, 10 * -rows, 0)
glVertex3f(10 * i, 10 * rows, 0)
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.6, 0.6, 0.6, 1))
glVertex3f(10 * -cols, 10 * -rows, 0)
glVertex3f(10 * -cols, 10 * -rows, zheight)
glVertex3f(10 * cols, 10 * rows, 0)
glVertex3f(10 * cols, 10 * rows, zheight)
glVertex3f(10 * cols, 10 * -rows, 0)
glVertex3f(10 * cols, 10 * -rows, zheight)
glVertex3f(10 * -cols, 10 * rows, 0)
glVertex3f(10 * -cols, 10 * rows, zheight)
glVertex3f(10 * -cols, 10 * rows, zheight)
glVertex3f(10 * cols, 10 * rows, zheight)
glVertex3f(10 * cols, 10 * rows, zheight)
glVertex3f(10 * cols, 10 * -rows, zheight)
glVertex3f(10 * cols, 10 * -rows, zheight)
glVertex3f(10 * -cols, 10 * -rows, zheight)
glVertex3f(10 * -cols, 10 * -rows, zheight)
glVertex3f(10 * -cols, 10 * rows, zheight)
glEnd()
glPushMatrix()
glTranslatef(self.mousepos[0] - self.bedsize[0] / 2, self.mousepos[1] - self.bedsize[1] / 2, 0)
glBegin(GL_TRIANGLES)
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(1, 0, 0, 1))
glNormal3f(0, 0, 1)
glVertex3f(2, 2, 0)
glVertex3f(-2, 2, 0)
glVertex3f(-2, -2, 0)
glVertex3f(2, -2, 0)
glVertex3f(2, 2, 0)
glVertex3f(-2, -2, 0)
glEnd()
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.3, 0.7, 0.5, 1))
#glTranslatef(0, 40, 0)
glPopMatrix()
glPushMatrix()
glTranslatef(-100, -100, 0)
glEnable(GL_LINE_SMOOTH)
glEnable(GL_BLEND)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST)
glLineWidth (1.5)
for i in self.parent.models.values():
glPushMatrix()
glTranslatef(*(i.offsets))
glRotatef(i.rot, 0.0, 0.0, 1.0)
glScalef(*i.scale)
#glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.93, 0.37, 0.25, 1))
glEnable(GL_COLOR_MATERIAL)
if i.curlayer == -1:
# curlayer == -1 means we are over the top.
glLineWidth (0.8)
[i.gc.layers[j].draw() for j in i.gc.layerlist]
else:
glLineWidth (0.6)
tmpindex = i.gc.layerlist.index(i.curlayer)
if tmpindex >= 5:
thin_layer = i.gc.layerlist[tmpindex - 5]
[i.gc.layers[j].draw() for j in i.gc.layerlist if j <= thin_layer]
if tmpindex > 4:
glLineWidth (0.9)
i.gc.layers[i.gc.layerlist[tmpindex - 4]].draw()
if tmpindex > 3:
glLineWidth (1.1)
i.gc.layers[i.gc.layerlist[tmpindex - 3]].draw()
if tmpindex > 2:
glLineWidth (1.3)
i.gc.layers[i.gc.layerlist[tmpindex - 2]].draw()
if tmpindex > 1:
glLineWidth (2.2)
i.gc.layers[i.gc.layerlist[tmpindex - 1]].draw()
glLineWidth (3.5)
i.gc.layers[i.curlayer].draw()
glLineWidth (1.5)
glDisable(GL_COLOR_MATERIAL)
glPopMatrix()
glPopMatrix()
#print "drawn batch"
def __init__(self, model):
self.offsets = [0, 0, 0]
self.rot = 0
self.curlayer = 0.0
self.scale = [1.0, 1.0, 1.0]
self.batch = pyglet.graphics.Batch()
self.model = model
def GetSelection(self):
return wx.NOT_FOUND
class GCFrame(wx.Frame):
class GcodeViewFrame(wx.Frame):
'''A simple class for using OpenGL with wxPython.'''
def __init__(self, parent, ID, title, pos = wx.DefaultPosition,
def __init__(self, parent, ID, title, build_dimensions, pos = wx.DefaultPosition,
size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
super(GCFrame, self).__init__(parent, ID, title, pos, (size[0] + 150, size[1]), style)
class d:
def GetSelection(self):
return wx.NOT_FOUND
self.p = self
m = d()
m.offsets = [0, 0, 0]
m.rot = 0
m.curlayer = -1
m.scale = [1.0, 1.0, 1.0]
m.batch = pyglet.graphics.Batch()
m.gc = gcview([], batch = m.batch)
self.models = {"GCODE": m}
self.l = d()
self.modelindex = 0
self.GLPanel1 = TestGlPanel(self, size)
def addfile(self, gcode = []):
self.models["GCODE"].gc.delete()
self.models["GCODE"].gc = gcview(gcode, batch = self.models["GCODE"].batch)
self.setlayerindex(None)
super(GcodeViewFrame, self).__init__(parent, ID, title, pos, size, style)
self.p = self # Hack for backwards compatibility with gviz API
self.platform = actors.Platform(build_dimensions)
self.model = None
self.objects = [GCObject(self.platform), GCObject(None)]
self.glpanel = GcodeViewPanel(self)
def addfile(self, gcode = None):
self.model = actors.GcodeModel()
if gcode:
self.model.load_data(gcode)
self.objects[-1].model = self.model
wx.CallAfter(self.Refresh)
def clear(self):
self.models["GCODE"].gc.delete()
self.models["GCODE"].gc = gcview([], batch = self.models["GCODE"].batch)
self.model = None
self.objects[-1].model = None
wx.CallAfter(self.Refresh)
def Show(self, arg = True):
wx.Frame.Show(self, arg)
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1))
self.Refresh()
wx.FutureCall(500, self.GLPanel1.forceresize)
#threading.Thread(target = self.update).start()
#self.initialized = 0
def setlayerindex(self, z):
m = self.models["GCODE"]
try:
mlk = m.gc.layerlist
except:
mlk = []
if z is None:
self.modelindex = -1
elif z > 0:
if self.modelindex < len(mlk) - 1:
if self.modelindex > -1:
model = self.objects[-1].model
if not model:
return
mlk = sorted(m.gc.layers.keys())
if z > 0 and self.modelindex < len(mlk) - 1:
self.modelindex += 1
else:
self.modelindex = -1
elif z < 0:
if self.modelindex > 0:
if z < 0 and self.modelindex > 0:
self.modelindex -= 1
elif self.modelindex == -1:
self.modelindex = len(mlk)
if self.modelindex >= 0:
m.curlayer = mlk[self.modelindex]
wx.CallAfter(self.SetTitle, "Gcode view, shift to move. Layer %d/%d, Z = %f" % (self.modelindex, len(mlk), m.curlayer))
else:
m.curlayer = -1
wx.CallAfter(self.SetTitle, "Gcode view, shift to move view, mousewheel to set layer")
wx.CallAfter(self.SetTitle, "Gcode view, shift to move. Layer %d, Z = %f" % (self.modelindex, m.curlayer))
def main():
app = wx.App(redirect = False)
frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size = (400, 400))
if __name__ == "__main__":
import sys
for filename in sys.argv:
if ".gcode" in filename:
frame.addfile(list(open(filename)))
elif ".stl" in filename:
#TODO: add stl here
pass
#frame = wx.Frame(None, -1, "GL Window", size = (400, 400))
#panel = TestGlPanel(frame, size = (300, 300))
app = wx.App(redirect = False)
build_dimensions = [200, 200, 100, 0, 0, 0]
frame = GcodeViewFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size = (400, 400), build_dimensions = build_dimensions)
frame.addfile(gcoder.GCode(open(sys.argv[1])))
frame.Show(True)
app.MainLoop()
app.Destroy()
if __name__ == "__main__":
#import cProfile
#print cProfile.run("main()")
main()
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