chiark / gitweb /
Split off some code from preview3d.py, which is becoming way to large.
[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
8 from Cura.util import meshLoader
9 from Cura.util import util3d
10 from Cura.util import profile
11 from Cura.util.resources import getPathForMesh, getPathForImage
12
13 import OpenGL
14
15 OpenGL.ERROR_CHECKING = False
16 from OpenGL.GLUT import *
17 from OpenGL.GLU import *
18 from OpenGL.GL import *
19 glutInit()
20
21 def InitGL(window, view3D, zoom):
22         # set viewing projection
23         glMatrixMode(GL_MODELVIEW)
24         glLoadIdentity()
25         size = window.GetSize()
26         glViewport(0, 0, size.GetWidth(), size.GetHeight())
27
28         glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
29         glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
30
31         glEnable(GL_RESCALE_NORMAL)
32         glEnable(GL_LIGHTING)
33         glEnable(GL_LIGHT0)
34         glEnable(GL_DEPTH_TEST)
35         glEnable(GL_CULL_FACE)
36         glDisable(GL_BLEND)
37
38         glClearColor(1.0, 1.0, 1.0, 1.0)
39         glClearStencil(0)
40         glClearDepth(1.0)
41
42         glMatrixMode(GL_PROJECTION)
43         glLoadIdentity()
44         aspect = float(size.GetWidth()) / float(size.GetHeight())
45         if view3D:
46                 gluPerspective(45.0, aspect, 1.0, 1000.0)
47         else:
48                 glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
49
50         glMatrixMode(GL_MODELVIEW)
51         glLoadIdentity()
52         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
53
54 platformMesh = None
55
56 def DrawMachine(machineSize):
57         if profile.getPreference('machine_type') == 'ultimaker':
58                 glPushMatrix()
59                 glEnable(GL_LIGHTING)
60                 glTranslate(100, 200, -5)
61                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
62                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
63                 glEnable(GL_BLEND)
64                 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
65
66                 global platformMesh
67                 if platformMesh is None:
68                         try:
69                                 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
70                         except:
71                                 platformMesh = False
72
73                 if platformMesh:
74                         DrawMesh(platformMesh)
75                 glPopMatrix()
76
77         glDisable(GL_LIGHTING)
78         if False:
79                 glColor3f(0.7, 0.7, 0.7)
80                 glLineWidth(2)
81                 glBegin(GL_LINES)
82                 for i in xrange(0, int(machineSize.x), 10):
83                         glVertex3f(i, 0, 0)
84                         glVertex3f(i, machineSize.y, 0)
85                 for i in xrange(0, int(machineSize.y), 10):
86                         glVertex3f(0, i, 0)
87                         glVertex3f(machineSize.x, i, 0)
88                 glEnd()
89
90                 glEnable(GL_LINE_SMOOTH)
91                 glEnable(GL_BLEND)
92                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
93                 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
94
95                 glColor3f(0.0, 0.0, 0.0)
96                 glLineWidth(4)
97                 glBegin(GL_LINE_LOOP)
98                 glVertex3f(0, 0, 0)
99                 glVertex3f(machineSize.x, 0, 0)
100                 glVertex3f(machineSize.x, machineSize.y, 0)
101                 glVertex3f(0, machineSize.y, 0)
102                 glEnd()
103
104                 glLineWidth(2)
105                 glBegin(GL_LINE_LOOP)
106                 glVertex3f(0, 0, machineSize.z)
107                 glVertex3f(machineSize.x, 0, machineSize.z)
108                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
109                 glVertex3f(0, machineSize.y, machineSize.z)
110                 glEnd()
111                 glBegin(GL_LINES)
112                 glVertex3f(0, 0, 0)
113                 glVertex3f(0, 0, machineSize.z)
114                 glVertex3f(machineSize.x, 0, 0)
115                 glVertex3f(machineSize.x, 0, machineSize.z)
116                 glVertex3f(machineSize.x, machineSize.y, 0)
117                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
118                 glVertex3f(0, machineSize.y, 0)
119                 glVertex3f(0, machineSize.y, machineSize.z)
120                 glEnd()
121         else:
122                 glDisable(GL_CULL_FACE)
123                 glEnable(GL_BLEND)
124                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
125
126                 sx = machineSize.x
127                 sy = machineSize.y
128                 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
129                         for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
130                                 x1 = sx/2+x * 10
131                                 x2 = x1 + 10
132                                 y1 = sx/2+y * 10
133                                 y2 = y1 + 10
134                                 x1 = max(min(x1, sx), 0)
135                                 y1 = max(min(y1, sy), 0)
136                                 x2 = max(min(x2, sx), 0)
137                                 y2 = max(min(y2, sy), 0)
138                                 if (x & 1) == (y & 1):
139                                         glColor4ub(5, 171, 231, 127)
140                                 else:
141                                         glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
142                                 glBegin(GL_QUADS)
143                                 glVertex3f(x1, y1, -0.01)
144                                 glVertex3f(x2, y1, -0.01)
145                                 glVertex3f(x2, y2, -0.01)
146                                 glVertex3f(x1, y2, -0.01)
147                                 glEnd()
148
149                 glEnable(GL_CULL_FACE)
150
151                 glColor4ub(5, 171, 231, 64)
152                 glBegin(GL_QUADS)
153                 glVertex3f(0, 0, machineSize.z)
154                 glVertex3f(0, machineSize.y, machineSize.z)
155                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
156                 glVertex3f(machineSize.x, 0, machineSize.z)
157                 glEnd()
158
159                 glColor4ub(5, 171, 231, 96)
160                 glBegin(GL_QUADS)
161                 glVertex3f(0, 0, 0)
162                 glVertex3f(0, 0, machineSize.z)
163                 glVertex3f(machineSize.x, 0, machineSize.z)
164                 glVertex3f(machineSize.x, 0, 0)
165
166                 glVertex3f(0, machineSize.y, machineSize.z)
167                 glVertex3f(0, machineSize.y, 0)
168                 glVertex3f(machineSize.x, machineSize.y, 0)
169                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
170                 glEnd()
171
172                 glColor4ub(5, 171, 231, 128)
173                 glBegin(GL_QUADS)
174                 glVertex3f(0, 0, machineSize.z)
175                 glVertex3f(0, 0, 0)
176                 glVertex3f(0, machineSize.y, 0)
177                 glVertex3f(0, machineSize.y, machineSize.z)
178
179                 glVertex3f(machineSize.x, 0, 0)
180                 glVertex3f(machineSize.x, 0, machineSize.z)
181                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
182                 glVertex3f(machineSize.x, machineSize.y, 0)
183                 glEnd()
184
185                 glDisable(GL_BLEND)
186
187         glPushMatrix()
188         glTranslate(5, 5, 2)
189         glLineWidth(2)
190         glColor3f(0.5, 0, 0)
191         glBegin(GL_LINES)
192         glVertex3f(0, 0, 0)
193         glVertex3f(20, 0, 0)
194         glEnd()
195         glColor3f(0, 0.5, 0)
196         glBegin(GL_LINES)
197         glVertex3f(0, 0, 0)
198         glVertex3f(0, 20, 0)
199         glEnd()
200         glColor3f(0, 0, 0.5)
201         glBegin(GL_LINES)
202         glVertex3f(0, 0, 0)
203         glVertex3f(0, 0, 20)
204         glEnd()
205
206         glDisable(GL_DEPTH_TEST)
207         #X
208         glColor3f(1, 0, 0)
209         glPushMatrix()
210         glTranslate(20, 0, 0)
211         noZ = ResetMatrixRotationAndScale()
212         glDrawStringCenter("X")
213         glPopMatrix()
214
215         #Y
216         glColor3f(0, 1, 0)
217         glPushMatrix()
218         glTranslate(0, 20, 0)
219         glDrawStringCenter("Y")
220         glPopMatrix()
221
222         #Z
223         if not noZ:
224                 glColor3f(0, 0, 1)
225                 glPushMatrix()
226                 glTranslate(0, 0, 20)
227                 glDrawStringCenter("Z")
228                 glPopMatrix()
229
230         glPopMatrix()
231         glEnable(GL_DEPTH_TEST)
232
233 def glDrawStringCenter(s):
234         glRasterPos2f(0, 0)
235         width = 0
236         for c in s:
237                 width += glutBitmapWidth(GLUT_BITMAP_HELVETICA_18, ord(c))
238         glBitmap(0,0,0,0, -width/2, 0, None)
239         for c in s:
240                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, ord(c))
241
242 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
243         npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
244         npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
245         finalMatrix = npModelMatrix * npProjMatrix
246         finalMatrix = numpy.linalg.inv(finalMatrix)
247
248         viewport = map(float, viewport)
249         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))
250         vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
251         ret = list(vector)[0:3] / vector[3]
252         return ret
253
254 def convert3x3MatrixTo4x4(matrix):
255         return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
256
257 def loadGLTexture(filename):
258         tex = glGenTextures(1)
259         glBindTexture(GL_TEXTURE_2D, tex)
260         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
261         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
262         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
263         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
264         img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
265         rgbData = img.GetData()
266         alphaData = img.GetAlphaData()
267         if alphaData != None:
268                 data = ''
269                 for i in xrange(0, len(alphaData)):
270                         data += rgbData[i*3:i*3+3] + alphaData[i]
271                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
272         else:
273                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
274         return tex
275
276 def ResetMatrixRotationAndScale():
277         matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
278         noZ = False
279         if matrix[3][2] > 0:
280                 return False
281         scale2D = matrix[0][0]
282         matrix[0][0] = 1.0
283         matrix[1][0] = 0.0
284         matrix[2][0] = 0.0
285         matrix[0][1] = 0.0
286         matrix[1][1] = 1.0
287         matrix[2][1] = 0.0
288         matrix[0][2] = 0.0
289         matrix[1][2] = 0.0
290         matrix[2][2] = 1.0
291
292         if matrix[3][2] != 0.0:
293                 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
294                 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
295                 matrix[3][2] = -100
296         else:
297                 matrix[0][0] = scale2D
298                 matrix[1][1] = scale2D
299                 matrix[2][2] = scale2D
300                 matrix[3][2] = -100
301                 noZ = True
302
303         glLoadMatrixf(matrix)
304         return noZ
305
306
307 def DrawBox(vMin, vMax):
308         glBegin(GL_LINE_LOOP)
309         glVertex3f(vMin[0], vMin[1], vMin[2])
310         glVertex3f(vMax[0], vMin[1], vMin[2])
311         glVertex3f(vMax[0], vMax[1], vMin[2])
312         glVertex3f(vMin[0], vMax[1], vMin[2])
313         glEnd()
314
315         glBegin(GL_LINE_LOOP)
316         glVertex3f(vMin[0], vMin[1], vMax[2])
317         glVertex3f(vMax[0], vMin[1], vMax[2])
318         glVertex3f(vMax[0], vMax[1], vMax[2])
319         glVertex3f(vMin[0], vMax[1], vMax[2])
320         glEnd()
321         glBegin(GL_LINES)
322         glVertex3f(vMin[0], vMin[1], vMin[2])
323         glVertex3f(vMin[0], vMin[1], vMax[2])
324         glVertex3f(vMax[0], vMin[1], vMin[2])
325         glVertex3f(vMax[0], vMin[1], vMax[2])
326         glVertex3f(vMax[0], vMax[1], vMin[2])
327         glVertex3f(vMax[0], vMax[1], vMax[2])
328         glVertex3f(vMin[0], vMax[1], vMin[2])
329         glVertex3f(vMin[0], vMax[1], vMax[2])
330         glEnd()
331
332
333 def DrawMeshOutline(mesh):
334         glEnable(GL_CULL_FACE)
335         glEnableClientState(GL_VERTEX_ARRAY);
336         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
337
338         glCullFace(GL_FRONT)
339         glLineWidth(3)
340         glPolygonMode(GL_BACK, GL_LINE)
341         glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
342         glPolygonMode(GL_BACK, GL_FILL)
343         glCullFace(GL_BACK)
344
345         glDisableClientState(GL_VERTEX_ARRAY)
346
347
348 def DrawMesh(mesh):
349         glEnable(GL_CULL_FACE)
350         glEnableClientState(GL_VERTEX_ARRAY);
351         glEnableClientState(GL_NORMAL_ARRAY);
352         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
353         glNormalPointer(GL_FLOAT, 0, mesh.normal)
354
355         #Odd, drawing in batchs is a LOT faster then drawing it all at once.
356         batchSize = 999    #Warning, batchSize needs to be dividable by 3
357         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
358         extraCount = mesh.vertexCount - extraStartPos
359
360         glCullFace(GL_BACK)
361         for i in xrange(0, int(mesh.vertexCount / batchSize)):
362                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
363         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
364
365         glCullFace(GL_FRONT)
366         glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
367         for i in xrange(0, int(mesh.vertexCount / batchSize)):
368                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
369         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
370         extraCount = mesh.vertexCount - extraStartPos
371         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
372         glCullFace(GL_BACK)
373
374         glDisableClientState(GL_VERTEX_ARRAY)
375         glDisableClientState(GL_NORMAL_ARRAY);
376
377
378 def DrawMeshSteep(mesh, angle):
379         cosAngle = math.sin(angle / 180.0 * math.pi)
380         glDisable(GL_LIGHTING)
381         glDepthFunc(GL_EQUAL)
382         for i in xrange(0, int(mesh.vertexCount), 3):
383                 if mesh.normal[i][2] < -0.999999:
384                         if mesh.vertexes[i + 0][2] > 0.01:
385                                 glColor3f(0.5, 0, 0)
386                                 glBegin(GL_TRIANGLES)
387                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
388                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
389                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
390                                 glEnd()
391                 elif mesh.normal[i][2] < -cosAngle:
392                         glColor3f(-mesh.normal[i][2], 0, 0)
393                         glBegin(GL_TRIANGLES)
394                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
395                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
396                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
397                         glEnd()
398                 elif mesh.normal[i][2] > 0.999999:
399                         if mesh.vertexes[i + 0][2] > 0.01:
400                                 glColor3f(0.5, 0, 0)
401                                 glBegin(GL_TRIANGLES)
402                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
403                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
404                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
405                                 glEnd()
406                 elif mesh.normal[i][2] > cosAngle:
407                         glColor3f(mesh.normal[i][2], 0, 0)
408                         glBegin(GL_TRIANGLES)
409                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
410                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
411                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
412                         glEnd()
413         glDepthFunc(GL_LESS)
414
415
416 def DrawGCodeLayer(layer):
417         filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
418         filamentArea = math.pi * filamentRadius * filamentRadius
419         lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
420
421         fillCycle = 0
422         fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
423         moveColor = [0, 0, 1]
424         retractColor = [1, 0, 0.5]
425         supportColor = [0, 1, 1]
426         extrudeColor = [1, 0, 0]
427         innerWallColor = [0, 1, 0]
428         skirtColor = [0, 0.5, 0.5]
429         prevPathWasRetract = False
430
431         glDisable(GL_CULL_FACE)
432         for path in layer:
433                 if path.type == 'move':
434                         if prevPathWasRetract:
435                                 c = retractColor
436                         else:
437                                 c = moveColor
438                 zOffset = 0.01
439                 if path.type == 'extrude':
440                         if path.pathType == 'FILL':
441                                 c = fillColorCycle[fillCycle]
442                                 fillCycle = (fillCycle + 1) % len(fillColorCycle)
443                         elif path.pathType == 'WALL-INNER':
444                                 c = innerWallColor
445                                 zOffset = 0.02
446                         elif path.pathType == 'SUPPORT':
447                                 c = supportColor
448                         elif path.pathType == 'SKIRT':
449                                 c = skirtColor
450                         else:
451                                 c = extrudeColor
452                 if path.type == 'retract':
453                         c = [0, 1, 1]
454                 if path.type == 'extrude':
455                         drawLength = 0.0
456                         prevNormal = None
457                         for i in xrange(0, len(path.list) - 1):
458                                 v0 = path.list[i]
459                                 v1 = path.list[i + 1]
460
461                                 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
462                                 dist = (v0 - v1).vsize()
463                                 if dist > 0 and path.layerThickness > 0:
464                                         extrusionMMperDist = (v1.e - v0.e) / dist
465                                         lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
466
467                                 drawLength += (v0 - v1).vsize()
468                                 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
469                                 normal.normalize()
470
471                                 vv2 = v0 + normal * lineWidth
472                                 vv3 = v1 + normal * lineWidth
473                                 vv0 = v0 - normal * lineWidth
474                                 vv1 = v1 - normal * lineWidth
475
476                                 glBegin(GL_QUADS)
477                                 glColor3fv(c)
478                                 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
479                                 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
480                                 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
481                                 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
482                                 glEnd()
483                                 if prevNormal is not None:
484                                         n = (normal + prevNormal)
485                                         n.normalize()
486                                         vv4 = v0 + n * lineWidth
487                                         vv5 = v0 - n * lineWidth
488                                         glBegin(GL_QUADS)
489                                         glColor3fv(c)
490                                         glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
491                                         glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
492                                         glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
493                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
494
495                                         glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
496                                         glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
497                                         glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
498                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
499                                         glEnd()
500
501                                 prevNormal = normal
502                                 prevVv1 = vv1
503                                 prevVv3 = vv3
504                 else:
505                         glBegin(GL_LINE_STRIP)
506                         glColor3fv(c)
507                         for v in path.list:
508                                 glVertex3f(v.x, v.y, v.z)
509                         glEnd()
510                 if not path.type == 'move':
511                         prevPathWasRetract = False
512                 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
513                         prevPathWasRetract = True
514         glEnable(GL_CULL_FACE)