2 from __future__ import absolute_import
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 *
22 def InitGL(window, view3D, zoom):
23 # set viewing projection
24 glMatrixMode(GL_MODELVIEW)
26 size = window.GetSize()
27 glViewport(0, 0, size.GetWidth(), size.GetHeight())
29 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
30 glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
32 glEnable(GL_RESCALE_NORMAL)
35 glEnable(GL_DEPTH_TEST)
36 glEnable(GL_CULL_FACE)
39 glClearColor(1.0, 1.0, 1.0, 1.0)
40 glClearColor(0.8, 0.8, 0.8, 1.0)
44 glMatrixMode(GL_PROJECTION)
46 aspect = float(size.GetWidth()) / float(size.GetHeight())
48 gluPerspective(45.0, aspect, 1.0, 1000.0)
50 glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
52 glMatrixMode(GL_MODELVIEW)
54 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
58 def DrawMachine(machineSize):
59 glDisable(GL_LIGHTING)
60 glDisable(GL_CULL_FACE)
62 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
66 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
67 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
72 x1 = max(min(x1, sx), 0)
73 y1 = max(min(y1, sy), 0)
74 x2 = max(min(x2, sx), 0)
75 y2 = max(min(y2, sy), 0)
76 if (x & 1) == (y & 1):
77 glColor4ub(5, 171, 231, 127)
79 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
81 glVertex3f(x1, y1, -0.02)
82 glVertex3f(x2, y1, -0.02)
83 glVertex3f(x2, y2, -0.02)
84 glVertex3f(x1, y2, -0.02)
87 glEnable(GL_CULL_FACE)
89 if profile.getPreference('machine_type') == 'ultimaker':
92 glTranslate(100, 200, -1)
93 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
94 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
96 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
99 if platformMesh is None:
101 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
106 DrawMesh(platformMesh)
108 glDisable(GL_LIGHTING)
109 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
111 glColor4ub(5, 171, 231, 64)
113 glVertex3f(0, 0, machineSize.z)
114 glVertex3f(0, machineSize.y, machineSize.z)
115 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
116 glVertex3f(machineSize.x, 0, machineSize.z)
119 glColor4ub(5, 171, 231, 96)
122 glVertex3f(0, 0, machineSize.z)
123 glVertex3f(machineSize.x, 0, machineSize.z)
124 glVertex3f(machineSize.x, 0, 0)
126 glVertex3f(0, machineSize.y, machineSize.z)
127 glVertex3f(0, machineSize.y, 0)
128 glVertex3f(machineSize.x, machineSize.y, 0)
129 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
132 glColor4ub(5, 171, 231, 128)
134 glVertex3f(0, 0, machineSize.z)
136 glVertex3f(0, machineSize.y, 0)
137 glVertex3f(0, machineSize.y, machineSize.z)
139 glVertex3f(machineSize.x, 0, 0)
140 glVertex3f(machineSize.x, 0, machineSize.z)
141 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
142 glVertex3f(machineSize.x, machineSize.y, 0)
147 #Draw the X/Y/Z indicator
167 glDisable(GL_DEPTH_TEST)
171 glTranslate(20, 0, 0)
172 noZ = ResetMatrixRotationAndScale()
173 glDrawStringCenter("X")
179 glTranslate(0, 20, 0)
180 glDrawStringCenter("Y")
187 glTranslate(0, 0, 20)
188 glDrawStringCenter("Z")
192 glEnable(GL_DEPTH_TEST)
194 def glDrawStringCenter(s):
196 glBitmap(0,0,0,0, -glGetStringSize(s)[0]/2, 0, None)
198 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
200 def glGetStringSize(s):
203 width += glutBitmapWidth(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
207 def glDrawStringLeft(s):
210 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
212 def glDrawStringRight(s):
214 glBitmap(0,0,0,0, -glGetStringSize(s)[0], 0, None)
216 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
218 def glDrawTexturedQuad(x, y, w, h, texID, mirror = 0):
219 tx = float(texID % 4) / 4
220 ty = float(int(texID / 4)) / 8
230 glTranslatef(x, y, 0)
231 glEnable(GL_TEXTURE_2D)
233 glTexCoord2f(tx+tsx, ty)
237 glTexCoord2f(tx, ty+tsy)
239 glTexCoord2f(tx+tsx, ty+tsy)
244 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
245 npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
246 npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
247 finalMatrix = npModelMatrix * npProjMatrix
248 finalMatrix = numpy.linalg.inv(finalMatrix)
250 viewport = map(float, viewport)
251 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))
252 vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
253 ret = list(vector)[0:3] / vector[3]
256 def convert3x3MatrixTo4x4(matrix):
257 return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
259 def loadGLTexture(filename):
260 tex = glGenTextures(1)
261 glBindTexture(GL_TEXTURE_2D, tex)
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
263 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
264 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
265 rgbData = img.GetData()
266 alphaData = img.GetAlphaData()
267 if alphaData is not None:
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)
273 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
276 def ResetMatrixRotationAndScale():
277 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
281 scale2D = matrix[0][0]
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)
297 matrix[0][0] = scale2D
298 matrix[1][1] = scale2D
299 matrix[2][2] = scale2D
303 glLoadMatrixf(matrix)
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])
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])
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])
333 def DrawMeshOutline(mesh):
334 glEnable(GL_CULL_FACE)
335 glEnableClientState(GL_VERTEX_ARRAY);
336 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
340 glPolygonMode(GL_BACK, GL_LINE)
341 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
342 glPolygonMode(GL_BACK, GL_FILL)
345 glDisableClientState(GL_VERTEX_ARRAY)
348 def DrawMesh(mesh, insideOut = False):
349 glEnable(GL_CULL_FACE)
350 glEnableClientState(GL_VERTEX_ARRAY);
351 glEnableClientState(GL_NORMAL_ARRAY);
352 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
354 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
356 glNormalPointer(GL_FLOAT, 0, mesh.normal)
358 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
359 batchSize = 999 #Warning, batchSize needs to be dividable by 3
360 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
361 extraCount = mesh.vertexCount - extraStartPos
364 for i in xrange(0, int(mesh.vertexCount / batchSize)):
365 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
366 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
370 glNormalPointer(GL_FLOAT, 0, mesh.normal)
372 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
373 for i in xrange(0, int(mesh.vertexCount / batchSize)):
374 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
375 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
376 extraCount = mesh.vertexCount - extraStartPos
377 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
380 glDisableClientState(GL_VERTEX_ARRAY)
381 glDisableClientState(GL_NORMAL_ARRAY)
384 def DrawMeshSteep(mesh, matrix, angle):
385 cosAngle = math.sin(angle / 180.0 * math.pi)
386 glDisable(GL_LIGHTING)
387 glDepthFunc(GL_EQUAL)
388 normals = (numpy.matrix(mesh.normal, copy = False) * matrix).getA()
389 for i in xrange(0, int(mesh.vertexCount), 3):
390 if normals[i][2] < -0.999999:
391 if mesh.vertexes[i + 0][2] > 0.01:
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])
398 elif normals[i][2] < -cosAngle:
399 glColor3f(-normals[i][2], 0, 0)
400 glBegin(GL_TRIANGLES)
401 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
402 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
403 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
405 elif normals[i][2] > 0.999999:
406 if mesh.vertexes[i + 0][2] > 0.01:
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])
413 elif normals[i][2] > cosAngle:
414 glColor3f(normals[i][2], 0, 0)
415 glBegin(GL_TRIANGLES)
416 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
417 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
418 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
423 def DrawGCodeLayer(layer, drawQuick = True):
424 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
425 filamentArea = math.pi * filamentRadius * filamentRadius
426 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
429 fillColorCycle = [[0.5, 0.5, 0.0, 1], [0.0, 0.5, 0.5, 1], [0.5, 0.0, 0.5, 1]]
430 moveColor = [0, 0, 1, 0.5]
431 retractColor = [1, 0, 0.5, 0.5]
432 supportColor = [0, 1, 1, 1]
433 extrudeColor = [[1, 0, 0, 1], [0, 1, 1, 1], [1, 1, 0, 1], [1, 0, 1, 1]]
434 innerWallColor = [0, 1, 0, 1]
435 skirtColor = [0, 0.5, 0.5, 1]
436 prevPathWasRetract = False
438 glDisable(GL_CULL_FACE)
440 if path.type == 'move':
441 if prevPathWasRetract:
448 if path.type == 'extrude':
449 if path.pathType == 'FILL':
450 c = fillColorCycle[fillCycle]
451 fillCycle = (fillCycle + 1) % len(fillColorCycle)
454 elif path.pathType == 'WALL-INNER':
457 elif path.pathType == 'SUPPORT':
459 elif path.pathType == 'SKIRT':
462 c = extrudeColor[path.extruder]
463 if path.type == 'retract':
465 if path.type == 'extrude' and not drawQuick:
468 for i in xrange(0, len(path.list) - 1):
470 v1 = path.list[i + 1]
472 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
473 dist = (v0 - v1).vsize()
474 if dist > 0 and path.layerThickness > 0:
475 extrusionMMperDist = (v1.e - v0.e) / dist
476 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
478 drawLength += (v0 - v1).vsize()
479 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
482 vv2 = v0 + normal * lineWidth
483 vv3 = v1 + normal * lineWidth
484 vv0 = v0 - normal * lineWidth
485 vv1 = v1 - normal * lineWidth
489 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
490 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
491 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
492 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
494 if prevNormal is not None:
495 n = (normal + prevNormal)
497 vv4 = v0 + n * lineWidth
498 vv5 = v0 - n * lineWidth
501 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
502 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
503 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
504 glVertex3f(v0.x, v0.y, v0.z - zOffset)
506 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
507 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
508 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
509 glVertex3f(v0.x, v0.y, v0.z - zOffset)
516 glBegin(GL_LINE_STRIP)
519 glVertex3f(v.x, v.y, v.z)
521 if not path.type == 'move':
522 prevPathWasRetract = False
523 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
524 prevPathWasRetract = True
525 glEnable(GL_CULL_FACE)