From: daid303 Date: Mon, 8 Apr 2013 17:24:05 +0000 (+0200) Subject: Fix AMF support. Support merging of objects for multi-extruder prints. X-Git-Tag: 13.05~118 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=c8f65c6e56ad52ff358b8f9d31a5d07262ead12f;p=cura.git Fix AMF support. Support merging of objects for multi-extruder prints. --- diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 72764e10..8216af47 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -50,7 +50,7 @@ class mainWindow(wx.Frame): self.menubar = wx.MenuBar() self.fileMenu = wx.Menu() i = self.fileMenu.Append(-1, 'Load model file...\tCTRL+L') - self.Bind(wx.EVT_MENU, lambda e: self.scene.ShowLoadModel(), i) + self.Bind(wx.EVT_MENU, lambda e: self.scene.ShowLoadModel(1), i) i = self.fileMenu.Append(-1, 'Print...\tCTRL+P') self.Bind(wx.EVT_MENU, lambda e: self.scene.ShowPrintWindow(), i) diff --git a/Cura/gui/sceneView.py b/Cura/gui/sceneView.py index 5ba9e9b4..d7b3bb94 100644 --- a/Cura/gui/sceneView.py +++ b/Cura/gui/sceneView.py @@ -237,6 +237,12 @@ class SceneView(openglGui.glGuiPanel): self.updateProfileToControls() self.sceneUpdated() + def OnMergeObjects(self, e): + if self._selectedObj is None or self._focusObj is None or self._selectedObj == self._focusObj: + return + self._scene.merge(self._selectedObj, self._focusObj) + self.sceneUpdated() + def sceneUpdated(self): self._sceneUpdateTimer.Start(1, True) self._slicer.abortSlicer() @@ -299,6 +305,7 @@ class SceneView(openglGui.glGuiPanel): self._objColors[2] = profile.getPreferenceColour('model_colour3') self._objColors[3] = profile.getPreferenceColour('model_colour4') self._scene.setMachineSize(self._machineSize) + self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32)) if self._selectedObj is not None: scale = self._selectedObj.getScale() @@ -358,12 +365,18 @@ class SceneView(openglGui.glGuiPanel): else: self._selectedObj = None self.Refresh() - if e.GetButton() == 3 and self._selectedObj == self._focusObj: - #menu = wx.Menu() - #menu.Append(-1, 'Test') - #self.PopupMenu(menu) - #menu.Destroy() - pass + if e.GetButton() == 3: + if self._selectedObj == self._focusObj: + #menu = wx.Menu() + #menu.Append(-1, 'Test') + #self.PopupMenu(menu) + #menu.Destroy() + pass + if self._selectedObj != self._focusObj and self._focusObj is not None: + menu = wx.Menu() + self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Merge')) + self.PopupMenu(menu) + menu.Destroy() elif self._mouseState == 'dragObject' and self._selectedObj is not None: self._scene.pushFree() self.sceneUpdated() @@ -568,18 +581,19 @@ void main(void) obj._loadAnim = None else: continue - col = self._objColors[0] - if not self._scene.checkPlatform(obj): - col = [0.5,0.5,0.5,0.8] + brightness = 1.0 glDisable(GL_STENCIL_TEST) if self._selectedObj == obj: glEnable(GL_STENCIL_TEST) if self._focusObj == obj: - col = map(lambda n: n * 1.2, col) + brightness = 1.2 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj: - col = map(lambda n: n * 0.8, col) - glColor4f(col[0], col[1], col[2], col[3]) - self._renderObject(obj) + brightness = 0.8 + if not self._scene.checkPlatform(obj): + glColor4f(0.5 * brightness, 0.5 * brightness, 0.5 * brightness, 0.8 * brightness) + self._renderObject(obj) + else: + self._renderObject(obj, brightness) self._objectShader.unbind() glDisable(GL_STENCIL_TEST) @@ -619,6 +633,7 @@ void main(void) glDisable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE) glEnable(GL_STENCIL_TEST) + glDisable(GL_BLEND) glStencilFunc(GL_EQUAL, 0, 255) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) @@ -639,7 +654,7 @@ void main(void) self.tool.OnDraw() glPopMatrix() - def _renderObject(self, obj): + def _renderObject(self, obj, brightness = False): glPushMatrix() glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2) @@ -653,9 +668,13 @@ void main(void) tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix()) glMultMatrixf(tempMatrix) + n = 0 for m in obj._meshList: if m.vbo is None: m.vbo = opengl.GLVBO(m.vertexes, m.normal) + if brightness: + glColor4fv(map(lambda n: n * brightness, self._objColors[n])) + n += 1 m.vbo.render() glPopMatrix() diff --git a/Cura/util/meshLoader.py b/Cura/util/meshLoader.py index bc514150..809a66a5 100644 --- a/Cura/util/meshLoader.py +++ b/Cura/util/meshLoader.py @@ -27,6 +27,6 @@ def loadMeshes(filename): if ext == '.dae': return dae.daeModel().load(filename) if ext == '.amf': - return amf.amfModel().load(filename) + return amf.loadScene(filename) print 'Error: Unknown model extension: %s' % (ext) return [] diff --git a/Cura/util/meshLoaders/amf.py b/Cura/util/meshLoaders/amf.py index 61a28b58..ad007705 100644 --- a/Cura/util/meshLoaders/amf.py +++ b/Cura/util/meshLoaders/amf.py @@ -8,69 +8,69 @@ except: from Cura.util import mesh -class amfModel(mesh.mesh): - def __init__(self): - super(amfModel, self).__init__() +def loadScene(filename): + try: + zfile = zipfile.ZipFile(filename) + xml = zfile.read(zfile.namelist()[0]) + zfile.close() + except zipfile.BadZipfile: + f = open(filename, "r") + xml = f.read() + f.close() + amf = ElementTree.fromstring(xml) + if 'unit' in amf.attrib: + unit = amf.attrib['unit'].lower() + else: + unit = 'millimeter' + if unit == 'millimeter': + scale = 1.0 + elif unit == 'meter': + scale = 1000.0 + elif unit == 'inch': + scale = 25.4 + elif unit == 'feet': + scale = 304.8 + elif unit == 'micron': + scale = 0.001 + else: + print "Unknown unit in amf: %s" % (unit) + scale = 1.0 - def load(self, filename): - try: - zfile = zipfile.ZipFile(filename) - xml = zfile.read(zfile.namelist()[0]) - zfile.close() - except zipfile.BadZipfile: - f = open(filename, "r") - xml = f.read() - f.close() - amf = ElementTree.fromstring(xml) - if 'unit' in amf.attrib: - unit = amf.attrib['unit'].lower() - else: - unit = 'millimeter' - if unit == 'millimeter': - scale = 1.0 - elif unit == 'meter': - scale = 1000.0 - elif unit == 'inch': - scale = 25.4 - elif unit == 'feet': - scale = 304.8 - elif unit == 'micron': - scale = 0.001 - else: - print "Unknown unit in amf: %s" % (unit) - scale = 1.0 + ret = [] + for amfObj in amf.iter('object'): + obj = mesh.printableObject() + for amfMesh in amfObj.iter('mesh'): + vertexList = [] + for vertices in amfMesh.iter('vertices'): + for vertex in vertices.iter('vertex'): + for coordinates in vertex.iter('coordinates'): + v = [0.0,0.0,0.0] + for t in coordinates: + if t.tag == 'x': + v[0] = float(t.text) + elif t.tag == 'y': + v[1] = float(t.text) + elif t.tag == 'z': + v[2] = float(t.text) + vertexList.append(v) - count = 0 - for obj in amf.iter('object'): - for mesh in obj.iter('mesh'): - for volume in mesh.iter('volume'): - for triangle in volume.iter('triangle'): - count += 3 + for volume in amfMesh.iter('volume'): + m = obj._addMesh() + count = 0 + for triangle in volume.iter('triangle'): + count += 1 + m._prepareFaceCount(count) - self._prepareVertexCount(count) + for triangle in volume.iter('triangle'): + for t in triangle: + if t.tag == 'v1': + v1 = vertexList[int(t.text)] + elif t.tag == 'v2': + v2 = vertexList[int(t.text)] + elif t.tag == 'v3': + v3 = vertexList[int(t.text)] + m._addFace(v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]) + obj._postProcessAfterLoad() + ret.append(obj) - for obj in amf.iter('object'): - for mesh in obj.iter('mesh'): - vertexList = [] - for vertices in mesh.iter('vertices'): - for vertex in vertices.iter('vertex'): - for coordinates in vertex.iter('coordinates'): - v = [0.0,0.0,0.0] - for t in coordinates: - if t.tag == 'x': - v[0] = float(t.text) - elif t.tag == 'y': - v[1] = float(t.text) - elif t.tag == 'z': - v[2] = float(t.text) - vertexList.append(v) - for volume in mesh.iter('volume'): - for triangle in volume.iter('triangle'): - for t in triangle: - if t.tag == 'v1' or t.tag == 'v2' or t.tag == 'v3': - v = vertexList[int(t.text)] - self.addVertex(v[0], v[1], v[2]) - - self.vertexes *= scale - self._postProcessAfterLoad() - return self + return ret diff --git a/Cura/util/objectScene.py b/Cura/util/objectScene.py index 2684bd5b..0ad1dda6 100644 --- a/Cura/util/objectScene.py +++ b/Cura/util/objectScene.py @@ -66,7 +66,7 @@ class _objectOrderFinder(object): class Scene(object): def __init__(self): self._objectList = [] - self._sizeOffsets = numpy.array([3.0,3.0], numpy.float32) + self._sizeOffsets = numpy.array([0.0,0.0], numpy.float32) self._machineSize = numpy.array([100,100,100], numpy.float32) self._headOffsets = numpy.array([18.0,18.0], numpy.float32) @@ -90,6 +90,11 @@ class Scene(object): def remove(self, obj): self._objectList.remove(obj) + def merge(self, obj1, obj2): + self.remove(obj2) + obj1._meshList += obj2._meshList + obj1.processMatrix() + def pushFree(self): n = 1000 while self._pushFree(): @@ -122,6 +127,8 @@ class Scene(object): order = _objectOrderFinder(self, self._headOffsets + self._sizeOffsets).order if order is None: print "ODD! Cannot find out proper printing order!!!" + for obj in self._objectList: + print obj.getPosition(), obj.getSize() return order def _pushFree(self): @@ -176,14 +183,14 @@ class Scene(object): for a in self._objectList: p = a.getPosition() s = (a.getSize()[0:2] + obj.getSize()[0:2]) / 2 + self._sizeOffsets + self._headOffsets - posList.append(p + s * ( 1, 1)) - posList.append(p + s * ( 0, 1)) - posList.append(p + s * (-1, 1)) - posList.append(p + s * ( 1, 0)) - posList.append(p + s * (-1, 0)) - posList.append(p + s * ( 1,-1)) - posList.append(p + s * ( 0,-1)) - posList.append(p + s * (-1,-1)) + posList.append(p + s * ( 1.0, 1.0)) + posList.append(p + s * ( 0.0, 1.0)) + posList.append(p + s * (-1.0, 1.0)) + posList.append(p + s * ( 1.0, 0.0)) + posList.append(p + s * (-1.0, 0.0)) + posList.append(p + s * ( 1.0,-1.0)) + posList.append(p + s * ( 0.0,-1.0)) + posList.append(p + s * (-1.0,-1.0)) best = None bestDist = None diff --git a/Cura/util/sliceEngine.py b/Cura/util/sliceEngine.py index 2589ff2a..2fa333e3 100644 --- a/Cura/util/sliceEngine.py +++ b/Cura/util/sliceEngine.py @@ -54,13 +54,14 @@ class Slicer(object): for n in scene.printOrder(): obj = scene.objects()[n] for mesh in obj._meshList: - n = numpy.array(mesh.vertexCount, numpy.int32) + n = numpy.array([mesh.vertexCount], numpy.int32) f.write(n.tostring()) f.write(mesh.vertexes.tostring()) pos = obj.getPosition() * 1000 pos += numpy.array([profile.getPreferenceFloat('machine_width') * 1000 / 2, profile.getPreferenceFloat('machine_depth') * 1000 / 2]) commandList += ['-m', ','.join(map(str, obj._matrix.getA().flatten()))] - commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1]), '#'] + commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])] + commandList += ['#' * len(obj._meshList)] self._objCount += 1 if self._objCount > 0: print ' '.join(commandList)