Increase performance and decrease memory usage by using numpy library for 3D models. Saves more then 50% memory, and is about 30% faster when loading models. I think more performance can be gained with this library.

This commit is contained in:
daid 2012-07-26 16:30:43 +02:00
parent e698fb067d
commit 8069d0633f
6 changed files with 164 additions and 179 deletions

View File

@ -180,44 +180,44 @@ def ResetMatrixRotationAndScale():
def DrawBox(vMin, vMax): def DrawBox(vMin, vMax):
glBegin(GL_LINE_LOOP) glBegin(GL_LINE_LOOP)
glVertex3f(vMin.x, vMin.y, vMin.z) glVertex3f(vMin[0], vMin[1], vMin[2])
glVertex3f(vMax.x, vMin.y, vMin.z) glVertex3f(vMax[0], vMin[1], vMin[2])
glVertex3f(vMax.x, vMax.y, vMin.z) glVertex3f(vMax[0], vMax[1], vMin[2])
glVertex3f(vMin.x, vMax.y, vMin.z) glVertex3f(vMin[0], vMax[1], vMin[2])
glEnd() glEnd()
glBegin(GL_LINE_LOOP) glBegin(GL_LINE_LOOP)
glVertex3f(vMin.x, vMin.y, vMax.z) glVertex3f(vMin[0], vMin[1], vMax[2])
glVertex3f(vMax.x, vMin.y, vMax.z) glVertex3f(vMax[0], vMin[1], vMax[2])
glVertex3f(vMax.x, vMax.y, vMax.z) glVertex3f(vMax[0], vMax[1], vMax[2])
glVertex3f(vMin.x, vMax.y, vMax.z) glVertex3f(vMin[0], vMax[1], vMax[2])
glEnd() glEnd()
glBegin(GL_LINES) glBegin(GL_LINES)
glVertex3f(vMin.x, vMin.y, vMin.z) glVertex3f(vMin[0], vMin[1], vMin[2])
glVertex3f(vMin.x, vMin.y, vMax.z) glVertex3f(vMin[0], vMin[1], vMax[2])
glVertex3f(vMax.x, vMin.y, vMin.z) glVertex3f(vMax[0], vMin[1], vMin[2])
glVertex3f(vMax.x, vMin.y, vMax.z) glVertex3f(vMax[0], vMin[1], vMax[2])
glVertex3f(vMax.x, vMax.y, vMin.z) glVertex3f(vMax[0], vMax[1], vMin[2])
glVertex3f(vMax.x, vMax.y, vMax.z) glVertex3f(vMax[0], vMax[1], vMax[2])
glVertex3f(vMin.x, vMax.y, vMin.z) glVertex3f(vMin[0], vMax[1], vMin[2])
glVertex3f(vMin.x, vMax.y, vMax.z) glVertex3f(vMin[0], vMax[1], vMax[2])
glEnd() glEnd()
def DrawSTL(mesh): def DrawSTL(mesh):
glEnable(GL_CULL_FACE) glEnable(GL_CULL_FACE)
for face in mesh.faces: for i in xrange(0, mesh.vertexCount, 3):
glBegin(GL_TRIANGLES) glBegin(GL_TRIANGLES)
v1 = face.v[0] v1 = mesh.vertexes[i]
v2 = face.v[1] v2 = mesh.vertexes[i+1]
v3 = face.v[2] v3 = mesh.vertexes[i+2]
glNormal3f(face.normal.x, face.normal.y, face.normal.z) glNormal3f(mesh.normal[i/3][0], mesh.normal[i/3][1], mesh.normal[i/3][2])
glVertex3f(v1.x, v1.y, v1.z) glVertex3f(v1[0], v1[1], v1[2])
glVertex3f(v2.x, v2.y, v2.z) glVertex3f(v2[0], v2[1], v2[2])
glVertex3f(v3.x, v3.y, v3.z) glVertex3f(v3[0], v3[1], v3[2])
glNormal3f(-face.normal.x, -face.normal.y, -face.normal.z) glNormal3f(-mesh.normal[i/3][0], -mesh.normal[i/3][1], -mesh.normal[i/3][2])
glVertex3f(v1.x, v1.y, v1.z) glVertex3f(v1[0], v1[1], v1[2])
glVertex3f(v3.x, v3.y, v3.z) glVertex3f(v2[0], v2[1], v2[2])
glVertex3f(v2.x, v2.y, v2.z) glVertex3f(v3[0], v3[1], v3[2])
glEnd() glEnd()
def DrawGCodeLayer(layer): def DrawGCodeLayer(layer):

