chiark / gitweb /
Small tooltip spelling update. fix an issue opening the save dialog on Mac.
[cura.git] / Cura / gui / tools / superformula.py
1 from __future__ import absolute_import
2
3 import wx
4 import math
5 import time
6 import random
7 import numpy
8
9 from wx import glcanvas
10 import OpenGL
11 OpenGL.ERROR_CHECKING = False
12 from OpenGL.GL import *
13 from OpenGL.GLU import *
14
15 from Cura.gui.util import opengl
16 from Cura.util import mesh
17
18 class superShape(object):
19         def __init__(self, a1, b1, m1, n11, n21, n31, a2, b2, m2, n12, n22, n32):
20                 self._a1 = a1
21                 self._b1 = b1
22                 self._m1 = math.floor(m1)
23                 self._n11 = n11
24                 self._n21 = n21
25                 self._n31 = n31
26                 self._a2 = a2
27                 self._b2 = b2
28                 self._m2 = m2
29                 self._n12 = n12
30                 self._n22 = n22
31                 self._n32 = n32
32
33                 points = []
34                 cnt = 64
35                 for n in xrange(-cnt, cnt):
36                         row = []
37                         points.append(row)
38                         f1 = n * math.pi / cnt
39                         try:
40                                 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))
41                         except:
42                                 r1 = 1.0
43                         for m in xrange(0, cnt):
44                                 f2 = m * math.pi / ((cnt*2) - 2)
45                                 try:
46                                         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))
47                                 except:
48                                         r2 = 1.0
49
50                                 x = r1 * math.cos(f1) * r2 * math.cos(f2)
51                                 y = r1 * math.sin(f1) * r2 * math.cos(f2)
52                                 z = r2 * math.sin(f2)
53
54                                 row.append([x,y,z])
55
56                 self._obj = mesh.printableObject()
57                 objMesh = self._obj._addMesh()
58                 objMesh._prepareFaceCount(len(points) * (len(points[0]) - 1) * 2)
59
60                 for n in xrange(-1, len(points) - 1):
61                         row1 = points[n]
62                         row2 = points[n+1]
63                         for m in xrange(0, len(row1) - 1):
64                                 p0 = row1[m]
65                                 p1 = row1[m+1]
66                                 p2 = row2[m]
67                                 p3 = row2[m+1]
68
69                                 objMesh._addFace(p0[0], p0[1], p0[2], p2[0], p2[1], p2[2], p1[0], p1[1], p1[2])
70                                 objMesh._addFace(p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], p3[0], p3[1], p3[2])
71
72                 self._obj._postProcessAfterLoad()
73
74         def isValid(self):
75                 size = self._obj.getSize()
76                 if size[0] / size[2] > 10:
77                         return False
78                 return True
79
80         def draw(self):
81                 for m in self._obj._meshList:
82                         if m.vbo is None:
83                                 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
84                         m.vbo.render()
85
86 class superformulaEvolver(wx.Frame):
87         def __init__(self, parent):
88                 super(superformulaEvolver, self).__init__(parent, title='Cura - Superformula')
89                 self._rotate = 0.0
90                 self._t0 = time.time()
91
92                 sizer = wx.BoxSizer()
93                 self.SetSizer(sizer)
94
95                 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 32, glcanvas.WX_GL_STENCIL_SIZE, 8)
96                 self._glCanvas = glcanvas.GLCanvas(self, style=wx.WANTS_CHARS, attribList = attribList)
97                 self._glCanvas.SetMinSize((800,600))
98                 sizer.Add(self._glCanvas, 1, flag=wx.EXPAND)
99                 self._context = glcanvas.GLContext(self._glCanvas)
100
101                 wx.EVT_PAINT(self._glCanvas, self._OnPaint)
102                 wx.EVT_SIZE(self._glCanvas, self._OnSize)
103                 wx.EVT_ERASE_BACKGROUND(self._glCanvas, self._OnEraseBackground)
104                 wx.EVT_IDLE(self, self._OnIdle)
105
106                 wx.EVT_LEFT_DOWN(self._glCanvas, self._OnMouseDown)
107
108                 self._shapes = [None] * 12
109                 self._releaseList = []
110
111                 self._randomize()
112
113                 self.Maximize()
114
115         def _OnMouseDown(self, e):
116                 size = self._glCanvas.GetSize()
117                 sel = e.GetX() / (size.GetWidth() / 4) + (size.GetHeight() - e.GetY()) / (size.GetHeight() / 3) * 4
118                 shape = self._shapes[sel]
119                 for n in xrange(0, len(self._shapes)):
120                         if n == sel:
121                                 continue
122                         for m in self._shapes[n]._obj._meshList:
123                                 if m.vbo is not None:
124                                         self._releaseList.append(m.vbo)
125                         f = 0.5 + n * 0.1
126                         update = True
127                         while update:
128                                 self._shapes[n] = superShape(
129                                         shape._a1 + random.uniform(-f, f) / 2.0,
130                                         shape._b1 + random.uniform(-f, f) / 2.0,
131                                         shape._m1 + random.uniform(-f, f) * 2.0,
132                                         shape._n11 + random.uniform(-f, f),
133                                         shape._n21 + random.uniform(-f, f),
134                                         shape._n31 + random.uniform(-f, f),
135                                         shape._a2 + random.uniform(-f, f) / 2.0,
136                                         shape._b2 + random.uniform(-f, f) / 2.0,
137                                         shape._m2 + random.uniform(-f, f),
138                                         shape._n12 + random.uniform(-f, f),
139                                         shape._n22 + random.uniform(-f, f),
140                                         shape._n32 + random.uniform(-f, f))
141                                 update = not self._shapes[n].isValid()
142
143         def _randomize(self):
144                 for shape in self._shapes:
145                         if shape is not None:
146                                 for m in shape._obj._meshList:
147                                         if m.vbo is not None:
148                                                 self._releaseList.append(m.vbo)
149                 for n in xrange(0, len(self._shapes)):
150                         update = True
151                         while update:
152                                 self._shapes[n] = superShape(
153                                         random.uniform(0.5, 5.0),
154                                         random.uniform(0.5, 5.0),
155                                         random.uniform(0.5, 20.0),
156                                         random.uniform(0.5, 10.0),
157                                         random.uniform(0.5, 10.0),
158                                         random.uniform(0.5, 10.0),
159                                         random.uniform(0.5, 5.0),
160                                         random.uniform(0.5, 5.0),
161                                         random.uniform(0.5, 10.0),
162                                         random.uniform(0.5, 10.0),
163                                         random.uniform(0.5, 10.0),
164                                         random.uniform(0.5, 10.0))
165                                 update = not self._shapes[n].isValid()
166
167         def _OnEraseBackground(self,event):
168                 #Workaround for windows background redraw flicker.
169                 pass
170
171         def _OnSize(self, e):
172                 self.Refresh()
173
174         def _OnIdle(self, e):
175                 self._glCanvas.Refresh()
176
177         def _OnPaint(self, e):
178                 dc = wx.PaintDC(self._glCanvas)
179
180                 self._glCanvas.SetCurrent(self._context)
181                 for obj in self._releaseList:
182                         obj.release()
183                 self._releaseList = []
184
185                 size = self._glCanvas.GetSize()
186                 glViewport(0, 0, size.GetWidth(), size.GetHeight())
187                 glLoadIdentity()
188
189                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
190
191                 glDisable(GL_RESCALE_NORMAL)
192                 glDisable(GL_LIGHTING)
193                 glDisable(GL_LIGHT0)
194                 glEnable(GL_DEPTH_TEST)
195                 glDisable(GL_CULL_FACE)
196                 glDisable(GL_BLEND)
197                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
198
199                 glClearColor(0.0, 0.0, 0.0, 1.0)
200                 glClearStencil(0)
201                 glClearDepth(1.0)
202
203                 glMatrixMode(GL_PROJECTION)
204                 glLoadIdentity()
205                 aspect = float(size.GetWidth()) / float(size.GetHeight())
206                 gluPerspective(30.0, aspect, 1.0, 1000.0)
207
208                 glMatrixMode(GL_MODELVIEW)
209                 glLoadIdentity()
210                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
211
212                 glTranslate(0,0,-2.0)
213                 glRotate(-45 - math.sin(self._rotate/50.0) * 30, 1, 0, 0)
214                 glRotate(self._rotate, 0, 0, 1)
215                 self._rotate += (self._t0 - time.time()) * 20
216                 self._t0 = time.time()
217
218                 glEnable(GL_LIGHTING)
219                 glEnable(GL_LIGHT0)
220                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
221                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8,1.0,0.8,0])
222                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.3,0.3,0.3,0])
223                 glEnable(GL_LIGHT1)
224                 glLightfv(GL_LIGHT1, GL_POSITION, [1.2, 0.2, 0.2, 0.0])
225                 glLightfv(GL_LIGHT1, GL_DIFFUSE, [0.5,0.3,0.2,0])
226                 glLightfv(GL_LIGHT1, GL_AMBIENT, [0.0,0.0,0.0,0])
227
228                 for n in xrange(0, len(self._shapes)):
229                         shape = self._shapes[n]
230                         scale = 1.0/numpy.max(shape._obj.getSize())
231                         glPushMatrix()
232                         glScalef(scale, scale, scale)
233                         glEnable(GL_NORMALIZE)
234                         glViewport(size.GetWidth() / 4 * (n % 4), size.GetHeight() / 3 * (n / 4), size.GetWidth() / 4, size.GetHeight() / 3)
235                         shape.draw()
236                         glPopMatrix()
237
238                 glFlush()
239                 self._glCanvas.SwapBuffers()
240
241 class superformulaWindow(wx.Frame):
242         def __init__(self, parent):
243                 super(superformulaWindow, self).__init__(parent, title='Cura - Superformula')
244                 self._rotate = 0.0
245                 self._t0 = time.time()
246
247                 self.panel = wx.Panel(self, -1)
248                 self.SetSizer(wx.BoxSizer())
249                 self.GetSizer().Add(self.panel, 1, wx.EXPAND)
250
251                 sizer = wx.GridBagSizer(2, 2)
252
253                 sizer.Add(wx.StaticText(self.panel, -1, 'A1'), pos=(0,0))
254                 self.sliderA1 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
255                 sizer.Add(self.sliderA1, pos=(0,1))
256                 sizer.Add(wx.StaticText(self.panel, -1, 'B1'), pos=(1,0))
257                 self.sliderB1 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
258                 sizer.Add(self.sliderB1, pos=(1,1))
259                 sizer.Add(wx.StaticText(self.panel, -1, 'M1'), pos=(2,0))
260                 self.sliderM1 = wx.Slider(self.panel, -1, 50, 5, 200, size=(150, -1))
261                 sizer.Add(self.sliderM1, pos=(2,1))
262                 sizer.Add(wx.StaticText(self.panel, -1, 'N11'), pos=(3,0))
263                 self.sliderN11 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
264                 sizer.Add(self.sliderN11, pos=(3,1))
265                 sizer.Add(wx.StaticText(self.panel, -1, 'N21'), pos=(4,0))
266                 self.sliderN21 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
267                 sizer.Add(self.sliderN21, pos=(4,1))
268                 sizer.Add(wx.StaticText(self.panel, -1, 'N31'), pos=(5,0))
269                 self.sliderN31 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
270                 sizer.Add(self.sliderN31, pos=(5,1))
271
272                 sizer.Add(wx.StaticText(self.panel, -1, 'A2'), pos=(6,0))
273                 self.sliderA2 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
274                 sizer.Add(self.sliderA2, pos=(6,1))
275                 sizer.Add(wx.StaticText(self.panel, -1, 'B2'), pos=(7,0))
276                 self.sliderB2 = wx.Slider(self.panel, -1, 10, 5, 50, size=(150, -1))
277                 sizer.Add(self.sliderB2, pos=(7,1))
278                 sizer.Add(wx.StaticText(self.panel, -1, 'M2'), pos=(8,0))
279                 self.sliderM2 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
280                 sizer.Add(self.sliderM2, pos=(8,1))
281                 sizer.Add(wx.StaticText(self.panel, -1, 'N12'), pos=(9,0))
282                 self.sliderN12 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
283                 sizer.Add(self.sliderN12, pos=(9,1))
284                 sizer.Add(wx.StaticText(self.panel, -1, 'N22'), pos=(10,0))
285                 self.sliderN22 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
286                 sizer.Add(self.sliderN22, pos=(10,1))
287                 sizer.Add(wx.StaticText(self.panel, -1, 'N32'), pos=(11,0))
288                 self.sliderN32 = wx.Slider(self.panel, -1, 20, 5, 100, size=(150, -1))
289                 sizer.Add(self.sliderN32, pos=(11,1))
290
291                 self.randomButton = wx.Button(self.panel, -1, 'Randomize')
292                 sizer.Add(self.randomButton, pos=(12,1))
293                 self.addButton = wx.Button(self.panel, -1, 'Add to print')
294                 sizer.Add(self.addButton, pos=(13,1))
295
296                 attribList = (glcanvas.WX_GL_RGBA, glcanvas.WX_GL_DOUBLEBUFFER, glcanvas.WX_GL_DEPTH_SIZE, 32, glcanvas.WX_GL_STENCIL_SIZE, 8)
297                 self._glCanvas = glcanvas.GLCanvas(self.panel, style=wx.WANTS_CHARS, attribList = attribList)
298                 self._glCanvas.SetMinSize((800,600))
299                 sizer.Add(self._glCanvas, pos=(0,2), span=(14,1), flag=wx.EXPAND)
300                 self._context = glcanvas.GLContext(self._glCanvas)
301
302                 sizer.AddGrowableRow(13)
303                 sizer.AddGrowableCol(2)
304                 self.panel.SetSizer(sizer)
305                 self.Layout()
306                 self.Fit()
307
308                 wx.EVT_PAINT(self._glCanvas, self._OnPaint)
309                 wx.EVT_SIZE(self._glCanvas, self._OnSize)
310                 wx.EVT_ERASE_BACKGROUND(self._glCanvas, self._OnEraseBackground)
311                 wx.EVT_IDLE(self, self._OnIdle)
312
313                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderA1)
314                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderB1)
315                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderM1)
316                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN11)
317                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN21)
318                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN31)
319
320                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderA2)
321                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderB2)
322                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderM2)
323                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN12)
324                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN22)
325                 self.Bind(wx.EVT_SLIDER, lambda e: self._updateShape(), self.sliderN32)
326
327                 self.Bind(wx.EVT_BUTTON, lambda e: self.onRandom(), self.randomButton)
328                 self.Bind(wx.EVT_BUTTON, lambda e: self.onAdd(), self.addButton)
329
330                 self._shape = None
331                 self._releaseList = []
332                 self._updateShape()
333
334         def onRandom(self):
335                 update = True
336                 while update:
337                         update = False
338                         self.sliderA1.SetValue(random.randint(self.sliderA1.GetMin(), self.sliderA1.GetMax()))
339                         self.sliderB1.SetValue(random.randint(self.sliderB1.GetMin(), self.sliderB1.GetMax()))
340                         self.sliderM1.SetValue(random.randint(self.sliderM1.GetMin(), self.sliderM1.GetMax()))
341                         self.sliderN11.SetValue(random.randint(self.sliderN11.GetMin(), self.sliderN11.GetMax()))
342                         self.sliderN21.SetValue(random.randint(self.sliderN21.GetMin(), self.sliderN21.GetMax()))
343                         self.sliderN31.SetValue(random.randint(self.sliderN31.GetMin(), self.sliderN31.GetMax()))
344                         self.sliderA2.SetValue(random.randint(self.sliderA2.GetMin(), self.sliderA2.GetMax()))
345                         self.sliderB2.SetValue(random.randint(self.sliderB2.GetMin(), self.sliderB2.GetMax()))
346                         self.sliderM2.SetValue(random.randint(self.sliderM2.GetMin(), self.sliderM2.GetMax()))
347                         self.sliderN12.SetValue(random.randint(self.sliderN12.GetMin(), self.sliderN12.GetMax()))
348                         self.sliderN22.SetValue(random.randint(self.sliderN22.GetMin(), self.sliderN22.GetMax()))
349                         self.sliderN32.SetValue(random.randint(self.sliderN32.GetMin(), self.sliderN32.GetMax()))
350                         self._updateShape()
351                         if not self._shape.isValid():
352                                 update = True
353
354         def onAdd(self):
355                 scale = 1.0/numpy.max(self._shape._obj.getSize()) * 50
356
357                 obj = mesh.printableObject()
358                 m = obj._addMesh()
359                 m._prepareFaceCount(self._shape._obj._meshList[0].vertexCount / 3)
360                 m.vertexes = self._shape._obj._meshList[0].vertexes * scale
361                 m.vertexCount = self._shape._obj._meshList[0].vertexCount
362                 obj._postProcessAfterLoad()
363                 self.GetParent().scene._scene.add(obj)
364
365         def _updateShape(self):
366                 if self._shape is not None:
367                         for m in self._shape._obj._meshList:
368                                 if m.vbo is not None:
369                                         self._releaseList.append(m.vbo)
370                 self._shape = superShape(
371                         float(self.sliderA1.GetValue()) / 10.0,
372                         float(self.sliderB1.GetValue()) / 10.0,
373                         float(self.sliderM1.GetValue()) / 10.0,
374
375                         float(self.sliderN11.GetValue()) / 10.0,
376                         float(self.sliderN21.GetValue()) / 10.0,
377                         float(self.sliderN31.GetValue()) / 10.0,
378
379                         float(self.sliderA2.GetValue()) / 10.0,
380                         float(self.sliderB2.GetValue()) / 10.0,
381                         float(self.sliderM2.GetValue()) / 10.0,
382
383                         float(self.sliderN12.GetValue()) / 10.0,
384                         float(self.sliderN22.GetValue()) / 10.0,
385                         float(self.sliderN32.GetValue()) / 10.0,
386                 )
387
388         def _OnEraseBackground(self,event):
389                 #Workaround for windows background redraw flicker.
390                 pass
391
392         def _OnSize(self, e):
393                 self.Refresh()
394
395         def _OnIdle(self, e):
396                 self._glCanvas.Refresh()
397
398         def _OnPaint(self, e):
399                 dc = wx.PaintDC(self._glCanvas)
400
401                 self._glCanvas.SetCurrent(self._context)
402                 for obj in self._releaseList:
403                         obj.release()
404                 self._releaseList = []
405
406                 size = self._glCanvas.GetSize()
407                 glViewport(0, 0, size.GetWidth(), size.GetHeight())
408                 glLoadIdentity()
409
410                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
411
412                 glDisable(GL_RESCALE_NORMAL)
413                 glDisable(GL_LIGHTING)
414                 glDisable(GL_LIGHT0)
415                 glEnable(GL_DEPTH_TEST)
416                 glDisable(GL_CULL_FACE)
417                 glDisable(GL_BLEND)
418                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
419
420                 glClearColor(0.0, 0.0, 0.0, 1.0)
421                 glClearStencil(0)
422                 glClearDepth(1.0)
423
424                 glMatrixMode(GL_PROJECTION)
425                 glLoadIdentity()
426                 aspect = float(size.GetWidth()) / float(size.GetHeight())
427                 gluPerspective(45.0, aspect, 1.0, 1000.0)
428
429                 glMatrixMode(GL_MODELVIEW)
430                 glLoadIdentity()
431                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
432
433                 glTranslate(0,0,-2)
434                 glRotate(-45 - math.sin(self._rotate/50.0) * 30, 1, 0, 0)
435                 glRotate(self._rotate, 0, 0, 1)
436                 self._rotate += (self._t0 - time.time()) * 20
437                 self._t0 = time.time()
438
439                 glEnable(GL_LIGHTING)
440                 glEnable(GL_LIGHT0)
441                 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
442                 glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8,1.0,0.8,0])
443                 glLightfv(GL_LIGHT0, GL_AMBIENT, [0.3,0.3,0.3,0])
444                 glEnable(GL_LIGHT1)
445                 glLightfv(GL_LIGHT1, GL_POSITION, [1.2, 0.2, 0.2, 0.0])
446                 glLightfv(GL_LIGHT1, GL_DIFFUSE, [0.5,0.3,0.2,0])
447                 glLightfv(GL_LIGHT1, GL_AMBIENT, [0.0,0.0,0.0,0])
448
449                 scale = 1.0/numpy.max(self._shape._obj.getSize())
450                 glScalef(scale, scale, scale)
451                 glEnable(GL_NORMALIZE)
452
453                 self._shape.draw()
454
455                 glFlush()
456                 self._glCanvas.SwapBuffers()