]> gitweb.factorcode.org Git - factor.git/blob - extra/jamshred/tunnel/tunnel.factor
96992c3b8cd82d88fb731d3a81151d364fa91aaa
[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 alien.c-types colors combinators jamshred.oint
4 kernel literals math math.constants math.order math.quadratic
5 math.vectors random sequences specialized-arrays vectors ;
6 FROM: jamshred.oint => distance ;
7 FROM: alien.c-types => float ;
8 SPECIALIZED-ARRAY: float
9 IN: jamshred.tunnel
10
11 CONSTANT: n-segments 5000
12
13 TUPLE: segment < oint number color radius ;
14 C: <segment> segment
15
16 : segment-number++ ( segment -- )
17     [ number>> 1 + ] keep number<< ;
18
19 : clamp-length ( n seq -- n' )
20     0 swap length clamp ;
21
22 : random-color ( -- color )
23     { 100 100 100 } [ random 100 / >float ] map first3 1.0 <rgba> ;
24
25 CONSTANT: tunnel-segment-distance 0.4
26 CONSTANT: random-rotation-angle $[ pi 20 / ]
27
28 : random-segment ( previous-segment -- segment )
29     clone dup random-rotation-angle random-turn
30     tunnel-segment-distance over go-forward
31     random-color >>color dup segment-number++ ;
32
33 : (random-segments) ( segments n -- segments )
34     [ dup last random-segment suffix! ] times ;
35
36 CONSTANT: default-segment-radius 1
37
38 : initial-segment ( -- segment )
39     float-array{ 0 0 0 } float-array{ 0 0 -1 } float-array{ 0 1 0 } float-array{ -1 0 0 }
40     0 random-color default-segment-radius <segment> ;
41
42 : random-segments ( n -- segments )
43     initial-segment 1vector swap (random-segments) ;
44
45 : simple-segment ( n -- segment )
46     [ float-array{ 0 0 -1 } n*v float-array{ 0 0 -1 } float-array{ 0 1 0 } float-array{ -1 0 0 } ] keep
47     random-color default-segment-radius <segment> ;
48
49 : simple-segments ( n -- segments )
50     [ simple-segment ] map ;
51
52 : <random-tunnel> ( -- segments )
53     n-segments random-segments ;
54
55 : <straight-tunnel> ( -- segments )
56     n-segments simple-segments ;
57
58 : sub-tunnel ( from to segments -- segments )
59     ! return segments between from and to, after clamping from and to to
60     ! valid values
61     [ '[ _ clamp-length ] bi@ ] keep <slice> ;
62
63 : get-segment ( segments n -- segment )
64     over clamp-length swap nth ;
65
66 : next-segment ( segments current-segment -- segment )
67     number>> 1 + get-segment ;
68
69 : previous-segment ( segments current-segment -- segment )
70     number>> 1 - get-segment ;
71
72 : heading-segment ( segments current-segment heading -- segment )
73     ! the next segment on the given heading
74     over forward>> vdot 0 <=> {
75         { +gt+ [ next-segment ] }
76         { +lt+ [ previous-segment ] }
77         { +eq+ [ nip ] } ! current segment
78     } case ;
79
80 :: distance-to-next-segment ( current next location heading -- distance )
81     current forward>> :> cf
82     cf next location>> vdot cf location vdot - cf heading vdot / ;
83
84 :: distance-to-next-segment-area ( current next location heading -- distance )
85     current forward>> :> cf
86     next current half-way-between-oints :> h
87     cf h vdot cf location vdot - cf heading vdot / ;
88
89 : vector-to-centre ( seg loc -- v )
90     over location>> swap v- swap forward>> proj-perp ;
91
92 : distance-from-centre ( seg loc -- distance )
93     vector-to-centre norm ;
94
95 : wall-normal ( seg oint -- n )
96     location>> vector-to-centre normalize ;
97
98 CONSTANT: distant 1000
99
100 : max-real ( a b -- c )
101     ! sometimes collision-coefficient yields complex roots, so we ignore these (hack)
102     dup real? [
103         over real? [ max ] [ nip ] if
104     ] [
105         drop dup real? [ drop distant ] unless
106     ] if ;
107
108 :: collision-coefficient ( v w r -- c )
109     v norm 0 = [
110         distant
111     ] [
112         v dup vdot :> a
113         v w vdot 2 * :> b
114         w dup vdot r sq - :> c
115         c b a quadratic max-real
116     ] if ;
117
118 : sideways-heading ( oint segment -- v )
119     [ forward>> ] bi@ proj-perp ;
120
121 : sideways-relative-location ( oint segment -- loc )
122     [ [ location>> ] bi@ v- ] keep forward>> proj-perp ;
123
124 : (distance-to-collision) ( oint segment -- distance )
125     [ sideways-heading ] [ sideways-relative-location ]
126     [ nip radius>> ] 2tri collision-coefficient ;
127
128 : collision-vector ( oint segment -- v )
129     dupd (distance-to-collision) swap forward>> n*v ;
130
131 : bounce-forward ( segment oint -- )
132     [ wall-normal ] [ forward>> swap reflect ] [ forward<< ] tri ;
133
134 : bounce-left ( segment oint -- )
135     ! must be done after forward
136     [ forward>> vneg ] dip [ left>> swap reflect ]
137     [ forward>> proj-perp normalize ] [ left<< ] tri ;
138
139 : bounce-up ( segment oint -- )
140     ! must be done after forward and left!
141     nip [ forward>> ] [ left>> cross ] [ up<< ] tri ;
142
143 : bounce-off-wall ( oint segment -- )
144     swap [ bounce-forward ] [ bounce-left ] [ bounce-up ] 2tri ;