2 from __future__ import absolute_import
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
16 OpenGL.ERROR_CHECKING = False
17 from OpenGL.GLUT import *
18 from OpenGL.GLU import *
19 from OpenGL.GL import *
24 print "Failed to find PyOpenGL: http://pyopengl.sourceforge.net/"
27 def InitGL(window, view3D, zoom):
28 # set viewing projection
29 glMatrixMode(GL_MODELVIEW)
31 size = window.GetSize()
32 glViewport(0, 0, size.GetWidth(), size.GetHeight())
34 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
35 glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
37 glEnable(GL_RESCALE_NORMAL)
40 glEnable(GL_DEPTH_TEST)
41 glEnable(GL_CULL_FACE)
44 glClearColor(1.0, 1.0, 1.0, 1.0)
48 glMatrixMode(GL_PROJECTION)
50 aspect = float(size.GetWidth()) / float(size.GetHeight())
52 gluPerspective(45.0, aspect, 1.0, 1000.0)
54 glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
56 glMatrixMode(GL_MODELVIEW)
58 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
62 def DrawMachine(machineSize):
63 if profile.getPreference('machine_type') == 'ultimaker':
66 glTranslate(100, 200, -5)
67 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
68 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
70 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
73 if platformMesh is None:
75 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
80 DrawMesh(platformMesh)
83 glDisable(GL_LIGHTING)
85 glColor3f(0.7, 0.7, 0.7)
88 for i in xrange(0, int(machineSize.x), 10):
90 glVertex3f(i, machineSize.y, 0)
91 for i in xrange(0, int(machineSize.y), 10):
93 glVertex3f(machineSize.x, i, 0)
96 glEnable(GL_LINE_SMOOTH)
98 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
99 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
101 glColor3f(0.0, 0.0, 0.0)
103 glBegin(GL_LINE_LOOP)
105 glVertex3f(machineSize.x, 0, 0)
106 glVertex3f(machineSize.x, machineSize.y, 0)
107 glVertex3f(0, machineSize.y, 0)
111 glBegin(GL_LINE_LOOP)
112 glVertex3f(0, 0, machineSize.z)
113 glVertex3f(machineSize.x, 0, machineSize.z)
114 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
115 glVertex3f(0, machineSize.y, machineSize.z)
119 glVertex3f(0, 0, machineSize.z)
120 glVertex3f(machineSize.x, 0, 0)
121 glVertex3f(machineSize.x, 0, machineSize.z)
122 glVertex3f(machineSize.x, machineSize.y, 0)
123 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
124 glVertex3f(0, machineSize.y, 0)
125 glVertex3f(0, machineSize.y, machineSize.z)
128 glDisable(GL_CULL_FACE)
130 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
134 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
135 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
140 x1 = max(min(x1, sx), 0)
141 y1 = max(min(y1, sy), 0)
142 x2 = max(min(x2, sx), 0)
143 y2 = max(min(y2, sy), 0)
144 if (x & 1) == (y & 1):
145 glColor4ub(5, 171, 231, 127)
147 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
149 glVertex3f(x1, y1, -0.01)
150 glVertex3f(x2, y1, -0.01)
151 glVertex3f(x2, y2, -0.01)
152 glVertex3f(x1, y2, -0.01)
155 glEnable(GL_CULL_FACE)
157 glColor4ub(5, 171, 231, 64)
159 glVertex3f(0, 0, machineSize.z)
160 glVertex3f(0, machineSize.y, machineSize.z)
161 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
162 glVertex3f(machineSize.x, 0, machineSize.z)
165 glColor4ub(5, 171, 231, 96)
168 glVertex3f(0, 0, machineSize.z)
169 glVertex3f(machineSize.x, 0, machineSize.z)
170 glVertex3f(machineSize.x, 0, 0)
172 glVertex3f(0, machineSize.y, machineSize.z)
173 glVertex3f(0, machineSize.y, 0)
174 glVertex3f(machineSize.x, machineSize.y, 0)
175 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
178 glColor4ub(5, 171, 231, 128)
180 glVertex3f(0, 0, machineSize.z)
182 glVertex3f(0, machineSize.y, 0)
183 glVertex3f(0, machineSize.y, machineSize.z)
185 glVertex3f(machineSize.x, 0, 0)
186 glVertex3f(machineSize.x, 0, machineSize.z)
187 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
188 glVertex3f(machineSize.x, machineSize.y, 0)
212 glDisable(GL_DEPTH_TEST)
216 glTranslate(20, 0, 0)
217 noZ = ResetMatrixRotationAndScale()
218 glDrawStringCenter("X")
224 glTranslate(0, 20, 0)
225 glDrawStringCenter("Y")
232 glTranslate(0, 0, 20)
233 glDrawStringCenter("Z")
237 glEnable(GL_DEPTH_TEST)
239 def glDrawStringCenter(s):
243 width += glutBitmapWidth(GLUT_BITMAP_HELVETICA_18, ord(c))
244 glBitmap(0,0,0,0, -width/2, 0, None)
246 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, ord(c))
248 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
249 npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
250 npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
251 finalMatrix = npModelMatrix * npProjMatrix
252 finalMatrix = numpy.linalg.inv(finalMatrix)
254 viewport = map(float, viewport)
255 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))
256 vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
257 ret = list(vector)[0:3] / vector[3]
260 def convert3x3MatrixTo4x4(matrix):
261 return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
263 def loadGLTexture(filename):
264 tex = glGenTextures(1)
265 glBindTexture(GL_TEXTURE_2D, tex)
266 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
268 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
270 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
271 rgbData = img.GetData()
272 alphaData = img.GetAlphaData()
273 if alphaData != None:
275 for i in xrange(0, len(alphaData)):
276 data += rgbData[i*3:i*3+3] + alphaData[i]
277 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
279 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
282 def ResetMatrixRotationAndScale():
283 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
287 scale2D = matrix[0][0]
298 if matrix[3][2] != 0.0:
299 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
300 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
303 matrix[0][0] = scale2D
304 matrix[1][1] = scale2D
305 matrix[2][2] = scale2D
309 glLoadMatrixf(matrix)
313 def DrawBox(vMin, vMax):
314 glBegin(GL_LINE_LOOP)
315 glVertex3f(vMin[0], vMin[1], vMin[2])
316 glVertex3f(vMax[0], vMin[1], vMin[2])
317 glVertex3f(vMax[0], vMax[1], vMin[2])
318 glVertex3f(vMin[0], vMax[1], vMin[2])
321 glBegin(GL_LINE_LOOP)
322 glVertex3f(vMin[0], vMin[1], vMax[2])
323 glVertex3f(vMax[0], vMin[1], vMax[2])
324 glVertex3f(vMax[0], vMax[1], vMax[2])
325 glVertex3f(vMin[0], vMax[1], vMax[2])
328 glVertex3f(vMin[0], vMin[1], vMin[2])
329 glVertex3f(vMin[0], vMin[1], vMax[2])
330 glVertex3f(vMax[0], vMin[1], vMin[2])
331 glVertex3f(vMax[0], vMin[1], vMax[2])
332 glVertex3f(vMax[0], vMax[1], vMin[2])
333 glVertex3f(vMax[0], vMax[1], vMax[2])
334 glVertex3f(vMin[0], vMax[1], vMin[2])
335 glVertex3f(vMin[0], vMax[1], vMax[2])
339 def DrawMeshOutline(mesh):
340 glEnable(GL_CULL_FACE)
341 glEnableClientState(GL_VERTEX_ARRAY);
342 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
346 glPolygonMode(GL_BACK, GL_LINE)
347 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
348 glPolygonMode(GL_BACK, GL_FILL)
351 glDisableClientState(GL_VERTEX_ARRAY)
355 glEnable(GL_CULL_FACE)
356 glEnableClientState(GL_VERTEX_ARRAY);
357 glEnableClientState(GL_NORMAL_ARRAY);
358 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
359 glNormalPointer(GL_FLOAT, 0, mesh.normal)
361 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
362 batchSize = 999 #Warning, batchSize needs to be dividable by 3
363 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
364 extraCount = mesh.vertexCount - extraStartPos
367 for i in xrange(0, int(mesh.vertexCount / batchSize)):
368 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
369 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
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, angle):
385 cosAngle = math.sin(angle / 180.0 * math.pi)
386 glDisable(GL_LIGHTING)
387 glDepthFunc(GL_EQUAL)
388 for i in xrange(0, int(mesh.vertexCount), 3):
389 if mesh.normal[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 mesh.normal[i][2] < -cosAngle:
398 glColor3f(-mesh.normal[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 mesh.normal[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 mesh.normal[i][2] > cosAngle:
413 glColor3f(mesh.normal[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):
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], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
429 moveColor = [0, 0, 1]
430 retractColor = [1, 0, 0.5]
431 supportColor = [0, 1, 1]
432 extrudeColor = [1, 0, 0]
433 innerWallColor = [0, 1, 0]
434 skirtColor = [0, 0.5, 0.5]
435 prevPathWasRetract = False
437 glDisable(GL_CULL_FACE)
439 if path.type == 'move':
440 if prevPathWasRetract:
445 if path.type == 'extrude':
446 if path.pathType == 'FILL':
447 c = fillColorCycle[fillCycle]
448 fillCycle = (fillCycle + 1) % len(fillColorCycle)
449 elif path.pathType == 'WALL-INNER':
452 elif path.pathType == 'SUPPORT':
454 elif path.pathType == 'SKIRT':
458 if path.type == 'retract':
460 if path.type == 'extrude':
463 for i in xrange(0, len(path.list) - 1):
465 v1 = path.list[i + 1]
467 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
468 dist = (v0 - v1).vsize()
469 if dist > 0 and path.layerThickness > 0:
470 extrusionMMperDist = (v1.e - v0.e) / dist
471 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
473 drawLength += (v0 - v1).vsize()
474 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
477 vv2 = v0 + normal * lineWidth
478 vv3 = v1 + normal * lineWidth
479 vv0 = v0 - normal * lineWidth
480 vv1 = v1 - normal * lineWidth
484 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
485 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
486 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
487 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
489 if prevNormal is not None:
490 n = (normal + prevNormal)
492 vv4 = v0 + n * lineWidth
493 vv5 = v0 - n * lineWidth
496 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
497 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
498 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
499 glVertex3f(v0.x, v0.y, v0.z - zOffset)
501 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
502 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
503 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
504 glVertex3f(v0.x, v0.y, v0.z - zOffset)
511 glBegin(GL_LINE_STRIP)
514 glVertex3f(v.x, v.y, v.z)
516 if not path.type == 'move':
517 prevPathWasRetract = False
518 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
519 prevPathWasRetract = True
520 glEnable(GL_CULL_FACE)