chiark / gitweb /
Added obj support to Cura.
authordaid <daid303@gmail.com>
Wed, 26 Sep 2012 12:35:35 +0000 (14:35 +0200)
committerdaid <daid303@gmail.com>
Wed, 26 Sep 2012 12:35:35 +0000 (14:35 +0200)
Cura/gui/batchRun.py
Cura/gui/dropTarget.py
Cura/gui/mainWindow.py
Cura/gui/preview3d.py
Cura/gui/projectPlanner.py
Cura/gui/simpleMode.py
Cura/util/meshLoader.py [new file with mode: 0644]
Cura/util/obj.py [new file with mode: 0644]

index db80d315466cb0f72bc57ceddaf0cb8db8b660f3..9762d6a07e8feafdd3155a58909b64ffa8876386 100644 (file)
@@ -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)
index 0c89fd039ce7e280753219e33aea5dea58becdfc..54f52a13b26cdaad7d9767befbf7b3b6fd1ad94c 100644 (file)
@@ -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)
 
index 6e75d07681500e37bf195a13adf98ad1552e1017..39e733a326eb62cc324941c570e24877a39b7ca8 100644 (file)
@@ -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:
index 567ddf8e28c76b15bdf1d39ac05fadbd274b13c7..a123d5a211d6234fb81b41c9d01ba28a2cfefa68 100644 (file)
@@ -20,7 +20,7 @@ from gui import toolbarUtil
 \r
 from util import profile\r
 from util import gcodeInterpreter\r
-from util import stl\r
+from util import meshLoader\r
 from util import util3d\r
 from util import sliceRun\r
 \r
@@ -264,8 +264,7 @@ class previewPanel(wx.Panel):
                for obj in self.objectList:\r
                        if obj.filename != None and os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime:\r
                                obj.ileTime = os.stat(obj.filename).st_mtime\r
-                               mesh = stl.stlModel()\r
-                               mesh.load(obj.filename)\r
+                               mesh = meshLoader.loadMesh(obj.filename)\r
                                obj.dirty = False\r
                                obj.mesh = mesh\r
                                self.updateModelTransform()\r
index 63a88cf256df748ee19d9ae539d6df323e0d2b92..1e21b527510e255d4f826b37797eff9db2426f6c 100644 (file)
@@ -25,6 +25,7 @@ from gui import dropTarget
 from util import validators\r
 from util import profile\r
 from util import util3d\r
+from util import meshLoader\r
 from util import stl\r
 from util import mesh\r
 from util import sliceRun\r
@@ -34,11 +35,11 @@ from util import exporer
 class Action(object):\r
        pass\r
 \r
-class ProjectObject(stl.stlModel):\r
+class ProjectObject(object):\r
        def __init__(self, parent, filename):\r
                super(ProjectObject, self).__init__()\r
 \r
-               self.load(filename)\r
+               self.mesh = meshLoader.loadMesh(filename)\r
 \r
                self.parent = parent\r
                self.filename = filename\r
@@ -55,7 +56,7 @@ class ProjectObject(stl.stlModel):
                self.modelDisplayList = None\r
                self.modelDirty = False\r
 \r
-               self.getMinimumZ()\r
+               self.mesh.getMinimumZ()\r
                \r
                self.centerX = -self.getMinimum()[0] + 5\r
                self.centerY = -self.getMinimum()[1] + 5\r
@@ -89,14 +90,21 @@ class ProjectObject(stl.stlModel):
                return True\r
 \r
        def updateModelTransform(self):\r
-               self.setRotateMirror(self.rotate, self.flipX, self.flipY, self.flipZ, self.swapXZ, self.swapYZ)\r
-               minZ = self.getMinimumZ()\r
+               self.mesh.setRotateMirror(self.rotate, self.flipX, self.flipY, self.flipZ, self.swapXZ, self.swapYZ)\r
+               minZ = self.mesh.getMinimumZ()\r
                minV = self.getMinimum()\r
                maxV = self.getMaximum()\r
-               self.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ])\r
-               minZ = self.getMinimumZ()\r
+               self.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ])\r
+               minZ = self.mesh.getMinimumZ()\r
                self.modelDirty = True\r
        \r
+       def getMinimum(self):\r
+               return self.mesh.getMinimum()\r
+       def getMaximum(self):\r
+               return self.mesh.getMaximum()\r
+       def getSize(self):\r
+               return self.mesh.getSize()\r
+       \r
        def clone(self):\r
                p = ProjectObject(self.parent, self.filename)\r
 \r
@@ -139,7 +147,7 @@ class projectPlanner(wx.Frame):
                self.GetSizer().Add(self.panel, 1, flag=wx.EXPAND)\r
                #self.SetIcon(icon.getMainIcon())\r
                \r
-               self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, '.stl'))\r
+               self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.supportedExtensions()))\r
                \r
                self.list = []\r
                self.selection = None\r
@@ -268,10 +276,10 @@ class projectPlanner(wx.Frame):
        \r
        def OnCutMesh(self, e):\r
                dlg=wx.FileDialog(self, "Open file to cut", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)\r
-               dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")\r
+               dlg.SetWildcard(meshLoader.wildcardFilter())\r
                if dlg.ShowModal() == wx.ID_OK:\r
                        filename = dlg.GetPath()\r
-                       model = stl.stlModel().load(filename)\r
+                       model = meshLoader.loadMesh(filename)\r
                        pd = wx.ProgressDialog('Splitting model.', 'Splitting model into multiple parts.', model.vertexCount, self, wx.PD_ELAPSED_TIME | wx.PD_REMAINING_TIME | wx.PD_SMOOTH)\r
                        parts = model.splitToParts(pd.Update)\r
                        for part in parts:\r
@@ -317,7 +325,7 @@ class projectPlanner(wx.Frame):
                output._prepareVertexCount(totalCount)\r
                for item in self.list:\r
                        offset = numpy.array([item.centerX, item.centerY, 0])\r
-                       for v in item.vertexes:\r
+                       for v in item.mesh.vertexes:\r
                                v0 = v * item.scale + offset\r
                                output.addVertex(v0[0], v0[1], v0[2])\r
                stl.saveAsSTL(output, filename)\r
@@ -419,7 +427,7 @@ class projectPlanner(wx.Frame):
        \r
        def OnAddModel(self, e):\r
                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)\r
-               dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")\r
+               dlg.SetWildcard(meshLoader.wildcardFilter())\r
                if dlg.ShowModal() == wx.ID_OK:\r
                        for filename in dlg.GetPaths():\r
                                item = ProjectObject(self, filename)\r
@@ -807,7 +815,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
                                item.modelDirty = False\r
                                modelSize = item.getMaximum() - item.getMinimum()\r
                                glNewList(item.modelDisplayList, GL_COMPILE)\r
-                               opengl.DrawMesh(item)\r
+                               opengl.DrawMesh(item.mesh)\r
                                glEndList()\r
                        \r
                        if item.validPlacement:\r
index b133fa1af665665a66f8f97115f9f76ff5ebcf79..ebc30b3ad75003543b14b8008d2af85d44c8f0b7 100644 (file)
@@ -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 (file)
index 0000000..fea8ef6
--- /dev/null
@@ -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 (file)
index 0000000..ed199d7
--- /dev/null
@@ -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
+