From: daid303 Date: Wed, 24 Apr 2013 11:41:11 +0000 (+0200) Subject: Add super-shaper tool.. X-Git-Tag: 13.05~54 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=69169f7a5e69d5cb20bb75ad8fa92f2939d17a31;p=cura.git Add super-shaper tool.. --- diff --git a/Cura/gui/mainWindow.py b/Cura/gui/mainWindow.py index 34ab293b..95599cd8 100644 --- a/Cura/gui/mainWindow.py +++ b/Cura/gui/mainWindow.py @@ -16,6 +16,7 @@ from Cura.gui import sceneView from Cura.gui.tools import batchRun from Cura.gui.util import dropTarget from Cura.gui.tools import minecraftImport +from Cura.gui.tools import superformula from Cura.util import profile from Cura.util import version from Cura.util import meshLoader @@ -107,6 +108,8 @@ class mainWindow(wx.Frame): if minecraftImport.hasMinecraft(): i = toolsMenu.Append(-1, 'Minecraft import...') self.Bind(wx.EVT_MENU, self.OnMinecraftImport, i) + i = toolsMenu.Append(-1, 'Super-shaper...') + self.Bind(wx.EVT_MENU, self.OnSuperformula, i) self.menubar.Append(toolsMenu, 'Tools') expertMenu = wx.Menu() @@ -394,6 +397,11 @@ class mainWindow(wx.Frame): mi.Centre() mi.Show(True) + def OnSuperformula(self, e): + sf = superformula.superformulaWindow(self) + sf.Centre() + sf.Show(True) + def OnCheckForUpdate(self, e): newVersion = version.checkForNewerVersion() if newVersion is not None: diff --git a/Cura/gui/tools/superformula.py b/Cura/gui/tools/superformula.py new file mode 100644 index 00000000..8032e78e --- /dev/null +++ b/Cura/gui/tools/superformula.py @@ -0,0 +1,280 @@ +from __future__ import absolute_import + +import wx +import math +import time +import random +import numpy + +from wx import glcanvas +import OpenGL +OpenGL.ERROR_CHECKING = False +from OpenGL.GL import * +from OpenGL.GLU import * + +from Cura.gui.util import opengl +from Cura.util import mesh + +class superShape(object): + def __init__(self, a1, b1, m1, n11, n21, n31, a2, b2, m2, n12, n22, n32): + self._a1 = a1 + self._b1 = b1 + self._m1 = math.floor(m1) + self._n11 = n11 + self._n21 = n21 + self._n31 = n31 + self._a2 = a2 + self._b2 = b2 + self._m2 = m2 + self._n12 = n12 + self._n22 = n22 + self._n32 = n32 + + points = [] + + for n in xrange(-64, 64): + row = [] + points.append(row) + f1 = n * math.pi / 64 + r1 = math.pow((math.pow(abs(math.cos(m1*f1/4)/a1),n21) + math.pow(abs(math.sin(m1*f1/4)/b1), n31)), -(1/n11)) + for m in xrange(0, 64): + f2 = m * math.pi / 128 + r2 = math.pow((math.pow(abs(math.cos(m2*f2/4)/a2),n22) + math.pow(abs(math.sin(m2*f2/4)/b2), n32)), -(1/n12)) + + x = r1 * math.cos(f1) * r2 * math.cos(f2) + y = r1 * math.sin(f1) * r2 * math.cos(f2) + z = r2 * math.sin(f2) + + row.append([x,y,z]) + + self._obj = mesh.printableObject() + objMesh = self._obj._addMesh() + objMesh._prepareFaceCount(len(points) * (len(points[0]) - 1) * 2) + + for n in xrange(-1, len(points) - 1): + row1 = points[n] + row2 = points[n+1] + for m in xrange(0, len(row1) - 1): + p0 = row1[m] + p1 = row1[m+1] + p2 = row2[m] + p3 = row2[m+1] + + objMesh._addFace(p0[0], p0[1], p0[2], p2[0], p2[1], p2[2], p1[0], p1[1], p1[2]) + objMesh._addFace(p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], p3[0], p3[1], p3[2]) + + self._obj._postProcessAfterLoad() + + def draw(self): + for m in self._obj._meshList: + if m.vbo is None: + m.vbo = opengl.GLVBO(m.vertexes, m.normal) + m.vbo.render() + +class superformulaWindow(wx.Frame): + def __init__(self, parent): + super(superformulaWindow, self).__init__(parent, title='Cura - Superformula') + self._rotate = 0.0 + self._t0 = time.time() + + self.panel = wx.Panel(self, -1) + self.SetSizer(wx.BoxSizer()) + self.GetSizer().Add(self.panel, 1, wx.EXPAND) + + sizer = wx.GridBagSizer(2, 2) + + sizer.Add(wx.StaticText(self.panel, -1, 'A1'), pos=(0,0)) + self.sliderA1 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1)) + sizer.Add(self.sliderA1, pos=(0,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'B1'), pos=(1,0)) + self.sliderB1 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1)) + sizer.Add(self.sliderB1, pos=(1,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'M1'), pos=(2,0)) + self.sliderM1 = wx.Slider(self.panel, -1, 50, 5, 200, size=(150, -1)) + sizer.Add(self.sliderM1, pos=(2,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'N11'), pos=(3,0)) + self.sliderN11 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1)) + sizer.Add(self.sliderN11, pos=(3,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'N21'), pos=(4,0)) + self.sliderN21 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1)) + sizer.Add(self.sliderN21, pos=(4,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'N31'), pos=(5,0)) + self.sliderN31 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1)) + sizer.Add(self.sliderN31, pos=(5,1)) + + sizer.Add(wx.StaticText(self.panel, -1, 'A2'), pos=(6,0)) + self.sliderA2 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1)) + sizer.Add(self.sliderA2, pos=(6,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'B2'), pos=(7,0)) + self.sliderB2 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1)) + sizer.Add(self.sliderB2, pos=(7,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'M2'), pos=(8,0)) + self.sliderM2 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1)) + sizer.Add(self.sliderM2, pos=(8,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'N12'), pos=(9,0)) + self.sliderN12 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1)) + sizer.Add(self.sliderN12, pos=(9,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'N22'), pos=(10,0)) + self.sliderN22 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1)) + sizer.Add(self.sliderN22, pos=(10,1)) + sizer.Add(wx.StaticText(self.panel, -1, 'N32'), pos=(11,0)) + self.sliderN32 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1)) + sizer.Add(self.sliderN32, pos=(11,1)) + + self.randomButton = wx.Button(self.panel, -1, 'Randomize') + sizer.Add(self.randomButton, pos=(12,1)) + self.addButton = wx.Button(self.panel, -1, 'Add to print') + sizer.Add(self.addButton, pos=(13,1)) + + attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 32, glcanvas.WX_GL_STENCIL_SIZE, 8) + self._glCanvas = glcanvas.GLCanvas(self.panel, style=wx.WANTS_CHARS, attribList = attribList) + self._glCanvas.SetMinSize((800,600)) + sizer.Add(self._glCanvas, pos=(0,2), span=(14,1), flag=wx.EXPAND) + self._context = glcanvas.GLContext(self._glCanvas) + + sizer.AddGrowableRow(13) + sizer.AddGrowableCol(2) + self.panel.SetSizer(sizer) + self.Layout() + self.Fit() + + wx.EVT_PAINT(self._glCanvas, self._OnPaint) + wx.EVT_SIZE(self._glCanvas, self._OnSize) + wx.EVT_ERASE_BACKGROUND(self._glCanvas, self._OnEraseBackground) + wx.EVT_IDLE(self, self._OnIdle) + + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderA1) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderB1) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderM1) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN11) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN21) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN31) + + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderA2) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderB2) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderM2) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN12) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN22) + self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN32) + + self.Bind(wx.EVT_BUTTON, lambda e: self.onRandom(), self.randomButton) + self.Bind(wx.EVT_BUTTON, lambda e: self.onAdd(), self.addButton) + + self._shape = None + self._releaseList = [] + self._updateShape() + + def onRandom(self): + self.sliderA1.SetValue(random.randint(self.sliderA1.GetMin(), self.sliderA1.GetMax())) + self.sliderB1.SetValue(random.randint(self.sliderB1.GetMin(), self.sliderB1.GetMax())) + self.sliderM1.SetValue(random.randint(self.sliderM1.GetMin(), self.sliderM1.GetMax())) + self.sliderN11.SetValue(random.randint(self.sliderN11.GetMin(), self.sliderN11.GetMax())) + self.sliderN21.SetValue(random.randint(self.sliderN21.GetMin(), self.sliderN21.GetMax())) + self.sliderN31.SetValue(random.randint(self.sliderN31.GetMin(), self.sliderN31.GetMax())) + self.sliderA2.SetValue(random.randint(self.sliderA2.GetMin(), self.sliderA2.GetMax())) + self.sliderB2.SetValue(random.randint(self.sliderB2.GetMin(), self.sliderB2.GetMax())) + self.sliderM2.SetValue(random.randint(self.sliderM2.GetMin(), self.sliderM2.GetMax())) + self.sliderN12.SetValue(random.randint(self.sliderN12.GetMin(), self.sliderN12.GetMax())) + self.sliderN22.SetValue(random.randint(self.sliderN22.GetMin(), self.sliderN22.GetMax())) + self.sliderN32.SetValue(random.randint(self.sliderN32.GetMin(), self.sliderN32.GetMax())) + self._updateShape() + + def onAdd(self): + scale = 1.0/numpy.max(self._shape._obj.getSize()) * 50 + + obj = mesh.printableObject() + m = obj._addMesh() + m._prepareFaceCount(self._shape._obj._meshList[0].vertexCount / 3) + m.vertexes = self._shape._obj._meshList[0].vertexes * scale + m.vertexCount = self._shape._obj._meshList[0].vertexCount + obj._postProcessAfterLoad() + self.GetParent().scene._scene.add(obj) + + def _updateShape(self): + if self._shape is not None: + for m in self._shape._obj._meshList: + if m.vbo is not None: + self._releaseList.append(m.vbo) + self._shape = superShape( + float(self.sliderA1.GetValue()) / 10.0, + float(self.sliderB1.GetValue()) / 10.0, + float(self.sliderM1.GetValue()) / 10.0, + + float(self.sliderN11.GetValue()) / 10.0, + float(self.sliderN21.GetValue()) / 10.0, + float(self.sliderN31.GetValue()) / 10.0, + + float(self.sliderA2.GetValue()) / 10.0, + float(self.sliderB2.GetValue()) / 10.0, + float(self.sliderM2.GetValue()) / 10.0, + + float(self.sliderN12.GetValue()) / 10.0, + float(self.sliderN22.GetValue()) / 10.0, + float(self.sliderN32.GetValue()) / 10.0, + ) + + def _OnEraseBackground(self,event): + #Workaround for windows background redraw flicker. + pass + + def _OnSize(self, e): + self.Refresh() + + def _OnIdle(self, e): + self._glCanvas.Refresh() + + def _OnPaint(self, e): + dc = wx.PaintDC(self._glCanvas) + + self._glCanvas.SetCurrent(self._context) + for obj in self._releaseList: + obj.release() + self._releaseList = [] + + size = self._glCanvas.GetSize() + glViewport(0, 0, size.GetWidth(), size.GetHeight()) + glLoadIdentity() + + 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) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + + glClearColor(0.0, 0.0, 0.0, 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) + + glTranslate(0,0,-2) + glRotate(-45 - math.sin(self._rotate/50.0) * 30, 1, 0, 0) + glRotate(self._rotate, 0, 0, 1) + self._rotate += (self._t0 - time.time()) * 20 + self._t0 = time.time() + + glEnable(GL_LIGHTING) + glEnable(GL_LIGHT0) + glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0]) + glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8,1.0,0.8,0]) + glLightfv(GL_LIGHT0, GL_AMBIENT, [0.3,0.3,0.3,0]) + + scale = 1.0/numpy.max(self._shape._obj.getSize()) + glScalef(scale, scale, scale) + glEnable(GL_NORMALIZE) + + self._shape.draw() + + glFlush() + self._glCanvas.SwapBuffers()