From: daid303 Date: Thu, 21 Mar 2013 16:42:29 +0000 (+0100) Subject: Massive breaking time, start of the new scene display which will cleanup a lot of... X-Git-Tag: 13.05~172 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=e50f27ab60573318319fc51dd37bffdbc979d7ea;p=cura.git Massive breaking time, start of the new scene display which will cleanup a lot of code. --- diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 67896479..890d83ce 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -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): diff --git a/Cura/gui/preview3d.py b/Cura/gui/preview3d.py index 23aa02a2..b3e41cb0 100644 --- a/Cura/gui/preview3d.py +++ b/Cura/gui/preview3d.py @@ -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 index 00000000..50ec7d90 --- /dev/null +++ b/Cura/gui/sceneView.py @@ -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() diff --git a/Cura/gui/util/opengl.py b/Cura/gui/util/opengl.py index dc7deb67..0adc43bb 100644 --- a/Cura/gui/util/opengl.py +++ b/Cura/gui/util/opengl.py @@ -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) diff --git a/Cura/gui/util/openglGui.py b/Cura/gui/util/openglGui.py index 3dccef65..ad9a7f08 100644 --- a/Cura/gui/util/openglGui.py +++ b/Cura/gui/util/openglGui.py @@ -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) diff --git a/Cura/util/mesh.py b/Cura/util/mesh.py index 6bbaeefd..18fd76e8 100644 --- a/Cura/util/mesh.py +++ b/Cura/util/mesh.py @@ -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) diff --git a/Cura/util/meshLoader.py b/Cura/util/meshLoader.py index 2bfa5096..f533a056 100644 --- a/Cura/util/meshLoader.py +++ b/Cura/util/meshLoader.py @@ -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 [] diff --git a/Cura/util/meshLoaders/stl.py b/Cura/util/meshLoaders/stl.py index 10b61db4..068154ec 100644 --- a/Cura/util/meshLoaders/stl.py +++ b/Cura/util/meshLoaders/stl.py @@ -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('