chiark / gitweb /
Massive breaking time, start of the new scene display which will cleanup a lot of...
authordaid303 <daid303@gmail.com>
Thu, 21 Mar 2013 16:42:29 +0000 (17:42 +0100)
committerdaid303 <daid303@gmail.com>
Thu, 21 Mar 2013 16:42:29 +0000 (17:42 +0100)
Cura/gui/mainWindow.py
Cura/gui/preview3d.py
Cura/gui/sceneView.py [new file with mode: 0644]
Cura/gui/util/opengl.py
Cura/gui/util/openglGui.py
Cura/util/mesh.py
Cura/util/meshLoader.py
Cura/util/meshLoaders/stl.py

index 678964797cd47f542dbadc431a899172e5a6fed2..890d83ced978ad5fbe3c8d2a6c47b60862ffe128 100644 (file)
@@ -6,8 +6,6 @@ import webbrowser
 
 from Cura.gui import configBase
 from Cura.gui import expertConfig
-from Cura.gui import preview3d
-from Cura.gui import sliceProgressPanel
 from Cura.gui import alterationPanel
 from Cura.gui import pluginPanel
 from Cura.gui import preferencesDialog
@@ -16,11 +14,10 @@ from Cura.gui import firmwareInstall
 from Cura.gui import printWindow
 from Cura.gui import simpleMode
 from Cura.gui import projectPlanner
+from Cura.gui import sceneView
 from Cura.gui.tools import batchRun
-from Cura.gui import flatSlicerWindow
 from Cura.gui.util import dropTarget
 from Cura.gui.tools import minecraftImport
-from Cura.util import validators
 from Cura.util import profile
 from Cura.util import version
 from Cura.util import sliceRun
@@ -171,7 +168,7 @@ class mainWindow(wx.Frame):
                self.leftPane.SetSizer(self.leftSizer)
                
                #Preview window
-               self.preview3d = preview3d.previewPanel(self.rightPane)
+               self.scene = sceneView.SceneView(self.rightPane)
 
                #Also bind double clicking the 3D preview to load an STL file.
                #self.preview3d.glCanvas.Bind(wx.EVT_LEFT_DCLICK, lambda e: self._showModelLoadDialog(1), self.preview3d.glCanvas)
@@ -179,7 +176,7 @@ class mainWindow(wx.Frame):
                #Main sizer, to position the preview window, buttons and tab control
                sizer = wx.BoxSizer()
                self.rightPane.SetSizer(sizer)
-               sizer.Add(self.preview3d, 1, flag=wx.EXPAND)
+               sizer.Add(self.scene, 1, flag=wx.EXPAND)
 
                # Main window sizer
                sizer = wx.BoxSizer(wx.VERTICAL)
@@ -189,7 +186,7 @@ class mainWindow(wx.Frame):
                self.sizer = sizer
 
                if len(self.filelist) > 0:
-                       self.preview3d.loadModelFiles(self.filelist)
+                       self.scene.loadScene(self.filelist)
 
                        # Update the Model MRU
                        for idx in xrange(0, len(self.filelist)):
@@ -290,8 +287,8 @@ class mainWindow(wx.Frame):
                self.filelist = filelist
                self.SetTitle('Cura - %s - %s' % (version.getVersion(), filelist[-1]))
                profile.putPreference('lastFile', ';'.join(self.filelist))
-               self.preview3d.loadModelFiles(self.filelist, True)
-               self.preview3d.setViewMode("Normal")
+               self.scene.loadScene(self.filelist)
+               #self.preview3d.setViewMode("Normal")
                
                # Update the Model MRU
                for idx in xrange(0, len(self.filelist)):
@@ -392,7 +389,7 @@ class mainWindow(wx.Frame):
                self.sizer.Layout()
 
        def updateProfileToControls(self):
-               self.preview3d.updateProfileToControls()
+               self.scene.updateProfileToControls()
                self.normalSettingsPanel.updateProfileToControls()
                self.simpleSettingsPanel.updateProfileToControls()
 
@@ -524,7 +521,7 @@ class mainWindow(wx.Frame):
                        profile.putPreference('window_normal_sash', self.normalSashPos)
 
                #HACK: Set the paint function of the glCanvas to nothing so it won't keep refreshing. Which keeps wxWidgets from quiting.