View File

@ -1,6 +1,7 @@
from __future__ import division from __future__ import division
import sys, math, threading, re, time, os import sys, math, threading, re, time, os
import numpy
from wx import glcanvas from wx import glcanvas
import wx import wx
@ -170,11 +171,11 @@ class previewPanel(wx.Panel):
return return
vMin = self.objectsMinV vMin = self.objectsMinV
vMax = self.objectsMaxV vMax = self.objectsMaxV
scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax.x - vMin.x) / 2) scaleX1 = (self.machineSize.x - self.machineCenter.x) / ((vMax[0] - vMin[0]) / 2)
scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax.y - vMin.y) / 2) scaleY1 = (self.machineSize.y - self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
scaleX2 = (self.machineCenter.x) / ((vMax.x - vMin.x) / 2) scaleX2 = (self.machineCenter.x) / ((vMax[0] - vMin[1]) / 2)
scaleY2 = (self.machineCenter.y) / ((vMax.y - vMin.y) / 2) scaleY2 = (self.machineCenter.y) / ((vMax[1] - vMin[1]) / 2)
scaleZ = self.machineSize.z / (vMax.z - vMin.z) scaleZ = self.machineSize.z / (vMax[2] - vMin[2])
scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ) scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ)
self.scale.SetValue(str(scale)) self.scale.SetValue(str(scale))
profile.putProfileSetting('model_scale', self.scale.GetValue()) profile.putProfileSetting('model_scale', self.scale.GetValue())
@ -356,8 +357,8 @@ class previewPanel(wx.Panel):
continue continue
obj.mesh.getMinimumZ() obj.mesh.getMinimumZ()
minV = minV.min(obj.mesh.getMinimum()) minV = numpy.minimum(minV, obj.mesh.getMinimum())
maxV = maxV.max(obj.mesh.getMaximum()) maxV = numpy.maximum(maxV, obj.mesh.getMaximum())
self.objectsMaxV = maxV self.objectsMaxV = maxV
self.objectsMinV = minV self.objectsMinV = minV
@ -365,10 +366,11 @@ class previewPanel(wx.Panel):
if obj.mesh == None: if obj.mesh == None:
continue continue
for v in obj.mesh.vertexes: obj.mesh.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minV[2]])
v.z -= minV.z #for v in obj.mesh.vertexes:
v.x -= minV.x + (maxV.x - minV.x) / 2 # v[2] -= minV[2]
v.y -= minV.y + (maxV.y - minV.y) / 2 # v[0] -= minV[0] + (maxV[0] - minV[0]) / 2
# v[1] -= minV[1] + (maxV[1] - minV[1]) / 2
obj.mesh.getMinimumZ() obj.mesh.getMinimumZ()
obj.dirty = True obj.dirty = True
self.glCanvas.Refresh() self.glCanvas.Refresh()
@ -461,7 +463,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
glTranslate(0,0,-self.parent.gcode.layerList[self.parent.layerSpin.GetValue()][0].list[-1].z) glTranslate(0,0,-self.parent.gcode.layerList[self.parent.layerSpin.GetValue()][0].list[-1].z)
else: else:
if self.parent.objectsMaxV != None: if self.parent.objectsMaxV != None:
glTranslate(0,0,-self.parent.objectsMaxV.z * profile.getProfileSettingFloat('model_scale') / 2) glTranslate(0,0,-self.parent.objectsMaxV[2] * profile.getProfileSettingFloat('model_scale') / 2)
else: else:
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0) glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
glTranslate(self.offsetX, self.offsetY, 0.0) glTranslate(self.offsetX, self.offsetY, 0.0)
@ -610,11 +612,11 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
modelScale = profile.getProfileSettingFloat('model_scale') modelScale = profile.getProfileSettingFloat('model_scale')
modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale modelSize = (obj.mesh.getMaximum() - obj.mesh.getMinimum()) * modelScale
glPushMatrix() glPushMatrix()
glTranslate(-(modelSize.x+10)*(multiX-1)/2,-(modelSize.y+10)*(multiY-1)/2, 0) glTranslate(-(modelSize[0]+10)*(multiX-1)/2,-(modelSize[1]+10)*(multiY-1)/2, 0)
for mx in xrange(0, multiX): for mx in xrange(0, multiX):
for my in xrange(0, multiY): for my in xrange(0, multiY):
glPushMatrix() glPushMatrix()
glTranslate((modelSize.x+10)*mx,(modelSize.y+10)*my, 0) glTranslate((modelSize[0]+10)*mx,(modelSize[1]+10)*my, 0)
glScalef(modelScale, modelScale, modelScale) glScalef(modelScale, modelScale, modelScale)
glCallList(obj.displayList) glCallList(obj.displayList)
glPopMatrix() glPopMatrix()

