1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
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
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
25 class GLReferenceCounter(object):
34 return self._refCounter <= 0
36 def hasShaderSupport():
37 if bool(glCreateShader):
41 class GLShader(GLReferenceCounter):
42 def __init__(self, vertexProgram, fragmentProgram):
43 super(GLShader, self).__init__()
44 self._vertexString = vertexProgram
45 self._fragmentString = fragmentProgram
47 vertexShader = shaders.compileShader(vertexProgram, GL_VERTEX_SHADER)
48 fragmentShader = shaders.compileShader(fragmentProgram, GL_FRAGMENT_SHADER)
50 #shader.compileProgram tries to return the shader program as a overloaded int. But the return value of a shader does not always fit in a int (needs to be a long). So we do raw OpenGL calls.
51 # self._program = shaders.compileProgram(self._vertexProgram, self._fragmentProgram)
52 self._program = glCreateProgram()
53 glAttachShader(self._program, vertexShader)
54 glAttachShader(self._program, fragmentShader)
55 glLinkProgram(self._program)
56 # Validation has to occur *after* linking
57 glValidateProgram(self._program)
58 if glGetProgramiv(self._program, GL_VALIDATE_STATUS) == GL_FALSE:
59 raise RuntimeError("Validation failure: %s"%(glGetProgramInfoLog(self._program)))
60 if glGetProgramiv(self._program, GL_LINK_STATUS) == GL_FALSE:
61 raise RuntimeError("Link failure: %s" % (glGetProgramInfoLog(self._program)))
62 glDeleteShader(vertexShader)
63 glDeleteShader(fragmentShader)
64 except RuntimeError, e:
69 if self._program is not None:
70 shaders.glUseProgram(self._program)
73 shaders.glUseProgram(0)
76 if self._program is not None:
77 glDeleteProgram(self._program)
80 def setUniform(self, name, value):
81 if self._program is not None:
82 if type(value) is float:
83 glUniform1f(glGetUniformLocation(self._program, name), value)
84 elif type(value) is numpy.matrix:
85 glUniformMatrix3fv(glGetUniformLocation(self._program, name), 1, False, value.getA().astype(numpy.float32))
87 print 'Unknown type for setUniform: %s' % (str(type(value)))
90 return self._program is not None
92 def getVertexShader(self):
93 return self._vertexString
95 def getFragmentShader(self):
96 return self._fragmentString
99 if self._program is not None and bool(glDeleteProgram):
100 print "Shader was not properly released!"
102 #A Class that acts as an OpenGL shader, but in reality is not none.
103 class GLFakeShader(GLReferenceCounter):
105 super(GLFakeShader, self).__init__()
108 glEnable(GL_LIGHTING)
110 glEnable(GL_COLOR_MATERIAL)
111 glLightfv(GL_LIGHT0, GL_DIFFUSE, [1,1,1,1])
112 glLightfv(GL_LIGHT0, GL_AMBIENT, [0,0,0,0])
113 glLightfv(GL_LIGHT0, GL_SPECULAR, [0,0,0,0])
116 glDisable(GL_LIGHTING)
121 def setUniform(self, name, value):
127 def getVertexShader(self):
130 def getFragmentShader(self):
133 class GLVBO(GLReferenceCounter):
134 def __init__(self, vertexArray, normalArray = None):
135 super(GLVBO, self).__init__()
136 if not bool(glGenBuffers):
137 self._vertexArray = vertexArray
138 self._normalArray = normalArray
141 self._buffer = glGenBuffers(1)
142 self._size = len(vertexArray)
143 self._hasNormals = normalArray is not None
144 glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
146 glBufferData(GL_ARRAY_BUFFER, numpy.concatenate((vertexArray, normalArray), 1), GL_STATIC_DRAW)
148 glBufferData(GL_ARRAY_BUFFER, vertexArray, GL_STATIC_DRAW)
149 glBindBuffer(GL_ARRAY_BUFFER, 0)
151 def render(self, render_type = GL_TRIANGLES):
152 if self._buffer is None:
153 glEnableClientState(GL_VERTEX_ARRAY)
154 glVertexPointer(3, GL_FLOAT, 0, self._vertexArray)
155 if self._normalArray is not None:
156 glEnableClientState(GL_NORMAL_ARRAY)
157 glNormalPointer(GL_FLOAT, 0, self._normalArray)
158 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
159 batchSize = 999 #Warning, batchSize needs to be dividable by 3
160 extraStartPos = int(len(self._vertexArray) / batchSize) * batchSize
161 extraCount = len(self._vertexArray) - extraStartPos
164 for i in xrange(0, int(len(self._vertexArray) / batchSize)):
165 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
166 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
168 glEnableClientState(GL_VERTEX_ARRAY)
169 glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
172 glEnableClientState(GL_NORMAL_ARRAY)
173 glVertexPointer(3, GL_FLOAT, 2*3*4, c_void_p(0))
174 glNormalPointer(GL_FLOAT, 2*3*4, c_void_p(3 * 4))
176 glVertexPointer(3, GL_FLOAT, 3*4, c_void_p(0))
178 batchSize = 996 #Warning, batchSize needs to be dividable by 4, 3 and 2
179 extraStartPos = int(self._size / batchSize) * batchSize
180 extraCount = self._size - extraStartPos
182 for i in xrange(0, int(self._size / batchSize)):
183 glDrawArrays(render_type, i * batchSize, batchSize)
184 glDrawArrays(render_type, extraStartPos, extraCount)
185 glBindBuffer(GL_ARRAY_BUFFER, 0)
187 glDisableClientState(GL_VERTEX_ARRAY)
189 glDisableClientState(GL_NORMAL_ARRAY)
192 if self._buffer is not None:
193 glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
194 glBufferData(GL_ARRAY_BUFFER, None, GL_STATIC_DRAW)
195 glBindBuffer(GL_ARRAY_BUFFER, 0)
196 glDeleteBuffers(1, [self._buffer])
198 self._vertexArray = None
199 self._normalArray = None
202 if self._buffer is not None and bool(glDeleteBuffers):
203 print "VBO was not properly released!"
205 def DrawMachine(machineSize):
206 glDisable(GL_LIGHTING)
207 glDisable(GL_CULL_FACE)
209 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
213 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
214 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
219 x1 = max(min(x1, sx), 0)
220 y1 = max(min(y1, sy), 0)
221 x2 = max(min(x2, sx), 0)
222 y2 = max(min(y2, sy), 0)
223 if (x & 1) == (y & 1):
224 glColor4ub(5, 171, 231, 127)
226 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
228 glVertex3f(x1, y1, -0.02)
229 glVertex3f(x2, y1, -0.02)
230 glVertex3f(x2, y2, -0.02)
231 glVertex3f(x1, y2, -0.02)
234 glEnable(GL_CULL_FACE)
236 if profile.getPreference('machine_type') == 'ultimaker':
238 glEnable(GL_LIGHTING)
239 glTranslate(100, 200, -1)
240 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
241 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
243 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
246 if platformMesh is None:
248 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
253 DrawMesh(platformMesh)
255 glDisable(GL_LIGHTING)
256 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
258 glColor4ub(5, 171, 231, 64)
260 glVertex3f(0, 0, machineSize.z)
261 glVertex3f(0, machineSize.y, machineSize.z)
262 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
263 glVertex3f(machineSize.x, 0, machineSize.z)
266 glColor4ub(5, 171, 231, 96)
269 glVertex3f(0, 0, machineSize.z)
270 glVertex3f(machineSize.x, 0, machineSize.z)
271 glVertex3f(machineSize.x, 0, 0)
273 glVertex3f(0, machineSize.y, machineSize.z)
274 glVertex3f(0, machineSize.y, 0)
275 glVertex3f(machineSize.x, machineSize.y, 0)
276 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
279 glColor4ub(5, 171, 231, 128)
281 glVertex3f(0, 0, machineSize.z)
283 glVertex3f(0, machineSize.y, 0)
284 glVertex3f(0, machineSize.y, machineSize.z)
286 glVertex3f(machineSize.x, 0, 0)
287 glVertex3f(machineSize.x, 0, machineSize.z)
288 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
289 glVertex3f(machineSize.x, machineSize.y, 0)
294 #Draw the X/Y/Z indicator
314 glDisable(GL_DEPTH_TEST)
318 glTranslate(20, 0, 0)
319 noZ = ResetMatrixRotationAndScale()
320 glDrawStringCenter("X")
326 glTranslate(0, 20, 0)
327 glDrawStringCenter("Y")
334 glTranslate(0, 0, 20)
335 glDrawStringCenter("Z")
339 glEnable(GL_DEPTH_TEST)
341 def glDrawStringCenter(s):
343 glBitmap(0,0,0,0, -glGetStringSize(s)[0]/2, 0, None)
345 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
347 def glGetStringSize(s):
350 width += glutBitmapWidth(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
354 def glDrawStringLeft(s):
360 glTranslate(0, 18 * n, 0)
365 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
367 def glDrawStringRight(s):
369 glBitmap(0,0,0,0, -glGetStringSize(s)[0], 0, None)
371 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
373 def glDrawQuad(x, y, w, h):
375 glTranslatef(x, y, 0)
376 glDisable(GL_TEXTURE_2D)
385 def glDrawTexturedQuad(x, y, w, h, texID, mirror = 0):
386 tx = float(texID % 4) / 4
387 ty = float(int(texID / 4)) / 8
397 glTranslatef(x, y, 0)
398 glEnable(GL_TEXTURE_2D)
400 glTexCoord2f(tx+tsx, ty)
404 glTexCoord2f(tx, ty+tsy)
406 glTexCoord2f(tx+tsx, ty+tsy)
411 def glDrawStretchedQuad(x, y, w, h, cornerSize, texID):
412 tx0 = float(texID % 4) / 4
413 ty0 = float(int(texID / 4)) / 8
414 tx1 = tx0 + 0.25 / 2.0
415 ty1 = ty0 + 0.125 / 2.0
420 glTranslatef(x, y, 0)
421 glEnable(GL_TEXTURE_2D)
424 glTexCoord2f(tx1, ty0)
425 glVertex2f( cornerSize, 0)
426 glTexCoord2f(tx0, ty0)
428 glTexCoord2f(tx0, ty1)
429 glVertex2f( 0, cornerSize)
430 glTexCoord2f(tx1, ty1)
431 glVertex2f( cornerSize, cornerSize)
433 glTexCoord2f(tx2, ty0)
435 glTexCoord2f(tx1, ty0)
436 glVertex2f( w - cornerSize, 0)
437 glTexCoord2f(tx1, ty1)
438 glVertex2f( w - cornerSize, cornerSize)
439 glTexCoord2f(tx2, ty1)
440 glVertex2f( w, cornerSize)
442 glTexCoord2f(tx1, ty1)
443 glVertex2f( cornerSize, h - cornerSize)
444 glTexCoord2f(tx0, ty1)
445 glVertex2f( 0, h - cornerSize)
446 glTexCoord2f(tx0, ty2)
448 glTexCoord2f(tx1, ty2)
449 glVertex2f( cornerSize, h)
451 glTexCoord2f(tx2, ty1)
452 glVertex2f( w, h - cornerSize)
453 glTexCoord2f(tx1, ty1)
454 glVertex2f( w - cornerSize, h - cornerSize)
455 glTexCoord2f(tx1, ty2)
456 glVertex2f( w - cornerSize, h)
457 glTexCoord2f(tx2, ty2)
461 glTexCoord2f(tx1, ty1)
462 glVertex2f( w-cornerSize, cornerSize)
463 glTexCoord2f(tx1, ty1)
464 glVertex2f( cornerSize, cornerSize)
465 glTexCoord2f(tx1, ty1)
466 glVertex2f( cornerSize, h-cornerSize)
467 glTexCoord2f(tx1, ty1)
468 glVertex2f( w-cornerSize, h-cornerSize)
471 glTexCoord2f(tx2, ty1)
472 glVertex2f( w, cornerSize)
473 glTexCoord2f(tx1, ty1)
474 glVertex2f( w-cornerSize, cornerSize)
475 glTexCoord2f(tx1, ty1)
476 glVertex2f( w-cornerSize, h-cornerSize)
477 glTexCoord2f(tx2, ty1)
478 glVertex2f( w, h-cornerSize)
481 glTexCoord2f(tx1, ty1)
482 glVertex2f( cornerSize, cornerSize)
483 glTexCoord2f(tx0, ty1)
484 glVertex2f( 0, cornerSize)
485 glTexCoord2f(tx0, ty1)
486 glVertex2f( 0, h-cornerSize)
487 glTexCoord2f(tx1, ty1)
488 glVertex2f( cornerSize, h-cornerSize)
491 glTexCoord2f(tx1, ty0)
492 glVertex2f( w-cornerSize, 0)
493 glTexCoord2f(tx1, ty0)
494 glVertex2f( cornerSize, 0)
495 glTexCoord2f(tx1, ty1)
496 glVertex2f( cornerSize, cornerSize)
497 glTexCoord2f(tx1, ty1)
498 glVertex2f( w-cornerSize, cornerSize)
501 glTexCoord2f(tx1, ty1)
502 glVertex2f( w-cornerSize, h-cornerSize)
503 glTexCoord2f(tx1, ty1)
504 glVertex2f( cornerSize, h-cornerSize)
505 glTexCoord2f(tx1, ty2)
506 glVertex2f( cornerSize, h)
507 glTexCoord2f(tx1, ty2)
508 glVertex2f( w-cornerSize, h)
511 glDisable(GL_TEXTURE_2D)
514 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
515 npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
516 npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
517 finalMatrix = npModelMatrix * npProjMatrix
518 finalMatrix = numpy.linalg.inv(finalMatrix)
520 viewport = map(float, viewport)
521 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))
522 vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
523 ret = list(vector)[0:3] / vector[3]
526 def convert3x3MatrixTo4x4(matrix):
527 return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
529 def loadGLTexture(filename):
530 tex = glGenTextures(1)
531 glBindTexture(GL_TEXTURE_2D, tex)
532 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
534 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
535 rgbData = img.GetData()
536 alphaData = img.GetAlphaData()
537 if alphaData is not None:
539 for i in xrange(0, len(alphaData)):
540 data += rgbData[i*3:i*3+3] + alphaData[i]
541 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
543 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
546 def ResetMatrixRotationAndScale():
547 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
551 scale2D = matrix[0][0]
562 if matrix[3][2] != 0.0:
563 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
564 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
567 matrix[0][0] = scale2D
568 matrix[1][1] = scale2D
569 matrix[2][2] = scale2D
573 glLoadMatrixf(matrix)
577 def DrawBox(vMin, vMax):
578 glBegin(GL_LINE_LOOP)
579 glVertex3f(vMin[0], vMin[1], vMin[2])
580 glVertex3f(vMax[0], vMin[1], vMin[2])
581 glVertex3f(vMax[0], vMax[1], vMin[2])
582 glVertex3f(vMin[0], vMax[1], vMin[2])
585 glBegin(GL_LINE_LOOP)
586 glVertex3f(vMin[0], vMin[1], vMax[2])
587 glVertex3f(vMax[0], vMin[1], vMax[2])
588 glVertex3f(vMax[0], vMax[1], vMax[2])
589 glVertex3f(vMin[0], vMax[1], vMax[2])
592 glVertex3f(vMin[0], vMin[1], vMin[2])
593 glVertex3f(vMin[0], vMin[1], vMax[2])
594 glVertex3f(vMax[0], vMin[1], vMin[2])
595 glVertex3f(vMax[0], vMin[1], vMax[2])
596 glVertex3f(vMax[0], vMax[1], vMin[2])
597 glVertex3f(vMax[0], vMax[1], vMax[2])
598 glVertex3f(vMin[0], vMax[1], vMin[2])
599 glVertex3f(vMin[0], vMax[1], vMax[2])
603 def DrawMeshOutline(mesh):
604 glEnable(GL_CULL_FACE)
605 glEnableClientState(GL_VERTEX_ARRAY);
606 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
610 glPolygonMode(GL_BACK, GL_LINE)
611 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
612 glPolygonMode(GL_BACK, GL_FILL)
615 glDisableClientState(GL_VERTEX_ARRAY)
618 def DrawMesh(mesh, insideOut = False):
619 glEnable(GL_CULL_FACE)
620 glEnableClientState(GL_VERTEX_ARRAY)
621 glEnableClientState(GL_NORMAL_ARRAY)
622 for m in mesh._meshList:
623 glVertexPointer(3, GL_FLOAT, 0, m.vertexes)
625 glNormalPointer(GL_FLOAT, 0, m.invNormal)
627 glNormalPointer(GL_FLOAT, 0, m.normal)
629 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
630 batchSize = 999 #Warning, batchSize needs to be dividable by 3
631 extraStartPos = int(m.vertexCount / batchSize) * batchSize
632 extraCount = m.vertexCount - extraStartPos
635 for i in xrange(0, int(m.vertexCount / batchSize)):
636 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
637 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
641 glNormalPointer(GL_FLOAT, 0, m.normal)
643 glNormalPointer(GL_FLOAT, 0, m.invNormal)
644 for i in xrange(0, int(m.vertexCount / batchSize)):
645 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
646 extraStartPos = int(m.vertexCount / batchSize) * batchSize
647 extraCount = m.vertexCount - extraStartPos
648 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
651 glDisableClientState(GL_VERTEX_ARRAY)
652 glDisableClientState(GL_NORMAL_ARRAY)
655 def DrawMeshSteep(mesh, matrix, angle):
656 cosAngle = math.sin(angle / 180.0 * math.pi)
657 glDisable(GL_LIGHTING)
658 glDepthFunc(GL_EQUAL)
659 normals = (numpy.matrix(mesh.normal, copy = False) * matrix).getA()
660 for i in xrange(0, int(mesh.vertexCount), 3):
661 if normals[i][2] < -0.999999:
662 if mesh.vertexes[i + 0][2] > 0.01:
664 glBegin(GL_TRIANGLES)
665 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
666 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
667 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
669 elif normals[i][2] < -cosAngle:
670 glColor3f(-normals[i][2], 0, 0)
671 glBegin(GL_TRIANGLES)
672 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
673 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
674 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
676 elif normals[i][2] > 0.999999:
677 if mesh.vertexes[i + 0][2] > 0.01:
679 glBegin(GL_TRIANGLES)
680 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
681 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
682 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
684 elif normals[i][2] > cosAngle:
685 glColor3f(normals[i][2], 0, 0)
686 glBegin(GL_TRIANGLES)
687 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
688 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
689 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
693 def DrawGCodeLayer(layer, drawQuick = True):
694 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
695 filamentArea = math.pi * filamentRadius * filamentRadius
696 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
699 fillColorCycle = [[0.5, 0.5, 0.0, 1], [0.0, 0.5, 0.5, 1], [0.5, 0.0, 0.5, 1]]
700 moveColor = [0, 0, 1, 0.5]
701 retractColor = [1, 0, 0.5, 0.5]
702 supportColor = [0, 1, 1, 1]
703 extrudeColor = [[1, 0, 0, 1], [0, 1, 1, 1], [1, 1, 0, 1], [1, 0, 1, 1]]
704 innerWallColor = [0, 1, 0, 1]
705 skirtColor = [0, 0.5, 0.5, 1]
706 prevPathWasRetract = False
708 glDisable(GL_CULL_FACE)
710 if path.type == 'move':
711 if prevPathWasRetract:
718 if path.type == 'extrude':
719 if path.pathType == 'FILL':
720 c = fillColorCycle[fillCycle]
721 fillCycle = (fillCycle + 1) % len(fillColorCycle)
722 elif path.pathType == 'WALL-INNER':
725 elif path.pathType == 'SUPPORT':
727 elif path.pathType == 'SKIRT':
730 c = extrudeColor[path.extruder]
731 if path.type == 'retract':
733 if path.type == 'extrude' and not drawQuick:
736 for i in xrange(0, len(path.points) - 1):
738 v1 = path.points[i + 1]
740 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
741 dist = (v0 - v1).vsize()
742 if dist > 0 and path.layerThickness > 0:
743 extrusionMMperDist = (v1.e - v0.e) / dist
744 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
746 drawLength += (v0 - v1).vsize()
747 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
750 vv2 = v0 + normal * lineWidth
751 vv3 = v1 + normal * lineWidth
752 vv0 = v0 - normal * lineWidth
753 vv1 = v1 - normal * lineWidth
757 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
758 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
759 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
760 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
762 if prevNormal is not None:
763 n = (normal + prevNormal)
765 vv4 = v0 + n * lineWidth
766 vv5 = v0 - n * lineWidth
769 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
770 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
771 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
772 glVertex3f(v0.x, v0.y, v0.z - zOffset)
774 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
775 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
776 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
777 glVertex3f(v0.x, v0.y, v0.z - zOffset)
785 glBegin(GL_TRIANGLES)
786 for v in path.points:
787 glVertex3f(v[0], v[1], v[2])
790 if not path.type == 'move':
791 prevPathWasRetract = False
792 #if path.type == 'retract' and path.points[0].almostEqual(path.points[-1]):
793 # prevPathWasRetract = True
794 glEnable(GL_CULL_FACE)