]> gitweb.factorcode.org Git - factor.git/blob - extra/jamshred/tunnel/tunnel.factor
Delete empty unit tests files, remove 1- and 1+, reorder IN: lines in a lot of places...
[factor.git] / extra / jamshred / tunnel / tunnel.factor
1 ! Copyright (C) 2007, 2008 Alex Chapman
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays colors combinators fry jamshred.oint
4 kernel literals locals math math.constants math.matrices
5 math.order math.quadratic math.ranges math.vectors random
6 sequences specialized-arrays.float vectors ;
7 FROM: jamshred.oint => distance ;
8 IN: jamshred.tunnel
9
10 CONSTANT: n-segments 5000
11
12 TUPLE: segment < oint number color radius ;
13 C: <segment> segment
14
15 : segment-number++ ( segment -- )
16     [ number>> 1 + ] keep (>>number) ;
17
18 : clamp-length ( n seq -- n' )
19     0 swap length clamp ;
20
21 : random-color ( -- color )
22     { 100 100 100 } [ random 100 / >float ] map first3 1.0 <rgba> ;
23
24 CONSTANT: tunnel-segment-distance 0.4
25 CONSTANT: random-rotation-angle $[ pi 20 / ]
26
27 : random-segment ( previous-segment -- segment )
28     clone dup random-rotation-angle random-turn
29     tunnel-segment-distance over go-forward
30     random-color >>color dup segment-number++ ;
31
32 : (random-segments) ( segments n -- segments )
33     dup 0 > [
34         [ dup last random-segment over push ] dip 1 - (random-segments)
35     ] [ drop ] if ;
36
37 CONSTANT: default-segment-radius 1
38
39 : initial-segment ( -- segment )
40     float-array{ 0 0 0 } float-array{ 0 0 -1 } float-array{ 0 1 0 } float-array{ -1 0 0 }
41     0 random-color default-segment-radius <segment> ;
42
43 : random-segments ( n -- segments )
44     initial-segment 1vector swap (random-segments) ;
45
46 : simple-segment ( n -- segment )
47     [ float-array{ 0 0 -1 } n*v float-array{ 0 0 -1 } float-array{ 0 1 0 } float-array{ -1 0 0 } ] keep
48     random-color default-segment-radius <segment> ;
49
50 : simple-segments ( n -- segments )
51     [ simple-segment ] map ;
52
53 : <random-tunnel> ( -- segments )
54     n-segments random-segments ;
55
56 : <straight-tunnel> ( -- segments )
57     n-segments simple-segments ;
58
59 : sub-tunnel ( from to segments -- segments )
60     #! return segments between from and to, after clamping from and to to
61     #! valid values
62     [ '[ _ clamp-length ] bi@ ] keep <slice> ;
63
64 : nearer-segment ( segment segment oint -- segment )
65     #! return whichever of the two segments is nearer to the oint
66     [ 2dup ] dip tuck distance [ distance ] dip < -rot ? ;
67
68 : (find-nearest-segment) ( nearest next oint -- nearest ? )
69     #! find the nearest of 'next' and 'nearest' to 'oint', and return
70     #! t if the nearest hasn't changed
71     pick [ nearer-segment dup ] dip = ;
72
73 : find-nearest-segment ( oint segments -- segment )
74     dup first swap rest-slice rot [ (find-nearest-segment) ] curry
75     find 2drop ;
76     
77 : nearest-segment-forward ( segments oint start -- segment )
78     rot dup length swap <slice> find-nearest-segment ;
79
80 : nearest-segment-backward ( segments oint start -- segment )
81     swapd 1 + 0 spin <slice> <reversed> find-nearest-segment ;
82
83 : nearest-segment ( segments oint start-segment -- segment )
84     #! find the segment nearest to 'oint', and return it.
85     #! start looking at segment 'start-segment'
86     number>> over [
87         [ nearest-segment-forward ] 3keep nearest-segment-backward
88     ] dip nearer-segment ;
89
90 : get-segment ( segments n -- segment )
91     over clamp-length swap nth ;
92
93 : next-segment ( segments current-segment -- segment )
94     number>> 1 + get-segment ;
95
96 : previous-segment ( segments current-segment -- segment )
97     number>> 1 - get-segment ;
98
99 : heading-segment ( segments current-segment heading -- segment )
100     #! the next segment on the given heading
101     over forward>> v. 0 <=> {
102         { +gt+ [ next-segment ] }
103         { +lt+ [ previous-segment ] }
104         { +eq+ [ nip ] } ! current segment
105     } case ;
106
107 :: distance-to-next-segment ( current next location heading -- distance )
108     [let | cf [ current forward>> ] |
109         cf next location>> v. cf location v. - cf heading v. / ] ;
110
111 :: distance-to-next-segment-area ( current next location heading -- distance )
112     [let | cf [ current forward>> ]
113            h [ next current half-way-between-oints ] |
114         cf h v. cf location v. - cf heading v. / ] ;
115
116 : vector-to-centre ( seg loc -- v )
117     over location>> swap v- swap forward>> proj-perp ;
118
119 : distance-from-centre ( seg loc -- distance )
120     vector-to-centre norm ;
121
122 : wall-normal ( seg oint -- n )
123     location>> vector-to-centre normalize ;
124
125 CONSTANT: distant 1000
126
127 : max-real ( a b -- c )
128     #! sometimes collision-coefficient yields complex roots, so we ignore these (hack)
129     dup real? [
130         over real? [ max ] [ nip ] if
131     ] [
132         drop dup real? [ drop distant ] unless
133     ] if ;
134
135 :: collision-coefficient ( v w r -- c )
136     v norm 0 = [
137         distant
138     ] [
139         [let* | a [ v dup v. ]
140                 b [ v w v. 2 * ]
141                 c [ w dup v. r sq - ] |
142             c b a quadratic max-real ]
143     ] if ;
144
145 : sideways-heading ( oint segment -- v )
146     [ forward>> ] bi@ proj-perp ;
147
148 : sideways-relative-location ( oint segment -- loc )
149     [ [ location>> ] bi@ v- ] keep forward>> proj-perp ;
150
151 : (distance-to-collision) ( oint segment -- distance )
152     [ sideways-heading ] [ sideways-relative-location ]
153     [ nip radius>> ] 2tri collision-coefficient ;
154
155 : collision-vector ( oint segment -- v )
156     dupd (distance-to-collision) swap forward>> n*v ;
157
158 : bounce-forward ( segment oint -- )
159     [ wall-normal ] [ forward>> swap reflect ] [ (>>forward) ] tri ;
160
161 : bounce-left ( segment oint -- )
162     #! must be done after forward
163     [ forward>> vneg ] dip [ left>> swap reflect ]
164     [ forward>> proj-perp normalize ] [ (>>left) ] tri ;
165
166 : bounce-up ( segment oint -- )
167     #! must be done after forward and left!
168     nip [ forward>> ] [ left>> cross ] [ (>>up) ] tri ;
169
170 : bounce-off-wall ( oint segment -- )
171     swap [ bounce-forward ] [ bounce-left ] [ bounce-up ] 2tri ;
172