36
36
< body >
37
37
<!-- <pre></pre> -->
38
38
< canvas > </ canvas >
39
- < script src ="code/bundle.js "> </ script >
39
+ <!-- <script src="code/bundle.js"></script> -->
40
+
41
+ < script >
42
+
43
+ // Find intersection of RAY & SEGMENT
44
+ function getIntersection ( ray , segment ) {
45
+ // RAY in parametric: Point + Delta*T1
46
+ var r_px = ray . a . x ;
47
+ var r_py = ray . a . y ;
48
+ var r_dx = ray . b . x - ray . a . x ;
49
+ var r_dy = ray . b . y - ray . a . y ;
50
+
51
+ // SEGMENT in parametric: Point + Delta*T2
52
+ var s_px = segment . a . x ;
53
+ var s_py = segment . a . y ;
54
+ var s_dx = segment . b . x - segment . a . x ;
55
+ var s_dy = segment . b . y - segment . a . y ;
56
+
57
+ // Are they parallel? If so, no intersect
58
+ var r_mag = Math . sqrt ( r_dx * r_dx + r_dy * r_dy ) ;
59
+ var s_mag = Math . sqrt ( s_dx * s_dx + s_dy * s_dy ) ;
60
+ if ( r_dx / r_mag == s_dx / s_mag && r_dy / r_mag == s_dy / s_mag ) {
61
+ // Unit vectors are the same.
62
+ return null ;
63
+ }
64
+
65
+ // SOLVE FOR T1 & T2
66
+ // r_px+r_dx*T1 = s_px+s_dx*T2 && r_py+r_dy*T1 = s_py+s_dy*T2
67
+ // ==> T1 = (s_px+s_dx*T2-r_px)/r_dx = (s_py+s_dy*T2-r_py)/r_dy
68
+ // ==> s_px*r_dy + s_dx*T2*r_dy - r_px*r_dy = s_py*r_dx + s_dy*T2*r_dx - r_py*r_dx
69
+ // ==> T2 = (r_dx*(s_py-r_py) + r_dy*(r_px-s_px))/(s_dx*r_dy - s_dy*r_dx)
70
+ var T2 = ( r_dx * ( s_py - r_py ) + r_dy * ( r_px - s_px ) ) / ( s_dx * r_dy - s_dy * r_dx ) ;
71
+ var T1 = ( s_px + s_dx * T2 - r_px ) / r_dx ;
72
+
73
+ // Must be within parametic whatevers for RAY/SEGMENT
74
+ if ( T1 < 0 ) return null ;
75
+ if ( T2 < 0 || T2 > 1 ) return null ;
76
+
77
+ // Return the POINT OF INTERSECTION
78
+ return {
79
+ x : r_px + r_dx * T1 ,
80
+ y : r_py + r_dy * T1 ,
81
+ param : T1
82
+ } ;
83
+ }
84
+
85
+ function getSightPolygon ( sightX , sightY ) {
86
+ // Get all unique points
87
+ var points = ( function ( segments ) {
88
+ var a = [ ] ;
89
+ segments . forEach ( function ( seg ) {
90
+ a . push ( seg . a , seg . b ) ;
91
+ } ) ;
92
+ return a ;
93
+ } ) ( segments ) ;
94
+
95
+ var uniquePoints = ( function ( points ) {
96
+ var set = { } ;
97
+ return points . filter ( function ( p ) {
98
+ var key = p . x + "," + p . y ;
99
+ if ( key in set ) {
100
+ return false ;
101
+ } else {
102
+ set [ key ] = true ;
103
+ return true ;
104
+ }
105
+ } ) ;
106
+ } ) ( points ) ;
107
+
108
+ // Get all angles
109
+ var uniqueAngles = [ ] ;
110
+ for ( var j = 0 ; j < uniquePoints . length ; j ++ ) {
111
+ var uniquePoint = uniquePoints [ j ] ;
112
+ var angle = Math . atan2 ( uniquePoint . y - sightY , uniquePoint . x - sightX ) ;
113
+ uniquePoint . angle = angle ;
114
+ uniqueAngles . push ( angle - 0.00001 , angle , angle + 0.00001 ) ;
115
+ }
116
+
117
+ // RAYS IN ALL DIRECTIONS
118
+ var intersects = [ ] ;
119
+ for ( var j = 0 ; j < uniqueAngles . length ; j ++ ) {
120
+ var angle = uniqueAngles [ j ] ;
121
+ // Calculate dx & dy from angle
122
+ var dx = Math . cos ( angle ) ;
123
+ var dy = Math . sin ( angle ) ;
124
+
125
+ // Ray from light coord to point coord
126
+ var ray = {
127
+ a : { x : sightX , y : sightY } ,
128
+ b : { x : sightX + dx , y : sightY + dy }
129
+ } ;
130
+
131
+ // Find CLOSEST intersection
132
+ var closestIntersect = null ;
133
+ for ( var i = 0 ; i < segments . length ; i ++ ) {
134
+ var intersect = getIntersection ( ray , segments [ i ] ) ;
135
+ if ( ! intersect ) continue ;
136
+
137
+ // param (aka distance)
138
+ if ( ! closestIntersect || intersect . param < closestIntersect . param ) {
139
+ closestIntersect = intersect ;
140
+ }
141
+ }
142
+
143
+ // if (Math.sqrt(Math.pow(closestIntersect.x - sightX, 2) + Math.pow(closestIntersect.y - sightY, 2)) > 500) continue;
144
+
145
+ // Intersect angle
146
+ if ( ! closestIntersect ) continue ;
147
+ closestIntersect . angle = angle ;
148
+
149
+ // Add to list of intersects
150
+ intersects . push ( closestIntersect ) ;
151
+ }
152
+
153
+ // Sort intersects by angle
154
+ intersects = intersects . sort ( function ( a , b ) {
155
+ return a . angle - b . angle ;
156
+ } ) ;
157
+
158
+ // Polygon is intersects, in order of angle
159
+ return intersects ;
160
+ }
161
+
162
+ ///////////////////////////////////////////////////////
163
+ // DRAWING
164
+ var canvas = document . querySelector ( "canvas" ) ;
165
+ canvas . width = window . innerWidth ;
166
+ canvas . height = window . innerHeight ;
167
+
168
+ var ctx = canvas . getContext ( "2d" ) ;
169
+
170
+ function draw ( ) {
171
+ // Clear canvas
172
+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
173
+
174
+ ctx . fillStyle = '#000' ;
175
+ ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
176
+
177
+ // Draw segments
178
+ ctx . strokeStyle = "#999" ;
179
+ for ( var i = 0 ; i < segments . length ; i ++ ) {
180
+ var seg = segments [ i ] ;
181
+ ctx . beginPath ( ) ;
182
+ ctx . moveTo ( seg . a . x , seg . a . y ) ;
183
+ ctx . lineTo ( seg . b . x , seg . b . y ) ;
184
+ ctx . stroke ( ) ;
185
+ }
186
+
187
+ var lightsCount = 1 ;
188
+
189
+
190
+ performance . mark ( 'getSightPolygonStart' ) ;
191
+
192
+ // Sight Polygons
193
+ var fuzzyRadius = 0 ;
194
+ var polygons = [ getSightPolygon ( Mouse . x , Mouse . y ) ] ;
195
+ for ( var angle = 0 ; angle < Math . PI * 2 ; angle += ( Math . PI * 2 ) / lightsCount ) {
196
+ var dx = Math . cos ( angle ) * fuzzyRadius ;
197
+ var dy = Math . sin ( angle ) * fuzzyRadius ;
198
+ polygons . push ( getSightPolygon ( Mouse . x + dx , Mouse . y + dy ) ) ;
199
+ } ;
200
+
201
+ performance . mark ( 'getSightPolygonEnd' ) ;
202
+ performance . measure ( 'getSightPolygon' , 'getSightPolygonStart' , 'getSightPolygonEnd' ) ;
203
+
204
+
205
+ // DRAW AS A GIANT POLYGON
206
+ for ( var i = 1 ; i < polygons . length ; i ++ ) {
207
+ drawPolygon ( polygons [ i ] , ctx , `rgba(255, 255, 255, ${ 1 / lightsCount } )` ) ;
208
+ }
209
+ drawPolygon ( polygons [ 0 ] , ctx , "#fff" ) ;
210
+
211
+
212
+ // Draw red dots
213
+ ctx . fillStyle = "#dd3838" ;
214
+ ctx . beginPath ( ) ;
215
+ ctx . arc ( Mouse . x , Mouse . y , 2 , 0 , 2 * Math . PI , false ) ;
216
+ ctx . fill ( ) ;
217
+ for ( var angle = 0 ; angle < Math . PI * 2 ; angle += ( Math . PI * 2 ) / lightsCount ) {
218
+ var dx = Math . cos ( angle ) * fuzzyRadius ;
219
+ var dy = Math . sin ( angle ) * fuzzyRadius ;
220
+ ctx . beginPath ( ) ;
221
+ ctx . arc ( Mouse . x + dx , Mouse . y + dy , 2 , 0 , 2 * Math . PI , false ) ;
222
+ ctx . fill ( ) ;
223
+ }
224
+ }
225
+
226
+ function drawPolygon ( polygon , ctx , fillStyle ) {
227
+ ctx . fillStyle = 'rgba(255, 255, 255, 0.1)' ; //fillStyle;
228
+ ctx . strokeStyle = '#3f0' ;
229
+ ctx . beginPath ( ) ;
230
+ ctx . moveTo ( polygon [ 0 ] . x , polygon [ 0 ] . y ) ;
231
+ for ( var i = 1 ; i < polygon . length ; i ++ ) {
232
+ var intersect = polygon [ i ] ;
233
+ ctx . lineTo ( Mouse . x , Mouse . y ) ;
234
+ ctx . lineTo ( intersect . x , intersect . y ) ;
235
+ }
236
+ // ctx.fill();
237
+ ctx . stroke ( ) ;
238
+ }
239
+
240
+ const kx = window . innerWidth / 640 ;
241
+ const ky = window . innerHeight / 360 ;
242
+
243
+ // LINE SEGMENTS
244
+ var segments = [
245
+ // Border
246
+ { a : { x : kx * 0 , y : ky * 0 } , b : { x : kx * 640 , y : ky * 0 } } ,
247
+ { a : { x : kx * 640 , y : ky * 0 } , b : { x : kx * 640 , y : ky * 360 } } ,
248
+ { a : { x : kx * 640 , y : ky * 360 } , b : { x : kx * 0 , y : ky * 360 } } ,
249
+ { a : { x : kx * 0 , y : ky * 360 } , b : { x : kx * 0 , y : ky * 0 } } ,
250
+ // Polygon #1
251
+ { a : { x : kx * 100 , y : ky * 150 } , b : { x : kx * 120 , y : ky * 50 } } ,
252
+ { a : { x : kx * 120 , y : ky * 50 } , b : { x : kx * 200 , y : ky * 80 } } ,
253
+ { a : { x : kx * 200 , y : ky * 80 } , b : { x : kx * 140 , y : ky * 210 } } ,
254
+ { a : { x : kx * 140 , y : ky * 210 } , b : { x : kx * 100 , y : ky * 150 } } ,
255
+ // Polygon #2
256
+ { a : { x : kx * 100 , y : ky * 200 } , b : { x : kx * 120 , y : ky * 250 } } ,
257
+ { a : { x : kx * 120 , y : ky * 250 } , b : { x : kx * 60 , y : ky * 300 } } ,
258
+ { a : { x : kx * 60 , y : ky * 300 } , b : { x : kx * 100 , y : ky * 200 } } ,
259
+ // Polygon #3
260
+ { a : { x : kx * 200 , y : ky * 260 } , b : { x : kx * 220 , y : ky * 150 } } ,
261
+ { a : { x : kx * 220 , y : ky * 150 } , b : { x : kx * 300 , y : ky * 200 } } ,
262
+ { a : { x : kx * 300 , y : ky * 200 } , b : { x : kx * 350 , y : ky * 320 } } ,
263
+ { a : { x : kx * 350 , y : ky * 320 } , b : { x : kx * 200 , y : ky * 260 } } ,
264
+ // Polygon #4
265
+ { a : { x : kx * 340 , y : ky * 60 } , b : { x : kx * 360 , y : ky * 40 } } ,
266
+ { a : { x : kx * 360 , y : ky * 40 } , b : { x : kx * 370 , y : ky * 70 } } ,
267
+ { a : { x : kx * 370 , y : ky * 70 } , b : { x : kx * 340 , y : ky * 60 } } ,
268
+ // Polygon #5
269
+ { a : { x : kx * 450 , y : ky * 190 } , b : { x : kx * 560 , y : ky * 170 } } ,
270
+ { a : { x : kx * 560 , y : ky * 170 } , b : { x : kx * 540 , y : ky * 270 } } ,
271
+ { a : { x : kx * 540 , y : ky * 270 } , b : { x : kx * 430 , y : ky * 290 } } ,
272
+ { a : { x : kx * 430 , y : ky * 290 } , b : { x : kx * 450 , y : ky * 190 } } ,
273
+ // Polygon #6
274
+ { a : { x : kx * 400 , y : ky * 95 } , b : { x : kx * 580 , y : ky * 50 } } ,
275
+ { a : { x : kx * 580 , y : ky * 50 } , b : { x : kx * 480 , y : ky * 150 } } ,
276
+ { a : { x : kx * 480 , y : ky * 150 } , b : { x : kx * 400 , y : ky * 95 } }
277
+ ] ;
278
+ // DRAW LOOP
279
+
280
+ var updateCanvas = true ;
281
+
282
+ function drawLoop ( ) {
283
+ requestAnimationFrame ( drawLoop ) ;
284
+ if ( updateCanvas ) {
285
+ draw ( ) ;
286
+ updateCanvas = false ;
287
+ }
288
+ }
289
+ window . onload = function ( ) {
290
+ drawLoop ( ) ;
291
+ } ;
292
+ // MOUSE
293
+ var Mouse = {
294
+ x : canvas . width / 2 ,
295
+ y : canvas . height / 2
296
+ } ;
297
+ canvas . onmousemove = function ( event ) {
298
+ Mouse . x = event . clientX ;
299
+ Mouse . y = event . clientY ;
300
+ updateCanvas = true ;
301
+ } ;
302
+
303
+ </ script >
40
304
</ body >
41
305
42
306
</ html >
0 commit comments