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 img = wx.ImageFromBitmap(wx.Bitmap(getPathForImage(filename)))
222 rgbData = img.GetData()
223 alphaData = img.GetAlphaData()
224 if alphaData is not None:
226 for i in xrange(0, len(alphaData)):
227 data += rgbData[i*3:i*3+3] + alphaData[i]
228 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
230 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, rgbData)
233 def ResetMatrixRotationAndScale():
234 matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
238 scale2D = matrix[0][0]
249 if matrix[3][2] != 0.0:
250 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
251 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
254 matrix[0][0] = scale2D
255 matrix[1][1] = scale2D
256 matrix[2][2] = scale2D
260 glLoadMatrixf(matrix)
264 def DrawBox(vMin, vMax):
265 glBegin(GL_LINE_LOOP)
266 glVertex3f(vMin[0], vMin[1], vMin[2])
267 glVertex3f(vMax[0], vMin[1], vMin[2])
268 glVertex3f(vMax[0], vMax[1], vMin[2])
269 glVertex3f(vMin[0], vMax[1], vMin[2])
272 glBegin(GL_LINE_LOOP)
273 glVertex3f(vMin[0], vMin[1], vMax[2])
274 glVertex3f(vMax[0], vMin[1], vMax[2])
275 glVertex3f(vMax[0], vMax[1], vMax[2])
276 glVertex3f(vMin[0], vMax[1], vMax[2])
279 glVertex3f(vMin[0], vMin[1], vMin[2])
280 glVertex3f(vMin[0], vMin[1], vMax[2])
281 glVertex3f(vMax[0], vMin[1], vMin[2])
282 glVertex3f(vMax[0], vMin[1], vMax[2])
283 glVertex3f(vMax[0], vMax[1], vMin[2])
284 glVertex3f(vMax[0], vMax[1], vMax[2])
285 glVertex3f(vMin[0], vMax[1], vMin[2])
286 glVertex3f(vMin[0], vMax[1], vMax[2])
290 def DrawMeshOutline(mesh):
291 glEnable(GL_CULL_FACE)
292 glEnableClientState(GL_VERTEX_ARRAY);
293 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
297 glPolygonMode(GL_BACK, GL_LINE)
298 glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
299 glPolygonMode(GL_BACK, GL_FILL)
302 glDisableClientState(GL_VERTEX_ARRAY)
306 glEnable(GL_CULL_FACE)
307 glEnableClientState(GL_VERTEX_ARRAY);
308 glEnableClientState(GL_NORMAL_ARRAY);
309 glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
310 glNormalPointer(GL_FLOAT, 0, mesh.normal)
312 #Odd, drawing in batchs is a LOT faster then drawing it all at once.
313 batchSize = 999 #Warning, batchSize needs to be dividable by 3
314 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
315 extraCount = mesh.vertexCount - extraStartPos
318 for i in xrange(0, int(mesh.vertexCount / batchSize)):
319 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
320 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
323 glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
324 for i in xrange(0, int(mesh.vertexCount / batchSize)):
325 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
326 extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
327 extraCount = mesh.vertexCount - extraStartPos
328 glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
331 glDisableClientState(GL_VERTEX_ARRAY)
332 glDisableClientState(GL_NORMAL_ARRAY);
335 def DrawMeshSteep(mesh, matrix, angle):
336 cosAngle = math.sin(angle / 180.0 * math.pi)
337 glDisable(GL_LIGHTING)
338 glDepthFunc(GL_EQUAL)
339 normals = (numpy.matrix(mesh.normal, copy = False) * matrix).getA()
340 for i in xrange(0, int(mesh.vertexCount), 3):
341 if normals[i][2] < -0.999999:
342 if mesh.vertexes[i + 0][2] > 0.01:
344 glBegin(GL_TRIANGLES)
345 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
346 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
347 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
349 elif normals[i][2] < -cosAngle:
350 glColor3f(-normals[i][2], 0, 0)
351 glBegin(GL_TRIANGLES)
352 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
353 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
354 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
356 elif normals[i][2] > 0.999999:
357 if mesh.vertexes[i + 0][2] > 0.01:
359 glBegin(GL_TRIANGLES)
360 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
361 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
362 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
364 elif normals[i][2] > cosAngle:
365 glColor3f(normals[i][2], 0, 0)
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 + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
369 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
374 def DrawGCodeLayer(layer):
375 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
376 filamentArea = math.pi * filamentRadius * filamentRadius
377 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
380 fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
381 moveColor = [0, 0, 1]
382 retractColor = [1, 0, 0.5]
383 supportColor = [0, 1, 1]
384 extrudeColor = [1, 0, 0]
385 innerWallColor = [0, 1, 0]
386 skirtColor = [0, 0.5, 0.5]
387 prevPathWasRetract = False
389 glDisable(GL_CULL_FACE)
391 if path.type == 'move':
392 if prevPathWasRetract:
397 if path.type == 'extrude':
398 if path.pathType == 'FILL':
399 c = fillColorCycle[fillCycle]
400 fillCycle = (fillCycle + 1) % len(fillColorCycle)
401 elif path.pathType == 'WALL-INNER':
404 elif path.pathType == 'SUPPORT':
406 elif path.pathType == 'SKIRT':
410 if path.type == 'retract':
412 if path.type == 'extrude':
415 for i in xrange(0, len(path.list) - 1):
417 v1 = path.list[i + 1]
419 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
420 dist = (v0 - v1).vsize()
421 if dist > 0 and path.layerThickness > 0:
422 extrusionMMperDist = (v1.e - v0.e) / dist
423 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
425 drawLength += (v0 - v1).vsize()
426 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
429 vv2 = v0 + normal * lineWidth
430 vv3 = v1 + normal * lineWidth
431 vv0 = v0 - normal * lineWidth
432 vv1 = v1 - normal * lineWidth
436 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
437 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
438 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
439 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
441 if prevNormal is not None:
442 n = (normal + prevNormal)
444 vv4 = v0 + n * lineWidth
445 vv5 = v0 - n * lineWidth
448 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
449 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
450 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
451 glVertex3f(v0.x, v0.y, v0.z - zOffset)
453 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
454 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
455 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
456 glVertex3f(v0.x, v0.y, v0.z - zOffset)
463 glBegin(GL_LINE_STRIP)
466 glVertex3f(v.x, v.y, v.z)
468 if not path.type == 'move':
469 prevPathWasRetract = False
470 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
471 prevPathWasRetract = True
472 glEnable(GL_CULL_FACE)