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