chiark / gitweb /
Update rotate tool with text, and add info tool.
[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.GLUT import *
16         from OpenGL.GLU import *
17         from OpenGL.GL import *
18
19         hasOpenGLlibs = True
20 except:
21         print "Failed to find PyOpenGL: http://pyopengl.sourceforge.net/"
22         hasOpenGLlibs = False
23
24 def InitGL(window, view3D, zoom):
25         # set viewing projection
26         glMatrixMode(GL_MODELVIEW)
27         glLoadIdentity()
28         size = window.GetSize()
29         glViewport(0, 0, size.GetWidth(), size.GetHeight())
30
31         glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
32         glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
33
34         glEnable(GL_RESCALE_NORMAL)
35         glEnable(GL_LIGHTING)
36         glEnable(GL_LIGHT0)
37         glEnable(GL_DEPTH_TEST)
38         glEnable(GL_CULL_FACE)
39         glDisable(GL_BLEND)
40
41         glClearColor(1.0, 1.0, 1.0, 1.0)
42         glClearStencil(0)
43         glClearDepth(1.0)
44
45         glMatrixMode(GL_PROJECTION)
46         glLoadIdentity()
47         aspect = float(size.GetWidth()) / float(size.GetHeight())
48         if view3D:
49                 gluPerspective(45.0, aspect, 1.0, 1000.0)
50         else:
51                 glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
52
53         glMatrixMode(GL_MODELVIEW)
54         glLoadIdentity()
55         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
56
57 platformMesh = None
58
59 def DrawMachine(machineSize):
60         if profile.getPreference('machine_type') == 'ultimaker':
61                 glPushMatrix()
62                 glEnable(GL_LIGHTING)
63                 glTranslate(100, 200, -5)
64                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8])
65                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5])
66                 glEnable(GL_BLEND)
67                 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR)
68
69                 global platformMesh
70                 if platformMesh is None:
71                         try:
72                                 platformMesh = meshLoader.loadMesh(getPathForMesh('ultimaker_platform.stl'))
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(20, 0, 0)
214         noZ = ResetMatrixRotationAndScale()
215         glDrawStringCenter("X")
216         glPopMatrix()
217
218         #Y
219         glColor3f(0, 1, 0)
220         glPushMatrix()
221         glTranslate(0, 20, 0)
222         glDrawStringCenter("Y")
223         glPopMatrix()
224
225         #Z
226         if not noZ:
227                 glColor3f(0, 0, 1)
228                 glPushMatrix()
229                 glTranslate(0, 0, 20)
230                 glDrawStringCenter("Z")
231                 glPopMatrix()
232
233         glPopMatrix()
234         glEnable(GL_DEPTH_TEST)
235
236 def glDrawStringCenter(s):
237         glRasterPos2f(0, 0)
238         width = 0
239         for c in s:
240                 width += glutBitmapWidth(GLUT_BITMAP_HELVETICA_18, ord(c))
241         glBitmap(0,0,0,0, -width/2, 0, None)
242         for c in s:
243                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, ord(c))
244
245 def ResetMatrixRotationAndScale():
246         matrix = glGetFloatv(GL_MODELVIEW_MATRIX)
247         noZ = False
248         if matrix[3][2] > 0:
249                 return False
250         scale2D = matrix[0][0]
251         matrix[0][0] = 1.0
252         matrix[1][0] = 0.0
253         matrix[2][0] = 0.0
254         matrix[0][1] = 0.0
255         matrix[1][1] = 1.0
256         matrix[2][1] = 0.0
257         matrix[0][2] = 0.0
258         matrix[1][2] = 0.0
259         matrix[2][2] = 1.0
260
261         if matrix[3][2] != 0.0:
262                 matrix[3][0] = matrix[3][0] / (-matrix[3][2] / 100)
263                 matrix[3][1] = matrix[3][1] / (-matrix[3][2] / 100)
264                 matrix[3][2] = -100
265         else:
266                 matrix[0][0] = scale2D
267                 matrix[1][1] = scale2D
268                 matrix[2][2] = scale2D
269                 matrix[3][2] = -100
270                 noZ = True
271
272         glLoadMatrixf(matrix)
273         return noZ
274
275
276 def DrawBox(vMin, vMax):
277         glBegin(GL_LINE_LOOP)
278         glVertex3f(vMin[0], vMin[1], vMin[2])
279         glVertex3f(vMax[0], vMin[1], vMin[2])
280         glVertex3f(vMax[0], vMax[1], vMin[2])
281         glVertex3f(vMin[0], vMax[1], vMin[2])
282         glEnd()
283
284         glBegin(GL_LINE_LOOP)
285         glVertex3f(vMin[0], vMin[1], vMax[2])
286         glVertex3f(vMax[0], vMin[1], vMax[2])
287         glVertex3f(vMax[0], vMax[1], vMax[2])
288         glVertex3f(vMin[0], vMax[1], vMax[2])
289         glEnd()
290         glBegin(GL_LINES)
291         glVertex3f(vMin[0], vMin[1], vMin[2])
292         glVertex3f(vMin[0], vMin[1], vMax[2])
293         glVertex3f(vMax[0], vMin[1], vMin[2])
294         glVertex3f(vMax[0], vMin[1], vMax[2])
295         glVertex3f(vMax[0], vMax[1], vMin[2])
296         glVertex3f(vMax[0], vMax[1], vMax[2])
297         glVertex3f(vMin[0], vMax[1], vMin[2])
298         glVertex3f(vMin[0], vMax[1], vMax[2])
299         glEnd()
300
301
302 def DrawMeshOutline(mesh):
303         glEnable(GL_CULL_FACE)
304         glEnableClientState(GL_VERTEX_ARRAY);
305         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
306
307         glCullFace(GL_FRONT)
308         glLineWidth(3)
309         glPolygonMode(GL_BACK, GL_LINE)
310         glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount)
311         glPolygonMode(GL_BACK, GL_FILL)
312         glCullFace(GL_BACK)
313
314         glDisableClientState(GL_VERTEX_ARRAY)
315
316
317 def DrawMesh(mesh):
318         glEnable(GL_CULL_FACE)
319         glEnableClientState(GL_VERTEX_ARRAY);
320         glEnableClientState(GL_NORMAL_ARRAY);
321         glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
322         glNormalPointer(GL_FLOAT, 0, mesh.normal)
323
324         #Odd, drawing in batchs is a LOT faster then drawing it all at once.
325         batchSize = 999    #Warning, batchSize needs to be dividable by 3
326         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
327         extraCount = mesh.vertexCount - extraStartPos
328
329         glCullFace(GL_BACK)
330         for i in xrange(0, int(mesh.vertexCount / batchSize)):
331                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
332         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
333
334         glCullFace(GL_FRONT)
335         glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
336         for i in xrange(0, int(mesh.vertexCount / batchSize)):
337                 glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
338         extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
339         extraCount = mesh.vertexCount - extraStartPos
340         glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
341         glCullFace(GL_BACK)
342
343         glDisableClientState(GL_VERTEX_ARRAY)
344         glDisableClientState(GL_NORMAL_ARRAY);
345
346
347 def DrawMeshSteep(mesh, angle):
348         cosAngle = math.sin(angle / 180.0 * math.pi)
349         glDisable(GL_LIGHTING)
350         glDepthFunc(GL_EQUAL)
351         for i in xrange(0, int(mesh.vertexCount), 3):
352                 if mesh.normal[i][2] < -0.999999:
353                         if mesh.vertexes[i + 0][2] > 0.01:
354                                 glColor3f(0.5, 0, 0)
355                                 glBegin(GL_TRIANGLES)
356                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
357                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
358                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
359                                 glEnd()
360                 elif mesh.normal[i][2] < -cosAngle:
361                         glColor3f(-mesh.normal[i][2], 0, 0)
362                         glBegin(GL_TRIANGLES)
363                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
364                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
365                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
366                         glEnd()
367                 elif mesh.normal[i][2] > 0.999999:
368                         if mesh.vertexes[i + 0][2] > 0.01:
369                                 glColor3f(0.5, 0, 0)
370                                 glBegin(GL_TRIANGLES)
371                                 glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
372                                 glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
373                                 glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
374                                 glEnd()
375                 elif mesh.normal[i][2] > cosAngle:
376                         glColor3f(mesh.normal[i][2], 0, 0)
377                         glBegin(GL_TRIANGLES)
378                         glVertex3f(mesh.vertexes[i + 0][0], mesh.vertexes[i + 0][1], mesh.vertexes[i + 0][2])
379                         glVertex3f(mesh.vertexes[i + 2][0], mesh.vertexes[i + 2][1], mesh.vertexes[i + 2][2])
380                         glVertex3f(mesh.vertexes[i + 1][0], mesh.vertexes[i + 1][1], mesh.vertexes[i + 1][2])
381                         glEnd()
382         glDepthFunc(GL_LESS)
383
384
385 def DrawGCodeLayer(layer):
386         filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
387         filamentArea = math.pi * filamentRadius * filamentRadius
388         lineWidth = profile.getProfileSettingFloat('nozzle_size') / 2 / 10
389
390         fillCycle = 0
391         fillColorCycle = [[0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5]]
392         moveColor = [0, 0, 1]
393         retractColor = [1, 0, 0.5]
394         supportColor = [0, 1, 1]
395         extrudeColor = [1, 0, 0]
396         innerWallColor = [0, 1, 0]
397         skirtColor = [0, 0.5, 0.5]
398         prevPathWasRetract = False
399
400         glDisable(GL_CULL_FACE)
401         for path in layer:
402                 if path.type == 'move':
403                         if prevPathWasRetract:
404                                 c = retractColor
405                         else:
406                                 c = moveColor
407                 zOffset = 0.01
408                 if path.type == 'extrude':
409                         if path.pathType == 'FILL':
410                                 c = fillColorCycle[fillCycle]
411                                 fillCycle = (fillCycle + 1) % len(fillColorCycle)
412                         elif path.pathType == 'WALL-INNER':
413                                 c = innerWallColor
414                                 zOffset = 0.02
415                         elif path.pathType == 'SUPPORT':
416                                 c = supportColor
417                         elif path.pathType == 'SKIRT':
418                                 c = skirtColor
419                         else:
420                                 c = extrudeColor
421                 if path.type == 'retract':
422                         c = [0, 1, 1]
423                 if path.type == 'extrude':
424                         drawLength = 0.0
425                         prevNormal = None
426                         for i in xrange(0, len(path.list) - 1):
427                                 v0 = path.list[i]
428                                 v1 = path.list[i + 1]
429
430                                 # Calculate line width from ePerDistance (needs layer thickness and filament diameter)
431                                 dist = (v0 - v1).vsize()
432                                 if dist > 0 and path.layerThickness > 0:
433                                         extrusionMMperDist = (v1.e - v0.e) / dist
434                                         lineWidth = extrusionMMperDist * filamentArea / path.layerThickness / 2 * v1.extrudeAmountMultiply
435
436                                 drawLength += (v0 - v1).vsize()
437                                 normal = (v0 - v1).cross(util3d.Vector3(0, 0, 1))
438                                 normal.normalize()
439
440                                 vv2 = v0 + normal * lineWidth
441                                 vv3 = v1 + normal * lineWidth
442                                 vv0 = v0 - normal * lineWidth
443                                 vv1 = v1 - normal * lineWidth
444
445                                 glBegin(GL_QUADS)
446                                 glColor3fv(c)
447                                 glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
448                                 glVertex3f(vv1.x, vv1.y, vv1.z - zOffset)
449                                 glVertex3f(vv3.x, vv3.y, vv3.z - zOffset)
450                                 glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
451                                 glEnd()
452                                 if prevNormal is not None:
453                                         n = (normal + prevNormal)
454                                         n.normalize()
455                                         vv4 = v0 + n * lineWidth
456                                         vv5 = v0 - n * lineWidth
457                                         glBegin(GL_QUADS)
458                                         glColor3fv(c)
459                                         glVertex3f(vv2.x, vv2.y, vv2.z - zOffset)
460                                         glVertex3f(vv4.x, vv4.y, vv4.z - zOffset)
461                                         glVertex3f(prevVv3.x, prevVv3.y, prevVv3.z - zOffset)
462                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
463
464                                         glVertex3f(vv0.x, vv0.y, vv0.z - zOffset)
465                                         glVertex3f(vv5.x, vv5.y, vv5.z - zOffset)
466                                         glVertex3f(prevVv1.x, prevVv1.y, prevVv1.z - zOffset)
467                                         glVertex3f(v0.x, v0.y, v0.z - zOffset)
468                                         glEnd()
469
470                                 prevNormal = normal
471                                 prevVv1 = vv1
472                                 prevVv3 = vv3
473                 else:
474                         glBegin(GL_LINE_STRIP)
475                         glColor3fv(c)
476                         for v in path.list:
477                                 glVertex3f(v.x, v.y, v.z)
478                         glEnd()
479                 if not path.type == 'move':
480                         prevPathWasRetract = False
481                 if path.type == 'retract' and path.list[0].almostEqual(path.list[-1]):
482                         prevPathWasRetract = True
483         glEnable(GL_CULL_FACE)