-               self.preview3d.glCanvas.OnPaint = lambda e : e
+               self.scene.OnPaint = lambda e : e
                self.Destroy()
 
        def OnQuit(self, e):
index 23aa02a2e7bc65035450e9364443a79d16fcaf9e..b3e41cb0a4ee0d56ab4984316183a593547be262 100644 (file)
@@ -7,6 +7,8 @@ import re
 import time
 import os
 import numpy
+import traceback
+import sys
 
 from wx import glcanvas
 import wx
@@ -363,8 +365,9 @@ class previewPanel(wx.Panel):
                        if obj.filename is not None and os.path.isfile(obj.filename) and obj.fileTime != os.stat(obj.filename).st_mtime:
                                obj.fileTime = os.stat(obj.filename).st_mtime
                                try:
-                                       mesh = meshLoader.loadMesh(obj.filename)
+                                       mesh = meshLoader.loadMeshes(obj.filename)[0]
                                except:
+                                       traceback.print_exc(file=sys.stdout)
                                        wx.CallAfter(self.ShowWarningPopup, 'Failed to load %s' % (obj.filename))
                                        obj.mesh = None
                                        obj.filename = None
@@ -495,14 +498,14 @@ class previewPanel(wx.Panel):
 
                minV = self.objectList[0].mesh.getMinimum()
                maxV = self.objectList[0].mesh.getMaximum()
-               objectsBoundaryCircleSize = self.objectList[0].mesh.boundaryCircleSize
+               objectsBoundaryCircleSize = self.objectList[0].mesh.getBoundaryCircle()
                for obj in self.objectList:
                        if obj.mesh is None:
                                continue
 
                        minV = numpy.minimum(minV, obj.mesh.getMinimum())
                        maxV = numpy.maximum(maxV, obj.mesh.getMaximum())
-                       objectsBoundaryCircleSize = max(objectsBoundaryCircleSize, obj.mesh.boundaryCircleSize)
+                       objectsBoundaryCircleSize = max(objectsBoundaryCircleSize, obj.mesh.getBoundaryCircle())
 
                self.objectsMaxV = maxV
                self.objectsMinV = minV