View File

@ -3,9 +3,9 @@ import __init__
import wx, os, platform, types, webbrowser, math, subprocess, threading, time, re import wx, os, platform, types, webbrowser, math, subprocess, threading, time, re
import ConfigParser import ConfigParser
import numpy
from wx import glcanvas from wx import glcanvas
import wx
try: try:
import OpenGL import OpenGL
OpenGL.ERROR_CHECKING = False OpenGL.ERROR_CHECKING = False
@ -55,18 +55,15 @@ class ProjectObject(stl.stlModel):
self.modelDisplayList = None self.modelDisplayList = None
self.modelDirty = False self.modelDirty = False
self.origonalVertexes = list(self.vertexes)
for i in xrange(0, len(self.origonalVertexes)):
self.origonalVertexes[i] = self.origonalVertexes[i].copy()
self.getMinimumZ() self.getMinimumZ()
self.centerX = -self.getMinimum().x + 5 self.centerX = -self.getMinimum()[0] + 5
self.centerY = -self.getMinimum().y + 5 self.centerY = -self.getMinimum()[1] + 5
self.updateModelTransform() self.updateModelTransform()
self.centerX = -self.getMinimum().x + 5 self.centerX = -self.getMinimum()[0] + 5
self.centerY = -self.getMinimum().y + 5 self.centerY = -self.getMinimum()[1] + 5
def isSameExceptForPosition(self, other): def isSameExceptForPosition(self, other):
if self.filename != other.filename: if self.filename != other.filename:
@ -96,10 +93,7 @@ class ProjectObject(stl.stlModel):
minZ = self.getMinimumZ() minZ = self.getMinimumZ()
minV = self.getMinimum() minV = self.getMinimum()
maxV = self.getMaximum() maxV = self.getMaximum()
for v in self.vertexes: self.vertexes -= numpy.array([minV[0] + (maxV[0] - minV[0]) / 2, minV[1] + (maxV[1] - minV[1]) / 2, minZ])
v.z -= minZ
v.x -= minV.x + (maxV.x - minV.x) / 2
v.y -= minV.y + (maxV.y - minV.y) / 2
minZ = self.getMinimumZ() minZ = self.getMinimumZ()
self.modelDirty = True self.modelDirty = True
@ -125,14 +119,14 @@ class ProjectObject(stl.stlModel):
return p return p
def clampXY(self): def clampXY(self):
if self.centerX < -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x: if self.centerX < -self.getMinimum()[0] * self.scale + self.parent.extruderOffset[self.extruder][0]:
self.centerX = -self.getMinimum().x * self.scale + self.parent.extruderOffset[self.extruder].x self.centerX = -self.getMinimum()[0] * self.scale + self.parent.extruderOffset[self.extruder][0]
if self.centerY < -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y: if self.centerY < -self.getMinimum()[1] * self.scale + self.parent.extruderOffset[self.extruder][1]:
self.centerY = -self.getMinimum().y * self.scale + self.parent.extruderOffset[self.extruder].y self.centerY = -self.getMinimum()[1] * self.scale + self.parent.extruderOffset[self.extruder][1]
if self.centerX > self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale: if self.centerX > self.parent.machineSize[0] + self.parent.extruderOffset[self.extruder][0] - self.getMaximum()[0] * self.scale:
self.centerX = self.parent.machineSize.x + self.parent.extruderOffset[self.extruder].x - self.getMaximum().x * self.scale self.centerX = self.parent.machineSize[0] + self.parent.extruderOffset[self.extruder][0] - self.getMaximum()[0] * self.scale
if self.centerY > self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale: if self.centerY > self.parent.machineSize[1] + self.parent.extruderOffset[self.extruder][1] - self.getMaximum()[1] * self.scale:
self.centerY = self.parent.machineSize.y + self.parent.extruderOffset[self.extruder].y - self.getMaximum().y * self.scale self.centerY = self.parent.machineSize[1] + self.parent.extruderOffset[self.extruder][1] - self.getMaximum()[1] * self.scale
class projectPlanner(wx.Frame): class projectPlanner(wx.Frame):
"Main user interface window" "Main user interface window"
@ -151,15 +145,15 @@ class projectPlanner(wx.Frame):
self.selection = None self.selection = None
self.printMode = 0 self.printMode = 0
self.machineSize = util3d.Vector3(profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')) self.machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
self.headSizeMin = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0) self.headSizeMin = numpy.array([profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0])
self.headSizeMax = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0) self.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
self.extruderOffset = [ self.extruderOffset = [
util3d.Vector3(0,0,0), numpy.array([0,0,0]),
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0), numpy.array([profile.getPreferenceFloat('extruder_offset_x1'), profile.getPreferenceFloat('extruder_offset_y1'), 0]),
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x2'), profile.getPreferenceFloat('extruder_offset_y2'), 0), numpy.array([profile.getPreferenceFloat('extruder_offset_x2'), profile.getPreferenceFloat('extruder_offset_y2'), 0]),
util3d.Vector3(profile.getPreferenceFloat('extruder_offset_x3'), profile.getPreferenceFloat('extruder_offset_y3'), 0)] numpy.array([profile.getPreferenceFloat('extruder_offset_x3'), profile.getPreferenceFloat('extruder_offset_y3'), 0])]
self.toolbar = toolbarUtil.Toolbar(self.panel) self.toolbar = toolbarUtil.Toolbar(self.panel)
@ -392,7 +386,7 @@ class projectPlanner(wx.Frame):
def OnTopClick(self): def OnTopClick(self):
self.preview.view3D = False self.preview.view3D = False
self.preview.zoom = self.machineSize.x / 2 + 10 self.preview.zoom = self.machineSize[0] / 2 + 10
self.preview.offsetX = 0 self.preview.offsetX = 0
self.preview.offsetY = 0 self.preview.offsetY = 0
self.preview.Refresh() self.preview.Refresh()
@ -499,9 +493,9 @@ class projectPlanner(wx.Frame):
self.listbox.SetSelection(-1) self.listbox.SetSelection(-1)
def OnAutoPlace(self, e): def OnAutoPlace(self, e):
bestAllowedSize = int(self.machineSize.y) bestAllowedSize = int(self.machineSize[1])
bestArea = self._doAutoPlace(bestAllowedSize) bestArea = self._doAutoPlace(bestAllowedSize)
for i in xrange(10, int(self.machineSize.y), 10): for i in xrange(10, int(self.machineSize[1]), 10):
area = self._doAutoPlace(i) area = self._doAutoPlace(i)
if area < bestArea: if area < bestArea:
bestAllowedSize = i bestAllowedSize = i
@ -516,18 +510,18 @@ class projectPlanner(wx.Frame):
extraSizeMax = self.headSizeMax extraSizeMax = self.headSizeMax
if profile.getProfileSettingFloat('skirt_line_count') > 0: if profile.getProfileSettingFloat('skirt_line_count') > 0:
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0) extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0])
extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0) extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0])
if profile.getProfileSetting('support') != 'None': if profile.getProfileSetting('support') != 'None':
extraSizeMin = extraSizeMin + util3d.Vector3(3.0, 0, 0) extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0])
extraSizeMax = extraSizeMax + util3d.Vector3(3.0, 0, 0) extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0])
if self.printMode == 1: if self.printMode == 1:
extraSizeMin = util3d.Vector3(6.0, 6.0, 0) extraSizeMin = numpy.array([6.0, 6.0, 0])
extraSizeMax = util3d.Vector3(6.0, 6.0, 0) extraSizeMax = numpy.array([6.0, 6.0, 0])
if extraSizeMin.x > extraSizeMax.x: if extraSizeMin[0] > extraSizeMax[0]:
posX = self.machineSize.x posX = self.machineSize[0]
dirX = -1 dirX = -1
else: else:
posX = 0 posX = 0
@ -535,35 +529,35 @@ class projectPlanner(wx.Frame):
posY = 0 posY = 0
dirY = 1 dirY = 1
minX = self.machineSize.x minX = self.machineSize[0]
minY = self.machineSize.y minY = self.machineSize[1]
maxX = 0 maxX = 0
maxY = 0 maxY = 0
for item in self.list: for item in self.list:
item.centerX = posX + item.getMaximum().x * item.scale * dirX item.centerX = posX + item.getMaximum()[0] * item.scale * dirX
item.centerY = posY + item.getMaximum().y * item.scale * dirY item.centerY = posY + item.getMaximum()[1] * item.scale * dirY
if item.centerY + item.getSize().y >= allowedSizeY: if item.centerY + item.getSize()[1] >= allowedSizeY:
if dirX < 0: if dirX < 0:
posX = minX - extraSizeMax.x - 1 posX = minX - extraSizeMax[0] - 1
else: else:
posX = maxX + extraSizeMin.x + 1 posX = maxX + extraSizeMin[0] + 1
posY = 0 posY = 0
item.centerX = posX + item.getMaximum().x * item.scale * dirX item.centerX = posX + item.getMaximum()[0] * item.scale * dirX
item.centerY = posY + item.getMaximum().y * item.scale * dirY item.centerY = posY + item.getMaximum()[1] * item.scale * dirY
posY += item.getSize().y * item.scale * dirY + extraSizeMin.y + 1 posY += item.getSize()[1] * item.scale * dirY + extraSizeMin[1] + 1
minX = min(minX, item.centerX - item.getSize().x * item.scale / 2) minX = min(minX, item.centerX - item.getSize()[0] * item.scale / 2)
minY = min(minY, item.centerY - item.getSize().y * item.scale / 2) minY = min(minY, item.centerY - item.getSize()[1] * item.scale / 2)
maxX = max(maxX, item.centerX + item.getSize().x * item.scale / 2) maxX = max(maxX, item.centerX + item.getSize()[0] * item.scale / 2)
maxY = max(maxY, item.centerY + item.getSize().y * item.scale / 2) maxY = max(maxY, item.centerY + item.getSize()[1] * item.scale / 2)
for item in self.list: for item in self.list:
if dirX < 0: if dirX < 0:
item.centerX -= minX / 2 item.centerX -= minX / 2
else: else:
item.centerX += (self.machineSize.x - maxX) / 2 item.centerX += (self.machineSize[0] - maxX) / 2
item.centerY += (self.machineSize.y - maxY) / 2 item.centerY += (self.machineSize[1] - maxY) / 2
if minX < 0 or maxX > self.machineSize.x: if minX < 0 or maxX > self.machineSize[0]:
return ((maxX - minX) + (maxY - minY)) * 100 return ((maxX - minX) + (maxY - minY)) * 100
return (maxX - minX) + (maxY - minY) return (maxX - minX) + (maxY - minY)
@ -590,8 +584,8 @@ class projectPlanner(wx.Frame):
for item in self.list: for item in self.list:
if item.profile != None and os.path.isfile(item.profile): if item.profile != None and os.path.isfile(item.profile):
profile.loadGlobalProfile(item.profile) profile.loadGlobalProfile(item.profile)
put('machine_center_x', item.centerX - self.extruderOffset[item.extruder].x) put('machine_center_x', item.centerX - self.extruderOffset[item.extruder][0])
put('machine_center_y', item.centerY - self.extruderOffset[item.extruder].y) put('machine_center_y', item.centerY - self.extruderOffset[item.extruder][1])
put('model_scale', item.scale) put('model_scale', item.scale)
put('flip_x', item.flipX) put('flip_x', item.flipX)
put('flip_y', item.flipY) put('flip_y', item.flipY)
@ -607,7 +601,7 @@ class projectPlanner(wx.Frame):
action.temperature = profile.getProfileSettingFloat('print_temperature') action.temperature = profile.getProfileSettingFloat('print_temperature')
action.extruder = item.extruder action.extruder = item.extruder
action.filename = item.filename action.filename = item.filename
clearZ = max(clearZ, item.getMaximum().z * item.scale + 5.0) clearZ = max(clearZ, item.getMaximum()[2] * item.scale + 5.0)
action.clearZ = clearZ action.clearZ = clearZ
action.leaveResultForNextSlice = False action.leaveResultForNextSlice = False
action.usePreviousSlice = False action.usePreviousSlice = False
@ -698,7 +692,7 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel) wx.EVT_MOUSEWHEEL(self, self.OnMouseWheel)
self.yaw = 30 self.yaw = 30
self.pitch = 60 self.pitch = 60
self.zoom = self.parent.machineSize.x / 2 + 10 self.zoom = self.parent.machineSize[0] / 2 + 10
self.offsetX = 0 self.offsetX = 0
self.offsetY = 0 self.offsetY = 0
self.view3D = False self.view3D = False
@ -760,32 +754,30 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
glTranslate(0,0,-self.zoom) glTranslate(0,0,-self.zoom)
glRotate(-self.pitch, 1,0,0) glRotate(-self.pitch, 1,0,0)
glRotate(self.yaw, 0,0,1) glRotate(self.yaw, 0,0,1)
if False: #self.parent.triangleMesh != None:
glTranslate(0,0,-self.parent.triangleMesh.getMaximum().z / 2)
else: else:
glScale(1.0/self.zoom, 1.0/self.zoom, 1.0) glScale(1.0/self.zoom, 1.0/self.zoom, 1.0)
glTranslate(self.offsetX, self.offsetY, 0.0) glTranslate(self.offsetX, self.offsetY, 0.0)
glTranslate(-self.parent.machineSize.x/2, -self.parent.machineSize.y/2, 0) glTranslate(-self.parent.machineSize[0]/2, -self.parent.machineSize[1]/2, 0)
self.OnDraw() self.OnDraw()
self.SwapBuffers() self.SwapBuffers()
def OnDraw(self): def OnDraw(self):
machineSize = self.parent.machineSize machineSize = self.parent.machineSize
opengl.DrawMachine(machineSize) opengl.DrawMachine(util3d.Vector3(machineSize[0], machineSize[1], machineSize[2]))
extraSizeMin = self.parent.headSizeMin extraSizeMin = self.parent.headSizeMin
extraSizeMax = self.parent.headSizeMax extraSizeMax = self.parent.headSizeMax
if profile.getProfileSettingFloat('skirt_line_count') > 0: if profile.getProfileSettingFloat('skirt_line_count') > 0:
skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap') skirtSize = profile.getProfileSettingFloat('skirt_line_count') * profile.calculateEdgeWidth() + profile.getProfileSettingFloat('skirt_gap')
extraSizeMin = extraSizeMin + util3d.Vector3(skirtSize, skirtSize, 0) extraSizeMin = extraSizeMin + numpy.array([skirtSize, skirtSize, 0])
extraSizeMax = extraSizeMax + util3d.Vector3(skirtSize, skirtSize, 0) extraSizeMax = extraSizeMax + numpy.array([skirtSize, skirtSize, 0])
if profile.getProfileSetting('support') != 'None': if profile.getProfileSetting('support') != 'None':
extraSizeMin = extraSizeMin + util3d.Vector3(3.0, 0, 0) extraSizeMin = extraSizeMin + numpy.array([3.0, 0, 0])
extraSizeMax = extraSizeMax + util3d.Vector3(3.0, 0, 0) extraSizeMax = extraSizeMax + numpy.array([3.0, 0, 0])
if self.parent.printMode == 1: if self.parent.printMode == 1:
extraSizeMin = util3d.Vector3(6.0, 6.0, 0) extraSizeMin = numpy.array([6.0, 6.0, 0])
extraSizeMax = util3d.Vector3(6.0, 6.0, 0) extraSizeMax = numpy.array([6.0, 6.0, 0])
for item in self.parent.list: for item in self.parent.list:
item.validPlacement = True item.validPlacement = True
@ -793,13 +785,13 @@ class PreviewGLCanvas(glcanvas.GLCanvas):
for idx1 in xrange(0, len(self.parent.list)): for idx1 in xrange(0, len(self.parent.list)):
item = self.parent.list[idx1] item = self.parent.list[idx1]
iMin1 = item.getMinimum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) - extraSizeMin - self.parent.extruderOffset[item.extruder] iMin1 = (item.getMinimum() * item.scale) + numpy.array([item.centerX, item.centerY, 0]) - extraSizeMin - self.parent.extruderOffset[item.extruder]
iMax1 = item.getMaximum() * item.scale + util3d.Vector3(item.centerX, item.centerY, 0) + extraSizeMax - self.parent.extruderOffset[item.extruder] iMax1 = (item.getMaximum() * item.scale) + numpy.array([item.centerX, item.centerY, 0]) + extraSizeMax - self.parent.extruderOffset[item.extruder]
for idx2 in xrange(0, idx1): for idx2 in xrange(0, idx1):
item2 = self.parent.list[idx2] item2 = self.parent.list[idx2]
iMin2 = item2.getMinimum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0) iMin2 = (item2.getMinimum() * item2.scale) + numpy.array([item2.centerX, item2.centerY, 0])
iMax2 = item2.getMaximum() * item2.scale + util3d.Vector3(item2.centerX, item2.centerY, 0) iMax2 = (item2.getMaximum() * item2.scale) + numpy.array([item2.centerX, item2.centerY, 0])
if item != item2 and iMax1.x >= iMin2.x and iMin1.x <= iMax2.x and iMax1.y >= iMin2.y and iMin1.y <= iMax2.y: if item != item2 and iMax1[0] >= iMin2[0] and iMin1[0] <= iMax2[0] and iMax1[1] >= iMin2[1] and iMin1[1] <= iMax2[1]:
item.validPlacement = False item.validPlacement = False
item2.gotHit = True item2.gotHit = True
@ -959,8 +951,8 @@ class ProjectSliceProgressWindow(wx.Frame):
line = p.stdout.readline() line = p.stdout.readline()
self.returnCode = p.wait() self.returnCode = p.wait()
put('machine_center_x', action.centerX - self.extruderOffset[action.extruder].x) put('machine_center_x', action.centerX - self.extruderOffset[action.extruder][0])
put('machine_center_y', action.centerY - self.extruderOffset[action.extruder].y) put('machine_center_y', action.centerY - self.extruderOffset[action.extruder][1])
put('clear_z', action.clearZ) put('clear_z', action.clearZ)
put('extruder', action.extruder) put('extruder', action.extruder)
put('print_temperature', action.temperature) put('print_temperature', action.temperature)
@ -1089,8 +1081,8 @@ class preferencesDialog(configBase.configWindowBase):
self.Fit() self.Fit()
def OnClose(self, e): def OnClose(self, e):
self.parent.headSizeMin = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0) self.parent.headSizeMin = numpy.array([profile.getPreferenceFloat('extruder_head_size_min_x'), profile.getPreferenceFloat('extruder_head_size_min_y'),0])
self.parent.headSizeMax = util3d.Vector3(profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0) self.parent.headSizeMax = numpy.array([profile.getPreferenceFloat('extruder_head_size_max_x'), profile.getPreferenceFloat('extruder_head_size_max_y'),0])
self.parent.Refresh() self.parent.Refresh()
self.MakeModal(False) self.MakeModal(False)

