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