diff --git a/Cura/gui/sceneView.py b/Cura/gui/sceneView.py
new file mode 100644 (file)
index 0000000..50ec7d9
--- /dev/null
@@ -0,0 +1,124 @@
+from __future__ import absolute_import
+from __future__ import division
+
+import numpy
+from ctypes import c_void_p
+
+import OpenGL
+OpenGL.ERROR_CHECKING = False
+from OpenGL.GLU import *
+from OpenGL.GL import *
+
+from Cura.util import profile
+from Cura.util import meshLoader
+from Cura.gui.util import opengl
+from Cura.gui.util import openglGui
+
+class SceneView(openglGui.glGuiPanel):
+       def __init__(self, parent):
+               super(SceneView, self).__init__(parent)
+
+               self._yaw = 30
+               self._pitch = 60
+               self._zoom = 100
+               self._objectList = []
+               self._objectShader = None
+               self._objColors = [None,None,None,None]
+               self._tmpVertex = None
+               self.updateProfileToControls()
+
+       def loadScene(self, fileList):
+               for filename in fileList:
+                       for obj in meshLoader.loadMeshes(filename):
+                               self._objectList.append(obj)
+
+       def updateProfileToControls(self):
+               self._objColors[0] = profile.getPreferenceColour('model_colour')
+               self._objColors[1] = profile.getPreferenceColour('model_colour2')
+               self._objColors[2] = profile.getPreferenceColour('model_colour3')
+               self._objColors[3] = profile.getPreferenceColour('model_colour4')
+
+       def OnMouseMotion(self,e):
+               if e.Dragging() and e.LeftIsDown():
+                       self._yaw += e.GetX() - self.oldX
+                       self._pitch -= e.GetY() - self.oldY
+                       if self._pitch > 170:
+                               self._pitch = 170
+                       if self._pitch < 10:
+                               self._pitch = 10
+               if e.Dragging() and e.RightIsDown():
+                       self._zoom += e.GetY() - self.oldY
+                       if self._zoom < 1:
+                               self._zoom = 1
+                       if self._zoom > 500:
+                               self._zoom = 500
+               self.oldX = e.GetX()
+               self.oldY = e.GetY()
+
+       def _init3DView(self):
+               # set viewing projection
+               size = self.GetSize()
+               glViewport(0, 0, size.GetWidth(), size.GetHeight())
+
+               glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
+
+               glDisable(GL_RESCALE_NORMAL)
+               glDisable(GL_LIGHTING)
+               glDisable(GL_LIGHT0)
+               glEnable(GL_DEPTH_TEST)
+               glDisable(GL_CULL_FACE)
+               glDisable(GL_BLEND)
+
+               glClearColor(0.8, 0.8, 0.8, 1.0)
+               glClearStencil(0)
+               glClearDepth(1.0)
+
+               glMatrixMode(GL_PROJECTION)
+               glLoadIdentity()
+               aspect = float(size.GetWidth()) / float(size.GetHeight())
+               gluPerspective(45.0, aspect, 1.0, 1000.0)
+
+               glMatrixMode(GL_MODELVIEW)
+               glLoadIdentity()
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
+
+       def OnPaint(self,e):
+               if self._objectShader is None:
+                       self._objectShader = opengl.GLShader("""
+uniform float cameraDistance;
+varying float light_amount;
+
+void main(void)
+{
+    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+    gl_FrontColor = gl_Color;
+
+       light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
+       light_amount *= 1 - (length(gl_Position.xyz - vec3(0,0,cameraDistance)) / 1.5 / cameraDistance);
+       light_amount += 0.2;
+}
+                       ""","""
+uniform float cameraDistance;
+varying float light_amount;
+
+void main(void)
+{
+       gl_FragColor = gl_Color * light_amount;
+}
+                       """)
+               self._init3DView()
+               glTranslate(0,0,-self._zoom)
+               glRotate(-self._pitch, 1,0,0)
+               glRotate(self._yaw, 0,0,1)
+               glTranslate(0,0,-15)
+               glColor3f(self._objColors[0][0], self._objColors[0][1], self._objColors[0][2])
+
+               self._objectShader.bind()
+               self._objectShader.setUniform('cameraDistance', self._zoom)
+               if self._tmpVertex is None:
+                       for obj in self._objectList:
+                               for m in obj._meshList:
+                                       self._tmpVertex = opengl.GLVBO(m.vertexes, m.normal)
+
+               self._tmpVertex.render()
+               self._objectShader.unbind()
index dc7deb67c0bda796de31b7aa768a89a96e2e2d97..0adc43bb823487795c40e27f89d15515f5871e6d 100644 (file)
@@ -17,44 +17,75 @@ OpenGL.ERROR_CHECKING = False
 from OpenGL.GLUT import *
 from OpenGL.GLU import *
 from OpenGL.GL import *
+from OpenGL.GL import shaders
 glutInit()
 
-def InitGL(window, view3D, zoom):
-       # set viewing projection
-       glMatrixMode(GL_MODELVIEW)
-       glLoadIdentity()
-       size = window.GetSize()
-       glViewport(0, 0, size.GetWidth(), size.GetHeight())
-
-       glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
-       glLightfv(GL_LIGHT1, GL_POSITION, [1.0, 1.0, 1.0, 0.0])
-
-       glEnable(GL_RESCALE_NORMAL)
-       glEnable(GL_LIGHTING)
-       glEnable(GL_LIGHT0)
-       glEnable(GL_DEPTH_TEST)
-       glEnable(GL_CULL_FACE)
-       glDisable(GL_BLEND)
-
-       glClearColor(1.0, 1.0, 1.0, 1.0)
-       glClearColor(0.8, 0.8, 0.8, 1.0)
-       glClearStencil(0)
-       glClearDepth(1.0)
-
-       glMatrixMode(GL_PROJECTION)
-       glLoadIdentity()
-       aspect = float(size.GetWidth()) / float(size.GetHeight())
-       if view3D:
-               gluPerspective(45.0, aspect, 1.0, 1000.0)
-       else:
-               glOrtho(-aspect * (zoom), aspect * (zoom), -1.0 * (zoom), 1.0 * (zoom), -1000.0, 1000.0)
-
-       glMatrixMode(GL_MODELVIEW)
-       glLoadIdentity()
-       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
-
 platformMesh = None
 
