2 from __future__ import absolute_import
6 from Cura.util import meshLoader
7 from Cura.util import util3d
8 from Cura.util import profile
9 from Cura.util.resources import getPathForMesh
14 OpenGL.ERROR_CHECKING = False
15 from OpenGL.GLUT import *
16 from OpenGL.GLU import *
17 from OpenGL.GL import *
22 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 ResetMatrixRotationAndScale():
264 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
268 scale2D = matrix[0][0]
279 if matrix[3][2] != 0.0:
280 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
281 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
284 matrix[0][0] = scale2D
285 matrix[1][1] = scale2D
286 matrix[2][2] = scale2D
290 glLoadMatrixf(matrix)
294 def DrawBox(vMin, vMax):
295 glBegin(GL_LINE_LOOP)
296 glVertex3f(vMin[0], vMin[1], vMin[2])
297 glVertex3f(vMax[0], vMin[1], vMin[2])
298 glVertex3f(vMax[0], vMax[1], vMin[2])
299 glVertex3f(vMin[0], vMax[1], vMin[2])
302 glBegin(GL_LINE_LOOP)
303 glVertex3f(vMin[0], vMin[1], vMax[2])
304 glVertex3f(vMax[0], vMin[1], vMax[2])
305 glVertex3f(vMax[0], vMax[1], vMax[2])
306 glVertex3f(vMin[0], vMax[1], vMax[2])
309 glVertex3f(vMin[0], vMin[1], vMin[2])
310 glVertex3f(vMin[0], vMin[1], vMax[2])
311 glVertex3f(vMax[0], vMin[1], vMin[2])
312 glVertex3f(vMax[0], vMin[1], vMax[2])
313 glVertex3f(vMax[0], vMax[1], vMin[2])
314 glVertex3f(vMax[0], vMax[1], vMax[2])
315 glVertex3f(vMin[0], vMax[1], vMin[2])
316 glVertex3f(vMin[0], vMax[1], vMax[2])
320 def DrawMeshOutline(mesh):
321 glEnable(GL_CULL_FACE)
322 glEnableClientState(GL_VERTEX_ARRAY);
323 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
327 glPolygonMode(GL_BACK, GL_LINE)
328 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
329 glPolygonMode(GL_BACK, GL_FILL)
332 glDisableClientState(GL_VERTEX_ARRAY)
336 glEnable(GL_CULL_FACE)
337 glEnableClientState(GL_VERTEX_ARRAY);
338 glEnableClientState(GL_NORMAL_ARRAY);
339 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
340 glNormalPointer(GL_FLOAT, 0, mesh.normal)
342 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
343 batchSize = 999 #Warning, batchSize needs to be dividable by 3
344 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
345 extraCount = mesh.vertexCount - extraStartPos
348 for i in xrange(0, int(mesh.vertexCount / batchSize)):
349 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
350 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
353 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
354 for i in xrange(0, int(mesh.vertexCount / batchSize)):
355 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
356 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
357 extraCount = mesh.vertexCount - extraStartPos
358 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
361 glDisableClientState(GL_VERTEX_ARRAY)
362 glDisableClientState(GL_NORMAL_ARRAY);
365 def DrawMeshSteep(mesh, angle):
366 cosAngle = math.sin(angle / 180.0 * math.pi)
367 glDisable(GL_LIGHTING)
368 glDepthFunc(GL_EQUAL)
369 for i in xrange(0, int(mesh.vertexCount), 3):
370 if mesh.normal[i][2] < -0.999999:
371 if mesh.vertexes[i + 0][2] > 0.01:
373 glBegin(GL_TRIANGLES)
374 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
375 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
376 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
378 elif mesh.normal[i][2] < -cosAngle:
379 glColor3f(-mesh.normal[i][2], 0, 0)
380 glBegin(GL_TRIANGLES)
381 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
382 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
383 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
385 elif mesh.normal[i][2] > 0.999999:
386 if mesh.vertexes[i + 0][2] > 0.01:
388 glBegin(GL_TRIANGLES)
389 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
390 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
391 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
393 elif mesh.normal[i][2] > cosAngle:
394 glColor3f(mesh.normal[i][2], 0, 0)
395 glBegin(GL_TRIANGLES)
396 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
397 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
398 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
403 def DrawGCodeLayer(layer):
404 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
405 filamentArea = math.pi * filamentRadius * filamentRadius
406 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
409 fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
410 moveColor = [0, 0, 1]
411 retractColor = [1, 0, 0.5]
412 supportColor = [0, 1, 1]
413 extrudeColor = [1, 0, 0]
414 innerWallColor = [0, 1, 0]
415 skirtColor = [0, 0.5, 0.5]
416 prevPathWasRetract = False
418 glDisable(GL_CULL_FACE)
420 if path.type == 'move':
421 if prevPathWasRetract:
426 if path.type == 'extrude':
427 if path.pathType == 'FILL':
428 c = fillColorCycle[fillCycle]
429 fillCycle = (fillCycle + 1) % len(fillColorCycle)
430 elif path.pathType == 'WALL-INNER':
433 elif path.pathType == 'SUPPORT':
435 elif path.pathType == 'SKIRT':
439 if path.type == 'retract':
441 if path.type == 'extrude':
444 for i in xrange(0, len(path.list) - 1):
446 v1 = path.list[i + 1]
448 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
449 dist = (v0 - v1).vsize()
450 if dist > 0 and path.layerThickness > 0:
451 extrusionMMperDist = (v1.e - v0.e) / dist
452 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
454 drawLength += (v0 - v1).vsize()
455 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
458 vv2 = v0 + normal * lineWidth
459 vv3 = v1 + normal * lineWidth
460 vv0 = v0 - normal * lineWidth
461 vv1 = v1 - normal * lineWidth
465 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
466 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
467 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
468 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
470 if prevNormal is not None:
471 n = (normal + prevNormal)
473 vv4 = v0 + n * lineWidth
474 vv5 = v0 - n * lineWidth
477 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
478 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
479 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
480 glVertex3f(v0.x, v0.y, v0.z - zOffset)
482 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
483 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
484 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
485 glVertex3f(v0.x, v0.y, v0.z - zOffset)
492 glBegin(GL_LINE_STRIP)
495 glVertex3f(v.x, v.y, v.z)
497 if not path.type == 'move':
498 prevPathWasRetract = False
499 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
500 prevPathWasRetract = True
501 glEnable(GL_CULL_FACE)