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):
196 width += glutBitmapWidth(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
197 glBitmap(0,0,0,0, -width/2, 0, None)
199 glutBitmapCharacter(OpenGL.GLUT.GLUT_BITMAP_HELVETICA_18, ord(c))
201 def unproject(winx, winy, winz, modelMatrix, projMatrix, viewport):
202 npModelMatrix = numpy.matrix(numpy.array(modelMatrix, numpy.float64).reshape((4,4)))
203 npProjMatrix = numpy.matrix(numpy.array(projMatrix, numpy.float64).reshape((4,4)))
204 finalMatrix = npModelMatrix * npProjMatrix
205 finalMatrix = numpy.linalg.inv(finalMatrix)
207 viewport = map(float, viewport)
208 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))
209 vector = (numpy.matrix(vector) * finalMatrix).getA().flatten()
210 ret = list(vector)[0:3] / vector[3]
213 def convert3x3MatrixTo4x4(matrix):
214 return list(matrix.getA()[0]) + [0] + list(matrix.getA()[1]) + [0] + list(matrix.getA()[2]) + [0, 0,0,0,1]
216 def loadGLTexture(filename):
217 tex = glGenTextures(1)
218 glBindTexture(GL_TEXTURE_2D, tex)
219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
222 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
223 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
224 rgbData = img.GetData()
225 alphaData = img.GetAlphaData()
226 if alphaData != None:
228 for i in xrange(0, len(alphaData)):
229 data += rgbData[i*3:i*3+3] + alphaData[i]
230 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
232 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
235 def ResetMatrixRotationAndScale():
236 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
240 scale2D = matrix[0][0]
251 if matrix[3][2] != 0.0:
252 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
253 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
256 matrix[0][0] = scale2D
257 matrix[1][1] = scale2D
258 matrix[2][2] = scale2D
262 glLoadMatrixf(matrix)
266 def DrawBox(vMin, vMax):
267 glBegin(GL_LINE_LOOP)
268 glVertex3f(vMin[0], vMin[1], vMin[2])
269 glVertex3f(vMax[0], vMin[1], vMin[2])
270 glVertex3f(vMax[0], vMax[1], vMin[2])
271 glVertex3f(vMin[0], vMax[1], vMin[2])
274 glBegin(GL_LINE_LOOP)
275 glVertex3f(vMin[0], vMin[1], vMax[2])
276 glVertex3f(vMax[0], vMin[1], vMax[2])
277 glVertex3f(vMax[0], vMax[1], vMax[2])
278 glVertex3f(vMin[0], vMax[1], vMax[2])
281 glVertex3f(vMin[0], vMin[1], vMin[2])
282 glVertex3f(vMin[0], vMin[1], vMax[2])
283 glVertex3f(vMax[0], vMin[1], vMin[2])
284 glVertex3f(vMax[0], vMin[1], vMax[2])
285 glVertex3f(vMax[0], vMax[1], vMin[2])
286 glVertex3f(vMax[0], vMax[1], vMax[2])
287 glVertex3f(vMin[0], vMax[1], vMin[2])
288 glVertex3f(vMin[0], vMax[1], vMax[2])
292 def DrawMeshOutline(mesh):
293 glEnable(GL_CULL_FACE)
294 glEnableClientState(GL_VERTEX_ARRAY);
295 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
299 glPolygonMode(GL_BACK, GL_LINE)
300 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
301 glPolygonMode(GL_BACK, GL_FILL)
304 glDisableClientState(GL_VERTEX_ARRAY)
308 glEnable(GL_CULL_FACE)
309 glEnableClientState(GL_VERTEX_ARRAY);
310 glEnableClientState(GL_NORMAL_ARRAY);
311 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
312 glNormalPointer(GL_FLOAT, 0, mesh.normal)
314 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
315 batchSize = 999 #Warning, batchSize needs to be dividable by 3
316 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
317 extraCount = mesh.vertexCount - extraStartPos
320 for i in xrange(0, int(mesh.vertexCount / batchSize)):
321 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
322 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
325 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
326 for i in xrange(0, int(mesh.vertexCount / batchSize)):
327 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
328 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
329 extraCount = mesh.vertexCount - extraStartPos
330 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
333 glDisableClientState(GL_VERTEX_ARRAY)
334 glDisableClientState(GL_NORMAL_ARRAY);
337 def DrawMeshSteep(mesh, angle):
338 cosAngle = math.sin(angle / 180.0 * math.pi)
339 glDisable(GL_LIGHTING)
340 glDepthFunc(GL_EQUAL)
341 for i in xrange(0, int(mesh.vertexCount), 3):
342 if mesh.normal[i][2] < -0.999999:
343 if mesh.vertexes[i + 0][2] > 0.01:
345 glBegin(GL_TRIANGLES)
346 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
347 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
348 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
350 elif mesh.normal[i][2] < -cosAngle:
351 glColor3f(-mesh.normal[i][2], 0, 0)
352 glBegin(GL_TRIANGLES)
353 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
354 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
355 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
357 elif mesh.normal[i][2] > 0.999999:
358 if mesh.vertexes[i + 0][2] > 0.01:
360 glBegin(GL_TRIANGLES)
361 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
362 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
363 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
365 elif mesh.normal[i][2] > cosAngle:
366 glColor3f(mesh.normal[i][2], 0, 0)
367 glBegin(GL_TRIANGLES)
368 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
369 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
370 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
375 def DrawGCodeLayer(layer):
376 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
377 filamentArea = math.pi * filamentRadius * filamentRadius
378 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
381 fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
382 moveColor = [0, 0, 1]
383 retractColor = [1, 0, 0.5]
384 supportColor = [0, 1, 1]
385 extrudeColor = [1, 0, 0]
386 innerWallColor = [0, 1, 0]
387 skirtColor = [0, 0.5, 0.5]
388 prevPathWasRetract = False
390 glDisable(GL_CULL_FACE)
392 if path.type == 'move':
393 if prevPathWasRetract:
398 if path.type == 'extrude':
399 if path.pathType == 'FILL':
400 c = fillColorCycle[fillCycle]
401 fillCycle = (fillCycle + 1) % len(fillColorCycle)
402 elif path.pathType == 'WALL-INNER':
405 elif path.pathType == 'SUPPORT':
407 elif path.pathType == 'SKIRT':
411 if path.type == 'retract':
413 if path.type == 'extrude':
416 for i in xrange(0, len(path.list) - 1):
418 v1 = path.list[i + 1]
420 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
421 dist = (v0 - v1).vsize()
422 if dist > 0 and path.layerThickness > 0:
423 extrusionMMperDist = (v1.e - v0.e) / dist
424 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
426 drawLength += (v0 - v1).vsize()
427 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
430 vv2 = v0 + normal * lineWidth
431 vv3 = v1 + normal * lineWidth
432 vv0 = v0 - normal * lineWidth
433 vv1 = v1 - normal * lineWidth
437 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
438 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
439 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
440 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
442 if prevNormal is not None:
443 n = (normal + prevNormal)
445 vv4 = v0 + n * lineWidth
446 vv5 = v0 - n * lineWidth
449 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
450 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
451 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
452 glVertex3f(v0.x, v0.y, v0.z - zOffset)
454 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
455 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
456 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
457 glVertex3f(v0.x, v0.y, v0.z - zOffset)
464 glBegin(GL_LINE_STRIP)
467 glVertex3f(v.x, v.y, v.z)
469 if not path.type == 'move':
470 prevPathWasRetract = False
471 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
472 prevPathWasRetract = True
473 glEnable(GL_CULL_FACE)