+class GLShader(object):
+       def __init__(self, vertexProgram, fragmentProgram):
+               try:
+                       self._vertexProgram = shaders.compileShader(vertexProgram, GL_VERTEX_SHADER)
+                       self._fragmentProgram = shaders.compileShader(fragmentProgram, GL_FRAGMENT_SHADER)
+                       self._program = shaders.compileProgram(self._vertexProgram, self._fragmentProgram)
+               except RuntimeError, e:
+                       print "Shader error:"
+                       print str(e)
+                       self._program = None
+
+       def bind(self):
+               if self._program is not None:
+                       shaders.glUseProgram(self._program)
+
+       def unbind(self):
+               shaders.glUseProgram(0)
+
+       def delete(self):
+               shaders.glDeleteShader(self._vertexProgram)
+               shaders.glDeleteShader(self._fragmentProgram)
+               glDeleteProgram(self._program)
+
+       def setUniform(self, name, value):
+               glUniform1f(glGetUniformLocation(self._program, name), value)
+
+class GLVBO(object):
+       def __init__(self, vertexArray, normalArray):
+               self._buffer = glGenBuffers(1)
+               self._size = len(vertexArray)
+               glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
+               glBufferData(GL_ARRAY_BUFFER, numpy.concatenate((vertexArray, normalArray), 1), GL_STATIC_DRAW)
+               glBindBuffer(GL_ARRAY_BUFFER, 0)
+
+       def render(self):
+               glEnableClientState(GL_VERTEX_ARRAY)
+               glEnableClientState(GL_NORMAL_ARRAY)
+               #glVertexPointer(3, GL_FLOAT, 0, m.vertexes)
+               #glNormalPointer(GL_FLOAT, 0, m.normal)
+               glBindBuffer(GL_ARRAY_BUFFER, self._buffer)
+               glVertexPointer(3, GL_FLOAT, 2*3*4, c_void_p(0))
+               glNormalPointer(GL_FLOAT, 2*3*4, c_void_p(3 * 4))
+
+               batchSize = 999    #Warning, batchSize needs to be dividable by 3
+               extraStartPos = int(self._size / batchSize) * batchSize
+               extraCount = self._size - extraStartPos
+
+               for i in xrange(0, int(self._size / batchSize)):
+                       glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
+               glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
+               glBindBuffer(GL_ARRAY_BUFFER, 0)
+               glDisableClientState(GL_VERTEX_ARRAY)
+               glDisableClientState(GL_NORMAL_ARRAY)
+
+       def release(self):
+               if self._buffer is not None:
+                       glDeleteBuffers(self._buffer, 1)
+                       self._buffer = None
+
+       def __del__(self):
+               if self._buffer is not None:
+                       print "OpenGL buffer was not properly cleaned, trying to clean it up now."
+                       glDeleteBuffers(self._buffer, 1)
+
 def DrawMachine(machineSize):
        glDisable(GL_LIGHTING)
        glDisable(GL_CULL_FACE)
@@ -347,35 +378,36 @@ def DrawMeshOutline(mesh):
 
 def DrawMesh(mesh, insideOut = False):
        glEnable(GL_CULL_FACE)
-       glEnableClientState(GL_VERTEX_ARRAY);
-       glEnableClientState(GL_NORMAL_ARRAY);
-       glVertexPointer(3, GL_FLOAT, 0, mesh.vertexes)
-       if insideOut:
-               glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
-       else:
-               glNormalPointer(GL_FLOAT, 0, mesh.normal)
+       glEnableClientState(GL_VERTEX_ARRAY)
+       glEnableClientState(GL_NORMAL_ARRAY)
+       for m in mesh._meshList:
+               glVertexPointer(3, GL_FLOAT, 0, m.vertexes)
+               if insideOut:
+                       glNormalPointer(GL_FLOAT, 0, m.invNormal)
+               else:
+                       glNormalPointer(GL_FLOAT, 0, m.normal)
 