View File

@ -2,41 +2,36 @@ import sys, math, re, os, struct, time
import util3d import util3d
class meshFace(object): import numpy
def __init__(self, v0, v1, v2):
self.v = [v0, v1, v2]
class mesh(object): class mesh(object):
def __init__(self): def __init__(self):
self.faces = [] self.vertexes = None
self.vertexes = [] self.origonalVertexes = None
self.vertexCount = 0
def addFace(self, v0, v1, v2): def addVertex(self, x, y, z):
self.vertexes.append(v0) n = self.vertexCount
self.vertexes.append(v1) self.origonalVertexes[n][0] = x
self.vertexes.append(v2) self.origonalVertexes[n][1] = y
self.faces.append(meshFace(v0, v1, v2)) self.origonalVertexes[n][2] = z
self.vertexCount += 1
def _prepareVertexCount(self, vertexNumber):
#Set the amount of faces before loading data in them. This way we can create the numpy arrays before we fill them.
self.origonalVertexes = numpy.zeros((vertexNumber, 3), float)
self.normal = numpy.zeros((vertexNumber / 3, 3))
self.vertexCount = 0
def _postProcessAfterLoad(self): def _postProcessAfterLoad(self):
self.origonalVertexes = list(self.vertexes) self.vertexes = self.origonalVertexes.copy()
for i in xrange(0, len(self.origonalVertexes)):
self.origonalVertexes[i] = self.origonalVertexes[i].copy()
self.getMinimumZ() self.getMinimumZ()
def getMinimumZ(self): def getMinimumZ(self):
minv = self.vertexes[0].copy() self.min = self.vertexes.min(0)
maxv = self.vertexes[0].copy() self.max = self.vertexes.max(0)
for v in self.vertexes: self.size = self.max - self.min
minv.x = min(minv.x, v.x) return self.min[2]
minv.y = min(minv.y, v.y)
minv.z = min(minv.z, v.z)
maxv.x = max(maxv.x, v.x)
maxv.y = max(maxv.y, v.y)
maxv.z = max(maxv.z, v.z)
self.min = minv
self.max = maxv
self.size = maxv - minv
return self.min.z
def getMaximum(self): def getMaximum(self):
return self.max return self.max
@ -62,23 +57,23 @@ class mesh(object):
mat11 = math.cos(rotate) * scaleY mat11 = math.cos(rotate) * scaleY
for i in xrange(0, len(self.origonalVertexes)): for i in xrange(0, len(self.origonalVertexes)):
x = self.origonalVertexes[i].x x = self.origonalVertexes[i][0]
y = self.origonalVertexes[i].y y = self.origonalVertexes[i][1]
z = self.origonalVertexes[i].z z = self.origonalVertexes[i][2]
if swapXZ: if swapXZ:
x, z = z, x x, z = z, x
if swapYZ: if swapYZ:
y, z = z, y y, z = z, y
self.vertexes[i].x = x * mat00 + y * mat01 self.vertexes[i][0] = x * mat00 + y * mat01
self.vertexes[i].y = x * mat10 + y * mat11 self.vertexes[i][1] = x * mat10 + y * mat11
self.vertexes[i].z = z * scaleZ self.vertexes[i][2] = z * scaleZ
for face in self.faces: for i in xrange(0, len(self.origonalVertexes), 3):
v1 = face.v[0] v1 = self.vertexes[i]
v2 = face.v[1] v2 = self.vertexes[i+1]
v3 = face.v[2] v3 = self.vertexes[i+2]
face.normal = (v2 - v1).cross(v3 - v1) self.normal[i/3] = numpy.cross((v2 - v1), (v3 - v1))
face.normal.normalize() self.normal[i/3] /= (self.normal[i/3] * self.normal[i/3]).sum()
self.getMinimumZ() self.getMinimumZ()

View File

@ -1,6 +1,5 @@
import sys, math, re, os, struct, time import sys, math, re, os, struct, time
import util3d
import mesh import mesh
class stlModel(mesh.mesh): class stlModel(mesh.mesh):
@ -11,7 +10,7 @@ class stlModel(mesh.mesh):
f = open(filename, "rb") f = open(filename, "rb")
if f.read(5).lower() == "solid": if f.read(5).lower() == "solid":
self._loadAscii(f) self._loadAscii(f)
if not self.faces: if self.vertexCount < 3:
f.seek(5, os.SEEK_SET) f.seek(5, os.SEEK_SET)
self._loadBinary(f) self._loadBinary(f)
else: else:
@ -22,31 +21,28 @@ class stlModel(mesh.mesh):
return self return self
def _loadAscii(self, f): def _loadAscii(self, f):
cnt = 0
for line in f:
if 'vertex' in line:
cnt += 1
self._prepareVertexCount(int(cnt))
f.seek(5, os.SEEK_SET)
cnt = 0 cnt = 0
for line in f: for line in f:
if 'vertex' in line: if 'vertex' in line:
data = line.split() data = line.split()
if cnt == 0: self.addVertex(float(data[1]), float(data[2]), float(data[3]))
v0 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
cnt = 1
elif cnt == 1:
v1 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
cnt = 2
elif cnt == 2:
v2 = util3d.Vector3(float(data[1]), float(data[2]), float(data[3]))
self.addFace(v0, v1, v2)
cnt = 0
def _loadBinary(self, f): def _loadBinary(self, f):
#Skip the header #Skip the header
f.read(80-5) f.read(80-5)
faceCount = struct.unpack('<I', f.read(4))[0] faceCount = struct.unpack('<I', f.read(4))[0]
self._prepareVertexCount(faceCount * 3)
for idx in xrange(0, faceCount): for idx in xrange(0, faceCount):
data = struct.unpack("<ffffffffffffH", f.read(50)) data = struct.unpack("<ffffffffffffH", f.read(50))
v0 = util3d.Vector3(data[3], data[4], data[5]) self.addVertex(data[3], data[4], data[5])
v1 = util3d.Vector3(data[6], data[7], data[8]) self.addVertex(data[6], data[7], data[8])
v2 = util3d.Vector3(data[9], data[10], data[11]) self.addVertex(data[9], data[10], data[11])
self.addFace(v0, v1, v2)
def saveAsSTL(mesh, filename): def saveAsSTL(mesh, filename):
f = open(filename, 'wb') f = open(filename, 'wb')
@ -70,8 +66,8 @@ def saveAsSTL(mesh, filename):
if __name__ == '__main__': if __name__ == '__main__':
for filename in sys.argv[1:]: for filename in sys.argv[1:]:
m = stlModel().load(filename) m = stlModel().load(filename)
print("Loaded %d faces" % (len(m.faces))) print("Loaded %d faces" % (m.vertexCount / 3))
parts = m.splitToParts() # parts = m.splitToParts()
for p in parts: # for p in parts:
saveAsSTL(p, "export_%i.stl" % parts.index(p)) # saveAsSTL(p, "export_%i.stl" % parts.index(p))

View File

@ -13,7 +13,7 @@ class Vector3(object):
return Vector3(self.x, self.y, self.z) return Vector3(self.x, self.y, self.z)
def __repr__(self): def __repr__(self):
return '[%s, %s, %s]' % ( self.x, self.y, self.z ) return 'V[%s, %s, %s]' % ( self.x, self.y, self.z )
def __add__(self, v): def __add__(self, v):
return Vector3( self.x + v.x, self.y + v.y, self.z + v.z ) return Vector3( self.x + v.x, self.y + v.y, self.z + v.z )