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)
43 glMatrixMode(GL_PROJECTION)
45 aspect = float(size.GetWidth()) / float(size.GetHeight())
47 gluPerspective(45.0, aspect, 1.0, 1000.0)
49 glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
51 glMatrixMode(GL_MODELVIEW)
53 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
57 def DrawMachine(machineSize):
58 glDisable(GL_LIGHTING)
59 glDisable(GL_CULL_FACE)
61 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
65 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
66 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
71 x1 = max(min(x1, sx), 0)
72 y1 = max(min(y1, sy), 0)
73 x2 = max(min(x2, sx), 0)
74 y2 = max(min(y2, sy), 0)
75 if (x & 1) == (y & 1):
76 glColor4ub(5, 171, 231, 127)
78 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
80 glVertex3f(x1, y1, -0.02)
81 glVertex3f(x2, y1, -0.02)
82 glVertex3f(x2, y2, -0.02)
83 glVertex3f(x1, y2, -0.02)
86 glEnable(GL_CULL_FACE)
88 if profile.getPreference('machine_type') == 'ultimaker':
91 glTranslate(100, 200, -1)
92 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
93 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
95 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
98 if platformMesh is None:
100 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
105 DrawMesh(platformMesh)
107 glDisable(GL_LIGHTING)
108 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
110 glColor4ub(5, 171, 231, 64)
112 glVertex3f(0, 0, machineSize.z)
113 glVertex3f(0, machineSize.y, machineSize.z)
114 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
115 glVertex3f(machineSize.x, 0, machineSize.z)
118 glColor4ub(5, 171, 231, 96)
121 glVertex3f(0, 0, machineSize.z)
122 glVertex3f(machineSize.x, 0, machineSize.z)
123 glVertex3f(machineSize.x, 0, 0)
125 glVertex3f(0, machineSize.y, machineSize.z)
126 glVertex3f(0, machineSize.y, 0)
127 glVertex3f(machineSize.x, machineSize.y, 0)
128 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
131 glColor4ub(5, 171, 231, 128)
133 glVertex3f(0, 0, machineSize.z)
135 glVertex3f(0, machineSize.y, 0)
136 glVertex3f(0, machineSize.y, machineSize.z)
138 glVertex3f(machineSize.x, 0, 0)
139 glVertex3f(machineSize.x, 0, machineSize.z)
140 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
141 glVertex3f(machineSize.x, machineSize.y, 0)
146 #Draw the X/Y/Z indicator
166 glDisable(GL_DEPTH_TEST)
170 glTranslate(20, 0, 0)
171 noZ = ResetMatrixRotationAndScale()
172 glDrawStringCenter("X")
178 glTranslate(0, 20, 0)
179 glDrawStringCenter("Y")
186 glTranslate(0, 0, 20)
187 glDrawStringCenter("Z")
191 glEnable(GL_DEPTH_TEST)
193 def glDrawStringCenter(s):
195 glBitmap(0,0,0,0, -glGetStringSize(s)[0]/2, 0, None)
197 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
199 def glGetStringSize(s):
202 width += glutBitmapWidth(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
206 def glDrawStringLeft(s):
209 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
211 def glDrawStringRight(s):
213 glBitmap(0,0,0,0, -glGetStringSize(s)[0], 0, None)
215 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
217 def glDrawTexturedQuad(x, y, w, h, texID, mirror = 0):
218 tx = float(texID % 4) / 4
219 ty = float(int(texID / 4)) / 8
229 glTranslatef(x, y, 0)
230 glEnable(GL_TEXTURE_2D)
232 glTexCoord2f(tx+tsx, ty)
236 glTexCoord2f(tx, ty+tsy)
238 glTexCoord2f(tx+tsx, ty+tsy)
243 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
244 npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
245 npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
246 finalMatrix = npModelMatrix * npProjMatrix
247 finalMatrix = numpy.linalg.inv(finalMatrix)
249 viewport = map(float, viewport)
250 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))
251 vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
252 ret = list(vector)[0:3] / vector[3]
255 def convert3x3MatrixTo4x4(matrix):
256 return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
258 def loadGLTexture(filename):
259 tex = glGenTextures(1)
260 glBindTexture(GL_TEXTURE_2D, tex)
261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
263 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
264 rgbData = img.GetData()
265 alphaData = img.GetAlphaData()
266 if alphaData is not None:
268 for i in xrange(0, len(alphaData)):
269 data += rgbData[i*3:i*3+3] + alphaData[i]
270 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
272 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
275 def ResetMatrixRotationAndScale():
276 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
280 scale2D = matrix[0][0]
291 if matrix[3][2] != 0.0:
292 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
293 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
296 matrix[0][0] = scale2D
297 matrix[1][1] = scale2D
298 matrix[2][2] = scale2D
302 glLoadMatrixf(matrix)
306 def DrawBox(vMin, vMax):
307 glBegin(GL_LINE_LOOP)
308 glVertex3f(vMin[0], vMin[1], vMin[2])
309 glVertex3f(vMax[0], vMin[1], vMin[2])
310 glVertex3f(vMax[0], vMax[1], vMin[2])
311 glVertex3f(vMin[0], vMax[1], vMin[2])
314 glBegin(GL_LINE_LOOP)
315 glVertex3f(vMin[0], vMin[1], vMax[2])
316 glVertex3f(vMax[0], vMin[1], vMax[2])
317 glVertex3f(vMax[0], vMax[1], vMax[2])
318 glVertex3f(vMin[0], vMax[1], vMax[2])
321 glVertex3f(vMin[0], vMin[1], vMin[2])
322 glVertex3f(vMin[0], vMin[1], vMax[2])
323 glVertex3f(vMax[0], vMin[1], vMin[2])
324 glVertex3f(vMax[0], vMin[1], vMax[2])
325 glVertex3f(vMax[0], vMax[1], vMin[2])
326 glVertex3f(vMax[0], vMax[1], vMax[2])
327 glVertex3f(vMin[0], vMax[1], vMin[2])
328 glVertex3f(vMin[0], vMax[1], vMax[2])
332 def DrawMeshOutline(mesh):
333 glEnable(GL_CULL_FACE)
334 glEnableClientState(GL_VERTEX_ARRAY);
335 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
339 glPolygonMode(GL_BACK, GL_LINE)
340 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
341 glPolygonMode(GL_BACK, GL_FILL)
344 glDisableClientState(GL_VERTEX_ARRAY)
347 def DrawMesh(mesh, insideOut = False):
348 glEnable(GL_CULL_FACE)
349 glEnableClientState(GL_VERTEX_ARRAY);
350 glEnableClientState(GL_NORMAL_ARRAY);
351 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
353 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
355 glNormalPointer(GL_FLOAT, 0, mesh.normal)
357 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
358 batchSize = 999 #Warning, batchSize needs to be dividable by 3
359 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
360 extraCount = mesh.vertexCount - extraStartPos
363 for i in xrange(0, int(mesh.vertexCount / batchSize)):
364 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
365 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
369 glNormalPointer(GL_FLOAT, 0, mesh.normal)
371 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
372 for i in xrange(0, int(mesh.vertexCount / batchSize)):
373 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
374 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
375 extraCount = mesh.vertexCount - extraStartPos
376 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
379 glDisableClientState(GL_VERTEX_ARRAY)
380 glDisableClientState(GL_NORMAL_ARRAY)
383 def DrawMeshSteep(mesh, matrix, angle):
384 cosAngle = math.sin(angle / 180.0 * math.pi)
385 glDisable(GL_LIGHTING)
386 glDepthFunc(GL_EQUAL)
387 normals = (numpy.matrix(mesh.normal, copy = False) * matrix).getA()
388 for i in xrange(0, int(mesh.vertexCount), 3):
389 if normals[i][2] < -0.999999:
390 if mesh.vertexes[i + 0][2] > 0.01:
392 glBegin(GL_TRIANGLES)
393 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
394 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
395 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
397 elif normals[i][2] < -cosAngle:
398 glColor3f(-normals[i][2], 0, 0)
399 glBegin(GL_TRIANGLES)
400 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
401 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
402 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
404 elif normals[i][2] > 0.999999:
405 if mesh.vertexes[i + 0][2] > 0.01:
407 glBegin(GL_TRIANGLES)
408 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
409 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
410 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
412 elif normals[i][2] > cosAngle:
413 glColor3f(normals[i][2], 0, 0)
414 glBegin(GL_TRIANGLES)
415 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
416 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
417 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
422 def DrawGCodeLayer(layer, drawQuick = True):
423 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
424 filamentArea = math.pi * filamentRadius * filamentRadius
425 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
428 fillColorCycle = [[0.5, 0.5, 0.0, 1], [0.0, 0.5, 0.5, 1], [0.5, 0.0, 0.5, 1]]
429 moveColor = [0, 0, 1, 0.5]
430 retractColor = [1, 0, 0.5, 0.5]
431 supportColor = [0, 1, 1, 1]
432 extrudeColor = [1, 0, 0, 1]
433 innerWallColor = [0, 1, 0, 1]
434 skirtColor = [0, 0.5, 0.5, 1]
435 prevPathWasRetract = False
437 glDisable(GL_CULL_FACE)
439 if path.type == 'move':
440 if prevPathWasRetract:
447 if path.type == 'extrude':
448 if path.pathType == 'FILL':
449 c = fillColorCycle[fillCycle]
450 fillCycle = (fillCycle + 1) % len(fillColorCycle)
453 elif path.pathType == 'WALL-INNER':
456 elif path.pathType == 'SUPPORT':
458 elif path.pathType == 'SKIRT':
462 if path.type == 'retract':
464 if path.type == 'extrude' and not drawQuick:
467 for i in xrange(0, len(path.list) - 1):
469 v1 = path.list[i + 1]
471 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
472 dist = (v0 - v1).vsize()
473 if dist > 0 and path.layerThickness > 0:
474 extrusionMMperDist = (v1.e - v0.e) / dist
475 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
477 drawLength += (v0 - v1).vsize()
478 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
481 vv2 = v0 + normal * lineWidth
482 vv3 = v1 + normal * lineWidth
483 vv0 = v0 - normal * lineWidth
484 vv1 = v1 - normal * lineWidth
488 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
489 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
490 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
491 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
493 if prevNormal is not None:
494 n = (normal + prevNormal)
496 vv4 = v0 + n * lineWidth
497 vv5 = v0 - n * lineWidth
500 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
501 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
502 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
503 glVertex3f(v0.x, v0.y, v0.z - zOffset)
505 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
506 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
507 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
508 glVertex3f(v0.x, v0.y, v0.z - zOffset)
515 glBegin(GL_LINE_STRIP)
518 glVertex3f(v.x, v.y, v.z)
520 if not path.type == 'move':
521 prevPathWasRetract = False
522 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
523 prevPathWasRetract = True
524 glEnable(GL_CULL_FACE)