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