chiark / gitweb /
Merge remote-tracking branch 'upstream/master'
[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 == None:
70                         platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
71                         platformMesh.setRotateMirror(0, False, False, False, False, False)
72
73                 DrawMesh(platformMesh)
74                 glPopMatrix()
75
76         glDisable(GL_LIGHTING)
77         if False:
78                 glColor3f(0.7, 0.7, 0.7)
79                 glLineWidth(2)
80                 glBegin(GL_LINES)
81                 for i in xrange(0, int(machineSize.x), 10):
82                         glVertex3f(i, 0, 0)
83                         glVertex3f(i, machineSize.y, 0)
84                 for i in xrange(0, int(machineSize.y), 10):
85                         glVertex3f(0, i, 0)
86                         glVertex3f(machineSize.x, i, 0)
87                 glEnd()
88
89                 glEnable(GL_LINE_SMOOTH)
90                 glEnable(GL_BLEND)
91                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
92                 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
93
94                 glColor3f(0.0, 0.0, 0.0)
95                 glLineWidth(4)
96                 glBegin(GL_LINE_LOOP)
97                 glVertex3f(0, 0, 0)
98                 glVertex3f(machineSize.x, 0, 0)
99                 glVertex3f(machineSize.x, machineSize.y, 0)
100                 glVertex3f(0, machineSize.y, 0)
101                 glEnd()
102
103                 glLineWidth(2)
104                 glBegin(GL_LINE_LOOP)
105                 glVertex3f(0, 0, machineSize.z)
106                 glVertex3f(machineSize.x, 0, machineSize.z)
107                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
108                 glVertex3f(0, machineSize.y, machineSize.z)
109                 glEnd()
110                 glBegin(GL_LINES)
111                 glVertex3f(0, 0, 0)
112                 glVertex3f(0, 0, machineSize.z)
113                 glVertex3f(machineSize.x, 0, 0)
114                 glVertex3f(machineSize.x, 0, machineSize.z)
115                 glVertex3f(machineSize.x, machineSize.y, 0)
116                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
117                 glVertex3f(0, machineSize.y, 0)
118                 glVertex3f(0, machineSize.y, machineSize.z)
119                 glEnd()
120         else:
121                 glDisable(GL_CULL_FACE)
122                 glEnable(GL_BLEND)
123                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
124                 glColor4ub(5, 171, 231, 127)
125                 glBegin(GL_QUADS)
126                 for x in xrange(0, int(machineSize.x), 20):
127                         for y in xrange(0, int(machineSize.y), 20):
128                                 glVertex3f(x, y, -0.01)
129                                 glVertex3f(min(x + 10, machineSize.x), y, -0.01)
130                                 glVertex3f(min(x + 10, machineSize.x), min(y + 10, machineSize.y), -0.01)
131                                 glVertex3f(x, min(y + 10, machineSize.y), -0.01)
132                 for x in xrange(10, int(machineSize.x), 20):
133                         for y in xrange(10, int(machineSize.y), 20):
134                                 glVertex3f(x, y, -0.01)
135                                 glVertex3f(min(x + 10, machineSize.x), y, -0.01)
136                                 glVertex3f(min(x + 10, machineSize.x), min(y + 10, machineSize.y), -0.01)
137                                 glVertex3f(x, min(y + 10, machineSize.y), -0.01)
138                 glEnd()
139                 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
140                 glBegin(GL_QUADS)
141                 for x in xrange(10, int(machineSize.x), 20):
142                         for y in xrange(0, int(machineSize.y), 20):
143                                 glVertex3f(x, y, -0.01)
144                                 glVertex3f(min(x + 10, machineSize.x), y, -0.01)
145                                 glVertex3f(min(x + 10, machineSize.x), min(y + 10, machineSize.y), -0.01)
146                                 glVertex3f(x, min(y + 10, machineSize.y), -0.01)
147                 for x in xrange(0, int(machineSize.x), 20):
148                         for y in xrange(10, int(machineSize.y), 20):
149                                 glVertex3f(x, y, -0.01)
150                                 glVertex3f(min(x + 10, machineSize.x), y, -0.01)
151                                 glVertex3f(min(x + 10, machineSize.x), min(y + 10, machineSize.y), -0.01)
152                                 glVertex3f(x, min(y + 10, machineSize.y), -0.01)
153                 glEnd()
154                 glEnable(GL_CULL_FACE)
155
156                 glColor4ub(5, 171, 231, 64)
157                 glBegin(GL_QUADS)
158                 glVertex3f(0, 0, machineSize.z)
159                 glVertex3f(0, machineSize.y, machineSize.z)
160                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
161                 glVertex3f(machineSize.x, 0, machineSize.z)
162                 glEnd()
163
164                 glColor4ub(5, 171, 231, 96)
165                 glBegin(GL_QUADS)
166                 glVertex3f(0, 0, 0)
167                 glVertex3f(0, 0, machineSize.z)
168                 glVertex3f(machineSize.x, 0, machineSize.z)
169                 glVertex3f(machineSize.x, 0, 0)
170
171                 glVertex3f(0, machineSize.y, machineSize.z)
172                 glVertex3f(0, machineSize.y, 0)
173                 glVertex3f(machineSize.x, machineSize.y, 0)
174                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
175                 glEnd()
176
177                 glColor4ub(5, 171, 231, 128)
178                 glBegin(GL_QUADS)
179                 glVertex3f(0, 0, machineSize.z)
180                 glVertex3f(0, 0, 0)
181                 glVertex3f(0, machineSize.y, 0)
182                 glVertex3f(0, machineSize.y, machineSize.z)
183
184                 glVertex3f(machineSize.x, 0, 0)
185                 glVertex3f(machineSize.x, 0, machineSize.z)
186                 glVertex3f(machineSize.x, machineSize.y, machineSize.z)
187                 glVertex3f(machineSize.x, machineSize.y, 0)
188                 glEnd()
189
190                 glDisable(GL_BLEND)
191
192         glPushMatrix()
193         glTranslate(5, 5, 2)
194         glLineWidth(2)
195         glColor3f(0.5, 0, 0)
196         glBegin(GL_LINES)
197         glVertex3f(0, 0, 0)
198         glVertex3f(20, 0, 0)
199         glEnd()
200         glColor3f(0, 0.5, 0)
201         glBegin(GL_LINES)
202         glVertex3f(0, 0, 0)
203         glVertex3f(0, 20, 0)
204         glEnd()
205         glColor3f(0, 0, 0.5)
206         glBegin(GL_LINES)
207         glVertex3f(0, 0, 0)
208         glVertex3f(0, 0, 20)
209         glEnd()
210
211         glDisable(GL_DEPTH_TEST)
212         #X
213         glColor3f(1, 0, 0)
214         glPushMatrix()
215         glTranslate(23, 0, 0)
216         noZ = ResetMatrixRotationAndScale()
217         glBegin(GL_LINES)
218         glVertex3f(-0.8, 1, 0)
219         glVertex3f(0.8, -1, 0)
220         glVertex3f(0.8, 1, 0)
221         glVertex3f(-0.8, -1, 0)
222         glEnd()
223         glPopMatrix()
224
225         #Y
226         glColor3f(0, 1, 0)
227         glPushMatrix()
228         glTranslate(0, 23, 0)
229         ResetMatrixRotationAndScale()
230         glBegin(GL_LINES)
231         glVertex3f(-0.8, 1, 0)
232         glVertex3f(0.0, 0, 0)
233         glVertex3f(0.8, 1, 0)
234         glVertex3f(-0.8, -1, 0)
235         glEnd()
236         glPopMatrix()
237
238         #Z
239         if not noZ:
240                 glColor3f(0, 0, 1)
241                 glPushMatrix()
242                 glTranslate(0, 0, 23)
243                 ResetMatrixRotationAndScale()
244                 glBegin(GL_LINES)
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                 glVertex3f(-0.8, -1, 0)
250                 glVertex3f(0.8, -1, 0)
251                 glEnd()
252                 glPopMatrix()
253
254         glPopMatrix()
255         glEnable(GL_DEPTH_TEST)
256
257
258 def ResetMatrixRotationAndScale():
259         matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
260         noZ = False
261         if matrix[3][2] > 0:
262                 return False
263         scale2D = matrix[0][0]
264         matrix[0][0] = 1.0
265         matrix[1][0] = 0.0
266         matrix[2][0] = 0.0
267         matrix[0][1] = 0.0
268         matrix[1][1] = 1.0
269         matrix[2][1] = 0.0
270         matrix[0][2] = 0.0
271         matrix[1][2] = 0.0
272         matrix[2][2] = 1.0
273
274         if matrix[3][2] != 0.0:
275                 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
276                 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
277                 matrix[3][2] = -100
278         else:
279                 matrix[0][0] = scale2D
280                 matrix[1][1] = scale2D
281                 matrix[2][2] = scale2D
282                 matrix[3][2] = -100
283                 noZ = True
284
285         glLoadMatrixf(matrix)
286         return noZ
287
288
289 def DrawBox(vMin, vMax):
290         glBegin(GL_LINE_LOOP)
291         glVertex3f(vMin[0], vMin[1], vMin[2])
292         glVertex3f(vMax[0], vMin[1], vMin[2])
293         glVertex3f(vMax[0], vMax[1], vMin[2])
294         glVertex3f(vMin[0], vMax[1], vMin[2])
295         glEnd()
296
297         glBegin(GL_LINE_LOOP)
298         glVertex3f(vMin[0], vMin[1], vMax[2])
299         glVertex3f(vMax[0], vMin[1], vMax[2])
300         glVertex3f(vMax[0], vMax[1], vMax[2])
301         glVertex3f(vMin[0], vMax[1], vMax[2])
302         glEnd()
303         glBegin(GL_LINES)
304         glVertex3f(vMin[0], vMin[1], vMin[2])
305         glVertex3f(vMin[0], vMin[1], vMax[2])
306         glVertex3f(vMax[0], vMin[1], vMin[2])
307         glVertex3f(vMax[0], vMin[1], vMax[2])
308         glVertex3f(vMax[0], vMax[1], vMin[2])
309         glVertex3f(vMax[0], vMax[1], vMax[2])
310         glVertex3f(vMin[0], vMax[1], vMin[2])
311         glVertex3f(vMin[0], vMax[1], vMax[2])
312         glEnd()
313
314
315 def DrawMeshOutline(mesh):
316         glEnable(GL_CULL_FACE)
317         glEnableClientState(GL_VERTEX_ARRAY);
318         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
319
320         glCullFace(GL_FRONT)
321         glLineWidth(3)
322         glPolygonMode(GL_BACK, GL_LINE)
323         glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
324         glPolygonMode(GL_BACK, GL_FILL)
325         glCullFace(GL_BACK)
326
327         glDisableClientState(GL_VERTEX_ARRAY)
328
329
330 def DrawMesh(mesh):
331         glEnable(GL_CULL_FACE)
332         glEnableClientState(GL_VERTEX_ARRAY);
333         glEnableClientState(GL_NORMAL_ARRAY);
334         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
335         glNormalPointer(GL_FLOAT, 0, mesh.normal)
336
337         #Odd, drawing in batchs is a LOT faster then drawing it all at once.
338         batchSize = 999    #Warning, batchSize needs to be dividable by 3
339         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
340         extraCount = mesh.vertexCount - extraStartPos
341
342         glCullFace(GL_BACK)
343         for i in xrange(0, int(mesh.vertexCount / batchSize)):
344                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
345         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
346
347         glCullFace(GL_FRONT)
348         glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
349         for i in xrange(0, int(mesh.vertexCount / batchSize)):
350                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
351         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
352         extraCount = mesh.vertexCount - extraStartPos
353         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
354         glCullFace(GL_BACK)
355
356         glDisableClientState(GL_VERTEX_ARRAY)
357         glDisableClientState(GL_NORMAL_ARRAY);
358
359
360 def DrawMeshSteep(mesh, angle):
361         cosAngle = math.sin(angle / 180.0 * math.pi)
362         glDisable(GL_LIGHTING)
363         glDepthFunc(GL_EQUAL)
364         for i in xrange(0, int(mesh.vertexCount), 3):
365                 if mesh.normal[i][2] < -0.999999:
366                         if mesh.vertexes[i + 0][2] > 0.01:
367                                 glColor3f(0.5, 0, 0)
368                                 glBegin(GL_TRIANGLES)
369                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
370                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
371                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
372                                 glEnd()
373                 elif mesh.normal[i][2] < -cosAngle:
374                         glColor3f(-mesh.normal[i][2], 0, 0)
375                         glBegin(GL_TRIANGLES)
376                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
377                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
378                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
379                         glEnd()
380                 elif mesh.normal[i][2] > 0.999999:
381                         if mesh.vertexes[i + 0][2] > 0.01:
382                                 glColor3f(0.5, 0, 0)
383                                 glBegin(GL_TRIANGLES)
384                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
385                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
386                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
387                                 glEnd()
388                 elif mesh.normal[i][2] > cosAngle:
389                         glColor3f(mesh.normal[i][2], 0, 0)
390                         glBegin(GL_TRIANGLES)
391                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
392                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
393                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
394                         glEnd()
395         glDepthFunc(GL_LESS)
396
397
398 def DrawGCodeLayer(layer):
399         filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
400         filamentArea = math.pi * filamentRadius * filamentRadius
401         lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
402
403         fillCycle = 0
404         fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
405         moveColor = [0, 0, 1]
406         retractColor = [1, 0, 0.5]
407         supportColor = [0, 1, 1]
408         extrudeColor = [1, 0, 0]
409         innerWallColor = [0, 1, 0]
410         skirtColor = [0, 0.5, 0.5]
411         prevPathWasRetract = False
412
413         glDisable(GL_CULL_FACE)
414         for path in layer:
415                 if path.type == 'move':
416                         if prevPathWasRetract:
417                                 c = retractColor
418                         else:
419                                 c = moveColor
420                 zOffset = 0.01
421                 if path.type == 'extrude':
422                         if path.pathType == 'FILL':
423                                 c = fillColorCycle[fillCycle]
424                                 fillCycle = (fillCycle + 1) % len(fillColorCycle)
425                         elif path.pathType == 'WALL-INNER':
426                                 c = innerWallColor
427                                 zOffset = 0.02
428                         elif path.pathType == 'SUPPORT':
429                                 c = supportColor
430                         elif path.pathType == 'SKIRT':
431                                 c = skirtColor
432                         else:
433                                 c = extrudeColor
434                 if path.type == 'retract':
435                         c = [0, 1, 1]
436                 if path.type == 'extrude':
437                         drawLength = 0.0
438                         prevNormal = None
439                         for i in xrange(0, len(path.list) - 1):
440                                 v0 = path.list[i]
441                                 v1 = path.list[i + 1]
442
443                                 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
444                                 dist = (v0 - v1).vsize()
445                                 if dist > 0 and path.layerThickness > 0:
446                                         extrusionMMperDist = (v1.e - v0.e) / dist
447                                         lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
448
449                                 drawLength += (v0 - v1).vsize()
450                                 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
451                                 normal.normalize()
452
453                                 vv2 = v0 + normal * lineWidth
454                                 vv3 = v1 + normal * lineWidth
455                                 vv0 = v0 - normal * lineWidth
456                                 vv1 = v1 - normal * lineWidth
457
458                                 glBegin(GL_QUADS)
459                                 glColor3fv(c)
460                                 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
461                                 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
462                                 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
463                                 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
464                                 glEnd()
465                                 if prevNormal != None:
466                                         n = (normal + prevNormal)
467                                         n.normalize()
468                                         vv4 = v0 + n * lineWidth
469                                         vv5 = v0 - n * lineWidth
470                                         glBegin(GL_QUADS)
471                                         glColor3fv(c)
472                                         glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
473                                         glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
474                                         glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
475                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
476
477                                         glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
478                                         glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
479                                         glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
480                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
481                                         glEnd()
482
483                                 prevNormal = normal
484                                 prevVv1 = vv1
485                                 prevVv3 = vv3
486                 else:
487                         glBegin(GL_LINE_STRIP)
488                         glColor3fv(c)
489                         for v in path.list:
490                                 glVertex3f(v.x, v.y, v.z)
491                         glEnd()
492                 if not path.type == 'move':
493                         prevPathWasRetract = False
494                 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
495                         prevPathWasRetract = True
496         glEnable(GL_CULL_FACE)