-       #Odd, drawing in batchs is a LOT faster then drawing it all at once.
-       batchSize = 999    #Warning, batchSize needs to be dividable by 3
-       extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
-       extraCount = mesh.vertexCount - extraStartPos
+               #Odd, drawing in batchs is a LOT faster then drawing it all at once.
+               batchSize = 999    #Warning, batchSize needs to be dividable by 3
+               extraStartPos = int(m.vertexCount / batchSize) * batchSize
+               extraCount = m.vertexCount - extraStartPos
 
-       glCullFace(GL_BACK)
-       for i in xrange(0, int(mesh.vertexCount / batchSize)):
-               glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
-       glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
+               glCullFace(GL_BACK)
+               for i in xrange(0, int(m.vertexCount / batchSize)):
+                       glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
+               glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
 
-       glCullFace(GL_FRONT)
-       if insideOut:
-               glNormalPointer(GL_FLOAT, 0, mesh.normal)
-       else:
-               glNormalPointer(GL_FLOAT, 0, mesh.invNormal)
-       for i in xrange(0, int(mesh.vertexCount / batchSize)):
-               glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
-       extraStartPos = int(mesh.vertexCount / batchSize) * batchSize
-       extraCount = mesh.vertexCount - extraStartPos
-       glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
-       glCullFace(GL_BACK)
+               glCullFace(GL_FRONT)
+               if insideOut:
+                       glNormalPointer(GL_FLOAT, 0, m.normal)
+               else:
+                       glNormalPointer(GL_FLOAT, 0, m.invNormal)
+               for i in xrange(0, int(m.vertexCount / batchSize)):
+                       glDrawArrays(GL_TRIANGLES, i * batchSize, batchSize)
+               extraStartPos = int(m.vertexCount / batchSize) * batchSize
+               extraCount = m.vertexCount - extraStartPos
+               glDrawArrays(GL_TRIANGLES, extraStartPos, extraCount)
+               glCullFace(GL_BACK)
 
        glDisableClientState(GL_VERTEX_ARRAY)
        glDisableClientState(GL_NORMAL_ARRAY)
index 3dccef6579d25c11f5f915654991f877dd4bd993..ad9a7f083aefae32ea73f0137e955794ae9d5d85 100644 (file)
@@ -193,6 +193,7 @@ class glGuiPanel(glcanvas.GLCanvas):
 
                glDisable(GL_DEPTH_TEST)
                glEnable(GL_BLEND)
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                glDisable(GL_LIGHTING)
                glColor4ub(255,255,255,255)
 
index 6bbaeefdc7cdab75a32bb1083f36e71ede457ed8..18fd76e85da396bf34976544ee346a3356133377 100644 (file)
@@ -13,61 +13,75 @@ class printableObject(object):
                self._meshList = []
                self._position = [0.0, 0.0]
                self._matrix = numpy.matrix([[1,0,0],[0,1,0],[0,0,1]], numpy.float64)
+               self._transformedMin = None
+               self._transformedMax = None
+               self._boundaryCircleSize = None
 
        def _addMesh(self):
                m = mesh()
                self._meshList.append(m)
                return m
 
+       def _postProcessAfterLoad(self):
+               for m in self._meshList:
+                       m._calculateNormals()
+               self.processMatrix()
+
        def processMatrix(self):
-               self.transformedMin = numpy.array([999999999999,999999999999,999999999999], numpy.float64)
-               self.transformedMax = numpy.array([-999999999999,-999999999999,-999999999999], numpy.float64)
-               self.boundaryCircleSize = 0
+               self._transformedMin = numpy.array([999999999999,999999999999,999999999999], numpy.float64)
+               self._transformedMax = numpy.array([-999999999999,-999999999999,-999999999999], numpy.float64)
+               self._boundaryCircleSize = 0
 
                for m in self._meshList:
