Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
Printrun
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
machinery
Printrun
Commits
20a28bb6
Commit
20a28bb6
authored
Jan 24, 2012
by
Václav 'Ax' Hůla
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
OpenGL gcode viewer, line only, working.
parent
95aaa81b
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
886 additions
and
0 deletions
+886
-0
gcview.py
gcview.py
+886
-0
No files found.
gcview.py
0 → 100644
View file @
20a28bb6
#!/usr/bin/python
import
os
import
math
import
wx
from
wx
import
glcanvas
import
time
import
threading
import
pyglet
pyglet
.
options
[
'shadow_window'
]
=
False
pyglet
.
options
[
'debug_gl'
]
=
False
from
pyglet.gl
import
*
import
stltool
class
GLPanel
(
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
)
#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
()
# bind events
self
.
canvas
.
Bind
(
wx
.
EVT_ERASE_BACKGROUND
,
self
.
processEraseBackgroundEvent
)
self
.
canvas
.
Bind
(
wx
.
EVT_SIZE
,
self
.
processSizeEvent
)
self
.
canvas
.
Bind
(
wx
.
EVT_PAINT
,
self
.
processPaintEvent
)
#==========================================================================
# Canvas Proxy Methods
#==========================================================================
def
GetGLExtents
(
self
):
'''Get the extents of the OpenGL canvas.'''
return
self
.
canvas
.
GetClientSize
()
def
SwapBuffers
(
self
):
'''Swap the OpenGL buffers.'''
self
.
canvas
.
SwapBuffers
()
#==========================================================================
# wxPython Window Handlers
#==========================================================================
def
processEraseBackgroundEvent
(
self
,
event
):
'''Process the erase background event.'''
pass
# Do nothing, to avoid flashing on MSWin
def
processSizeEvent
(
self
,
event
):
'''Process the resize event.'''
if
self
.
canvas
.
GetContext
():
# Make sure the frame is shown before calling SetCurrent.
self
.
Show
()
self
.
canvas
.
SetCurrent
()
size
=
self
.
GetGLExtents
()
self
.
winsize
=
(
size
.
width
,
size
.
height
)
self
.
width
,
self
.
height
=
size
.
width
,
size
.
height
self
.
OnReshape
(
size
.
width
,
size
.
height
)
self
.
canvas
.
Refresh
(
False
)
event
.
Skip
()
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
self
.
OnDraw
()
event
.
Skip
()
def
Destroy
(
self
):
#clean up the pyglet OpenGL context
#self.pygletcontext.destroy()
#call the super method
super
(
wx
.
Panel
,
self
)
.
Destroy
()
#==========================================================================
# GLFrame OpenGL Event Handlers
#==========================================================================
def
OnInitGL
(
self
):
'''Initialize OpenGL for use in the window.'''
#create a pyglet context for this panel
self
.
pmat
=
(
GLdouble
*
16
)()
self
.
mvmat
=
(
GLdouble
*
16
)()
self
.
pygletcontext
=
Context
(
current_context
)
self
.
pygletcontext
.
set_current
()
self
.
dist
=
1000
self
.
vpmat
=
None
#normal gl init
glClearColor
(
0
,
0
,
0
,
1
)
glColor3f
(
1
,
0
,
0
)
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()
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
()
gluPerspective
(
60.
,
width
/
float
(
height
),
.1
,
1000.
)
glMatrixMode
(
GL_MODELVIEW
)
glLoadIdentity
()
#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
:
self
.
pygletcontext
.
set_current
()
self
.
update_object_resize
()
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
()
#==========================================================================
# To be implemented by a sub class
#==========================================================================
def
create_objects
(
self
):
'''create opengl objects when opengl is initialized'''
pass
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'''
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
class
gcline
(
object
):
"""gcode move line
Once initialised,it knows its position, length and extrusion ratio
"""
def
__init__
(
self
,
x
=
None
,
y
=
None
,
z
=
None
,
e
=
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
.
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
\n
%
s"
%
(
self
.
prev_gcline
.
x
,
self
.
prev_gcline
.
y
,
self
.
prev_gcline
.
z
,
self
.
x
,
self
.
y
,
self
.
z
,
self
.
extrusion_ratio
,
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
):
if
self
.
extrusion_ratio
==
0
:
return
[
10
,
10
,
10
,
0
,
10
,
10
,
10
,
0
]
else
:
return
[
255
,
128
,
128
,
120
,
255
,
128
,
128
,
120
]
def
float_from_line
(
axe
,
line
):
return
float
(
line
.
split
(
axe
)[
1
]
.
split
(
" "
)[
0
])
class
gcview
(
object
):
"""gcode visualiser"""
def
__init__
(
self
,
lines
,
batch
,
w
=
0.5
,
h
=
0.5
):
print
len
(
lines
)
self
.
sq2
=
math
.
sqrt
(
2.0
)
/
2.0
# Create the vertex and normal arrays.
vertices
=
[]
normals
=
[]
#End pos of previous mode
self
.
prev
=
gcpoint
()
# Correction for G92 moves
self
.
delta
=
[
0
,
0
,
0
,
0
]
self
.
fline
=
True
#self.vlists = []
self
.
layers
=
{}
t0
=
time
.
time
()
lines
=
[
self
.
transform
(
i
)
for
i
in
lines
]
lines
=
[
i
for
i
in
lines
if
i
is
not
None
]
t1
=
time
.
time
()
print
"transformed
%
s lines in
%
fs"
%
(
len
(
lines
),
t1
-
t0
)
layertemp
=
{}
counter
=
0
for
line
in
lines
:
layer_name
=
line
.
z
if
line
.
z
not
in
self
.
layers
:
self
.
layers
[
line
.
z
]
=
pyglet
.
graphics
.
Batch
()
self
.
layers
[
line
.
z
]
.
add
(
2
,
GL_LINES
,
None
,
(
"c4B"
,
line
.
glcolor
()))
self
.
layers
[
line
.
z
]
.
add
(
2
,
GL_LINES
,
None
,
(
"v3f"
,
line
.
glline
()))
self
.
layerlist
=
self
.
layers
.
keys
()
self
.
layerlist
.
sort
()
t2
=
time
.
time
()
print
"Rendered lines in
%
fs"
%
(
t2
-
t1
)
def
transform
(
self
,
line
):
orgline
=
line
line
=
line
.
split
(
";"
)[
0
]
cur
=
[
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
cur
==
[
None
,
None
,
None
,
None
]:
return
None
else
:
#print cur
r
=
gcline
(
cur
[
0
],
cur
[
1
],
cur
[
2
],
cur
[
3
],
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];
#float t;
if
(
p1x
==
p2x
and
p1y
==
p2y
):
return
[
0.0
,
0.0
,
0.0
,
1.0
]
p1
=
[
p1x
,
p1y
,
project_to_sphere
(
TRACKBALLSIZE
,
p1x
,
p1y
)]
p2
=
[
p2x
,
p2y
,
project_to_sphere
(
TRACKBALLSIZE
,
p2x
,
p2y
)]
a
=
stltool
.
cross
(
p2
,
p1
)
d
=
map
(
lambda
x
,
y
:
x
-
y
,
p1
,
p2
)
t
=
math
.
sqrt
(
sum
(
map
(
lambda
x
:
x
*
x
,
d
)))
/
(
2.0
*
TRACKBALLSIZE
)
if
(
t
>
1.0
):
t
=
1.0
if
(
t
<
-
1.0
):
t
=
-
1.0
phi
=
2.0
*
math
.
asin
(
t
)
return
axis_to_quat
(
a
,
phi
)
def
vec
(
*
args
):
return
(
GLfloat
*
len
(
args
))(
*
args
)
def
axis_to_quat
(
a
,
phi
):
#print a, phi
lena
=
math
.
sqrt
(
sum
(
map
(
lambda
x
:
x
*
x
,
a
)))
q
=
map
(
lambda
x
:
x
*
(
1
/
lena
),
a
)
q
=
map
(
lambda
x
:
x
*
math
.
sin
(
phi
/
2.0
),
q
)
q
.
append
(
math
.
cos
(
phi
/
2.0
))
return
q
def
build_rotmatrix
(
q
):
m
=
(
GLdouble
*
16
)()
m
[
0
]
=
1.0
-
2.0
*
(
q
[
1
]
*
q
[
1
]
+
q
[
2
]
*
q
[
2
])
m
[
1
]
=
2.0
*
(
q
[
0
]
*
q
[
1
]
-
q
[
2
]
*
q
[
3
])
m
[
2
]
=
2.0
*
(
q
[
2
]
*
q
[
0
]
+
q
[
1
]
*
q
[
3
])
m
[
3
]
=
0.0
m
[
4
]
=
2.0
*
(
q
[
0
]
*
q
[
1
]
+
q
[
2
]
*
q
[
3
])
m
[
5
]
=
1.0
-
2.0
*
(
q
[
2
]
*
q
[
2
]
+
q
[
0
]
*
q
[
0
])
m
[
6
]
=
2.0
*
(
q
[
1
]
*
q
[
2
]
-
q
[
0
]
*
q
[
3
])
m
[
7
]
=
0.0
m
[
8
]
=
2.0
*
(
q
[
2
]
*
q
[
0
]
-
q
[
1
]
*
q
[
3
])
m
[
9
]
=
2.0
*
(
q
[
1
]
*
q
[
2
]
+
q
[
0
]
*
q
[
3
])
m
[
10
]
=
1.0
-
2.0
*
(
q
[
1
]
*
q
[
1
]
+
q
[
0
]
*
q
[
0
])
m
[
11
]
=
0.0
m
[
12
]
=
0.0
m
[
13
]
=
0.0
m
[
14
]
=
0.0
m
[
15
]
=
1.0
return
m
def
project_to_sphere
(
r
,
x
,
y
):
d
=
math
.
sqrt
(
x
*
x
+
y
*
y
)
if
(
d
<
r
*
0.70710678118654752440
):
return
math
.
sqrt
(
r
*
r
-
d
*
d
)
else
:
t
=
r
/
1.41421356237309504880
return
t
*
t
/
d
def
mulquat
(
q1
,
rq
):
return
[
q1
[
3
]
*
rq
[
0
]
+
q1
[
0
]
*
rq
[
3
]
+
q1
[
1
]
*
rq
[
2
]
-
q1
[
2
]
*
rq
[
1
],
q1
[
3
]
*
rq
[
1
]
+
q1
[
1
]
*
rq
[
3
]
+
q1
[
2
]
*
rq
[
0
]
-
q1
[
0
]
*
rq
[
2
],
q1
[
3
]
*
rq
[
2
]
+
q1
[
2
]
*
rq
[
3
]
+
q1
[
0
]
*
rq
[
1
]
-
q1
[
1
]
*
rq
[
0
],
q1
[
3
]
*
rq
[
3
]
-
q1
[
0
]
*
rq
[
0
]
-
q1
[
1
]
*
rq
[
1
]
-
q1
[
2
]
*
rq
[
2
]]
class
TestGlPanel
(
GLPanel
):
def
__init__
(
self
,
parent
,
size
,
id
=
wx
.
ID_ANY
):
super
(
TestGlPanel
,
self
)
.
__init__
(
parent
,
id
,
wx
.
DefaultPosition
,
size
,
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
.
canvas
.
Bind
(
wx
.
EVT_MOUSEWHEEL
,
self
.
wheel
)
self
.
parent
=
parent
self
.
initpos
=
None
self
.
dist
=
200
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
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
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
"""
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
p2
=
event
.
GetPositionTuple
()
sz
=
self
.
GetClientSize
()
p1x
=
(
float
(
p1
[
0
])
-
sz
[
0
]
/
2
)
/
(
sz
[
0
]
/
2
)
p1y
=
-
(
float
(
p1
[
1
])
-
sz
[
1
]
/
2
)
/
(
sz
[
1
]
/
2
)
p2x
=
(
float
(
p2
[
0
])
-
sz
[
0
]
/
2
)
/
(
sz
[
0
]
/
2
)
p2y
=
-
(
float
(
p2
[
1
])
-
sz
[
1
]
/
2
)
/
(
sz
[
1
]
/
2
)
#print p1x,p1y,p2x,p2y
quat
=
trackball
(
p1x
,
p1y
,
p2x
,
p2y
,
-
self
.
transv
[
2
]
/
250.0
)
if
self
.
rot
:
self
.
basequat
=
mulquat
(
self
.
basequat
,
quat
)
#else:
glGetDoublev
(
GL_MODELVIEW_MATRIX
,
self
.
mvmat
)
#self.basequat = quatx
mat
=
build_rotmatrix
(
self
.
basequat
)
glLoadIdentity
()
glTranslatef
(
self
.
transv
[
0
],
self
.
transv
[
1
],
0
)
glTranslatef
(
0
,
0
,
self
.
transv
[
2
])
glMultMatrixd
(
mat
)
glGetDoublev
(
GL_MODELVIEW_MATRIX
,
self
.
mvmat
)
self
.
rot
=
1
elif
event
.
ButtonUp
(
wx
.
MOUSE_BTN_LEFT
):
if
self
.
initpos
is
not
None
:
self
.
initpos
=
None
elif
event
.
ButtonUp
(
wx
.
MOUSE_BTN_RIGHT
):
if
self
.
initpos
is
not
None
:
self
.
initpos
=
None
elif
event
.
Dragging
()
and
event
.
RightIsDown
()
and
event
.
ShiftDown
():
if
self
.
initpos
is
None
:
self
.
initpos
=
event
.
GetPositionTuple
()
else
:
p1
=
self
.
initpos
p2
=
event
.
GetPositionTuple
()
sz
=
self
.
GetClientSize
()
p1
=
list
(
p1
)
p2
=
list
(
p2
)
p1
[
1
]
*=
-
1
p2
[
1
]
*=
-
1
self
.
transv
=
map
(
lambda
x
,
y
,
z
,
c
:
c
-
self
.
dist
*
(
x
-
y
)
/
z
,
list
(
p1
)
+
[
0
],
list
(
p2
)
+
[
0
],
list
(
sz
)
+
[
1
],
self
.
transv
)
glLoadIdentity
()
glTranslatef
(
self
.
transv
[
0
],
self
.
transv
[
1
],
0
)
glTranslatef
(
0
,
0
,
self
.
transv
[
2
])
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
def
wheel
(
self
,
event
):
"""react to mouse wheel actions:
rotate object
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
return
if
z
>
0
:
self
.
rotate_shape
(
angle
/
2
)
else
:
self
.
rotate_shape
(
-
angle
/
2
)
return
if
z
>
0
:
self
.
transv
[
2
]
+=
angle
else
:
self
.
transv
[
2
]
-=
angle
glLoadIdentity
()
glTranslatef
(
*
self
.
transv
)
if
(
self
.
rot
):
glMultMatrixd
(
build_rotmatrix
(
self
.
basequat
))
glGetDoublev
(
GL_MODELVIEW_MATRIX
,
self
.
mvmat
)
self
.
rot
=
1
def
keypress
(
self
,
event
):
"""gets keypress events and moves/rotates acive shape"""
keycode
=
event
.
GetKeyCode
()
print
keycode
step
=
5
angle
=
18
if
event
.
ControlDown
():
step
=
1
angle
=
1
#h
if
keycode
==
72
:
self
.
move_shape
((
-
step
,
0
))
#l
if
keycode
==
76
:
self
.
move_shape
((
step
,
0
))
#j
if
keycode
==
75
:
self
.
move_shape
((
0
,
step
))
#k
if
keycode
==
74
:
self
.
move_shape
((
0
,
-
step
))
#[
if
keycode
==
91
:
self
.
rotate_shape
(
-
angle
)
#]
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
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
)
#glEnable(GL_COLOR_MATERIAL)
glMaterialfv
(
GL_FRONT_AND_BACK
,
GL_AMBIENT_AND_DIFFUSE
,
vec
(
0.93
,
0.37
,
0.25
,
1
))
[
i
.
gc
.
layers
[
j
]
.
draw
()
for
j
in
i
.
gc
.
layerlist
if
j
<
i
.
curlayer
]
glMaterialfv
(
GL_FRONT_AND_BACK
,
GL_AMBIENT_AND_DIFFUSE
,
vec
(
0.5
,
0.6
,
0.9
,
1
))
i
.
gc
.
layers
[
i
.
curlayer
]
.
draw
()
glPopMatrix
()
glPopMatrix
()
#print "drawn batch"
class
GCFrame
(
wx
.
Frame
):
'''A simple class for using OpenGL with wxPython.'''
def
__init__
(
self
,
parent
,
ID
,
title
,
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
=
{
""
:
m
}
self
.
l
=
d
()
self
.
modelindex
=
0
self
.
GLPanel1
=
TestGlPanel
(
self
,
size
)
def
addfile
(
self
,
gcode
=
[]):
self
.
models
[
""
]
.
gc
.
delete
()
self
.
models
[
""
]
.
gc
=
gcview
(
gcode
,
batch
=
self
.
models
[
""
]
.
batch
)
self
.
setlayerindex
(
None
)
def
clear
(
self
):
self
.
models
[
""
]
.
gc
.
delete
()
self
.
models
[
""
]
.
gc
=
gcview
([],
batch
=
self
.
models
[
""
]
.
batch
)
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
[
""
]
mlk
=
m
.
gc
.
layerlist
if
z
>
0
and
self
.
modelindex
<
len
(
mlk
)
-
1
:
self
.
modelindex
+=
1
elif
z
<
0
and
self
.
modelindex
>
0
:
self
.
modelindex
-=
1
elif
z
is
None
:
self
.
modelindex
=
len
(
mlk
)
-
1
m
.
curlayer
=
mlk
[
self
.
modelindex
]
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
))
import
sys
for
gcfile
in
sys
.
argv
:
if
"gcode"
in
gcfile
:
print
gcfile
frame
.
addfile
(
list
(
open
(
gcfile
)))
#frame = wx.Frame(None, -1, "GL Window", size=(400, 400))
#panel = TestGlPanel(frame, size=(300,300))
frame
.
Show
(
True
)
app
.
MainLoop
()
app
.
Destroy
()
if
__name__
==
"__main__"
:
#import cProfile
#print cProfile.run("main()")
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment