1 ! Eduardo Cavazos - wayo.cavazos@gmail.com
6 contrib/lindenmayer/opengl
7 contrib/lindenmayer/turtle
8 contrib/lindenmayer/camera
9 contrib/lindenmayer/camera-slate ;
11 USING: kernel alien namespaces arrays vectors math opengl sequences threads
12 hashtables strings gadgets
13 math-contrib vars slate turtle turtle-camera camera-slate
18 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20 : record-vertex ( -- ) position> gl-vertex ;
22 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
26 : draw-forward ( length -- )
27 GL_LINES glBegin record-vertex step-turtle record-vertex glEnd ;
29 : move-forward ( length -- ) step-turtle polygon-vertex ;
31 : sneak-forward ( length -- ) step-turtle ;
33 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
35 ! (v0 - v1) x (v1 - v2)
37 : polygon-normal ( {_v0_v1_v2_} -- normal ) first3 dupd v- -rot v- swap cross ;
39 : (polygon) ( vertices -- )
40 GL_POLYGON glBegin dup polygon-normal gl-normal [ gl-vertex ] each glEnd ;
42 : polygon ( vertices -- ) dup length 3 >= [ (polygon) ] [ drop ] if ;
44 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
46 ! Maybe use an array instead of a vector
50 : start-polygon ( -- ) 0 <vector> >vertices ;
52 : finish-polygon ( -- ) vertices> polygon ;
54 : polygon-vertex ( -- ) position> vertices> push ;
56 : reset-vertices start-polygon ;
58 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
59 ! Lindenmayer string rewriting
60 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
62 ! Maybe use an array instead of a quot in the work of segment
66 : segment ( str -- seq )
67 { { [ dup "" = ] [ drop [ ] ] }
68 { [ dup length 1 = ] [ unit ] }
69 { [ 1 over nth CHAR: ( = ]
70 [ CHAR: ) over index 1 + ! str i
71 2dup head ! str i head
74 { [ t ] [ dup 1 head swap 1 tail segment swap add* ] } }
77 : lookup ( str -- str ) dup 1 head rules get hash dup [ nip ] [ drop ] if ;
79 : rewrite ( str -- str ) segment [ lookup ] map concat ;
81 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
82 ! Lindenmayer string interpretation
83 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
87 : segment-command ( seg -- command ) 1 head ;
89 ! : segment-parameter ( seg -- parameter )
90 ! dup length 1 - 2 swap rot subseq parse call ;
92 : segment-parameter ( seg -- parameter )
93 dup length 1 - 2 swap rot subseq string>number ;
95 : segment-parts ( seg -- param command )
96 dup segment-parameter swap segment-command ;
98 : exec-command ( str -- ) command-table get hash dup [ call ] [ drop ] if ;
100 : exec-command-with-param ( param command -- )
101 command-table get hash dup [ peek unit call ] [ 2drop ] if ;
103 : (interpret) ( seg -- )
105 [ exec-command ] [ segment-parts exec-command-with-param ] if ;
107 : interpret ( str -- ) segment [ (interpret) ] each ;
109 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
111 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
118 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
121 DEFER: set-color-index
123 TUPLE: state position orientation angle len thickness color-index ;
127 : reset-state-stack ( -- ) V{ } clone >states ;
130 position> orientation> angle> len> thickness> color-index> <state>
133 : restore-state ( -- )
135 dup state-position >position
136 dup state-orientation >orientation
138 dup state-angle >angle
139 dup state-color-index set-color-index
140 dup state-thickness set-thickness
143 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
145 : scale-len ( m -- ) len> * >len ;
147 : scale-angle ( m -- ) angle> * >angle ;
149 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
153 : init-color-table ( -- )
155 { 0.5 0.5 0.5 } ! grey
159 { 0.25 0.88 0.82 } ! turquoise
161 { 0.63 0.13 0.94 } ! purple
162 { 0.00 0.50 0.00 } ! dark green
163 { 0.00 0.82 0.82 } ! dark turquoise
164 { 0.00 0.00 0.50 } ! dark blue
165 { 0.58 0.00 0.82 } ! dark purple
166 { 0.50 0.00 0.00 } ! dark red
167 { 0.25 0.25 0.25 } ! dark grey
168 { 0.75 0.75 0.75 } ! medium grey
170 } [ 1 set-color-alpha ] map color-table set ;
172 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
174 : material-color ( color -- )
175 GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE rot gl-material-fv ;
177 : set-color-index ( i -- )
178 dup >color-index color-table> nth dup gl-color material-color ;
180 : inc-color-index ( -- ) color-index> 1 + set-color-index ;
182 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
184 : set-thickness ( i -- ) dup >thickness glLineWidth ;
186 : scale-thickness ( m -- ) thickness> * 0.5 max set-thickness ;
188 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
193 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
195 : lparser-dialect ( -- )
197 [ 1 >len 45 >angle 1 >thickness 2 >color-index ] >default-values
199 H{ { "+" [ angle get turn-left ] }
200 { "-" [ angle get turn-right ] }
201 { "&" [ angle get pitch-down ] }
202 { "^" [ angle get pitch-up ] }
203 { "<" [ angle get roll-left ] }
204 { ">" [ angle get roll-right ] }
206 { "|" [ 180.0 rotate-y ] }
207 { "%" [ 180.0 rotate-z ] }
208 { "$" [ roll-until-horizontal ] }
210 { "F" [ len get draw-forward ] }
211 { "Z" [ len get 2 / draw-forward ] }
212 { "f" [ len get move-forward ] }
213 { "z" [ len get 2 / move-forward ] }
214 { "g" [ len get sneak-forward ] }
215 { "." [ polygon-vertex ] }
217 { "[" [ save-state ] }
218 { "]" [ restore-state ] }
219 { "{" [ start-polygon ] }
220 { "}" [ finish-polygon ] }
222 { "/" [ 1.1 scale-len ] } ! double quote command in lparser
223 { "'" [ 0.9 scale-len ] }
224 { ";" [ 1.1 scale-angle ] }
225 { ":" [ 0.9 scale-angle ] }
226 { "?" [ 1.4 scale-thickness ] }
227 { "!" [ 0.7 scale-thickness ] }
229 { "c" [ color-index> 1 + color-table get length mod set-color-index ] }
231 } command-table set ;
233 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
238 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
240 : iterate ( -- ) result> rewrite >result ;
242 : iterations ( n -- ) [ iterate ] times ;
244 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
248 : init-model ( -- ) 1 glGenLists >model ;
250 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
258 GL_PROJECTION glMatrixMode
260 -1 1 -1 1 1.5 200 glFrustum
262 GL_MODELVIEW glMatrixMode
266 [ do-look-at ] camera> with-turtle
268 GL_COLOR_BUFFER_BIT glClear
270 GL_FRONT_AND_BACK GL_LINE glPolygonMode
273 GL_LINES glBegin { 0 0 0 } gl-vertex { 0 0 1 } gl-vertex glEnd
275 color-index> set-color-index
279 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
281 : init-turtle ( -- ) <turtle> >turtle ;
283 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
285 : init-camera ( -- ) <turtle> >camera ;
287 : reset-camera ( -- ) [
293 ] camera> with-turtle ;
295 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
298 <camera-slate> >slate
299 namespace slate> set-slate-ns
300 slate> "L-system" open-titled-window
301 [ display ] >action ;
303 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
308 init-camera reset-camera
316 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
318 : result>model ( -- )
319 [ model> GL_COMPILE glNewList result> interpret glEndList ] >action .slate ;
329 [ display ] >action .slate ;
331 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
333 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
335 : koch ( -- ) lparser-dialect [ 90 >angle ] >model-values
337 H{ { "K" "[[a|b] '(0.41)f'(2.439) |<(60) [a|b]]" }
338 { "k" "[ c'(0.5) K]" }
339 { "a" "[d <(120) d <(120) d ]" }
341 { "e" "[^ '(.2887)f'(3.4758) &(180) +z{.-(120)f-(120)f}]" }
342 { "d" "[^ '(.2887)f'(3.4758) &(109.5111) +zk{.-(120)f-(120)f}]" }
345 "K" >axiom axiom> >result ;
347 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
349 : spiral-0 ( -- ) lparser-dialect [ 10 >angle 5 >thickness ] >model-values
353 H{ { "P" "[A]>>>>>>>>>[cB]>>>>>>>>>[ccC]>>>>>>>>>[cccD]" }
357 { "D" "F!>^+F>^+;'D" }
362 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
364 : tree-5 ( -- ) lparser-dialect [ 5 >angle 1 >thickness ] >model-values
368 H{ { "S" "FFR>(60)R>(60)R>(60)R>(60)R>(60)R>(30)S" }
379 { "F" "'(1.25)F'(.8)" }
382 : tree-5-scene ( -- )
386 [ reset-turtle 90 pitch-down -70 step-turtle 50 strafe-up ] camera> with-turtle
389 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
391 : abop-1 ( -- ) lparser-dialect [ 45 >angle 5 >thickness ] >model-values
393 H{ { "A" "F[&'(.8)!BL]>(137)'!(.9)A" }
394 { "B" "F[-'(.8)!(.9)$CL]'!(.9)C" }
395 { "C" "F[+'(.8)!(.9)$BL]'!(.9)B" }
397 { "L" "~c(8){+(30)f-(120)f-(120)f}" }
400 "c(12)FFAL" >result ;
402 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
404 : abop-2 ( -- ) lparser-dialect [ 30 >angle 5 >thickness ] >model-values
406 H{ { "A" "F[&'(.7)!BL]>(137)[&'(.6)!BL]>(137)'(.9)!(.9)A" }
407 { "B" "F[-'(.7)!(.9)$CL]'(.9)!(.9)C" }
408 { "C" "F[+'(.7)!(.9)$BL]'(.9)!(.9)B" }
410 { "L" "~c(8){+(45)f(.1)-(45)f(.1)-(45)f(.1)+(45)|+(45)f(.1)-(45)f(.1)-(45)f(.1)}" }
416 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
418 : abop-3 ( -- ) lparser-dialect [ 30 >angle 5 >thickness ] >model-values
420 H{ { "A" "!(.9)t(.4)FB>(94)B>(132)B" }
421 { "B" "[&t(.4)F$A]" }
422 { "F" "'(1.25)F'(.8)" }
427 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
429 : abop-4 ( -- ) lparser-dialect [ 18 >angle 5 >thickness ] >model-values
431 H{ { "N" "FII[&(60)rY]>(90)[&(45)'(0.8)rA]>(90)[&(60)rY]>(90)[&(45)'(0.8)rD]!FIK" }
432 { "Y" "[c(4){++l.--l.--l.++|++l.--l.--l.}]" }
434 { "K" "[!c(2)FF>w>(72)w>(72)w>(72)w>(72)w]" }
435 { "w" "[c(2)^!F][c(5)&(72){-(54)f(3)+(54)f(3)|-(54)f(3)+(54)f(3)}]" }
462 "c(12)&(20)N" >result ;
464 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
466 : abop-5 ( -- ) lparser-dialect [ 5 >angle 5 >thickness ] >model-values
468 H{ { "a" "F[+(45)l][-(45)l]^;ca" }
477 { "F" "'(1.17)F'(.855)" }
480 "&(90)+(90)a" >result ;
482 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
484 : abop-6 ( -- ) lparser-dialect [ 5 >angle 5 >thickness ] >model-values
486 "&(90)+(90)FFF[-(120)'(.6)x][-(60)'(.8)x][+(120)'(.6)x][+(60)'(.8)x]x" >result
488 H{ { "a" "F[cdx][cex]F!(.9)a" }
494 { "F" "'(1.25)F'(.8)" }
497 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
499 : airhorse ( -- ) lparser-dialect [ 10 >angle 5 >thickness ] >model-values
505 { "B" "[[''aH]|[g]]" }
508 { "s" "[::cc!!!!&&[FFcccZ]^^^^FFcccZ]" }
509 { "t" "[c!!!!&[FF]^^FF]" }
519 { "V" "[cc!!!&(90)[Zp]|[Zp]]" }
520 { "p" "h>(120)h>(120)h" }
521 { "h" "[+(40)!F'''p]" }
523 { "H" "[cccci[>(50)dcFFF][<(50)ecFFF]]" }
528 { "W" "[%[!!cb][<<<!!cb][>>>!!cb]]" }
530 { "l" "[-cc{--z++z++z--|--z++z++z}]" }
533 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
535 ! These should be moved into a separate file. They are used to pretty
536 ! print matricies and vectors.
538 USING: styles prettyprint io ;
540 : decimal-places ( n d -- n )
541 10 swap ^ tuck * >fixnum swap /f ;
543 ! : .mat ( matrix -- ) [ [ 2 decimal-places ] map ] map . ;
546 H{ { table-gap 4 } { table-border 4 } }
547 [ 2 decimal-places pprint ]
550 : .vec ( vector -- ) [ 2 decimal-places ] map . ;
552 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
554 PROVIDE: lindenmayer ;
556 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!