-                       transformedVertexes = (numpy.matrix(m.vertexes, copy = False) * self.matrix).getA()
+                       transformedVertexes = (numpy.matrix(m.vertexes, copy = False) * self._matrix).getA()
                        transformedMin = transformedVertexes.min(0)
                        transformedMax = transformedVertexes.max(0)
                        for n in xrange(0, 3):
-                               self.transformedMin[n] = min(transformedMin[n], self.transformedMin[n])
-                               self.transformedMax[n] = min(transformedMax[n], self.transformedMax[n])
+                               self._transformedMin[n] = min(transformedMin[n], self._transformedMin[n])
+                               self._transformedMax[n] = max(transformedMax[n], self._transformedMax[n])
 
                        #Calculate the boundary circle
                        transformedSize = transformedMax - transformedMin
                        center = transformedMin + transformedSize / 2.0
                        boundaryCircleSize = round(math.sqrt(numpy.max(((transformedVertexes[::,0] - center[0]) * (transformedVertexes[::,0] - center[0])) + ((transformedVertexes[::,1] - center[1]) * (transformedVertexes[::,1] - center[1])) + ((transformedVertexes[::,2] - center[2]) * (transformedVertexes[::,2] - center[2])))), 3)
-                       self.boundaryCircleSize = max(self.boundaryCircleSize, boundaryCircleSize)
-               self.transformedSize = self.transformedMax - self.transformedMin
+                       self._boundaryCircleSize = max(self._boundaryCircleSize, boundaryCircleSize)
+               self._transformedSize = self._transformedMax - self._transformedMin
 
        def getMaximum(self):
-               return self.transformedMax
+               return self._transformedMax
        def getMinimum(self):
-               return self.transformedMin
+               return self._transformedMin
        def getSize(self):
-               return self.transformedSize
+               return self._transformedSize
+       def getBoundaryCircle(self):
+               return self._boundaryCircleSize
 
 class mesh(object):
        def __init__(self):
                self.vertexes = None
                self.vertexCount = 0
 
-       def _addVertex(self, x, y, z):
+       def _addFace(self, x0, y0, z0, x1, y1, z1, x2, y2, z2):
                n = self.vertexCount
-               self.vertexes[n][0] = x
-               self.vertexes[n][1] = y
-               self.vertexes[n][2] = z
-               self.vertexCount += 1
+               self.vertexes[n][0] = x0
+               self.vertexes[n][1] = y0
+               self.vertexes[n][2] = z0
+               n += 1
+               self.vertexes[n][0] = x1
+               self.vertexes[n][1] = y1
+               self.vertexes[n][2] = z1
+               n += 1
+               self.vertexes[n][0] = x2
+               self.vertexes[n][1] = y2
+               self.vertexes[n][2] = z2
+               self.vertexCount += 3
        
-       def _prepareVertexCount(self, vertexNumber):
+       def _prepareFaceCount(self, faceNumber):
                #Set the amount of faces before loading data in them. This way we can create the numpy arrays before we fill them.
-               self.vertexes = numpy.zeros((vertexNumber, 3), numpy.float32)
-               self.normal = numpy.zeros((vertexNumber, 3), numpy.float32)
+               self.vertexes = numpy.zeros((faceNumber*3, 3), numpy.float32)
+               self.normal = numpy.zeros((faceNumber*3, 3), numpy.float32)
                self.vertexCount = 0
 
-       def _postProcessAfterLoad(self):
-               self.processMatrix()
-               self._calculateNormals()
-
        def _calculateNormals(self):
                #Calculate the normals
                tris = self.vertexes.reshape(self.vertexCount / 3, 3, 3)
index 2bfa5096d8c82ec87faaa5c84674a8dbbb2827c6..f533a056395fe079ba84456744eccd245bbf03dc 100644 (file)
@@ -12,10 +12,16 @@ def wildcardFilter():
        wildcardList = ';'.join(map(lambda s: '*' + s, supportedExtensions()))
        return "Mesh files (%s)|%s;%s" % (wildcardList, wildcardList, wildcardList.upper())
 
-def loadMesh(filename):
+#loadMeshes loads 1 or more printableObjects from a file.
+# STL files are a single printableObject with a single mesh, these are most common.
+# OBJ files usually contain a single mesh, but they can contain multiple meshes
+# AMF can contain whole scenes of objects with each object having multiple meshes.
+# DAE files are a mess, but they can contain scenes of objects as well as grouped meshes
+
+def loadMeshes(filename):
        ext = filename[filename.rfind('.'):].lower()
        if ext == '.stl':
