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 vectors ;
7 FROM: jamshred.oint => distance ;
8 FROM: alien.c-types => float ;
9 SPECIALIZED-ARRAY: float
12 CONSTANT: n-segments 5000
14 TUPLE: segment < oint number color radius ;
17 : segment-number++ ( segment -- )
18 [ number>> 1 + ] keep number<< ;
20 : clamp-length ( n seq -- n' )
23 : random-color ( -- color )
24 { 100 100 100 } [ random 100 / >float ] map first3 1.0 <rgba> ;
26 CONSTANT: tunnel-segment-distance 0.4
27 CONSTANT: random-rotation-angle $[ pi 20 / ]
29 : random-segment ( previous-segment -- segment )
30 clone dup random-rotation-angle random-turn
31 tunnel-segment-distance over go-forward
32 random-color >>color dup segment-number++ ;
34 : (random-segments) ( segments n -- segments )
36 [ dup last random-segment over push ] dip 1 - (random-segments)
39 CONSTANT: default-segment-radius 1
41 : initial-segment ( -- segment )
42 float-array{ 0 0 0 } float-array{ 0 0 -1 } float-array{ 0 1 0 } float-array{ -1 0 0 }
43 0 random-color default-segment-radius <segment> ;
45 : random-segments ( n -- segments )
46 initial-segment 1vector swap (random-segments) ;
48 : simple-segment ( n -- segment )
49 [ float-array{ 0 0 -1 } n*v float-array{ 0 0 -1 } float-array{ 0 1 0 } float-array{ -1 0 0 } ] keep
50 random-color default-segment-radius <segment> ;
52 : simple-segments ( n -- segments )
53 [ simple-segment ] map ;
55 : <random-tunnel> ( -- segments )
56 n-segments random-segments ;
58 : <straight-tunnel> ( -- segments )
59 n-segments simple-segments ;
61 : sub-tunnel ( from to segments -- segments )
62 #! return segments between from and to, after clamping from and to to
64 [ '[ _ clamp-length ] bi@ ] keep <slice> ;
66 : get-segment ( segments n -- segment )
67 over clamp-length swap nth ;
69 : next-segment ( segments current-segment -- segment )
70 number>> 1 + get-segment ;
72 : previous-segment ( segments current-segment -- segment )
73 number>> 1 - get-segment ;
75 : heading-segment ( segments current-segment heading -- segment )
76 #! the next segment on the given heading
77 over forward>> v. 0 <=> {
78 { +gt+ [ next-segment ] }
79 { +lt+ [ previous-segment ] }
80 { +eq+ [ nip ] } ! current segment
83 :: distance-to-next-segment ( current next location heading -- distance )
84 current forward>> :> cf
85 cf next location>> v. cf location v. - cf heading v. / ;
87 :: distance-to-next-segment-area ( current next location heading -- distance )
88 current forward>> :> cf
89 next current half-way-between-oints :> h
90 cf h v. cf location v. - cf heading v. / ;
92 : vector-to-centre ( seg loc -- v )
93 over location>> swap v- swap forward>> proj-perp ;
95 : distance-from-centre ( seg loc -- distance )
96 vector-to-centre norm ;
98 : wall-normal ( seg oint -- n )
99 location>> vector-to-centre normalize ;
101 CONSTANT: distant 1000
103 : max-real ( a b -- c )
104 #! sometimes collision-coefficient yields complex roots, so we ignore these (hack)
106 over real? [ max ] [ nip ] if
108 drop dup real? [ drop distant ] unless
111 :: collision-coefficient ( v w r -- c )
118 c b a quadratic max-real
121 : sideways-heading ( oint segment -- v )
122 [ forward>> ] bi@ proj-perp ;
124 : sideways-relative-location ( oint segment -- loc )
125 [ [ location>> ] bi@ v- ] keep forward>> proj-perp ;
127 : (distance-to-collision) ( oint segment -- distance )
128 [ sideways-heading ] [ sideways-relative-location ]
129 [ nip radius>> ] 2tri collision-coefficient ;
131 : collision-vector ( oint segment -- v )
132 dupd (distance-to-collision) swap forward>> n*v ;
134 : bounce-forward ( segment oint -- )
135 [ wall-normal ] [ forward>> swap reflect ] [ forward<< ] tri ;
137 : bounce-left ( segment oint -- )
138 #! must be done after forward
139 [ forward>> vneg ] dip [ left>> swap reflect ]
140 [ forward>> proj-perp normalize ] [ left<< ] tri ;
142 : bounce-up ( segment oint -- )
143 #! must be done after forward and left!
144 nip [ forward>> ] [ left>> cross ] [ up<< ] tri ;
146 : bounce-off-wall ( oint segment -- )
147 swap [ bounce-forward ] [ bounce-left ] [ bounce-up ] 2tri ;