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
15 OpenGL.ERROR_CHECKING = False
16 from OpenGL.GLUT import *
17 from OpenGL.GLU import *
18 from OpenGL.GL import *
21 def InitGL(window, view3D, zoom):
22 # set viewing projection
23 glMatrixMode(GL_MODELVIEW)
25 size = window.GetSize()
26 glViewport(0, 0, size.GetWidth(), size.GetHeight())
28 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
29 glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
31 glEnable(GL_RESCALE_NORMAL)
34 glEnable(GL_DEPTH_TEST)
35 glEnable(GL_CULL_FACE)
38 glClearColor(1.0, 1.0, 1.0, 1.0)
42 glMatrixMode(GL_PROJECTION)
44 aspect = float(size.GetWidth()) / float(size.GetHeight())
46 gluPerspective(45.0, aspect, 1.0, 1000.0)
48 glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
50 glMatrixMode(GL_MODELVIEW)
52 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
56 def DrawMachine(machineSize):
57 glDisable(GL_LIGHTING)
58 glDisable(GL_CULL_FACE)
60 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
64 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
65 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
70 x1 = max(min(x1, sx), 0)
71 y1 = max(min(y1, sy), 0)
72 x2 = max(min(x2, sx), 0)
73 y2 = max(min(y2, sy), 0)
74 if (x & 1) == (y & 1):
75 glColor4ub(5, 171, 231, 127)
77 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
79 glVertex3f(x1, y1, -0.02)
80 glVertex3f(x2, y1, -0.02)
81 glVertex3f(x2, y2, -0.02)
82 glVertex3f(x1, y2, -0.02)
85 glEnable(GL_CULL_FACE)
87 if profile.getPreference('machine_type') == 'ultimaker':
90 glTranslate(100, 200, -1)
91 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
92 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
94 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
97 if platformMesh is None:
99 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
104 DrawMesh(platformMesh)
106 glDisable(GL_LIGHTING)
107 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
109 glColor4ub(5, 171, 231, 64)
111 glVertex3f(0, 0, machineSize.z)
112 glVertex3f(0, machineSize.y, machineSize.z)
113 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
114 glVertex3f(machineSize.x, 0, machineSize.z)
117 glColor4ub(5, 171, 231, 96)
120 glVertex3f(0, 0, machineSize.z)
121 glVertex3f(machineSize.x, 0, machineSize.z)
122 glVertex3f(machineSize.x, 0, 0)
124 glVertex3f(0, machineSize.y, machineSize.z)
125 glVertex3f(0, machineSize.y, 0)
126 glVertex3f(machineSize.x, machineSize.y, 0)
127 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
130 glColor4ub(5, 171, 231, 128)
132 glVertex3f(0, 0, machineSize.z)
134 glVertex3f(0, machineSize.y, 0)
135 glVertex3f(0, machineSize.y, machineSize.z)
137 glVertex3f(machineSize.x, 0, 0)
138 glVertex3f(machineSize.x, 0, machineSize.z)
139 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
140 glVertex3f(machineSize.x, machineSize.y, 0)
145 #Draw the X/Y/Z indicator
165 glDisable(GL_DEPTH_TEST)
169 glTranslate(20, 0, 0)
170 noZ = ResetMatrixRotationAndScale()
171 glDrawStringCenter("X")
177 glTranslate(0, 20, 0)
178 glDrawStringCenter("Y")
185 glTranslate(0, 0, 20)
186 glDrawStringCenter("Z")
190 glEnable(GL_DEPTH_TEST)
192 def glDrawStringCenter(s):
194 glBitmap(0,0,0,0, -glGetStringSize(s)[0]/2, 0, None)
196 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
198 def glGetStringSize(s):
201 width += glutBitmapWidth(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
205 def glDrawStringLeft(s):
208 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
210 def glDrawStringRight(s):
212 glBitmap(0,0,0,0, -glGetStringSize(s)[0], 0, None)
214 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
216 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
217 npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
218 npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
219 finalMatrix = npModelMatrix * npProjMatrix
220 finalMatrix = numpy.linalg.inv(finalMatrix)
222 viewport = map(float, viewport)
223 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))
224 vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
225 ret = list(vector)[0:3] / vector[3]
228 def convert3x3MatrixTo4x4(matrix):
229 return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
231 def loadGLTexture(filename):
232 tex = glGenTextures(1)
233 glBindTexture(GL_TEXTURE_2D, tex)
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
236 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
237 rgbData = img.GetData()
238 alphaData = img.GetAlphaData()
239 if alphaData is not None:
241 for i in xrange(0, len(alphaData)):
242 data += rgbData[i*3:i*3+3] + alphaData[i]
243 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
245 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
248 def ResetMatrixRotationAndScale():
249 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
253 scale2D = matrix[0][0]
264 if matrix[3][2] != 0.0:
265 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
266 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
269 matrix[0][0] = scale2D
270 matrix[1][1] = scale2D
271 matrix[2][2] = scale2D
275 glLoadMatrixf(matrix)
279 def DrawBox(vMin, vMax):
280 glBegin(GL_LINE_LOOP)
281 glVertex3f(vMin[0], vMin[1], vMin[2])
282 glVertex3f(vMax[0], vMin[1], vMin[2])
283 glVertex3f(vMax[0], vMax[1], vMin[2])
284 glVertex3f(vMin[0], vMax[1], vMin[2])
287 glBegin(GL_LINE_LOOP)
288 glVertex3f(vMin[0], vMin[1], vMax[2])
289 glVertex3f(vMax[0], vMin[1], vMax[2])
290 glVertex3f(vMax[0], vMax[1], vMax[2])
291 glVertex3f(vMin[0], vMax[1], vMax[2])
294 glVertex3f(vMin[0], vMin[1], vMin[2])
295 glVertex3f(vMin[0], vMin[1], vMax[2])
296 glVertex3f(vMax[0], vMin[1], vMin[2])
297 glVertex3f(vMax[0], vMin[1], vMax[2])
298 glVertex3f(vMax[0], vMax[1], vMin[2])
299 glVertex3f(vMax[0], vMax[1], vMax[2])
300 glVertex3f(vMin[0], vMax[1], vMin[2])
301 glVertex3f(vMin[0], vMax[1], vMax[2])
305 def DrawMeshOutline(mesh):
306 glEnable(GL_CULL_FACE)
307 glEnableClientState(GL_VERTEX_ARRAY);
308 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
312 glPolygonMode(GL_BACK, GL_LINE)
313 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
314 glPolygonMode(GL_BACK, GL_FILL)
317 glDisableClientState(GL_VERTEX_ARRAY)
320 def DrawMesh(mesh, insideOut = False):
321 glEnable(GL_CULL_FACE)
322 glEnableClientState(GL_VERTEX_ARRAY);
323 glEnableClientState(GL_NORMAL_ARRAY);
324 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
326 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
328 glNormalPointer(GL_FLOAT, 0, mesh.normal)
330 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
331 batchSize = 999 #Warning, batchSize needs to be dividable by 3
332 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
333 extraCount = mesh.vertexCount - extraStartPos
336 for i in xrange(0, int(mesh.vertexCount / batchSize)):
337 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
338 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
342 glNormalPointer(GL_FLOAT, 0, mesh.normal)
344 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
345 for i in xrange(0, int(mesh.vertexCount / batchSize)):
346 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
347 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
348 extraCount = mesh.vertexCount - extraStartPos
349 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
352 glDisableClientState(GL_VERTEX_ARRAY)
353 glDisableClientState(GL_NORMAL_ARRAY)
356 def DrawMeshSteep(mesh, matrix, angle):
357 cosAngle = math.sin(angle / 180.0 * math.pi)
358 glDisable(GL_LIGHTING)
359 glDepthFunc(GL_EQUAL)
360 normals = (numpy.matrix(mesh.normal, copy = False) * matrix).getA()
361 for i in xrange(0, int(mesh.vertexCount), 3):
362 if normals[i][2] < -0.999999:
363 if mesh.vertexes[i + 0][2] > 0.01:
365 glBegin(GL_TRIANGLES)
366 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
367 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
368 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
370 elif normals[i][2] < -cosAngle:
371 glColor3f(-normals[i][2], 0, 0)
372 glBegin(GL_TRIANGLES)
373 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
374 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
375 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
377 elif normals[i][2] > 0.999999:
378 if mesh.vertexes[i + 0][2] > 0.01:
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 + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
383 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
385 elif normals[i][2] > cosAngle:
386 glColor3f(normals[i][2], 0, 0)
387 glBegin(GL_TRIANGLES)
388 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
389 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
390 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
395 def DrawGCodeLayer(layer):
396 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
397 filamentArea = math.pi * filamentRadius * filamentRadius
398 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
401 fillColorCycle = [[0.5, 0.5, 0.0, 1], [0.0, 0.5, 0.5, 1], [0.5, 0.0, 0.5, 1]]
402 moveColor = [0, 0, 1, 0.5]
403 retractColor = [1, 0, 0.5, 0.5]
404 supportColor = [0, 1, 1, 1]
405 extrudeColor = [1, 0, 0, 1]
406 innerWallColor = [0, 1, 0, 1]
407 skirtColor = [0, 0.5, 0.5, 1]
408 prevPathWasRetract = False
410 glDisable(GL_CULL_FACE)
412 if path.type == 'move':
413 if prevPathWasRetract:
418 if path.type == 'extrude':
419 if path.pathType == 'FILL':
420 c = fillColorCycle[fillCycle]
421 fillCycle = (fillCycle + 1) % len(fillColorCycle)
422 elif path.pathType == 'WALL-INNER':
425 elif path.pathType == 'SUPPORT':
427 elif path.pathType == 'SKIRT':
431 if path.type == 'retract':
433 if path.type == 'extrude':
436 for i in xrange(0, len(path.list) - 1):
438 v1 = path.list[i + 1]
440 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
441 dist = (v0 - v1).vsize()
442 if dist > 0 and path.layerThickness > 0:
443 extrusionMMperDist = (v1.e - v0.e) / dist
444 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
446 drawLength += (v0 - v1).vsize()
447 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
450 vv2 = v0 + normal * lineWidth
451 vv3 = v1 + normal * lineWidth
452 vv0 = v0 - normal * lineWidth
453 vv1 = v1 - normal * lineWidth
457 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
458 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
459 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
460 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
462 if prevNormal is not None:
463 n = (normal + prevNormal)
465 vv4 = v0 + n * lineWidth
466 vv5 = v0 - n * lineWidth
469 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
470 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
471 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
472 glVertex3f(v0.x, v0.y, v0.z - zOffset)
474 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
475 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
476 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
477 glVertex3f(v0.x, v0.y, v0.z - zOffset)
484 glBegin(GL_LINE_STRIP)
487 glVertex3f(v.x, v.y, v.z)
489 if not path.type == 'move':
490 prevPathWasRetract = False
491 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
492 prevPathWasRetract = True
493 glEnable(GL_CULL_FACE)