-               return stl.stlModel().load(filename)
+               return stl.loadSTLscene(filename)
        if ext == '.obj':
                return obj.objModel().load(filename)
        if ext == '.dae':
@@ -23,4 +29,4 @@ def loadMesh(filename):
        if ext == '.amf':
                return amf.amfModel().load(filename)
        print 'Error: Unknown model extension: %s' % (ext)
-       return None
+       return []
index 10b61db42659216d7356fe5ae8ea0ed0254bc8dc..068154ece4c5f08b2d5efee8622b72168c4fa072 100644 (file)
@@ -7,48 +7,49 @@ import time
 
 from Cura.util import mesh
 
-class stlModel(mesh.mesh):
-       def __init__(self):
-               super(stlModel, self).__init__()
+def _loadAscii(m, f):
+       cnt = 0
+       for lines in f:
+               for line in lines.split('\r'):
+                       if 'vertex' in line:
+                               cnt += 1
+       m._prepareFaceCount(int(cnt) / 3)
+       f.seek(5, os.SEEK_SET)
+       cnt = 0
+       data = [None,None,None]
+       for lines in f:
+               for line in lines.split('\r'):
+                       if 'vertex' in line:
+                               data[cnt] = line.split()[1:]
+                               cnt += 1
+                               if cnt == 3:
+                                       m._addFace(float(data[0][0]), float(data[0][1]), float(data[0][2]), float(data[1][0]), float(data[1][1]), float(data[1][2]), float(data[2][0]), float(data[2][1]), float(data[2][2]))
+                                       cnt = 0
 
-       def load(self, filename):
-               f = open(filename, "rb")
-               if f.read(5).lower() == "solid":
-                       self._loadAscii(f)
-                       if self.vertexCount < 3:
-                               f.seek(5, os.SEEK_SET)
-                               self._loadBinary(f)
-               else:
-                       self._loadBinary(f)
-               f.close()
-               self._postProcessAfterLoad()
-               return self
-       
-       def _loadAscii(self, f):
-               cnt = 0
-               for lines in f:
-                       for line in lines.split('\r'):
-                               if 'vertex' in line:
-                                       cnt += 1
-               self._prepareVertexCount(int(cnt))
-               f.seek(5, os.SEEK_SET)
-               cnt = 0
-               for lines in f:
-                       for line in lines.split('\r'):
-                               if 'vertex' in line:
-                                       data = line.split()
-                                       self.addVertex(float(data[1]), float(data[2]), float(data[3]))
+def _loadBinary(m, f):
+       #Skip the header
+       f.read(80-5)
+       faceCount = struct.unpack('<I', f.read(4))[0]
+       m._prepareFaceCount(faceCount)
+       for idx in xrange(0, faceCount):
+               data = struct.unpack("<ffffffffffffH", f.read(50))
+               m._addFace(data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11])
 
-       def _loadBinary(self, f):
-               #Skip the header
-               f.read(80-5)
-               faceCount = struct.unpack('<I', f.read(4))[0]
-               self._prepareVertexCount(faceCount * 3)
-               for idx in xrange(0, faceCount):
-                       data = struct.unpack("<ffffffffffffH", f.read(50))
-                       self.addVertex(data[3], data[4], data[5])
-                       self.addVertex(data[6], data[7], data[8])
-                       self.addVertex(data[9], data[10], data[11])
+def loadSTLscene(filename):
+       obj = mesh.printableObject()
+       m = obj._addMesh()
+
+       f = open(filename, "rb")
+       if f.read(5).lower() == "solid":
+               _loadAscii(m, f)
+               if m.vertexCount < 3:
+                       f.seek(5, os.SEEK_SET)
+                       _loadBinary(m, f)
+       else:
+               _loadBinary(m, f)
+       f.close()
+       obj._postProcessAfterLoad()
+       return [obj]
 
 def saveAsSTL(mesh, filename):
        f = open(filename, 'wb')