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