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 unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
218 npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
219 npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
220 finalMatrix = npModelMatrix * npProjMatrix
221 finalMatrix = numpy.linalg.inv(finalMatrix)
223 viewport = map(float, viewport)
224 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))
225 vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
226 ret = list(vector)[0:3] / vector[3]
229 def convert3x3MatrixTo4x4(matrix):
230 return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
232 def loadGLTexture(filename):
233 tex = glGenTextures(1)
234 glBindTexture(GL_TEXTURE_2D, tex)
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
237 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
238 rgbData = img.GetData()
239 alphaData = img.GetAlphaData()
240 if alphaData is not None:
242 for i in xrange(0, len(alphaData)):
243 data += rgbData[i*3:i*3+3] + alphaData[i]
244 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
246 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
249 def ResetMatrixRotationAndScale():
250 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
254 scale2D = matrix[0][0]
265 if matrix[3][2] != 0.0:
266 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
267 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
270 matrix[0][0] = scale2D
271 matrix[1][1] = scale2D
272 matrix[2][2] = scale2D
276 glLoadMatrixf(matrix)
280 def DrawBox(vMin, vMax):
281 glBegin(GL_LINE_LOOP)
282 glVertex3f(vMin[0], vMin[1], vMin[2])
283 glVertex3f(vMax[0], vMin[1], vMin[2])
284 glVertex3f(vMax[0], vMax[1], vMin[2])
285 glVertex3f(vMin[0], vMax[1], vMin[2])
288 glBegin(GL_LINE_LOOP)
289 glVertex3f(vMin[0], vMin[1], vMax[2])
290 glVertex3f(vMax[0], vMin[1], vMax[2])
291 glVertex3f(vMax[0], vMax[1], vMax[2])
292 glVertex3f(vMin[0], vMax[1], vMax[2])
295 glVertex3f(vMin[0], vMin[1], vMin[2])
296 glVertex3f(vMin[0], vMin[1], vMax[2])
297 glVertex3f(vMax[0], vMin[1], vMin[2])
298 glVertex3f(vMax[0], vMin[1], vMax[2])
299 glVertex3f(vMax[0], vMax[1], vMin[2])
300 glVertex3f(vMax[0], vMax[1], vMax[2])
301 glVertex3f(vMin[0], vMax[1], vMin[2])
302 glVertex3f(vMin[0], vMax[1], vMax[2])
306 def DrawMeshOutline(mesh):
307 glEnable(GL_CULL_FACE)
308 glEnableClientState(GL_VERTEX_ARRAY);
309 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
313 glPolygonMode(GL_BACK, GL_LINE)
314 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
315 glPolygonMode(GL_BACK, GL_FILL)
318 glDisableClientState(GL_VERTEX_ARRAY)
321 def DrawMesh(mesh, insideOut = False):
322 glEnable(GL_CULL_FACE)
323 glEnableClientState(GL_VERTEX_ARRAY);
324 glEnableClientState(GL_NORMAL_ARRAY);
325 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
327 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
329 glNormalPointer(GL_FLOAT, 0, mesh.normal)
331 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
332 batchSize = 999 #Warning, batchSize needs to be dividable by 3
333 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
334 extraCount = mesh.vertexCount - extraStartPos
337 for i in xrange(0, int(mesh.vertexCount / batchSize)):
338 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
339 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
343 glNormalPointer(GL_FLOAT, 0, mesh.normal)
345 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
346 for i in xrange(0, int(mesh.vertexCount / batchSize)):
347 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
348 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
349 extraCount = mesh.vertexCount - extraStartPos
350 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
353 glDisableClientState(GL_VERTEX_ARRAY)
354 glDisableClientState(GL_NORMAL_ARRAY)
357 def DrawMeshSteep(mesh, matrix, angle):
358 cosAngle = math.sin(angle / 180.0 * math.pi)
359 glDisable(GL_LIGHTING)
360 glDepthFunc(GL_EQUAL)
361 normals = (numpy.matrix(mesh.normal, copy = False) * matrix).getA()
362 for i in xrange(0, int(mesh.vertexCount), 3):
363 if normals[i][2] < -0.999999:
364 if mesh.vertexes[i + 0][2] > 0.01:
366 glBegin(GL_TRIANGLES)
367 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
368 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
369 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
371 elif normals[i][2] < -cosAngle:
372 glColor3f(-normals[i][2], 0, 0)
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 normals[i][2] > 0.999999:
379 if mesh.vertexes[i + 0][2] > 0.01:
381 glBegin(GL_TRIANGLES)
382 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
383 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
384 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
386 elif normals[i][2] > cosAngle:
387 glColor3f(normals[i][2], 0, 0)
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])
396 def DrawGCodeLayer(layer, drawQuick = True):
397 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
398 filamentArea = math.pi * filamentRadius * filamentRadius
399 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
402 fillColorCycle = [[0.5, 0.5, 0.0, 1], [0.0, 0.5, 0.5, 1], [0.5, 0.0, 0.5, 1]]
403 moveColor = [0, 0, 1, 0.5]
404 retractColor = [1, 0, 0.5, 0.5]
405 supportColor = [0, 1, 1, 1]
406 extrudeColor = [1, 0, 0, 1]
407 innerWallColor = [0, 1, 0, 1]
408 skirtColor = [0, 0.5, 0.5, 1]
409 prevPathWasRetract = False
411 glDisable(GL_CULL_FACE)
413 if path.type == 'move':
414 if prevPathWasRetract:
421 if path.type == 'extrude':
422 if path.pathType == 'FILL':
423 c = fillColorCycle[fillCycle]
424 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' and not drawQuick:
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)