1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
8 #OpenGL.ERROR_CHECKING = False
9 from OpenGL.GLU import *
10 from OpenGL.GL import *
12 from Cura.util import profile
13 from Cura.gui.util import opengl
14 from Cura.gui.util import openglGui
16 class engineResultView(object):
17 def __init__(self, parent):
22 self._layer20VBOs = []
24 self.layerSelect = openglGui.glSlider(self._parent, 10000, 0, 1, (-1,-2), lambda : self._parent.QueueRefresh())
26 def setResult(self, result):
27 if self._result == result:
32 #Clean the saved VBO's
33 for layer in self._layerVBOs:
34 for typeName in layer.keys():
35 self._parent.glReleaseList.append(layer[typeName])
36 for layer in self._layer20VBOs:
37 for typeName in layer.keys():
38 self._parent.glReleaseList.append(layer[typeName])
40 self._layer20VBOs = []
42 def setEnabled(self, enabled):
43 self._enabled = enabled
44 self.layerSelect.setHidden(not enabled)
50 if self._result is not None and self._result._polygons is not None:
51 self.layerSelect.setRange(1, len(self._result._polygons))
55 if profile.getMachineSetting('machine_center_is_zero') != 'True':
56 glTranslate(-profile.getMachineSettingFloat('machine_width') / 2, -profile.getMachineSettingFloat('machine_depth') / 2, 0)
59 layerNr = self.layerSelect.getValue()
60 if layerNr == self.layerSelect.getMaxValue():
61 layerNr = max(layerNr, len(self._result._polygons))
62 viewZ = (layerNr - 1) * profile.getProfileSettingFloat('layer_height') + profile.getProfileSettingFloat('bottom_thickness')
63 self._parent._viewTarget[2] = viewZ
64 msize = max(profile.getMachineSettingFloat('machine_width'), profile.getMachineSettingFloat('machine_depth'))
65 lineTypeList = [('inset0',[1,0,0,1]), ('insetx',[0,1,0,1]), ('openoutline',[1,0,0,1]), ('skin',[1,1,0,1]), ('infill',[1,1,0,1]), ('support',[0,1,1,1]), ('outline',[0,0,0,1])]
67 layers = None #self._result.getGCodeLayers()
72 while len(self._layer20VBOs) < idx + 1:
73 self._layer20VBOs.append({})
74 if self._result is not None and self._result._polygons is not None and n + 20 < len(self._result._polygons):
75 layerVBOs = self._layer20VBOs[idx]
76 for typeName, color in lineTypeList:
77 if typeName in self._result._polygons[n + 19]:
78 if typeName not in self._layer20VBOs[idx]:
82 for i in xrange(0, 20):
83 if typeName in self._result._polygons[n + i]:
84 polygons += self._result._polygons[n + i][typeName]
85 layerVBOs[typeName] = self._polygonsToVBO_lines(polygons)
87 glColor4f(color[0]*0.5,color[1]*0.5,color[2]*0.5,color[3])
88 layerVBOs[typeName].render()
91 while len(self._layerVBOs) < n + 1:
92 self._layerVBOs.append({})
93 c = 1.0 - ((layerNr - n) - 1) * 0.05
95 layerVBOs = self._layerVBOs[n]
96 if layers is not None and n < len(layers):
97 if 'GCODE-FILL' not in layerVBOs:
98 layerVBOs['GCODE-FILL'] = self._gcodeToVBO_quads(layers[n:n+1], 'FILL')
100 layerVBOs['GCODE-FILL'].render()
101 elif self._result is not None and self._result._polygons is not None and n < len(self._result._polygons):
102 polygons = self._result._polygons[n]
103 for typeName, color in lineTypeList:
104 if typeName in polygons:
105 if typeName not in layerVBOs:
106 layerVBOs[typeName] = self._polygonsToVBO_lines(polygons[typeName])
107 glColor4f(color[0]*c,color[1]*c,color[2]*c,color[3])
108 layerVBOs[typeName].render()
112 self._parent._queueRefresh()
114 def _polygonsToVBO_lines(self, polygons):
115 verts = numpy.zeros((0, 3), numpy.float32)
116 indices = numpy.zeros((0), numpy.uint32)
117 for poly in polygons:
118 i = numpy.arange(len(verts), len(verts) + len(poly) + 1, 1, numpy.uint32)
120 i = numpy.dstack((i[0:-1],i[1:])).flatten()
121 indices = numpy.concatenate((indices, i), 0)
122 verts = numpy.concatenate((verts, poly), 0)
123 return opengl.GLVBO(GL_LINES, verts, indicesArray=indices)
125 def _polygonsToVBO_quads(self, polygons):
126 verts = numpy.zeros((0, 3), numpy.float32)
127 indices = numpy.zeros((0), numpy.uint32)
128 for poly in polygons:
129 i = numpy.arange(len(verts), len(verts) + len(poly) + 1, 1, numpy.uint32)
130 i2 = numpy.arange(len(verts) + len(poly), len(verts) + len(poly) + len(poly) + 1, 1, numpy.uint32)
132 i2[-1] = len(verts) + len(poly)
133 i = numpy.dstack((i[0:-1],i2[0:-1],i2[1:],i[1:])).flatten()
134 indices = numpy.concatenate((indices, i), 0)
135 verts = numpy.concatenate((verts, poly), 0)
136 verts = numpy.concatenate((verts, poly * numpy.array([1,0,1],numpy.float32) + numpy.array([0,-100,0],numpy.float32)), 0)
137 return opengl.GLVBO(GL_QUADS, verts, indicesArray=indices)
139 def _gcodeToVBO_lines(self, gcodeLayers, extrudeType):
140 if ':' in extrudeType:
141 extruder = int(extrudeType[extrudeType.find(':')+1:])
142 extrudeType = extrudeType[0:extrudeType.find(':')]
145 verts = numpy.zeros((0, 3), numpy.float32)
146 indices = numpy.zeros((0), numpy.uint32)
147 for layer in gcodeLayers:
149 if path['type'] == 'extrude' and path['pathType'] == extrudeType and (extruder is None or path['extruder'] == extruder):
150 i = numpy.arange(len(verts), len(verts) + len(path['points']), 1, numpy.uint32)
151 i = numpy.dstack((i[0:-1],i[1:])).flatten()
152 indices = numpy.concatenate((indices, i), 0)
153 verts = numpy.concatenate((verts, path['points']))
154 return opengl.GLVBO(GL_LINES, verts, indicesArray=indices)
156 def _gcodeToVBO_quads(self, gcodeLayers, extrudeType):
157 useFilamentArea = profile.getMachineSetting('gcode_flavor') == 'UltiGCode'
158 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
159 filamentArea = math.pi * filamentRadius * filamentRadius
161 if ':' in extrudeType:
162 extruder = int(extrudeType[extrudeType.find(':')+1:])
163 extrudeType = extrudeType[0:extrudeType.find(':')]
167 verts = numpy.zeros((0, 3), numpy.float32)
168 indices = numpy.zeros((0), numpy.uint32)
169 for layer in gcodeLayers:
171 if path['type'] == 'extrude' and path['pathType'] == extrudeType and (extruder is None or path['extruder'] == extruder):
173 if extrudeType == 'FILL':
176 #Construct the normals of each line 90deg rotated on the X/Y plane
177 normals = a[1:] - a[:-1]
178 lengths = numpy.sqrt(normals[:,0]**2 + normals[:,1]**2)
179 normals[:,0], normals[:,1] = -normals[:,1] / lengths, normals[:,0] / lengths
180 normals[:,2] /= lengths
182 ePerDist = path['extrusion'][1:] / lengths
184 lineWidth = ePerDist / path['layerThickness'] / 2.0
186 lineWidth = ePerDist * (filamentArea / path['layerThickness'] / 2)
188 normals[:,0] *= lineWidth
189 normals[:,1] *= lineWidth
191 b = numpy.zeros((len(a)-1, 0), numpy.float32)
192 b = numpy.concatenate((b, a[1:] + normals), 1)
193 b = numpy.concatenate((b, a[1:] - normals), 1)
194 b = numpy.concatenate((b, a[:-1] - normals), 1)
195 b = numpy.concatenate((b, a[:-1] + normals), 1)
196 b = b.reshape((len(b) * 4, 3))
198 i = numpy.arange(len(verts), len(verts) + len(b), 1, numpy.uint32)
200 verts = numpy.concatenate((verts, b))
201 indices = numpy.concatenate((indices, i))
202 return opengl.GLVBO(GL_QUADS, verts, indicesArray=indices)
204 def OnKeyChar(self, keyCode):
205 if not self._enabled:
208 if wx.GetKeyState(wx.WXK_SHIFT) or wx.GetKeyState(wx.WXK_CONTROL):
209 if keyCode == wx.WXK_UP:
210 self.layerSelect.setValue(self.layerSelect.getValue() + 1)
211 self._parent.QueueRefresh()
213 elif keyCode == wx.WXK_DOWN:
214 self.layerSelect.setValue(self.layerSelect.getValue() - 1)
215 self._parent.QueueRefresh()
217 elif keyCode == wx.WXK_PAGEUP:
218 self.layerSelect.setValue(self.layerSelect.getValue() + 10)
219 self._parent.QueueRefresh()
221 elif keyCode == wx.WXK_PAGEDOWN:
222 self.layerSelect.setValue(self.layerSelect.getValue() - 10)
223 self._parent.QueueRefresh()
227 # if self.viewMode == 'gcode' and self._gcode is not None:
229 # self._viewTarget[2] = self._gcode.layerList[self.layerSelect.getValue()][-1]['points'][0][2]
233 # def _loadGCode(self):
234 # self._gcode.progressCallback = self._gcodeLoadCallback
235 # if self._gcodeFilename is not None:
236 # self._gcode.load(self._gcodeFilename)
238 # self._gcode.load(self._gcodeData)
240 # def _gcodeLoadCallback(self, progress):
241 # if not self or self._gcode is None:
243 # if len(self._gcode.layerList) % 15 == 0:
245 # if self._gcode is None:
247 # self.layerSelect.setRange(1, len(self._gcode.layerList) - 1)
248 # if self.viewMode == 'gcode':
249 # self._queueRefresh()
252 # if self._gcodeLoadThread is not None and self._gcodeLoadThread.isAlive():
253 # glDisable(GL_DEPTH_TEST)
256 # glTranslate(0,-4,-10)
257 # glColor4ub(60,60,60,255)
258 # opengl.glDrawStringCenter(_("Loading toolpath for visualization..."))
262 # if self._gcode is not None:
264 # for layerVBOlist in self._gcodeVBOs:
265 # for vbo in layerVBOlist:
266 # self.glReleaseList.append(vbo)
267 # self._gcodeVBOs = []
269 # if self._gcode is not None and self._gcode.layerList is None:
270 # self._gcodeLoadThread = threading.Thread(target=self._loadGCode)
271 # self._gcodeLoadThread.daemon = True
272 # self._gcodeLoadThread.start()
276 # if self._gcode is not None and self._gcode.layerList is not None:
278 # if profile.getMachineSetting('machine_center_is_zero') != 'True':
279 # glTranslate(-self._machineSize[0] / 2, -self._machineSize[1] / 2, 0)
281 # drawUpTill = min(len(self._gcode.layerList), self.layerSelect.getValue() + 1)
282 # for n in xrange(0, drawUpTill):
283 # c = 1.0 - float(drawUpTill - n) / 15
285 # if len(self._gcodeVBOs) < n + 1:
286 # self._gcodeVBOs.append(self._generateGCodeVBOs(self._gcode.layerList[n]))
287 # if time.time() - t > 0.5:
288 # self.QueueRefresh()
290 # #['WALL-OUTER', 'WALL-INNER', 'FILL', 'SUPPORT', 'SKIRT']
291 # if n == drawUpTill - 1:
292 # if len(self._gcodeVBOs[n]) < 9:
293 # self._gcodeVBOs[n] += self._generateGCodeVBOs2(self._gcode.layerList[n])
295 # self._gcodeVBOs[n][8].render(GL_QUADS)
296 # glColor3f(c/2, 0, c)
297 # self._gcodeVBOs[n][9].render(GL_QUADS)
298 # glColor3f(0, c, c/2)
299 # self._gcodeVBOs[n][10].render(GL_QUADS)
301 # self._gcodeVBOs[n][11].render(GL_QUADS)
304 # self._gcodeVBOs[n][12].render(GL_QUADS)
305 # glColor3f(c/2, c/2, 0.0)
306 # self._gcodeVBOs[n][13].render(GL_QUADS)
308 # self._gcodeVBOs[n][14].render(GL_QUADS)
309 # self._gcodeVBOs[n][15].render(GL_QUADS)
311 # self._gcodeVBOs[n][16].render(GL_LINES)
314 # self._gcodeVBOs[n][0].render(GL_LINES)
315 # glColor3f(c/2, 0, c)
316 # self._gcodeVBOs[n][1].render(GL_LINES)
317 # glColor3f(0, c, c/2)
318 # self._gcodeVBOs[n][2].render(GL_LINES)
320 # self._gcodeVBOs[n][3].render(GL_LINES)
323 # self._gcodeVBOs[n][4].render(GL_LINES)
324 # glColor3f(c/2, c/2, 0.0)
325 # self._gcodeVBOs[n][5].render(GL_LINES)
327 # self._gcodeVBOs[n][6].render(GL_LINES)
328 # self._gcodeVBOs[n][7].render(GL_LINES)
331 # def _generateGCodeVBOs(self, layer):
333 # for extrudeType in ['WALL-OUTER:0', 'WALL-OUTER:1', 'WALL-OUTER:2', 'WALL-OUTER:3', 'WALL-INNER', 'FILL', 'SUPPORT', 'SKIRT']:
334 # if ':' in extrudeType:
335 # extruder = int(extrudeType[extrudeType.find(':')+1:])
336 # extrudeType = extrudeType[0:extrudeType.find(':')]
339 # pointList = numpy.zeros((0,3), numpy.float32)
341 # if path['type'] == 'extrude' and path['pathType'] == extrudeType and (extruder is None or path['extruder'] == extruder):
343 # a = numpy.concatenate((a[:-1], a[1:]), 1)
344 # a = a.reshape((len(a) * 2, 3))
345 # pointList = numpy.concatenate((pointList, a))
346 # ret.append(opengl.GLVBO(pointList))
349 # def _generateGCodeVBOs2(self, layer):
350 # filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
351 # filamentArea = math.pi * filamentRadius * filamentRadius
352 # useFilamentArea = profile.getMachineSetting('gcode_flavor') == 'UltiGCode'
355 # for extrudeType in ['WALL-OUTER:0', 'WALL-OUTER:1', 'WALL-OUTER:2', 'WALL-OUTER:3', 'WALL-INNER', 'FILL', 'SUPPORT', 'SKIRT']:
356 # if ':' in extrudeType:
357 # extruder = int(extrudeType[extrudeType.find(':')+1:])
358 # extrudeType = extrudeType[0:extrudeType.find(':')]
361 # pointList = numpy.zeros((0,3), numpy.float32)
363 # if path['type'] == 'extrude' and path['pathType'] == extrudeType and (extruder is None or path['extruder'] == extruder):
365 # if extrudeType == 'FILL':
368 # normal = a[1:] - a[:-1]
369 # lens = numpy.sqrt(normal[:,0]**2 + normal[:,1]**2)
370 # normal[:,0], normal[:,1] = -normal[:,1] / lens, normal[:,0] / lens
371 # normal[:,2] /= lens
373 # ePerDist = path['extrusion'][1:] / lens
374 # if useFilamentArea:
375 # lineWidth = ePerDist / path['layerThickness'] / 2.0
377 # lineWidth = ePerDist * (filamentArea / path['layerThickness'] / 2)
379 # normal[:,0] *= lineWidth
380 # normal[:,1] *= lineWidth
382 # b = numpy.zeros((len(a)-1, 0), numpy.float32)
383 # b = numpy.concatenate((b, a[1:] + normal), 1)
384 # b = numpy.concatenate((b, a[1:] - normal), 1)
385 # b = numpy.concatenate((b, a[:-1] - normal), 1)
386 # b = numpy.concatenate((b, a[:-1] + normal), 1)
387 # b = b.reshape((len(b) * 4, 3))
390 # normal2 = normal[:-1] + normal[1:]
391 # lens2 = numpy.sqrt(normal2[:,0]**2 + normal2[:,1]**2)
392 # normal2[:,0] /= lens2
393 # normal2[:,1] /= lens2
394 # normal2[:,0] *= lineWidth[:-1]
395 # normal2[:,1] *= lineWidth[:-1]
397 # c = numpy.zeros((len(a)-2, 0), numpy.float32)
398 # c = numpy.concatenate((c, a[1:-1]), 1)
399 # c = numpy.concatenate((c, a[1:-1]+normal[1:]), 1)
400 # c = numpy.concatenate((c, a[1:-1]+normal2), 1)
401 # c = numpy.concatenate((c, a[1:-1]+normal[:-1]), 1)
403 # c = numpy.concatenate((c, a[1:-1]), 1)
404 # c = numpy.concatenate((c, a[1:-1]-normal[1:]), 1)
405 # c = numpy.concatenate((c, a[1:-1]-normal2), 1)
406 # c = numpy.concatenate((c, a[1:-1]-normal[:-1]), 1)
408 # c = c.reshape((len(c) * 8, 3))
410 # pointList = numpy.concatenate((pointList, b, c))
412 # pointList = numpy.concatenate((pointList, b))
413 # ret.append(opengl.GLVBO(pointList))
415 # pointList = numpy.zeros((0,3), numpy.float32)
417 # if path['type'] == 'move':
418 # a = path['points'] + numpy.array([0,0,0.01], numpy.float32)
419 # a = numpy.concatenate((a[:-1], a[1:]), 1)
420 # a = a.reshape((len(a) * 2, 3))
421 # pointList = numpy.concatenate((pointList, a))
422 # if path['type'] == 'retract':
423 # a = path['points'] + numpy.array([0,0,0.01], numpy.float32)
424 # a = numpy.concatenate((a[:-1], a[1:] + numpy.array([0,0,1], numpy.float32)), 1)
425 # a = a.reshape((len(a) * 2, 3))
426 # pointList = numpy.concatenate((pointList, a))
427 # ret.append(opengl.GLVBO(pointList))