chiark / gitweb /
Save the filename of loaded files so we can use that when saving to SD card. Make...
[cura.git] / Cura / gui / tools / superformula.py
1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
3
4 import wx
5 import math
6 import time
7 import random
8 import numpy
9
10 from wx import glcanvas
11 import OpenGL
12 OpenGL.ERROR_CHECKING = False
13 from OpenGL.GL import *
14 from OpenGL.GLU import *
15
16 from Cura.gui.util import opengl
17 from Cura.util import mesh
18 from Cura.util import meshLoader
19 from Cura.util import machineCom
20
21 class superShape(object):
22         def __init__(self, a1, b1, m1, n11, n21, n31, a2, b2, m2, n12, n22, n32):
23                 self._a1 = a1
24                 self._b1 = b1
25                 self._m1 = math.floor(m1)
26                 self._n11 = n11
27                 self._n21 = n21
28                 self._n31 = n31
29                 self._a2 = a2
30                 self._b2 = b2
31                 self._m2 = m2
32                 self._n12 = n12
33                 self._n22 = n22
34                 self._n32 = n32
35
36                 points = []
37                 cnt = 64
38                 for n in xrange(-cnt, cnt):
39                         row = []
40                         points.append(row)
41                         f1 = n * math.pi / cnt
42                         try:
43                                 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))
44                         except:
45                                 r1 = 1.0
46                         for m in xrange(0, cnt):
47                                 f2 = m * math.pi / ((cnt*2) - 2)
48                                 try:
49                                         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))
50                                 except:
51                                         r2 = 1.0
52
53                                 x = r1 * math.cos(f1) * r2 * math.cos(f2)
54                                 y = r1 * math.sin(f1) * r2 * math.cos(f2)
55                                 z = r2 * math.sin(f2)
56
57                                 row.append([x,y,z])
58
59                 self._obj = mesh.printableObject("super")
60                 objMesh = self._obj._addMesh()
61                 objMesh._prepareFaceCount(len(points) * (len(points[0]) - 1) * 2)
62
63                 for n in xrange(-1, len(points) - 1):
64                         row1 = points[n]
65                         row2 = points[n+1]
66                         for m in xrange(0, len(row1) - 1):
67                                 p0 = row1[m]
68                                 p1 = row1[m+1]
69                                 p2 = row2[m]
70                                 p3 = row2[m+1]
71
72                                 objMesh._addFace(p0[0], p0[1], p0[2], p2[0], p2[1], p2[2], p1[0], p1[1], p1[2])
73                                 objMesh._addFace(p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], p3[0], p3[1], p3[2])
74
75                 self._obj._postProcessAfterLoad()
76
77         def isValid(self):
78                 size = self._obj.getSize()
79                 if size[0] / size[2] > 10:
80                         return False
81                 return True
82
83         def draw(self):
84                 for m in self._obj._meshList:
85                         if m.vbo is None:
86                                 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
87                         m.vbo.render()
88
89 class superformulaEvolver(wx.Frame):
90         def __init__(self, parent):
91                 super(superformulaEvolver, self).__init__(parent, title='Cura - Superformula')
92                 self._rotate = 0.0
93                 self._t0 = time.time()
94                 self._timeout = 0.0
95                 self._lampState = 0
96                 self._lampSpeed = 3
97                 self._lampUpdateTime = time.time()
98                 self._buttonDown = False
99                 self._doPrint = False
100
101                 sizer = wx.BoxSizer()
102                 self.SetSizer(sizer)
103
104                 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 32, glcanvas.WX_GL_STENCIL_SIZE, 8)
105                 self._glCanvas = glcanvas.GLCanvas(self, style=wx.WANTS_CHARS, attribList = attribList)
106                 self._glCanvas.SetMinSize((800,600))
107                 sizer.Add(self._glCanvas, 1, flag=wx.EXPAND)
108                 self._context = glcanvas.GLContext(self._glCanvas)
109
110                 wx.EVT_PAINT(self._glCanvas, self._OnPaint)
111                 wx.EVT_SIZE(self._glCanvas, self._OnSize)
112                 wx.EVT_ERASE_BACKGROUND(self._glCanvas, self._OnEraseBackground)
113                 wx.EVT_IDLE(self, self._OnIdle)
114
115                 wx.EVT_LEFT_DOWN(self._glCanvas, self._OnMouseDown)
116                 wx.EVT_MOTION(self._glCanvas, self._OnMouseMotion)
117                 wx.EVT_CHAR(self._glCanvas, self._OnKeyChar)
118
119                 self._hover = 6
120                 self._shapes = [None] * 12
121                 self._releaseList = []
122
123                 self._randomize()
124
125                 #style = self.GetWindowStyle()
126                 #self.SetWindowStyle(style | wx.STAY_ON_TOP)
127                 #self.Maximize()
128                 self.ShowFullScreen(True, wx.FULLSCREEN_ALL)
129
130                 self._comm = None
131                 self._comm = machineCom.MachineCom(callbackObject=self)
132
133         def mcLog(self, message):
134                 wx.CallAfter(self.SetTitle, message)
135                 print message.strip()
136
137         def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
138                 pass
139
140         def mcStateChange(self, state):
141                 if self._comm is None:
142                         return
143                 if self._comm.isClosedOrError():
144                         self._comm.close()
145                         self._comm = machineCom.MachineCom(callbackObject=self)
146
147         def mcMessage(self, message):
148                 cmd = message.strip()
149                 if cmd == 'D0':
150                         self._lampState = 127
151                         self._lampSpeed = 25
152                         self._comm.sendCommand('M42 S127')
153                         self._buttonDown = True
154                 elif cmd == 'U0':
155                         self._buttonDown = False
156                         if self._lampSpeed < 10:
157                                 wx.CallAfter(self._OnKey, wx.WXK_SPACE)
158                         else:
159                                 wx.CallAfter(self._OnKey, ord('z'))
160                         self._lampSpeed = 3
161                 elif cmd == 'D1' and not self._comm.isPrinting():
162                         wx.CallAfter(self._OnKey, wx.WXK_DOWN)
163                 elif cmd == 'D2' and not self._comm.isPrinting():
164                         wx.CallAfter(self._OnKey, wx.WXK_LEFT)
165                 elif cmd == 'D3' and not self._comm.isPrinting():
166                         wx.CallAfter(self._OnKey, wx.WXK_UP)
167                 elif cmd == 'D4' and not self._comm.isPrinting():
168                         wx.CallAfter(self._OnKey, wx.WXK_RIGHT)
169
170         def mcProgress(self, lineNr):
171                 pass
172
173         def mcZChange(self, newZ):
174                 pass
175
176         def _OnKeyChar(self, e):
177                 self._OnKey(e.GetKeyCode())
178
179         def _OnKey(self, code):
180                 self._timeout = 0.0
181                 if code == wx.WXK_LEFT:
182                         if self._hover % 4 != 0:
183                                 self._hover -= 1
184                 elif code == wx.WXK_RIGHT:
185                         if self._hover % 4 != 3:
186                                 self._hover += 1
187                 elif code == wx.WXK_UP:
188                         if self._hover / 4 != 2:
189                                 self._hover += 4
190                 elif code == wx.WXK_DOWN:
191                         if self._hover / 4 != 0:
192                                 self._hover -= 4
193                 elif code == wx.WXK_SPACE:
194                         self._select()
195                 elif code == ord('z'):
196                         hole = meshLoader.loadMeshes('C:/Models/Delicate_Stubby_Ring-A-Thing_Sized/StubbyPinHoleNegFlat.stl')[0]
197                         v = hole._meshList[0].vertexes * 1.03
198                         v[::,1] = hole._meshList[0].vertexes[::,2]
199                         v[::,2] = hole._meshList[0].vertexes[::,1]
200                         v -= numpy.array([0,0,15], numpy.float32)
201                         numpy.clip(v, numpy.array([-100,-100,0], numpy.float32), numpy.array([100,100,100], numpy.float32), v)
202
203                         shape = self._shapes[self._hover]
204                         scale = 1.0/numpy.max(shape._obj.getSize()) * 40
205
206                         sv = shape._obj._meshList[0].vertexes * scale
207
208                         obj = mesh.printableObject("super")
209                         m = obj._addMesh()
210                         m._prepareFaceCount(shape._obj._meshList[0].vertexCount / 3 + hole._meshList[0].vertexCount / 3)
211                         for n in xrange(0, shape._obj._meshList[0].vertexCount):
212                                 l = numpy.linalg.norm(sv[n])
213                                 if l < 6.5:
214                                         sv[n] *= 6.5 / l
215                         m.vertexes = numpy.concatenate((sv, v))
216                         m.vertexCount = shape._obj._meshList[0].vertexCount + hole._meshList[0].vertexCount
217                         obj._postProcessAfterLoad()
218                         self.GetParent().scene.OnDeleteAll(None)
219                         self.GetParent().scene._scene.add(obj)
220                         self.GetParent().scene.sceneUpdated()
221                         self.GetParent().scene._updateSliceProgress(0, False)
222                         self._doPrint = True
223                 elif code == ord('c'):
224                         self._comm.cancelPrint()
225                 elif code == ord('r'):
226                         self._randomize()
227
228         def _OnMouseMotion(self, e):
229                 size = self._glCanvas.GetSize()
230                 self._hover = e.GetX() / (size.GetWidth() / 4) + (size.GetHeight() - e.GetY()) / (size.GetHeight() / 3) * 4
231
232         def _OnMouseDown(self, e):
233                 self._timeout = 0.0
234                 self._select()
235
236         def _select(self):
237                 shape = self._shapes[self._hover]
238                 for n in xrange(0, len(self._shapes)):
239                         if n == self._hover:
240                                 continue
241                         for m in self._shapes[n]._obj._meshList:
242                                 if m.vbo is not None:
243                                         self._releaseList.append(m.vbo)
244                         f = 0.5 + n * 0.1
245                         update = True
246                         while update:
247                                 self._shapes[n] = superShape(
248                                         shape._a1 + random.uniform(-f, f) / 2.0,
249                                         shape._b1 + random.uniform(-f, f) / 2.0,
250                                         shape._m1 + random.uniform(-f, f) * 2.0,
251                                         shape._n11 + random.uniform(-f, f),
252                                         shape._n21 + random.uniform(-f, f),
253                                         shape._n31 + random.uniform(-f, f),
254                                         shape._a2 + random.uniform(-f, f) / 2.0,
255                                         shape._b2 + random.uniform(-f, f) / 2.0,
256                                         shape._m2 + random.uniform(-f, f),
257                                         shape._n12 + random.uniform(-f, f),
258                                         shape._n22 + random.uniform(-f, f),
259                                         shape._n32 + random.uniform(-f, f))
260                                 update = not self._shapes[n].isValid()
261
262         def _randomize(self):
263                 for shape in self._shapes:
264                         if shape is not None:
265                                 for m in shape._obj._meshList:
266                                         if m.vbo is not None:
267                                                 self._releaseList.append(m.vbo)
268                 for n in xrange(0, len(self._shapes)):
269                         update = True
270                         while update:
271                                 self._shapes[n] = superShape(
272                                         random.uniform(0.5, 5.0),
273                                         random.uniform(0.5, 5.0),
274                                         random.uniform(0.5, 20.0),
275                                         random.uniform(0.5, 10.0),
276                                         random.uniform(0.5, 10.0),
277                                         random.uniform(0.5, 10.0),
278                                         random.uniform(0.5, 5.0),
279                                         random.uniform(0.5, 5.0),
280                                         random.uniform(0.5, 10.0),
281                                         random.uniform(0.5, 10.0),
282                                         random.uniform(0.5, 10.0),
283                                         random.uniform(0.5, 10.0))
284                                 update = not self._shapes[n].isValid()
285
286         def _OnEraseBackground(self,event):
287                 #Workaround for windows background redraw flicker.
288                 pass
289
290         def _OnSize(self, e):
291                 self.Refresh()
292
293         def _OnIdle(self, e):
294                 self._glCanvas.Refresh()
295
296         def _OnPaint(self, e):
297                 dc = wx.PaintDC(self._glCanvas)
298
299                 if time.time() > self._lampUpdateTime:
300                         self._lampUpdateTime = time.time() + 0.05
301                         if self._comm.isOperational():
302                                 self._lampState += self._lampSpeed
303                                 if self._lampState > 255:
304                                         self._lampState -= 256
305                                         if self._buttonDown:
306                                                 self._lampSpeed = 20
307                                 if self._lampState < 127:
308                                         brightness = self._lampState
309                                 else:
310                                         brightness = 255 - self._lampState
311                                 if not self._comm.isPrinting():
312                                         self._comm.sendCommand('M42 S%d' % (brightness))
313
314                 if self.GetParent().scene._gcode is not None and self.GetParent().scene._gcode.filename is not None and self._doPrint and not self._comm.isPrinting():
315                         self._doPrint = False
316                         gcodeList = ["M110", "M42 S0"]
317                         for line in open(self.GetParent().scene._gcode.filename, 'r'):
318                                 if ';' in line:
319                                         line = line[0:line.find(';')]
320                                 line = line.strip()
321                                 if len(line) > 0:
322                                         gcodeList.append(line)
323                         print len(gcodeList)
324                         self._comm.printGCode(gcodeList)
325
326                 self._glCanvas.SetCurrent(self._context)
327                 for obj in self._releaseList:
328                         obj.release()
329                 self._releaseList = []
330
331                 size = self._glCanvas.GetSize()
332                 glViewport(0, 0, size.GetWidth(), size.GetHeight())
333                 glLoadIdentity()
334
335                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
336
337                 glDisable(GL_RESCALE_NORMAL)
338                 glDisable(GL_LIGHTING)
339                 glDisable(GL_LIGHT0)
340                 glEnable(GL_DEPTH_TEST)
341                 glDisable(GL_CULL_FACE)
342                 glDisable(GL_BLEND)
343                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
344
345                 glClearColor(0.0, 0.0, 0.0, 1.0)
346                 glClearStencil(0)
347                 glClearDepth(1.0)
348
349                 glMatrixMode(GL_PROJECTION)
350                 glLoadIdentity()
351                 aspect = float(size.GetWidth()) / float(size.GetHeight())
352                 gluPerspective(30.0, aspect, 1.0, 1000.0)
353
354                 glMatrixMode(GL_MODELVIEW)
355                 glLoadIdentity()
356                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
357
358                 glTranslate(0,0,-2.0)
359                 glRotate(-45 - math.sin(self._rotate/50.0) * 30, 1, 0, 0)
360                 glRotate(self._rotate, 0, 0, 1)
361                 self._rotate += (time.time() - self._t0) * 20
362                 self._timeout += time.time() - self._t0
363                 if self._timeout > 60:
364                         self._timeout = 0.0
365                         self._randomize()
366                 self._t0 = time.time()
367
368                 glEnable(GL_LIGHTING)
369                 glEnable(GL_LIGHT0)
370                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
371                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8,1.0,0.8,0])
372                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.3,0.3,0.3,0])
373                 glEnable(GL_LIGHT1)
374                 glLightfv(GL_LIGHT1, GL_POSITION, [1.2, 0.2, 0.2, 0.0])
375                 glLightfv(GL_LIGHT1, GL_DIFFUSE, [0.5,0.3,0.2,0])
376                 glLightfv(GL_LIGHT1, GL_AMBIENT, [0.0,0.0,0.0,0])
377
378                 if self._comm.isPrinting():
379                         self._timeout = 0
380                         shape = self._shapes[self._hover]
381                         scale = 1.0/numpy.max(shape._obj.getSize())
382                         glPushMatrix()
383                         glScalef(scale, scale, scale)
384                         glTranslate(0,0,-shape._obj.getSize()[2] / 2.0)
385                         glEnable(GL_NORMALIZE)
386                         shape.draw()
387                         glPopMatrix()
388                 else:
389                         for n in xrange(0, len(self._shapes)):
390                                 shape = self._shapes[n]
391                                 scale = 1.0/numpy.max(shape._obj.getSize())
392                                 glPushMatrix()
393                                 glScalef(scale, scale, scale)
394                                 glTranslate(0,0,-shape._obj.getSize()[2] / 2.0)
395                                 glEnable(GL_NORMALIZE)
396                                 glViewport(size.GetWidth() / 4 * (n % 4), size.GetHeight() / 3 * (n / 4), size.GetWidth() / 4, size.GetHeight() / 3)
397                                 shape.draw()
398                                 glPopMatrix()
399
400                                 if n == self._hover:
401                                         glDisable(GL_LIGHTING)
402                                         glPushMatrix()
403                                         glLoadIdentity()
404                                         glBegin(GL_LINE_LOOP)
405                                         glVertex3f(-0.40, 0.25,-1)
406                                         glVertex3f( 0.40, 0.25,-1)
407                                         glVertex3f( 0.40,-0.25,-1)
408                                         glVertex3f(-0.40,-0.25,-1)
409                                         glEnd()
410                                         glPopMatrix()
411                                         glEnable(GL_LIGHTING)
412
413                 glFlush()
414                 self._glCanvas.SwapBuffers()
415
416 class superformulaWindow(wx.Frame):
417         def __init__(self, parent):
418                 super(superformulaWindow, self).__init__(parent, title='Cura - Superformula')
419                 self._rotate = 0.0
420                 self._t0 = time.time()
421
422                 self.panel = wx.Panel(self, -1)
423                 self.SetSizer(wx.BoxSizer())
424                 self.GetSizer().Add(self.panel, 1, wx.EXPAND)
425
426                 sizer = wx.GridBagSizer(2, 2)
427
428                 sizer.Add(wx.StaticText(self.panel, -1, 'A1'), pos=(0,0))
429                 self.sliderA1 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
430                 sizer.Add(self.sliderA1, pos=(0,1))
431                 sizer.Add(wx.StaticText(self.panel, -1, 'B1'), pos=(1,0))
432                 self.sliderB1 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
433                 sizer.Add(self.sliderB1, pos=(1,1))
434                 sizer.Add(wx.StaticText(self.panel, -1, 'M1'), pos=(2,0))
435                 self.sliderM1 = wx.Slider(self.panel, -1, 50, 5, 200, size=(150, -1))
436                 sizer.Add(self.sliderM1, pos=(2,1))
437                 sizer.Add(wx.StaticText(self.panel, -1, 'N11'), pos=(3,0))
438                 self.sliderN11 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
439                 sizer.Add(self.sliderN11, pos=(3,1))
440                 sizer.Add(wx.StaticText(self.panel, -1, 'N21'), pos=(4,0))
441                 self.sliderN21 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
442                 sizer.Add(self.sliderN21, pos=(4,1))
443                 sizer.Add(wx.StaticText(self.panel, -1, 'N31'), pos=(5,0))
444                 self.sliderN31 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
445                 sizer.Add(self.sliderN31, pos=(5,1))
446
447                 sizer.Add(wx.StaticText(self.panel, -1, 'A2'), pos=(6,0))
448                 self.sliderA2 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
449                 sizer.Add(self.sliderA2, pos=(6,1))
450                 sizer.Add(wx.StaticText(self.panel, -1, 'B2'), pos=(7,0))
451                 self.sliderB2 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
452                 sizer.Add(self.sliderB2, pos=(7,1))
453                 sizer.Add(wx.StaticText(self.panel, -1, 'M2'), pos=(8,0))
454                 self.sliderM2 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
455                 sizer.Add(self.sliderM2, pos=(8,1))
456                 sizer.Add(wx.StaticText(self.panel, -1, 'N12'), pos=(9,0))
457                 self.sliderN12 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
458                 sizer.Add(self.sliderN12, pos=(9,1))
459                 sizer.Add(wx.StaticText(self.panel, -1, 'N22'), pos=(10,0))
460                 self.sliderN22 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
461                 sizer.Add(self.sliderN22, pos=(10,1))
462                 sizer.Add(wx.StaticText(self.panel, -1, 'N32'), pos=(11,0))
463                 self.sliderN32 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
464                 sizer.Add(self.sliderN32, pos=(11,1))
465
466                 self.randomButton = wx.Button(self.panel, -1, 'Randomize')
467                 sizer.Add(self.randomButton, pos=(12,1))
468                 self.addButton = wx.Button(self.panel, -1, 'Add to print')
469                 sizer.Add(self.addButton, pos=(13,1))
470
471                 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 32, glcanvas.WX_GL_STENCIL_SIZE, 8)
472                 self._glCanvas = glcanvas.GLCanvas(self.panel, style=wx.WANTS_CHARS, attribList = attribList)
473                 self._glCanvas.SetMinSize((800,600))
474                 sizer.Add(self._glCanvas, pos=(0,2), span=(14,1), flag=wx.EXPAND)
475                 self._context = glcanvas.GLContext(self._glCanvas)
476
477                 sizer.AddGrowableRow(13)
478                 sizer.AddGrowableCol(2)
479                 self.panel.SetSizer(sizer)
480                 self.Layout()
481                 self.Fit()
482
483                 wx.EVT_PAINT(self._glCanvas, self._OnPaint)
484                 wx.EVT_SIZE(self._glCanvas, self._OnSize)
485                 wx.EVT_ERASE_BACKGROUND(self._glCanvas, self._OnEraseBackground)
486                 wx.EVT_IDLE(self, self._OnIdle)
487
488                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderA1)
489                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderB1)
490                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderM1)
491                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN11)
492                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN21)
493                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN31)
494
495                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderA2)
496                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderB2)
497                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderM2)
498                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN12)
499                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN22)
500                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN32)
501
502                 self.Bind(wx.EVT_BUTTON, lambda e: self.onRandom(), self.randomButton)
503                 self.Bind(wx.EVT_BUTTON, lambda e: self.onAdd(), self.addButton)
504
505                 self._shape = None
506                 self._releaseList = []
507                 self._updateShape()
508
509         def onRandom(self):
510                 update = True
511                 while update:
512                         update = False
513                         self.sliderA1.SetValue(random.randint(self.sliderA1.GetMin(), self.sliderA1.GetMax()))
514                         self.sliderB1.SetValue(random.randint(self.sliderB1.GetMin(), self.sliderB1.GetMax()))
515                         self.sliderM1.SetValue(random.randint(self.sliderM1.GetMin(), self.sliderM1.GetMax()))
516                         self.sliderN11.SetValue(random.randint(self.sliderN11.GetMin(), self.sliderN11.GetMax()))
517                         self.sliderN21.SetValue(random.randint(self.sliderN21.GetMin(), self.sliderN21.GetMax()))
518                         self.sliderN31.SetValue(random.randint(self.sliderN31.GetMin(), self.sliderN31.GetMax()))
519                         self.sliderA2.SetValue(random.randint(self.sliderA2.GetMin(), self.sliderA2.GetMax()))
520                         self.sliderB2.SetValue(random.randint(self.sliderB2.GetMin(), self.sliderB2.GetMax()))
521                         self.sliderM2.SetValue(random.randint(self.sliderM2.GetMin(), self.sliderM2.GetMax()))
522                         self.sliderN12.SetValue(random.randint(self.sliderN12.GetMin(), self.sliderN12.GetMax()))
523                         self.sliderN22.SetValue(random.randint(self.sliderN22.GetMin(), self.sliderN22.GetMax()))
524                         self.sliderN32.SetValue(random.randint(self.sliderN32.GetMin(), self.sliderN32.GetMax()))
525                         self._updateShape()
526                         if not self._shape.isValid():
527                                 update = True
528
529         def onAdd(self):
530                 scale = 1.0/numpy.max(self._shape._obj.getSize()) * 50
531
532                 obj = mesh.printableObject("super")
533                 m = obj._addMesh()
534                 m._prepareFaceCount(self._shape._obj._meshList[0].vertexCount / 3)
535                 m.vertexes = self._shape._obj._meshList[0].vertexes * scale
536                 m.vertexCount = self._shape._obj._meshList[0].vertexCount
537                 obj._postProcessAfterLoad()
538                 self.GetParent().scene._scene.add(obj)
539                 self.GetParent().scene.sceneUpdated()
540
541         def _updateShape(self):
542                 if self._shape is not None:
543                         for m in self._shape._obj._meshList:
544                                 if m.vbo is not None:
545                                         self._releaseList.append(m.vbo)
546                 self._shape = superShape(
547                         float(self.sliderA1.GetValue()) / 10.0,
548                         float(self.sliderB1.GetValue()) / 10.0,
549                         float(self.sliderM1.GetValue()) / 10.0,
550
551                         float(self.sliderN11.GetValue()) / 10.0,
552                         float(self.sliderN21.GetValue()) / 10.0,
553                         float(self.sliderN31.GetValue()) / 10.0,
554
555                         float(self.sliderA2.GetValue()) / 10.0,
556                         float(self.sliderB2.GetValue()) / 10.0,
557                         float(self.sliderM2.GetValue()) / 10.0,
558
559                         float(self.sliderN12.GetValue()) / 10.0,
560                         float(self.sliderN22.GetValue()) / 10.0,
561                         float(self.sliderN32.GetValue()) / 10.0,
562                 )
563
564         def _OnEraseBackground(self,event):
565                 #Workaround for windows background redraw flicker.
566                 pass
567
568         def _OnSize(self, e):
569                 self.Refresh()
570
571         def _OnIdle(self, e):
572                 self._glCanvas.Refresh()
573
574         def _OnPaint(self, e):
575                 dc = wx.PaintDC(self._glCanvas)
576
577                 self._glCanvas.SetCurrent(self._context)
578                 for obj in self._releaseList:
579                         obj.release()
580                 self._releaseList = []
581
582                 size = self._glCanvas.GetSize()
583                 glViewport(0, 0, size.GetWidth(), size.GetHeight())
584                 glLoadIdentity()
585
586                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
587
588                 glDisable(GL_RESCALE_NORMAL)
589                 glDisable(GL_LIGHTING)
590                 glDisable(GL_LIGHT0)
591                 glEnable(GL_DEPTH_TEST)
592                 glDisable(GL_CULL_FACE)
593                 glDisable(GL_BLEND)
594                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
595
596                 glClearColor(0.0, 0.0, 0.0, 1.0)
597                 glClearStencil(0)
598                 glClearDepth(1.0)
599
600                 glMatrixMode(GL_PROJECTION)
601                 glLoadIdentity()
602                 aspect = float(size.GetWidth()) / float(size.GetHeight())
603                 gluPerspective(45.0, aspect, 1.0, 1000.0)
604
605                 glMatrixMode(GL_MODELVIEW)
606                 glLoadIdentity()
607                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
608
609                 glTranslate(0,0,-2)
610                 glRotate(-45 - math.sin(self._rotate/50.0) * 30, 1, 0, 0)
611                 glRotate(self._rotate, 0, 0, 1)
612                 self._rotate += (self._t0 - time.time()) * 20
613                 self._t0 = time.time()
614
615                 glEnable(GL_LIGHTING)
616                 glEnable(GL_LIGHT0)
617                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
618                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8,1.0,0.8,0])
619                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.3,0.3,0.3,0])
620                 glEnable(GL_LIGHT1)
621                 glLightfv(GL_LIGHT1, GL_POSITION, [1.2, 0.2, 0.2, 0.0])
622                 glLightfv(GL_LIGHT1, GL_DIFFUSE, [0.5,0.3,0.2,0])
623                 glLightfv(GL_LIGHT1, GL_AMBIENT, [0.0,0.0,0.0,0])
624
625                 scale = 1.0/numpy.max(self._shape._obj.getSize())
626                 glScalef(scale, scale, scale)
627                 glEnable(GL_NORMALIZE)
628
629                 self._shape.draw()
630
631                 glFlush()
632                 self._glCanvas.SwapBuffers()