From: daid Date: Wed, 26 Sep 2012 12:35:35 +0000 (+0200) Subject: Added obj support to Cura. X-Git-Tag: 13.03~326 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=7eb9967ee4ace4f647572db9bfd1ab13eba26c8d;p=cura.git Added obj support to Cura. --- diff --git a/Cura/gui/batchRun.py b/Cura/gui/batchRun.py index db80d315..9762d6a0 100644 --- a/Cura/gui/batchRun.py +++ b/Cura/gui/batchRun.py @@ -5,6 +5,7 @@ import wx, os, platform, types, webbrowser, math, subprocess, multiprocessing, t from util import profile from util import sliceRun +from util import meshLoader from gui import dropTarget class batchRunWindow(wx.Frame): @@ -13,7 +14,7 @@ class batchRunWindow(wx.Frame): self.list = [] - self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, '.stl')) + self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions())) wx.EVT_CLOSE(self, self.OnClose) self.panel = wx.Panel(self, -1) diff --git a/Cura/gui/dropTarget.py b/Cura/gui/dropTarget.py index 0c89fd03..54f52a13 100644 --- a/Cura/gui/dropTarget.py +++ b/Cura/gui/dropTarget.py @@ -11,8 +11,14 @@ class FileDropTarget(wx.FileDropTarget): self.filenameFilter = filenameFilter def OnDropFiles(self, x, y, filenames): + filteredList = [] if self.filenameFilter != None: - filenames = filter(lambda f: f.endswith(self.filenameFilter) or f.endswith(self.filenameFilter.upper()), filenames) - if len(filenames) > 0: - self.callback(filenames) + for f in filenames: + for ext in self.filenameFilter: + if f.endswith(ext) or f.endswith(ext.upper()): + filteredList.append(f) + else: + filteredList = filenames + if len(filteredList) > 0: + self.callback(filteredList) diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 6e75d076..39e733a3 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -22,6 +22,7 @@ from util import validators from util import profile from util import version from util import sliceRun +from util import meshLoader def main(): #app = wx.App(False) @@ -44,7 +45,7 @@ class mainWindow(configBase.configWindowBase): wx.EVT_CLOSE(self, self.OnClose) #self.SetIcon(icon.getMainIcon()) - self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, '.stl')) + self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions())) menubar = wx.MenuBar() fileMenu = wx.Menu() @@ -339,7 +340,7 @@ class mainWindow(configBase.configWindowBase): configWizard.configWizard() self.updateProfileToControls() - def _showOpenDialog(self, title, wildcard = "STL files (*.stl)|*.stl;*.STL"): + def _showOpenDialog(self, title, wildcard = meshLoader.wildcardFilter()): dlg=wx.FileDialog(self, title, os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) dlg.SetWildcard(wildcard) if dlg.ShowModal() == wx.ID_OK: diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 567ddf8e..a123d5a2 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -20,7 +20,7 @@ from gui import toolbarUtil from util import profile from util import gcodeInterpreter -from util import stl +from util import meshLoader from util import util3d from util import sliceRun @@ -264,8 +264,7 @@ class previewPanel(wx.Panel): for obj in self.objectList: if obj.filename != None and os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime: obj.ileTime = os.stat(obj.filename).st_mtime - mesh = stl.stlModel() - mesh.load(obj.filename) + mesh = meshLoader.loadMesh(obj.filename) obj.dirty = False obj.mesh = mesh self.updateModelTransform() diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 63a88cf2..1e21b527 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -25,6 +25,7 @@ from gui import dropTarget from util import validators from util import profile from util import util3d +from util import meshLoader from util import stl from util import mesh from util import sliceRun @@ -34,11 +35,11 @@ from util import exporer class Action(object): pass -class ProjectObject(stl.stlModel): +class ProjectObject(object): def __init__(self, parent, filename): super(ProjectObject, self).__init__() - self.load(filename) + self.mesh = meshLoader.loadMesh(filename) self.parent = parent self.filename = filename @@ -55,7 +56,7 @@ class ProjectObject(stl.stlModel): self.modelDisplayList = None self.modelDirty = False - self.getMinimumZ() + self.mesh.getMinimumZ() self.centerX = -self.getMinimum()[0] + 5 self.centerY = -self.getMinimum()[1] + 5 @@ -89,14 +90,21 @@ class ProjectObject(stl.stlModel): return True def updateModelTransform(self): - self.setRotateMirror(self.rotate, self.flipX, self.flipY, self.flipZ, self.swapXZ, self.swapYZ) - minZ = self.getMinimumZ() + self.mesh.setRotateMirror(self.rotate, self.flipX, self.flipY, self.flipZ, self.swapXZ, self.swapYZ) + minZ = self.mesh.getMinimumZ() minV = self.getMinimum() maxV = self.getMaximum() - self.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ]) - minZ = self.getMinimumZ() + self.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ]) + minZ = self.mesh.getMinimumZ() self.modelDirty = True + def getMinimum(self): + return self.mesh.getMinimum() + def getMaximum(self): + return self.mesh.getMaximum() + def getSize(self): + return self.mesh.getSize() + def clone(self): p = ProjectObject(self.parent, self.filename) @@ -139,7 +147,7 @@ class projectPlanner(wx.Frame): self.GetSizer().Add(self.panel, 1, flag=wx.EXPAND) #self.SetIcon(icon.getMainIcon()) - self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, '.stl')) + self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions())) self.list = [] self.selection = None @@ -268,10 +276,10 @@ class projectPlanner(wx.Frame): def OnCutMesh(self, e): dlg=wx.FileDialog(self, "Open file to cut", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) - dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL") + dlg.SetWildcard(meshLoader.wildcardFilter()) if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath() - model = stl.stlModel().load(filename) + model = meshLoader.loadMesh(filename) pd = wx.ProgressDialog('Splitting model.', 'Splitting model into multiple parts.', model.vertexCount, self, wx.PD_ELAPSED_TIME | wx.PD_REMAINING_TIME | wx.PD_SMOOTH) parts = model.splitToParts(pd.Update) for part in parts: @@ -317,7 +325,7 @@ class projectPlanner(wx.Frame): output._prepareVertexCount(totalCount) for item in self.list: offset = numpy.array([item.centerX, item.centerY, 0]) - for v in item.vertexes: + for v in item.mesh.vertexes: v0 = v * item.scale + offset output.addVertex(v0[0], v0[1], v0[2]) stl.saveAsSTL(output, filename) @@ -419,7 +427,7 @@ class projectPlanner(wx.Frame): def OnAddModel(self, e): dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST|wx.FD_MULTIPLE) - dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL") + dlg.SetWildcard(meshLoader.wildcardFilter()) if dlg.ShowModal() == wx.ID_OK: for filename in dlg.GetPaths(): item = ProjectObject(self, filename) @@ -807,7 +815,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas): item.modelDirty = False modelSize = item.getMaximum() - item.getMinimum() glNewList(item.modelDisplayList, GL_COMPILE) - opengl.DrawMesh(item) + opengl.DrawMesh(item.mesh) glEndList() if item.validPlacement: diff --git a/Cura/gui/simpleMode.py b/Cura/gui/simpleMode.py index b133fa1a..ebc30b3a 100644 --- a/Cura/gui/simpleMode.py +++ b/Cura/gui/simpleMode.py @@ -151,7 +151,7 @@ class simpleModeWindow(configBase.configWindowBase): def OnLoadModel(self, e): dlg=wx.FileDialog(self, "Open file to print", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST) - dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL") + dlg.SetWildcard(meshLoader.wildcardFilter()) if dlg.ShowModal() == wx.ID_OK: self.filelist = [dlg.GetPath()] profile.putPreference('lastFile', ';'.join(self.filelist)) diff --git a/Cura/util/meshLoader.py b/Cura/util/meshLoader.py new file mode 100644 index 00000000..fea8ef6b --- /dev/null +++ b/Cura/util/meshLoader.py @@ -0,0 +1,20 @@ + +import stl +import obj + +def supportedExtensions(): + return ['.stl', '.obj'] + +def wildcardFilter(): + wildcardList = ';'.join(map(lambda s: '*' + s, supportedExtensions())) + return "Mesh files (%s)|%s;%s" % (wildcardList, wildcardList, wildcardList.upper()) + +def loadMesh(filename): + ext = filename[filename.rfind('.'):].lower() + if ext == '.stl': + return stl.stlModel().load(filename) + if ext == '.obj': + return obj.objModel().load(filename) + print 'Error: Unknown model extension: %s' % (ext) + return None + diff --git a/Cura/util/obj.py b/Cura/util/obj.py new file mode 100644 index 00000000..ed199d71 --- /dev/null +++ b/Cura/util/obj.py @@ -0,0 +1,38 @@ +import sys, math, re, os, struct, time + +import mesh + +class objModel(mesh.mesh): + def __init__(self): + super(objModel, self).__init__() + + def load(self, filename): + vertexList = [] + faceList = [] + + f = open(filename, "r") + for line in f: + parts = line.split() + if len(parts) < 1: + continue + if parts[0] == 'v': + vertexList.append([float(parts[1]), float(parts[2]), float(parts[3])]) + if parts[0] == 'f': + parts[1] = parts[1].split('/')[0] + parts[2] = parts[2].split('/')[0] + parts[3] = parts[3].split('/')[0] + faceList.append([int(parts[1]), int(parts[2]), int(parts[3])]) + f.close() + + self._prepareVertexCount(len(faceList) * 3) + for f in faceList: + i = f[0] - 1 + self.addVertex(vertexList[i][0], vertexList[i][1], vertexList[i][2]) + i = f[1] - 1 + self.addVertex(vertexList[i][0], vertexList[i][1], vertexList[i][2]) + i = f[2] - 1 + self.addVertex(vertexList[i][0], vertexList[i][1], vertexList[i][2]) + + self._postProcessAfterLoad() + return self +