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 ResetMatrixRotationAndScale():
261 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
265 scale2D = matrix[0][0]
276 if matrix[3][2] != 0.0:
277 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
278 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
281 matrix[0][0] = scale2D
282 matrix[1][1] = scale2D
283 matrix[2][2] = scale2D
287 glLoadMatrixf(matrix)
291 def DrawBox(vMin, vMax):
292 glBegin(GL_LINE_LOOP)
293 glVertex3f(vMin[0], vMin[1], vMin[2])
294 glVertex3f(vMax[0], vMin[1], vMin[2])
295 glVertex3f(vMax[0], vMax[1], vMin[2])
296 glVertex3f(vMin[0], vMax[1], vMin[2])
299 glBegin(GL_LINE_LOOP)
300 glVertex3f(vMin[0], vMin[1], vMax[2])
301 glVertex3f(vMax[0], vMin[1], vMax[2])
302 glVertex3f(vMax[0], vMax[1], vMax[2])
303 glVertex3f(vMin[0], vMax[1], vMax[2])
306 glVertex3f(vMin[0], vMin[1], vMin[2])
307 glVertex3f(vMin[0], vMin[1], vMax[2])
308 glVertex3f(vMax[0], vMin[1], vMin[2])
309 glVertex3f(vMax[0], vMin[1], vMax[2])
310 glVertex3f(vMax[0], vMax[1], vMin[2])
311 glVertex3f(vMax[0], vMax[1], vMax[2])
312 glVertex3f(vMin[0], vMax[1], vMin[2])
313 glVertex3f(vMin[0], vMax[1], vMax[2])
317 def DrawMeshOutline(mesh):
318 glEnable(GL_CULL_FACE)
319 glEnableClientState(GL_VERTEX_ARRAY);
320 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
324 glPolygonMode(GL_BACK, GL_LINE)
325 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
326 glPolygonMode(GL_BACK, GL_FILL)
329 glDisableClientState(GL_VERTEX_ARRAY)
333 glEnable(GL_CULL_FACE)
334 glEnableClientState(GL_VERTEX_ARRAY);
335 glEnableClientState(GL_NORMAL_ARRAY);
336 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
337 glNormalPointer(GL_FLOAT, 0, mesh.normal)
339 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
340 batchSize = 999 #Warning, batchSize needs to be dividable by 3
341 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
342 extraCount = mesh.vertexCount - extraStartPos
345 for i in xrange(0, int(mesh.vertexCount / batchSize)):
346 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
347 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
350 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
351 for i in xrange(0, int(mesh.vertexCount / batchSize)):
352 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
353 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
354 extraCount = mesh.vertexCount - extraStartPos
355 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
358 glDisableClientState(GL_VERTEX_ARRAY)
359 glDisableClientState(GL_NORMAL_ARRAY);
362 def DrawMeshSteep(mesh, angle):
363 cosAngle = math.sin(angle / 180.0 * math.pi)
364 glDisable(GL_LIGHTING)
365 glDepthFunc(GL_EQUAL)
366 for i in xrange(0, int(mesh.vertexCount), 3):
367 if mesh.normal[i][2] < -0.999999:
368 if mesh.vertexes[i + 0][2] > 0.01:
370 glBegin(GL_TRIANGLES)
371 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
372 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
373 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
375 elif mesh.normal[i][2] < -cosAngle:
376 glColor3f(-mesh.normal[i][2], 0, 0)
377 glBegin(GL_TRIANGLES)
378 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
379 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
380 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
382 elif mesh.normal[i][2] > 0.999999:
383 if mesh.vertexes[i + 0][2] > 0.01:
385 glBegin(GL_TRIANGLES)
386 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
387 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
388 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
390 elif mesh.normal[i][2] > cosAngle:
391 glColor3f(mesh.normal[i][2], 0, 0)
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 + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
395 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
400 def DrawGCodeLayer(layer):
401 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
402 filamentArea = math.pi * filamentRadius * filamentRadius
403 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
406 fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
407 moveColor = [0, 0, 1]
408 retractColor = [1, 0, 0.5]
409 supportColor = [0, 1, 1]
410 extrudeColor = [1, 0, 0]
411 innerWallColor = [0, 1, 0]
412 skirtColor = [0, 0.5, 0.5]
413 prevPathWasRetract = False
415 glDisable(GL_CULL_FACE)
417 if path.type == 'move':
418 if prevPathWasRetract:
423 if path.type == 'extrude':
424 if path.pathType == 'FILL':
425 c = fillColorCycle[fillCycle]
426 fillCycle = (fillCycle + 1) % len(fillColorCycle)
427 elif path.pathType == 'WALL-INNER':
430 elif path.pathType == 'SUPPORT':
432 elif path.pathType == 'SKIRT':
436 if path.type == 'retract':
438 if path.type == 'extrude':
441 for i in xrange(0, len(path.list) - 1):
443 v1 = path.list[i + 1]
445 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
446 dist = (v0 - v1).vsize()
447 if dist > 0 and path.layerThickness > 0:
448 extrusionMMperDist = (v1.e - v0.e) / dist
449 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
451 drawLength += (v0 - v1).vsize()
452 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
455 vv2 = v0 + normal * lineWidth
456 vv3 = v1 + normal * lineWidth
457 vv0 = v0 - normal * lineWidth
458 vv1 = v1 - normal * lineWidth
462 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
463 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
464 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
465 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
467 if prevNormal is not None:
468 n = (normal + prevNormal)
470 vv4 = v0 + n * lineWidth
471 vv5 = v0 - n * lineWidth
474 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
475 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
476 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
477 glVertex3f(v0.x, v0.y, v0.z - zOffset)
479 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
480 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
481 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
482 glVertex3f(v0.x, v0.y, v0.z - zOffset)
489 glBegin(GL_LINE_STRIP)
492 glVertex3f(v.x, v.y, v.z)
494 if not path.type == 'move':
495 prevPathWasRetract = False
496 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
497 prevPathWasRetract = True
498 glEnable(GL_CULL_FACE)