chiark / gitweb /
Some cleanup, move the animation code to openglGUI, move scaled quad code to opengl.
[cura.git] / Cura / gui / util / opengl.py
1 # coding=utf-8
2 from __future__ import absolute_import
3
4 import math
5 import numpy
6 import wx
7 import time
8
9 from Cura.util import meshLoader
10 from Cura.util import util3d
11 from Cura.util import profile
12 from Cura.util.resources import getPathForMesh, getPathForImage
13
14 import OpenGL
15
16 OpenGL.ERROR_CHECKING = False
17 from OpenGL.GLUT import *
18 from OpenGL.GLU import *
19 from OpenGL.GL import *
20 from OpenGL.GL import shaders
21 glutInit()
22
23 platformMesh = None
24
25 class GLShader(object):
26         def __init__(self, vertexProgram, fragmentProgram):
27                 self._vertexString = vertexProgram
28                 self._fragmentString = fragmentProgram
29                 try:
30                         self._vertexProgram = shaders.compileShader(vertexProgram, GL_VERTEX_SHADER)
31                         self._fragmentProgram = shaders.compileShader(fragmentProgram, GL_FRAGMENT_SHADER)
32                         self._program = shaders.compileProgram(self._vertexProgram, self._fragmentProgram)
33                 except RuntimeError, e:
34                         print str(e)
35                         self._program = None
36
37         def bind(self):
38                 if self._program is not None:
39                         shaders.glUseProgram(self._program)
40
41         def unbind(self):
42                 shaders.glUseProgram(0)
43
44         def release(self):
45                 if self._program is not None:
46                         shaders.glDeleteShader(self._vertexProgram)
47                         shaders.glDeleteShader(self._fragmentProgram)
48                         glDeleteProgram(self._program)
49                         self._program = None
50
51         def setUniform(self, name, value):
52                 if self._program is not None:
53                         glUniform1f(glGetUniformLocation(self._program, name), value)
54
55         def isValid(self):
56                 return self._program is not None
57
58         def getVertexShader(self):
59                 return self._vertexString
60
61         def getFragmentShader(self):
62                 return self._fragmentString
63
64         def __del__(self):
65                 if self._program is not None and bool(glDeleteProgram):
66                         print "Shader was not properly released!"
67
68 class GLVBO(object):
69         def __init__(self, vertexArray, normalArray):
70                 self._buffer = glGenBuffers(1)
71                 self._size = len(vertexArray)
72                 glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
73                 glBufferData(GL_ARRAY_BUFFER, numpy.concatenate((vertexArray, normalArray), 1), GL_STATIC_DRAW)
74                 glBindBuffer(GL_ARRAY_BUFFER, 0)
75
76         def render(self, render_type = GL_TRIANGLES):
77                 glEnableClientState(GL_VERTEX_ARRAY)
78                 glEnableClientState(GL_NORMAL_ARRAY)
79                 glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
80                 glVertexPointer(3, GL_FLOAT, 2*3*4, c_void_p(0))
81                 glNormalPointer(GL_FLOAT, 2*3*4, c_void_p(3 * 4))
82
83                 batchSize = 999    #Warning, batchSize needs to be dividable by 3
84                 extraStartPos = int(self._size / batchSize) * batchSize
85                 extraCount = self._size - extraStartPos
86
87                 for i in xrange(0, int(self._size / batchSize)):
88                         glDrawArrays(render_type, i * batchSize, batchSize)
89                 glDrawArrays(render_type, extraStartPos, extraCount)
90                 glBindBuffer(GL_ARRAY_BUFFER, 0)
91                 glDisableClientState(GL_VERTEX_ARRAY)
92                 glDisableClientState(GL_NORMAL_ARRAY)
93
94         def release(self):
95                 if self._buffer is not None:
96                         glDeleteBuffers(1, [self._buffer])
97                         self._buffer = None
98
99         def __del__(self):
100                 if self._buffer is not None and bool(glDeleteBuffers):
101                         print "VBO was not properly released!"
102
103 def DrawMachine(machineSize):
104         glDisable(GL_LIGHTING)
105         glDisable(GL_CULL_FACE)
106         glEnable(GL_BLEND)
107         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
108
109         sx = machineSize.x
110         sy = machineSize.y
111         for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
112                 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
113                         x1 = sx/2+x * 10
114                         x2 = x1 + 10
115                         y1 = sx/2+y * 10
116                         y2 = y1 + 10
117                         x1 = max(min(x1, sx), 0)
118                         y1 = max(min(y1, sy), 0)
119                         x2 = max(min(x2, sx), 0)
120                         y2 = max(min(y2, sy), 0)
121                         if (x & 1) == (y & 1):
122                                 glColor4ub(5, 171, 231, 127)
123                         else:
124                                 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
125                         glBegin(GL_QUADS)
126                         glVertex3f(x1, y1, -0.02)
127                         glVertex3f(x2, y1, -0.02)
128                         glVertex3f(x2, y2, -0.02)
129                         glVertex3f(x1, y2, -0.02)
130                         glEnd()
131
132         glEnable(GL_CULL_FACE)
133
134         if profile.getPreference('machine_type') == 'ultimaker':
135                 glPushMatrix()
136                 glEnable(GL_LIGHTING)
137                 glTranslate(100, 200, -1)
138                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
139                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
140                 glEnable(GL_BLEND)
141                 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
142
143                 global platformMesh
144                 if platformMesh is None:
145                         try:
146                                 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
147                         except:
148                                 platformMesh = False
149
150                 if platformMesh:
151                         DrawMesh(platformMesh)
152                 glPopMatrix()
153                 glDisable(GL_LIGHTING)
154                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
155
156         glColor4ub(5, 171, 231, 64)
157         glBegin(GL_QUADS)
158         glVertex3f(0, 0, machineSize.z)
159         glVertex3f(0, machineSize.y, machineSize.z)
160         glVertex3f(machineSize.x, machineSize.y, machineSize.z)
161         glVertex3f(machineSize.x, 0, machineSize.z)
162         glEnd()
163
164         glColor4ub(5, 171, 231, 96)
165         glBegin(GL_QUADS)
166         glVertex3f(0, 0, 0)
167         glVertex3f(0, 0, machineSize.z)
168         glVertex3f(machineSize.x, 0, machineSize.z)
169         glVertex3f(machineSize.x, 0, 0)
170
171         glVertex3f(0, machineSize.y, machineSize.z)
172         glVertex3f(0, machineSize.y, 0)
173         glVertex3f(machineSize.x, machineSize.y, 0)
174         glVertex3f(machineSize.x, machineSize.y, machineSize.z)
175         glEnd()
176
177         glColor4ub(5, 171, 231, 128)
178         glBegin(GL_QUADS)
179         glVertex3f(0, 0, machineSize.z)
180         glVertex3f(0, 0, 0)
181         glVertex3f(0, machineSize.y, 0)
182         glVertex3f(0, machineSize.y, machineSize.z)
183
184         glVertex3f(machineSize.x, 0, 0)
185         glVertex3f(machineSize.x, 0, machineSize.z)
186         glVertex3f(machineSize.x, machineSize.y, machineSize.z)
187         glVertex3f(machineSize.x, machineSize.y, 0)
188         glEnd()
189
190         glDisable(GL_BLEND)
191
192         #Draw the X/Y/Z indicator
193         glPushMatrix()
194         glTranslate(5, 5, 2)
195         glLineWidth(2)
196         glColor3f(0.5, 0, 0)
197         glBegin(GL_LINES)
198         glVertex3f(0, 0, 0)
199         glVertex3f(20, 0, 0)
200         glEnd()
201         glColor3f(0, 0.5, 0)
202         glBegin(GL_LINES)
203         glVertex3f(0, 0, 0)
204         glVertex3f(0, 20, 0)
205         glEnd()
206         glColor3f(0, 0, 0.5)
207         glBegin(GL_LINES)
208         glVertex3f(0, 0, 0)
209         glVertex3f(0, 0, 20)
210         glEnd()
211
212         glDisable(GL_DEPTH_TEST)
213         #X
214         glColor3f(1, 0, 0)
215         glPushMatrix()
216         glTranslate(20, 0, 0)
217         noZ = ResetMatrixRotationAndScale()
218         glDrawStringCenter("X")
219         glPopMatrix()
220
221         #Y
222         glColor3f(0, 1, 0)
223         glPushMatrix()
224         glTranslate(0, 20, 0)
225         glDrawStringCenter("Y")
226         glPopMatrix()
227
228         #Z
229         if not noZ:
230                 glColor3f(0, 0, 1)
231                 glPushMatrix()
232                 glTranslate(0, 0, 20)
233                 glDrawStringCenter("Z")
234                 glPopMatrix()
235
236         glPopMatrix()
237         glEnable(GL_DEPTH_TEST)
238
239 def glDrawStringCenter(s):
240         glRasterPos2f(0, 0)
241         glBitmap(0,0,0,0, -glGetStringSize(s)[0]/2, 0, None)
242         for c in s:
243                 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
244
245 def glGetStringSize(s):
246         width = 0
247         for c in s:
248                 width += glutBitmapWidth(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
249         height = 18
250         return width, height
251
252 def glDrawStringLeft(s):
253         glRasterPos2f(0, 0)
254         for c in s:
255                 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
256
257 def glDrawStringRight(s):
258         glRasterPos2f(0, 0)
259         glBitmap(0,0,0,0, -glGetStringSize(s)[0], 0, None)
260         for c in s:
261                 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
262
263 def glDrawTexturedQuad(x, y, w, h, texID, mirror = 0):
264         tx = float(texID % 4) / 4
265         ty = float(int(texID / 4)) / 8
266         tsx = 0.25
267         tsy = 0.125
268         if mirror & 1:
269                 tx += tsx
270                 tsx = -tsx
271         if mirror & 2:
272                 ty += tsy
273                 tsy = -tsy
274         glPushMatrix()
275         glTranslatef(x, y, 0)
276         glEnable(GL_TEXTURE_2D)
277         glBegin(GL_QUADS)
278         glTexCoord2f(tx+tsx, ty)
279         glVertex2f(w, 0)
280         glTexCoord2f(tx, ty)
281         glVertex2f(0, 0)
282         glTexCoord2f(tx, ty+tsy)
283         glVertex2f(0, h)
284         glTexCoord2f(tx+tsx, ty+tsy)
285         glVertex2f(w, h)
286         glEnd()
287         glPopMatrix()
288
289 def glDrawStretchedQuad(x, y, w, h, cornerSize, texID):
290         tx0 = float(texID % 4) / 4
291         ty0 = float(int(texID / 4)) / 8
292         tx1 = tx0 + 0.25 / 2.0
293         ty1 = ty0 + 0.125 / 2.0
294         tx2 = tx0 + 0.25
295         ty2 = ty0 + 0.125
296
297         glPushMatrix()
298         glTranslatef(x, y, 0)
299         glEnable(GL_TEXTURE_2D)
300         glBegin(GL_QUADS)
301         #TopLeft
302         glTexCoord2f(tx1, ty0)
303         glVertex2f( cornerSize, 0)
304         glTexCoord2f(tx0, ty0)
305         glVertex2f( 0, 0)
306         glTexCoord2f(tx0, ty1)
307         glVertex2f( 0, cornerSize)
308         glTexCoord2f(tx1, ty1)
309         glVertex2f( cornerSize, cornerSize)
310         #TopRight
311         glTexCoord2f(tx2, ty0)
312         glVertex2f( w, 0)
313         glTexCoord2f(tx1, ty0)
314         glVertex2f( w - cornerSize, 0)
315         glTexCoord2f(tx1, ty1)
316         glVertex2f( w - cornerSize, cornerSize)
317         glTexCoord2f(tx2, ty1)
318         glVertex2f( w, cornerSize)
319         #BottomLeft
320         glTexCoord2f(tx1, ty1)
321         glVertex2f( cornerSize, h - cornerSize)
322         glTexCoord2f(tx0, ty1)
323         glVertex2f( 0, h - cornerSize)
324         glTexCoord2f(tx0, ty2)
325         glVertex2f( 0, h)
326         glTexCoord2f(tx1, ty2)
327         glVertex2f( cornerSize, h)
328         #BottomRight
329         glTexCoord2f(tx2, ty1)
330         glVertex2f( w, h - cornerSize)
331         glTexCoord2f(tx1, ty1)
332         glVertex2f( w - cornerSize, h - cornerSize)
333         glTexCoord2f(tx1, ty2)
334         glVertex2f( w - cornerSize, h)
335         glTexCoord2f(tx2, ty2)
336         glVertex2f( w, h)
337
338         #Center
339         glTexCoord2f(tx1, ty1)
340         glVertex2f( w-cornerSize, cornerSize)
341         glTexCoord2f(tx1, ty1)
342         glVertex2f( cornerSize, cornerSize)
343         glTexCoord2f(tx1, ty1)
344         glVertex2f( cornerSize, h-cornerSize)
345         glTexCoord2f(tx1, ty1)
346         glVertex2f( w-cornerSize, h-cornerSize)
347
348         #Right
349         glTexCoord2f(tx2, ty1)
350         glVertex2f( w, cornerSize)
351         glTexCoord2f(tx1, ty1)
352         glVertex2f( w-cornerSize, cornerSize)
353         glTexCoord2f(tx1, ty1)
354         glVertex2f( w-cornerSize, h-cornerSize)
355         glTexCoord2f(tx2, ty1)
356         glVertex2f( w, h-cornerSize)
357
358         #Left
359         glTexCoord2f(tx1, ty1)
360         glVertex2f( cornerSize, cornerSize)
361         glTexCoord2f(tx0, ty1)
362         glVertex2f( 0, cornerSize)
363         glTexCoord2f(tx0, ty1)
364         glVertex2f( 0, h-cornerSize)
365         glTexCoord2f(tx1, ty1)
366         glVertex2f( cornerSize, h-cornerSize)
367
368         #Top
369         glTexCoord2f(tx1, ty0)
370         glVertex2f( w-cornerSize, 0)
371         glTexCoord2f(tx1, ty0)
372         glVertex2f( cornerSize, 0)
373         glTexCoord2f(tx1, ty1)
374         glVertex2f( cornerSize, cornerSize)
375         glTexCoord2f(tx1, ty1)
376         glVertex2f( w-cornerSize, cornerSize)
377
378         #Bottom
379         glTexCoord2f(tx1, ty1)
380         glVertex2f( w-cornerSize, h-cornerSize)
381         glTexCoord2f(tx1, ty1)
382         glVertex2f( cornerSize, h-cornerSize)
383         glTexCoord2f(tx1, ty2)
384         glVertex2f( cornerSize, h)
385         glTexCoord2f(tx1, ty2)
386         glVertex2f( w-cornerSize, h)
387
388         glEnd()
389         glDisable(GL_TEXTURE_2D)
390         glPopMatrix()
391
392 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
393         npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
394         npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
395         finalMatrix = npModelMatrix * npProjMatrix
396         finalMatrix = numpy.linalg.inv(finalMatrix)
397
398         viewport = map(float, viewport)
399         vector = numpy.array([(winx - viewport[0]) / viewport[2] * 2.0 - 1.0, (winy - viewport[1]) / viewport[3] * 2.0 - 1.0, winz * 2.0 - 1.0, 1]).reshape((1,4))
400         vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
401         ret = list(vector)[0:3] / vector[3]
402         return ret
403
404 def convert3x3MatrixTo4x4(matrix):
405         return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
406
407 def loadGLTexture(filename):
408         tex = glGenTextures(1)
409         glBindTexture(GL_TEXTURE_2D, tex)
410         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
411         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
412         img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
413         rgbData = img.GetData()
414         alphaData = img.GetAlphaData()
415         if alphaData is not None:
416                 data = ''
417                 for i in xrange(0, len(alphaData)):
418                         data += rgbData[i*3:i*3+3] + alphaData[i]
419                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
420         else:
421                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
422         return tex
423
424 def ResetMatrixRotationAndScale():
425         matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
426         noZ = False
427         if matrix[3][2] > 0:
428                 return False
429         scale2D = matrix[0][0]
430         matrix[0][0] = 1.0
431         matrix[1][0] = 0.0
432         matrix[2][0] = 0.0
433         matrix[0][1] = 0.0
434         matrix[1][1] = 1.0
435         matrix[2][1] = 0.0
436         matrix[0][2] = 0.0
437         matrix[1][2] = 0.0
438         matrix[2][2] = 1.0
439
440         if matrix[3][2] != 0.0:
441                 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
442                 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
443                 matrix[3][2] = -100
444         else:
445                 matrix[0][0] = scale2D
446                 matrix[1][1] = scale2D
447                 matrix[2][2] = scale2D
448                 matrix[3][2] = -100
449                 noZ = True
450
451         glLoadMatrixf(matrix)
452         return noZ
453
454
455 def DrawBox(vMin, vMax):
456         glBegin(GL_LINE_LOOP)
457         glVertex3f(vMin[0], vMin[1], vMin[2])
458         glVertex3f(vMax[0], vMin[1], vMin[2])
459         glVertex3f(vMax[0], vMax[1], vMin[2])
460         glVertex3f(vMin[0], vMax[1], vMin[2])
461         glEnd()
462
463         glBegin(GL_LINE_LOOP)
464         glVertex3f(vMin[0], vMin[1], vMax[2])
465         glVertex3f(vMax[0], vMin[1], vMax[2])
466         glVertex3f(vMax[0], vMax[1], vMax[2])
467         glVertex3f(vMin[0], vMax[1], vMax[2])
468         glEnd()
469         glBegin(GL_LINES)
470         glVertex3f(vMin[0], vMin[1], vMin[2])
471         glVertex3f(vMin[0], vMin[1], vMax[2])
472         glVertex3f(vMax[0], vMin[1], vMin[2])
473         glVertex3f(vMax[0], vMin[1], vMax[2])
474         glVertex3f(vMax[0], vMax[1], vMin[2])
475         glVertex3f(vMax[0], vMax[1], vMax[2])
476         glVertex3f(vMin[0], vMax[1], vMin[2])
477         glVertex3f(vMin[0], vMax[1], vMax[2])
478         glEnd()
479
480
481 def DrawMeshOutline(mesh):
482         glEnable(GL_CULL_FACE)
483         glEnableClientState(GL_VERTEX_ARRAY);
484         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
485
486         glCullFace(GL_FRONT)
487         glLineWidth(3)
488         glPolygonMode(GL_BACK, GL_LINE)
489         glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
490         glPolygonMode(GL_BACK, GL_FILL)
491         glCullFace(GL_BACK)
492
493         glDisableClientState(GL_VERTEX_ARRAY)
494
495
496 def DrawMesh(mesh, insideOut = False):
497         glEnable(GL_CULL_FACE)
498         glEnableClientState(GL_VERTEX_ARRAY)
499         glEnableClientState(GL_NORMAL_ARRAY)
500         for m in mesh._meshList:
501                 glVertexPointer(3, GL_FLOAT, 0, m.vertexes)
502                 if insideOut:
503                         glNormalPointer(GL_FLOAT, 0, m.invNormal)
504                 else:
505                         glNormalPointer(GL_FLOAT, 0, m.normal)
506
507                 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
508                 batchSize = 999    #Warning, batchSize needs to be dividable by 3
509                 extraStartPos = int(m.vertexCount / batchSize) * batchSize
510                 extraCount = m.vertexCount - extraStartPos
511
512                 glCullFace(GL_BACK)
513                 for i in xrange(0, int(m.vertexCount / batchSize)):
514                         glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
515                 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
516
517                 glCullFace(GL_FRONT)
518                 if insideOut:
519                         glNormalPointer(GL_FLOAT, 0, m.normal)
520                 else:
521                         glNormalPointer(GL_FLOAT, 0, m.invNormal)
522                 for i in xrange(0, int(m.vertexCount / batchSize)):
523                         glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
524                 extraStartPos = int(m.vertexCount / batchSize) * batchSize
525                 extraCount = m.vertexCount - extraStartPos
526                 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
527                 glCullFace(GL_BACK)
528
529         glDisableClientState(GL_VERTEX_ARRAY)
530         glDisableClientState(GL_NORMAL_ARRAY)
531
532
533 def DrawMeshSteep(mesh, matrix, angle):
534         cosAngle = math.sin(angle / 180.0 * math.pi)
535         glDisable(GL_LIGHTING)
536         glDepthFunc(GL_EQUAL)
537         normals = (numpy.matrix(mesh.normal, copy = False) * matrix).getA()
538         for i in xrange(0, int(mesh.vertexCount), 3):
539                 if normals[i][2] < -0.999999:
540                         if mesh.vertexes[i + 0][2] > 0.01:
541                                 glColor3f(0.5, 0, 0)
542                                 glBegin(GL_TRIANGLES)
543                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
544                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
545                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
546                                 glEnd()
547                 elif normals[i][2] < -cosAngle:
548                         glColor3f(-normals[i][2], 0, 0)
549                         glBegin(GL_TRIANGLES)
550                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
551                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
552                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
553                         glEnd()
554                 elif normals[i][2] > 0.999999:
555                         if mesh.vertexes[i + 0][2] > 0.01:
556                                 glColor3f(0.5, 0, 0)
557                                 glBegin(GL_TRIANGLES)
558                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
559                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
560                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
561                                 glEnd()
562                 elif normals[i][2] > cosAngle:
563                         glColor3f(normals[i][2], 0, 0)
564                         glBegin(GL_TRIANGLES)
565                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
566                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
567                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
568                         glEnd()
569         glDepthFunc(GL_LESS)
570
571
572 def DrawGCodeLayer(layer, drawQuick = True):
573         filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
574         filamentArea = math.pi * filamentRadius * filamentRadius
575         lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
576
577         fillCycle = 0
578         fillColorCycle = [[0.5, 0.5, 0.0, 1], [0.0, 0.5, 0.5, 1], [0.5, 0.0, 0.5, 1]]
579         moveColor = [0, 0, 1, 0.5]
580         retractColor = [1, 0, 0.5, 0.5]
581         supportColor = [0, 1, 1, 1]
582         extrudeColor = [[1, 0, 0, 1], [0, 1, 1, 1], [1, 1, 0, 1], [1, 0, 1, 1]]
583         innerWallColor = [0, 1, 0, 1]
584         skirtColor = [0, 0.5, 0.5, 1]
585         prevPathWasRetract = False
586
587         glDisable(GL_CULL_FACE)
588         for path in layer:
589                 if path.type == 'move':
590                         if prevPathWasRetract:
591                                 c = retractColor
592                         else:
593                                 c = moveColor
594                         if drawQuick:
595                                 continue
596                 zOffset = 0.01
597                 if path.type == 'extrude':
598                         if path.pathType == 'FILL':
599                                 c = fillColorCycle[fillCycle]
600                                 fillCycle = (fillCycle + 1) % len(fillColorCycle)
601                                 if drawQuick:
602                                         continue
603                         elif path.pathType == 'WALL-INNER':
604                                 c = innerWallColor
605                                 zOffset = 0.02
606                         elif path.pathType == 'SUPPORT':
607                                 c = supportColor
608                         elif path.pathType == 'SKIRT':
609                                 c = skirtColor
610                         else:
611                                 c = extrudeColor[path.extruder]
612                 if path.type == 'retract':
613                         c = retractColor
614                 if path.type == 'extrude' and not drawQuick:
615                         drawLength = 0.0
616                         prevNormal = None
617                         for i in xrange(0, len(path.list) - 1):
618                                 v0 = path.list[i]
619                                 v1 = path.list[i + 1]
620
621                                 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
622                                 dist = (v0 - v1).vsize()
623                                 if dist > 0 and path.layerThickness > 0:
624                                         extrusionMMperDist = (v1.e - v0.e) / dist
625                                         lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
626
627                                 drawLength += (v0 - v1).vsize()
628                                 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
629                                 normal.normalize()
630
631                                 vv2 = v0 + normal * lineWidth
632                                 vv3 = v1 + normal * lineWidth
633                                 vv0 = v0 - normal * lineWidth
634                                 vv1 = v1 - normal * lineWidth
635
636                                 glBegin(GL_QUADS)
637                                 glColor4fv(c)
638                                 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
639                                 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
640                                 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
641                                 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
642                                 glEnd()
643                                 if prevNormal is not None:
644                                         n = (normal + prevNormal)
645                                         n.normalize()
646                                         vv4 = v0 + n * lineWidth
647                                         vv5 = v0 - n * lineWidth
648                                         glBegin(GL_QUADS)
649                                         glColor4fv(c)
650                                         glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
651                                         glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
652                                         glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
653                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
654
655                                         glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
656                                         glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
657                                         glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
658                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
659                                         glEnd()
660
661                                 prevNormal = normal
662                                 prevVv1 = vv1
663                                 prevVv3 = vv3
664                 else:
665                         glBegin(GL_LINE_STRIP)
666                         glColor4fv(c)
667                         for v in path.list:
668                                 glVertex3f(v.x, v.y, v.z)
669                         glEnd()
670                 if not path.type == 'move':
671                         prevPathWasRetract = False
672                 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
673                         prevPathWasRetract = True
674         glEnable(GL_CULL_FACE)