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, angle):
336 cosAngle = math.sin(angle / 180.0 * math.pi)
337 glDisable(GL_LIGHTING)
338 glDepthFunc(GL_EQUAL)
339 for i in xrange(0, int(mesh.vertexCount), 3):
340 if mesh.normal[i][2] < -0.999999:
341 if mesh.vertexes[i + 0][2] > 0.01:
343 glBegin(GL_TRIANGLES)
344 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
345 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
346 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
348 elif mesh.normal[i][2] < -cosAngle:
349 glColor3f(-mesh.normal[i][2], 0, 0)
350 glBegin(GL_TRIANGLES)
351 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
352 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
353 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
355 elif mesh.normal[i][2] > 0.999999:
356 if mesh.vertexes[i + 0][2] > 0.01:
358 glBegin(GL_TRIANGLES)
359 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
360 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
361 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
363 elif mesh.normal[i][2] > cosAngle:
364 glColor3f(mesh.normal[i][2], 0, 0)
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 + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
368 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
373 def DrawGCodeLayer(layer):
374 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
375 filamentArea = math.pi * filamentRadius * filamentRadius
376 lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
379 fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
380 moveColor = [0, 0, 1]
381 retractColor = [1, 0, 0.5]
382 supportColor = [0, 1, 1]
383 extrudeColor = [1, 0, 0]
384 innerWallColor = [0, 1, 0]
385 skirtColor = [0, 0.5, 0.5]
386 prevPathWasRetract = False
388 glDisable(GL_CULL_FACE)
390 if path.type == 'move':
391 if prevPathWasRetract:
396 if path.type == 'extrude':
397 if path.pathType == 'FILL':
398 c = fillColorCycle[fillCycle]
399 fillCycle = (fillCycle + 1) % len(fillColorCycle)
400 elif path.pathType == 'WALL-INNER':
403 elif path.pathType == 'SUPPORT':
405 elif path.pathType == 'SKIRT':
409 if path.type == 'retract':
411 if path.type == 'extrude':
414 for i in xrange(0, len(path.list) - 1):
416 v1 = path.list[i + 1]
418 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
419 dist = (v0 - v1).vsize()
420 if dist > 0 and path.layerThickness > 0:
421 extrusionMMperDist = (v1.e - v0.e) / dist
422 lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
424 drawLength += (v0 - v1).vsize()
425 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
428 vv2 = v0 + normal * lineWidth
429 vv3 = v1 + normal * lineWidth
430 vv0 = v0 - normal * lineWidth
431 vv1 = v1 - normal * lineWidth
435 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
436 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
437 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
438 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
440 if prevNormal is not None:
441 n = (normal + prevNormal)
443 vv4 = v0 + n * lineWidth
444 vv5 = v0 - n * lineWidth
447 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
448 glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
449 glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
450 glVertex3f(v0.x, v0.y, v0.z - zOffset)
452 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
453 glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
454 glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
455 glVertex3f(v0.x, v0.y, v0.z - zOffset)
462 glBegin(GL_LINE_STRIP)
465 glVertex3f(v.x, v.y, v.z)
467 if not path.type == 'move':
468 prevPathWasRetract = False
469 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
470 prevPathWasRetract = True
471 glEnable(GL_CULL_FACE)