chiark / gitweb /
Keep working when the platform stl is missing.
[cura.git] / Cura / gui / util / opengl.py
1 # coding=utf-8
2 from __future__ import absolute_import
3
4 import math
5
6 from Cura.util import meshLoader
7 from Cura.util import util3d
8 from Cura.util import profile
9 from Cura.util.resources import getPathForMesh
10
11 try:
12         import OpenGL
13
14         OpenGL.ERROR_CHECKING = False
15         from OpenGL.GLU import *
16         from OpenGL.GL import *
17
18         hasOpenGLlibs = True
19 except:
20         print "Failed to find PyOpenGL: http://pyopengl.sourceforge.net/"
21         hasOpenGLlibs = False
22
23 def InitGL(window, view3D, zoom):
24         # set viewing projection
25         glMatrixMode(GL_MODELVIEW)
26         glLoadIdentity()
27         size = window.GetSize()
28         glViewport(0, 0, size.GetWidth(), size.GetHeight())
29
30         glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
31         glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
32
33         glEnable(GL_RESCALE_NORMAL)
34         glEnable(GL_LIGHTING)
35         glEnable(GL_LIGHT0)
36         glEnable(GL_DEPTH_TEST)
37         glEnable(GL_CULL_FACE)
38         glDisable(GL_BLEND)
39
40         glClearColor(1.0, 1.0, 1.0, 1.0)
41         glClearStencil(0)
42         glClearDepth(1.0)
43
44         glMatrixMode(GL_PROJECTION)
45         glLoadIdentity()
46         aspect = float(size.GetWidth()) / float(size.GetHeight())
47         if view3D:
48                 gluPerspective(45.0, aspect, 1.0, 1000.0)
49         else:
50                 glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
51
52         glMatrixMode(GL_MODELVIEW)
53         glLoadIdentity()
54         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
55
56 platformMesh = None
57
58 def DrawMachine(machineSize):
59         if profile.getPreference('machine_type') == 'ultimaker':
60                 glPushMatrix()
61                 glEnable(GL_LIGHTING)
62                 glTranslate(100, 200, -5)
63                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
64                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
65                 glEnable(GL_BLEND)
66                 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
67
68                 global platformMesh
69                 if platformMesh is None:
70                         try:
71                                 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
72                                 platformMesh.setRotateMirror(0, False, False, False, False, False)
73                         except:
74                                 platformMesh = False
75
76                 if platformMesh:
77                         DrawMesh(platformMesh)
78                 glPopMatrix()
79
80         glDisable(GL_LIGHTING)
81         if False:
82                 glColor3f(0.7, 0.7, 0.7)
83                 glLineWidth(2)
84                 glBegin(GL_LINES)
85                 for i in xrange(0, int(machineSize.x), 10):
86                         glVertex3f(i, 0, 0)
87                         glVertex3f(i, machineSize.y, 0)
88                 for i in xrange(0, int(machineSize.y), 10):
89                         glVertex3f(0, i, 0)
90                         glVertex3f(machineSize.x, i, 0)
91                 glEnd()
92
93                 glEnable(GL_LINE_SMOOTH)
94                 glEnable(GL_BLEND)
95                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
96                 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
97
98                 glColor3f(0.0, 0.0, 0.0)
99                 glLineWidth(4)
100                 glBegin(GL_LINE_LOOP)
101                 glVertex3f(0, 0, 0)
102                 glVertex3f(machineSize.x, 0, 0)
103                 glVertex3f(machineSize.x, machineSize.y, 0)
104                 glVertex3f(0, machineSize.y, 0)
105                 glEnd()
106
107                 glLineWidth(2)
108                 glBegin(GL_LINE_LOOP)
109                 glVertex3f(0, 0, machineSize.z)
110                 glVertex3f(machineSize.x, 0, machineSize.z)
111                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
112                 glVertex3f(0, machineSize.y, machineSize.z)
113                 glEnd()
114                 glBegin(GL_LINES)
115                 glVertex3f(0, 0, 0)
116                 glVertex3f(0, 0, machineSize.z)
117                 glVertex3f(machineSize.x, 0, 0)
118                 glVertex3f(machineSize.x, 0, machineSize.z)
119                 glVertex3f(machineSize.x, machineSize.y, 0)
120                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
121                 glVertex3f(0, machineSize.y, 0)
122                 glVertex3f(0, machineSize.y, machineSize.z)
123                 glEnd()
124         else:
125                 glDisable(GL_CULL_FACE)
126                 glEnable(GL_BLEND)
127                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
128
129                 sx = machineSize.x
130                 sy = machineSize.y
131                 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
132                         for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
133                                 x1 = sx/2+x * 10
134                                 x2 = x1 + 10
135                                 y1 = sx/2+y * 10
136                                 y2 = y1 + 10
137                                 x1 = max(min(x1, sx), 0)
138                                 y1 = max(min(y1, sy), 0)
139                                 x2 = max(min(x2, sx), 0)
140                                 y2 = max(min(y2, sy), 0)
141                                 if (x & 1) == (y & 1):
142                                         glColor4ub(5, 171, 231, 127)
143                                 else:
144                                         glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
145                                 glBegin(GL_QUADS)
146                                 glVertex3f(x1, y1, -0.01)
147                                 glVertex3f(x2, y1, -0.01)
148                                 glVertex3f(x2, y2, -0.01)
149                                 glVertex3f(x1, y2, -0.01)
150                                 glEnd()
151
152                 glEnable(GL_CULL_FACE)
153
154                 glColor4ub(5, 171, 231, 64)
155                 glBegin(GL_QUADS)
156                 glVertex3f(0, 0, machineSize.z)
157                 glVertex3f(0, machineSize.y, machineSize.z)
158                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
159                 glVertex3f(machineSize.x, 0, machineSize.z)
160                 glEnd()
161
162                 glColor4ub(5, 171, 231, 96)
163                 glBegin(GL_QUADS)
164                 glVertex3f(0, 0, 0)
165                 glVertex3f(0, 0, machineSize.z)
166                 glVertex3f(machineSize.x, 0, machineSize.z)
167                 glVertex3f(machineSize.x, 0, 0)
168
169                 glVertex3f(0, machineSize.y, machineSize.z)
170                 glVertex3f(0, machineSize.y, 0)
171                 glVertex3f(machineSize.x, machineSize.y, 0)
172                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
173                 glEnd()
174
175                 glColor4ub(5, 171, 231, 128)
176                 glBegin(GL_QUADS)
177                 glVertex3f(0, 0, machineSize.z)
178                 glVertex3f(0, 0, 0)
179                 glVertex3f(0, machineSize.y, 0)
180                 glVertex3f(0, machineSize.y, machineSize.z)
181
182                 glVertex3f(machineSize.x, 0, 0)
183                 glVertex3f(machineSize.x, 0, machineSize.z)
184                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
185                 glVertex3f(machineSize.x, machineSize.y, 0)
186                 glEnd()
187
188                 glDisable(GL_BLEND)
189
190         glPushMatrix()
191         glTranslate(5, 5, 2)
192         glLineWidth(2)
193         glColor3f(0.5, 0, 0)
194         glBegin(GL_LINES)
195         glVertex3f(0, 0, 0)
196         glVertex3f(20, 0, 0)
197         glEnd()
198         glColor3f(0, 0.5, 0)
199         glBegin(GL_LINES)
200         glVertex3f(0, 0, 0)
201         glVertex3f(0, 20, 0)
202         glEnd()
203         glColor3f(0, 0, 0.5)
204         glBegin(GL_LINES)
205         glVertex3f(0, 0, 0)
206         glVertex3f(0, 0, 20)
207         glEnd()
208
209         glDisable(GL_DEPTH_TEST)
210         #X
211         glColor3f(1, 0, 0)
212         glPushMatrix()
213         glTranslate(23, 0, 0)
214         noZ = ResetMatrixRotationAndScale()
215         glBegin(GL_LINES)
216         glVertex3f(-0.8, 1, 0)
217         glVertex3f(0.8, -1, 0)
218         glVertex3f(0.8, 1, 0)
219         glVertex3f(-0.8, -1, 0)
220         glEnd()
221         glPopMatrix()
222
223         #Y
224         glColor3f(0, 1, 0)
225         glPushMatrix()
226         glTranslate(0, 23, 0)
227         ResetMatrixRotationAndScale()
228         glBegin(GL_LINES)
229         glVertex3f(-0.8, 1, 0)
230         glVertex3f(0.0, 0, 0)
231         glVertex3f(0.8, 1, 0)
232         glVertex3f(-0.8, -1, 0)
233         glEnd()
234         glPopMatrix()
235
236         #Z
237         if not noZ:
238                 glColor3f(0, 0, 1)
239                 glPushMatrix()
240                 glTranslate(0, 0, 23)
241                 ResetMatrixRotationAndScale()
242                 glBegin(GL_LINES)
243                 glVertex3f(-0.8, 1, 0)
244                 glVertex3f(0.8, 1, 0)
245                 glVertex3f(0.8, 1, 0)
246                 glVertex3f(-0.8, -1, 0)
247                 glVertex3f(-0.8, -1, 0)
248                 glVertex3f(0.8, -1, 0)
249                 glEnd()
250                 glPopMatrix()
251
252         glPopMatrix()
253         glEnable(GL_DEPTH_TEST)
254
255
256 def ResetMatrixRotationAndScale():
257         matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
258         noZ = False
259         if matrix[3][2] > 0:
260                 return False
261         scale2D = matrix[0][0]
262         matrix[0][0] = 1.0
263         matrix[1][0] = 0.0
264         matrix[2][0] = 0.0
265         matrix[0][1] = 0.0
266         matrix[1][1] = 1.0
267         matrix[2][1] = 0.0
268         matrix[0][2] = 0.0
269         matrix[1][2] = 0.0
270         matrix[2][2] = 1.0
271
272         if matrix[3][2] != 0.0:
273                 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
274                 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
275                 matrix[3][2] = -100
276         else:
277                 matrix[0][0] = scale2D
278                 matrix[1][1] = scale2D
279                 matrix[2][2] = scale2D
280                 matrix[3][2] = -100
281                 noZ = True
282
283         glLoadMatrixf(matrix)
284         return noZ
285
286
287 def DrawBox(vMin, vMax):
288         glBegin(GL_LINE_LOOP)
289         glVertex3f(vMin[0], vMin[1], vMin[2])
290         glVertex3f(vMax[0], vMin[1], vMin[2])
291         glVertex3f(vMax[0], vMax[1], vMin[2])
292         glVertex3f(vMin[0], vMax[1], vMin[2])
293         glEnd()
294
295         glBegin(GL_LINE_LOOP)
296         glVertex3f(vMin[0], vMin[1], vMax[2])
297         glVertex3f(vMax[0], vMin[1], vMax[2])
298         glVertex3f(vMax[0], vMax[1], vMax[2])
299         glVertex3f(vMin[0], vMax[1], vMax[2])
300         glEnd()
301         glBegin(GL_LINES)
302         glVertex3f(vMin[0], vMin[1], vMin[2])
303         glVertex3f(vMin[0], vMin[1], vMax[2])
304         glVertex3f(vMax[0], vMin[1], vMin[2])
305         glVertex3f(vMax[0], vMin[1], vMax[2])
306         glVertex3f(vMax[0], vMax[1], vMin[2])
307         glVertex3f(vMax[0], vMax[1], vMax[2])
308         glVertex3f(vMin[0], vMax[1], vMin[2])
309         glVertex3f(vMin[0], vMax[1], vMax[2])
310         glEnd()
311
312
313 def DrawMeshOutline(mesh):
314         glEnable(GL_CULL_FACE)
315         glEnableClientState(GL_VERTEX_ARRAY);
316         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
317
318         glCullFace(GL_FRONT)
319         glLineWidth(3)
320         glPolygonMode(GL_BACK, GL_LINE)
321         glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
322         glPolygonMode(GL_BACK, GL_FILL)
323         glCullFace(GL_BACK)
324
325         glDisableClientState(GL_VERTEX_ARRAY)
326
327
328 def DrawMesh(mesh):
329         glEnable(GL_CULL_FACE)
330         glEnableClientState(GL_VERTEX_ARRAY);
331         glEnableClientState(GL_NORMAL_ARRAY);
332         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
333         glNormalPointer(GL_FLOAT, 0, mesh.normal)
334
335         #Odd, drawing in batchs is a LOT faster then drawing it all at once.
336         batchSize = 999    #Warning, batchSize needs to be dividable by 3
337         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
338         extraCount = mesh.vertexCount - extraStartPos
339
340         glCullFace(GL_BACK)
341         for i in xrange(0, int(mesh.vertexCount / batchSize)):
342                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
343         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
344
345         glCullFace(GL_FRONT)
346         glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
347         for i in xrange(0, int(mesh.vertexCount / batchSize)):
348                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
349         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
350         extraCount = mesh.vertexCount - extraStartPos
351         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
352         glCullFace(GL_BACK)
353
354         glDisableClientState(GL_VERTEX_ARRAY)
355         glDisableClientState(GL_NORMAL_ARRAY);
356
357
358 def DrawMeshSteep(mesh, angle):
359         cosAngle = math.sin(angle / 180.0 * math.pi)
360         glDisable(GL_LIGHTING)
361         glDepthFunc(GL_EQUAL)
362         for i in xrange(0, int(mesh.vertexCount), 3):
363                 if mesh.normal[i][2] < -0.999999:
364                         if mesh.vertexes[i + 0][2] > 0.01:
365                                 glColor3f(0.5, 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 + 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])
370                                 glEnd()
371                 elif mesh.normal[i][2] < -cosAngle:
372                         glColor3f(-mesh.normal[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])
377                         glEnd()
378                 elif mesh.normal[i][2] > 0.999999:
379                         if mesh.vertexes[i + 0][2] > 0.01:
380                                 glColor3f(0.5, 0, 0)
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])
385                                 glEnd()
386                 elif mesh.normal[i][2] > cosAngle:
387                         glColor3f(mesh.normal[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])
392                         glEnd()
393         glDepthFunc(GL_LESS)
394
395
396 def DrawGCodeLayer(layer):
397         filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
398         filamentArea = math.pi * filamentRadius * filamentRadius
399         lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
400
401         fillCycle = 0
402         fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
403         moveColor = [0, 0, 1]
404         retractColor = [1, 0, 0.5]
405         supportColor = [0, 1, 1]
406         extrudeColor = [1, 0, 0]
407         innerWallColor = [0, 1, 0]
408         skirtColor = [0, 0.5, 0.5]
409         prevPathWasRetract = False
410
411         glDisable(GL_CULL_FACE)
412         for path in layer:
413                 if path.type == 'move':
414                         if prevPathWasRetract:
415                                 c = retractColor
416                         else:
417                                 c = moveColor
418                 zOffset = 0.01
419                 if path.type == 'extrude':
420                         if path.pathType == 'FILL':
421                                 c = fillColorCycle[fillCycle]
422                                 fillCycle = (fillCycle + 1) % len(fillColorCycle)
423                         elif path.pathType == 'WALL-INNER':
424                                 c = innerWallColor
425                                 zOffset = 0.02
426                         elif path.pathType == 'SUPPORT':
427                                 c = supportColor
428                         elif path.pathType == 'SKIRT':
429                                 c = skirtColor
430                         else:
431                                 c = extrudeColor
432                 if path.type == 'retract':
433                         c = [0, 1, 1]
434                 if path.type == 'extrude':
435                         drawLength = 0.0
436                         prevNormal = None
437                         for i in xrange(0, len(path.list) - 1):
438                                 v0 = path.list[i]
439                                 v1 = path.list[i + 1]
440
441                                 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
442                                 dist = (v0 - v1).vsize()
443                                 if dist > 0 and path.layerThickness > 0:
444                                         extrusionMMperDist = (v1.e - v0.e) / dist
445                                         lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
446
447                                 drawLength += (v0 - v1).vsize()
448                                 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
449                                 normal.normalize()
450
451                                 vv2 = v0 + normal * lineWidth
452                                 vv3 = v1 + normal * lineWidth
453                                 vv0 = v0 - normal * lineWidth
454                                 vv1 = v1 - normal * lineWidth
455
456                                 glBegin(GL_QUADS)
457                                 glColor3fv(c)
458                                 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
459                                 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
460                                 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
461                                 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
462                                 glEnd()
463                                 if prevNormal is not None:
464                                         n = (normal + prevNormal)
465                                         n.normalize()
466                                         vv4 = v0 + n * lineWidth
467                                         vv5 = v0 - n * lineWidth
468                                         glBegin(GL_QUADS)
469                                         glColor3fv(c)
470                                         glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
471                                         glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
472                                         glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
473                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
474
475                                         glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
476                                         glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
477                                         glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
478                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
479                                         glEnd()
480
481                                 prevNormal = normal
482                                 prevVv1 = vv1
483                                 prevVv3 = vv3
484                 else:
485                         glBegin(GL_LINE_STRIP)
486                         glColor3fv(c)
487                         for v in path.list:
488                                 glVertex3f(v.x, v.y, v.z)
489                         glEnd()
490                 if not path.type == 'move':
491                         prevPathWasRetract = False
492                 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
493                         prevPathWasRetract = True
494         glEnable(GL_CULL_FACE)