chiark / gitweb /
Add super-shaper tool..
authordaid303 <daid303@gmail.com>
Wed, 24 Apr 2013 11:41:11 +0000 (13:41 +0200)
committerdaid303 <daid303@gmail.com>
Wed, 24 Apr 2013 11:41:11 +0000 (13:41 +0200)
Cura/gui/mainWindow.py
Cura/gui/tools/superformula.py [new file with mode: 0644]

index 34ab293b4cff3eec80d6b8ec8c1717a50e370742..95599cd8e8c11c8882d42745e85e20921c5e9a20 100644 (file)
@@ -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 (file)
index 0000000..8032e78
--- /dev/null
@@ -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()