]> gitweb.factorcode.org Git - factor.git/blob - extra/L-system/L-system.factor
calendar.format: make duration>human-readable more human readable
[factor.git] / extra / L-system / L-system.factor
1
2 USING: accessors arrays assocs calendar colors
3 combinators.short-circuit help help.markup help.syntax kernel
4 math math.functions math.matrices math.order math.parser
5 math.trig math.vectors opengl opengl.demo-support opengl.gl
6 opengl.glu sbufs sequences strings threads ui.gadgets
7 ui.gadgets.worlds ui.gestures ui.render ;
8
9 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10
11 IN: L-system
12
13 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
14
15 TUPLE: turtle pos ori angle length thickness color vertices saved ;
16
17 DEFER: default-L-parser-values
18
19 : reset-turtle ( turtle -- turtle )
20   { 0 0 0 } clone   >>pos
21   3 <identity-matrix> >>ori
22   V{ } clone >>vertices
23   V{ } clone >>saved
24
25   default-L-parser-values ;
26
27 : <turtle> ( -- turtle ) turtle new reset-turtle ;
28
29 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
30
31 :: step-turtle ( TURTLE LENGTH -- turtle )
32
33   TURTLE
34     TURTLE pos>>   TURTLE ori>> { 0 0 LENGTH } mdotv v+
35   >>pos ;
36
37 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
38
39 : Rx ( ANGLE -- Rx )
40   
41   [let deg>rad :> ANGLE
42
43     ANGLE cos     :> A
44     ANGLE sin neg :> B
45     ANGLE sin     :> C
46     ANGLE cos     :> D
47
48       { { 1 0 0 }
49         { 0 A B }
50         { 0 C D } }
51
52     ] ;
53
54 : Ry ( ANGLE -- Ry )
55   
56   [let deg>rad :> ANGLE
57
58     ANGLE cos     :> A
59     ANGLE sin     :> B
60     ANGLE sin neg :> C
61     ANGLE cos     :> D
62
63       { { A 0 B }
64         { 0 1 0 }
65         { C 0 D } }
66
67     ] ;
68
69 : Rz ( ANGLE -- Rz )
70   
71   [let deg>rad :> ANGLE
72
73     ANGLE cos     :> A
74     ANGLE sin neg :> B
75     ANGLE sin     :> C
76     ANGLE cos     :> D
77
78       { { A B 0 }
79         { C D 0 }
80         { 0 0 1 } }
81
82     ] ;
83
84 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
85
86 :: apply-rotation ( TURTLE ROTATION -- turtle )
87   
88   TURTLE  TURTLE ori>> ROTATION mdot >>ori ;
89
90 : rotate-x ( turtle angle -- turtle ) Rx apply-rotation ;
91 : rotate-y ( turtle angle -- turtle ) Ry apply-rotation ;
92 : rotate-z ( turtle angle -- turtle ) Rz apply-rotation ;
93
94 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
95
96 : pitch-up   ( turtle angle -- turtle ) neg rotate-x ;
97 : pitch-down ( turtle angle -- turtle )     rotate-x ;
98
99 : turn-left  ( turtle angle -- turtle )     rotate-y ;
100 : turn-right ( turtle angle -- turtle ) neg rotate-y ;
101
102 : roll-left  ( turtle angle -- turtle ) neg rotate-z ;
103 : roll-right ( turtle angle -- turtle )     rotate-z ;
104
105 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
106
107 : V ( -- V ) { 0 1 0 } ;
108
109 : X ( turtle -- 3array ) ori>> [ first  ] map ;
110 : Y ( turtle -- 3array ) ori>> [ second ] map ;
111 : Z ( turtle -- 3array ) ori>> [ third  ] map ;
112
113 : set-X ( turtle seq -- turtle ) over ori>> [ set-first  ] 2each ;
114 : set-Y ( turtle seq -- turtle ) over ori>> [ set-second ] 2each ;
115 : set-Z ( turtle seq -- turtle ) over ori>> [ set-third  ] 2each ;
116
117 :: roll-until-horizontal ( TURTLE -- turtle )
118
119   TURTLE
120   
121     V         TURTLE Z  cross normalize  set-X
122
123     TURTLE Z  TURTLE X  cross normalize  set-Y ;
124
125 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
126
127 :: strafe-up ( TURTLE LENGTH -- turtle )
128   TURTLE 90 pitch-up LENGTH step-turtle 90 pitch-down ;
129
130 :: strafe-down ( TURTLE LENGTH -- turtle )
131   TURTLE 90 pitch-down LENGTH step-turtle 90 pitch-up ;
132
133 :: strafe-left ( TURTLE LENGTH -- turtle )
134   TURTLE 90 turn-left LENGTH step-turtle 90 turn-right ;
135
136 :: strafe-right ( TURTLE LENGTH -- turtle )
137   TURTLE 90 turn-right LENGTH step-turtle 90 turn-left ;
138
139 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
140
141 : polygon ( vertices -- ) GL_POLYGON glBegin [ first3 glVertex3d ] each glEnd ;
142
143 : start-polygon ( turtle -- turtle ) dup vertices>> delete-all ;
144
145 : finish-polygon ( turtle -- turtle ) dup vertices>> polygon ;
146
147 : polygon-vertex ( turtle -- turtle ) dup [ pos>> ] [ vertices>> ] bi push ;
148
149 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
150
151 : record-vertex ( turtle -- turtle ) dup pos>> first3 glVertex3d ;
152
153 : draw-forward ( turtle length -- turtle )
154   GL_LINES glBegin [ record-vertex ] dip step-turtle record-vertex glEnd ;
155
156 : move-forward ( turtle length -- turtle ) step-turtle polygon-vertex ;
157
158 : sneak-forward ( turtle length -- turtle ) step-turtle ;
159
160 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
161
162 : scale-length ( turtle m -- turtle ) over length>> * >>length ;
163 : scale-angle  ( turtle m -- turtle ) over angle>>  * >>angle  ;
164
165 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
166
167 : set-thickness ( turtle i -- turtle ) dup glLineWidth >>thickness ;
168
169 : scale-thickness ( turtle m -- turtle )
170   over thickness>> * 0.5 max set-thickness ;
171
172 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
173
174 : color-table ( -- colors )
175   {
176     COLOR: black
177     COLOR: grey50
178     COLOR: red
179     COLOR: yellow
180     COLOR: green
181     COLOR: turquoise
182     COLOR: blue
183     COLOR: purple
184     COLOR: green4
185     COLOR: dark-turquoise
186     COLOR: dark-blue
187     T{ rgba f 0.58 0.00 0.82 1 } ! dark purple
188     COLOR: dark-red
189     COLOR: grey25
190     COLOR: grey75
191     COLOR: white
192   } ;
193
194 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
195
196 ! : material-color ( color -- )
197 !   GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE rot gl-material ;
198
199 : material-color ( color -- )
200   GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE rot >rgba-components 4array
201   gl-material ;
202
203 : set-color ( turtle i -- turtle )
204   dup color-table nth dup gl-color material-color >>color ;
205
206 : inc-color ( turtle -- turtle ) dup color>> 1 + set-color ;
207
208 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
209
210 : save-turtle    ( turtle -- turtle ) dup clone over saved>> push ;
211
212 : restore-turtle ( turtle -- turtle ) saved>> pop dup color>> set-color ;
213
214 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
215
216 : default-L-parser-values ( turtle -- turtle )
217   1 >>length 45 >>angle 1 >>thickness 2 >>color ;
218
219 : L-parser-dialect ( -- commands )
220
221   {
222       { "+" [ dup angle>> turn-left  ] }
223       { "-" [ dup angle>> turn-right ] }
224       { "&" [ dup angle>> pitch-down ] }
225       { "^" [ dup angle>> pitch-up   ] }
226       { "<" [ dup angle>> roll-left  ] }
227       { ">" [ dup angle>> roll-right ] }
228
229       { "|" [ 180.0         rotate-y ] }
230       { "%" [ 180.0         rotate-z ] }
231       { "$" [ roll-until-horizontal  ]  }
232
233       { "F" [ dup length>>     draw-forward  ] }
234       { "Z" [ dup length>> 2 / draw-forward  ] }
235       { "f" [ dup length>>     move-forward  ] }
236       { "z" [ dup length>> 2 / move-forward  ] }
237       { "g" [ dup length>>     sneak-forward ] }
238       { "." [ polygon-vertex                 ] }
239
240       { "[" [ save-turtle      ] }
241       { "]" [ restore-turtle   ] }
242       
243       { "{" [ start-polygon    ] }
244       { "}" [ finish-polygon   ] }
245
246       { "/" [ 1.1 scale-length    ] } ! double quote command in lparser
247       { "'" [ 0.9 scale-length    ] }
248       { ";" [ 1.1 scale-angle     ] }
249       { ":" [ 0.9 scale-angle     ] }
250       { "?" [ 1.4 scale-thickness ] }
251       { "!" [ 0.7 scale-thickness ] }
252
253       { "c" [ dup color>> 1 + color-table length mod set-color ] }
254
255     }
256     ;
257
258 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
259
260 TUPLE: L-system < gadget
261   camera display-list pedestal paused
262   turtle-values
263   commands axiom rules string ;
264
265 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
266
267 :: iterate-system ( GADGET -- ) GADGET pedestal>> 0.5 + GADGET pedestal<< ;
268
269 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
270
271 :: start-rotation-thread ( GADGET -- )
272   GADGET f >>paused drop
273   [
274     [
275       GADGET paused>>
276         [ f ]
277         [ GADGET iterate-system GADGET relayout-1 25 milliseconds sleep t ]
278       if
279     ]
280     loop
281   ]
282   in-thread ;
283
284 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
285
286 : open-paren  ( -- ch ) CHAR: ( ;
287 : close-paren ( -- ch ) CHAR: ) ;
288
289 : open-paren?  ( obj -- ? ) open-paren  = ;
290 : close-paren? ( obj -- ? ) close-paren = ;
291
292 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
293
294 :: read-instruction ( STRING -- next rest )
295   
296   { [ STRING length 1 > ] [ STRING second open-paren? ] } 0&&
297     [ STRING  close-paren STRING index 1 + cut ]
298     [ STRING  1                            cut ]
299   if ;
300
301 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
302
303 :: iterate-string-loop ( STRING RULES ACCUM -- )
304   STRING empty? not
305     [
306       [let
307         STRING read-instruction :> ( NEXT REST )
308
309         NEXT 1 head RULES at  NEXT  or  ACCUM push-all
310
311         REST RULES ACCUM iterate-string-loop ]
312     ]
313   when ;
314
315 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
316
317 :: iterate-string ( STRING RULES -- string )
318
319   [let STRING length 10 * <sbuf> :> ACCUM
320
321     STRING RULES ACCUM iterate-string-loop
322
323     ACCUM >string ] ;
324
325 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
326
327 :: interpret-string ( TURTLE STRING COMMANDS -- turtle )
328
329   STRING empty? not
330     [
331       [let
332           STRING read-instruction :> ( NEXT REST )
333           NEXT 1 head COMMANDS at :> COMMAND
334           COMMAND
335             [
336               NEXT length 1 =
337                 [ TURTLE COMMAND call( turtle -- turtle ) drop ]
338                 [
339                   TURTLE
340                   NEXT 2 tail 1 head* string>number
341                   COMMAND 1 tail*
342                   call( turtle x -- turtle ) drop
343                 ]
344               if
345             ]
346           when
347
348         TURTLE REST COMMANDS interpret-string drop ]
349     ]
350   when TURTLE ;
351
352 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
353
354 :: iterate-L-system-string ( L-SYSTEM -- )
355   L-SYSTEM string>> L-SYSTEM axiom>> or
356   L-SYSTEM rules>>
357   iterate-string
358   L-SYSTEM string<< ;
359
360 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
361
362 :: do-camera-look-at ( CAMERA -- )
363
364   [let
365       CAMERA pos>> :> EYE
366       CAMERA clone 1 step-turtle pos>> :> FOCUS
367       CAMERA clone 90 pitch-up 1 step-turtle pos>> CAMERA pos>> v- :> UP
368
369     EYE FOCUS UP gl-look-at ] ;
370
371 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
372
373 :: generate-display-list ( L-SYSTEM -- )
374
375   L-SYSTEM find-gl-context
376
377   L-SYSTEM display-list>> GL_COMPILE glNewList
378
379     <turtle>
380     L-SYSTEM turtle-values>> [ ] or call( turtle -- turtle )
381     L-SYSTEM string>> L-SYSTEM axiom>> or
382     L-SYSTEM commands>>
383     interpret-string
384     drop
385
386   glEndList ;
387
388 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
389
390 M:: L-system draw-gadget* ( L-SYSTEM -- )
391
392   COLOR: black gl-clear
393
394   GL_FLAT glShadeModel
395
396   GL_PROJECTION glMatrixMode
397   glLoadIdentity
398   -1 1 -1 1 1.5 200 glFrustum
399
400   GL_MODELVIEW glMatrixMode
401
402   glLoadIdentity
403
404   L-SYSTEM camera>> do-camera-look-at
405
406   GL_FRONT_AND_BACK GL_LINE glPolygonMode
407
408   ! draw axis
409   COLOR: white gl-color GL_LINES
410   glBegin { 0 0 0 } gl-vertex { 0 0 1 } gl-vertex glEnd
411
412   ! rotate pedestal
413
414   L-SYSTEM pedestal>> 0 0 1 glRotated
415   
416   L-SYSTEM display-list>> glCallList ;
417
418 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
419
420 M:: L-system graft* ( L-SYSTEM -- )
421
422   L-SYSTEM find-gl-context
423
424   1 glGenLists L-SYSTEM display-list<< ;
425
426 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
427
428 M:: L-system pref-dim* ( L-SYSTEM -- dim ) { 400 400 } ;
429
430 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
431
432 :: with-camera ( L-SYSTEM QUOT -- )
433   L-SYSTEM camera>> QUOT call drop
434   L-SYSTEM relayout-1 ; inline
435
436 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
437
438 L-system
439 H{
440   { T{ key-down f f "LEFT"  } [ [  5 turn-left   ] with-camera ] }
441   { T{ key-down f f "RIGHT" } [ [  5 turn-right  ] with-camera ] }
442   { T{ key-down f f "UP"    } [ [  5 pitch-down  ] with-camera ] }
443   { T{ key-down f f "DOWN"  } [ [  5 pitch-up    ] with-camera ] }
444   
445   { T{ key-down f f "a"     } [ [  1 step-turtle ] with-camera ] }
446   { T{ key-down f f "z"     } [ [ -1 step-turtle ] with-camera ] }
447
448   { T{ key-down f f "q"     } [ [ 5 roll-left    ] with-camera ] }
449   { T{ key-down f f "w"     } [ [ 5 roll-right   ] with-camera ] }
450
451   { T{ key-down f { A+ } "LEFT"  } [ [ 1 strafe-left  ] with-camera ] }
452   { T{ key-down f { A+ } "RIGHT" } [ [ 1 strafe-right ] with-camera ] }
453   { T{ key-down f { A+ } "UP"    } [ [ 1 strafe-up    ] with-camera ] }
454   { T{ key-down f { A+ } "DOWN"  } [ [ 1 strafe-down  ] with-camera ] }
455
456   { T{ key-down f f "r"     } [ start-rotation-thread          ] }
457
458   {
459     T{ key-down f f "x" }
460     [
461       dup iterate-L-system-string
462       dup generate-display-list
463       dup relayout-1
464       drop
465     ]
466   }
467
468   { T{ key-down f f "F1" } [ drop "L-system" help ] }
469     
470 }
471 set-gestures
472
473 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
474
475 : <L-system> ( -- L-system )
476
477   L-system new
478
479     0 >>pedestal
480   
481     ! <turtle> 45 turn-left 45 pitch-up 5 step-turtle 180 turn-left >>camera ;
482
483     <turtle> 90 pitch-down -5 step-turtle 2 strafe-up >>camera
484
485     dup start-rotation-thread
486
487   ;
488
489 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
490
491 ARTICLE: "L-system" "L-system"
492
493 "Press 'x' to iterate the L-system." $nl
494
495 "Camera control:"
496
497 { $table
498
499   { "a" "Forward" }
500   { "z" "Backward" }
501
502   { "LEFT" "Turn left" }
503   { "RIGHT" "Turn right" }
504   { "UP" "Pitch down" }
505   { "DOWN" "Pitch up" }
506
507   { "q" "Roll left" }
508   { "w" "Roll right" } } ;
509
510 ABOUT: "L-system"