chiark / gitweb /
Update on rotation tools, this breaks a lot of functionality, but is really needed.
[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(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                 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, 64)
251                 glutStrokeCharacter(GLUT_STROKE_ROMAN, 64)
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 is not 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)