Skip to content

Commit 9b67583

Browse files
authoredSep 19, 2016
Merge pull request #19 from snowkit/ray-fixes
Ray infinite state fixes
2 parents 12d9e1d + 2a9c9e6 commit 9b67583

File tree

8 files changed

+213
-58
lines changed

8 files changed

+213
-58
lines changed
 

‎differ/sat/SAT2D.hx

+45-16
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,13 @@ class SAT2D {
242242
var t1 = (-b - d) / (2 * a);
243243
var t2 = (-b + d) / (2 * a);
244244

245-
if (ray.infinite || (t1 <= 1.0 && t1 >= 0.0)) {
245+
var valid = switch(ray.infinite) {
246+
case not_infinite: t1 >= 0.0 && t1 <= 1.0;
247+
case infinite_from_start: t1 >= 0.0;
248+
case infinite: true;
249+
}
250+
251+
if (valid) {
246252

247253
into = (into == null) ? new RayCollision() : into.reset();
248254

@@ -265,7 +271,7 @@ class SAT2D {
265271
public static function testRayVsPolygon( ray:Ray, polygon:Polygon, ?into:RayCollision ) : RayCollision {
266272

267273
var min_u = Math.POSITIVE_INFINITY;
268-
var max_u = 0.0;
274+
var max_u = Math.NEGATIVE_INFINITY;
269275

270276
var startX = ray.start.x;
271277
var startY = ray.start.y;
@@ -280,12 +286,12 @@ class SAT2D {
280286
var ua = rayU(ud, startX, startY, v1.x, v1.y, v2.x - v1.x, v2.y - v1.y);
281287
var ub = rayU(ud, startX, startY, v1.x, v1.y, deltaX, deltaY);
282288

283-
if (ud != 0.0 && ub >= 0.0 && ub <= 1.0) {
284-
if (ua < min_u) min_u = ua;
285-
if (ua > max_u) max_u = ua;
289+
if(ud != 0.0 && ub >= 0.0 && ub <= 1.0) {
290+
if(ua < min_u) min_u = ua;
291+
if(ua > max_u) max_u = ua;
286292
}
287293

288-
for (i in 1...verts.length) {
294+
for(i in 1...verts.length) {
289295

290296
v1 = verts[i - 1];
291297
v2 = verts[i];
@@ -294,14 +300,20 @@ class SAT2D {
294300
ua = rayU(ud, startX, startY, v1.x, v1.y, v2.x - v1.x, v2.y - v1.y);
295301
ub = rayU(ud, startX, startY, v1.x, v1.y, deltaX, deltaY);
296302

297-
if (ud != 0.0 && ub >= 0.0 && ub <= 1.0) {
298-
if (ua < min_u) min_u = ua;
299-
if (ua > max_u) max_u = ua;
303+
if(ud != 0.0 && ub >= 0.0 && ub <= 1.0) {
304+
if(ua < min_u) min_u = ua;
305+
if(ua > max_u) max_u = ua;
300306
}
301307

302308
} //each vert
303309

304-
if(ray.infinite || (min_u <= 1.0 && min_u >= 0.0) ) {
310+
var valid = switch(ray.infinite) {
311+
case not_infinite: min_u >= 0.0 && min_u <= 1.0;
312+
case infinite_from_start: min_u != Math.POSITIVE_INFINITY && min_u >= 0.0;
313+
case infinite: (min_u != Math.POSITIVE_INFINITY);
314+
}
315+
316+
if(valid) {
305317
into = (into == null) ? new RayCollision() : into.reset();
306318
into.shape = polygon;
307319
into.ray = ray;
@@ -329,15 +341,32 @@ class SAT2D {
329341

330342
var u1 = (delta2X * diffY - delta2Y * diffX) / ud;
331343
var u2 = (delta1X * diffY - delta1Y * diffX) / ud;
344+
345+
//:todo: ask if ray hit condition difference is intentional (> 0 and not >= 0 like other checks)
346+
var valid1 = switch(ray1.infinite) {
347+
case not_infinite: (u1 > 0.0 && u1 <= 1.0);
348+
case infinite_from_start: u1 > 0.0;
349+
case infinite: true;
350+
}
351+
352+
var valid2 = switch(ray2.infinite) {
353+
case not_infinite: (u2 > 0.0 && u2 <= 1.0);
354+
case infinite_from_start: u2 > 0.0;
355+
case infinite: true;
356+
}
332357

333-
if ((ray1.infinite || (u1 > 0.0 && u1 <= 1.0)) && (ray2.infinite || (u2 > 0.0 && u2 <= 1.0))) {
358+
if(valid1 && valid2) {
359+
334360
into = (into == null) ? new RayIntersection() : into.reset();
335-
into.ray1 = ray1;
336-
into.ray2 = ray2;
337-
into.u1 = u1;
338-
into.u2 = u2;
361+
362+
into.ray1 = ray1;
363+
into.ray2 = ray2;
364+
into.u1 = u1;
365+
into.u2 = u2;
366+
339367
return into;
340-
}
368+
369+
} //both valid
341370

342371
return null;
343372

‎differ/shapes/Polygon.hx

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import differ.shapes.*;
55
import differ.data.*;
66
import differ.sat.*;
77

8-
/** A polygon collision shape */
8+
/** A polygonal collision shape */
99
class Polygon extends Shape {
1010

11-
1211
/** The transformed (rotated/scale) vertices cache */
1312
public var transformedVertices ( get, never ) : Array<Vector>;
1413
/** The vertices of this shape */

‎differ/shapes/Ray.hx

+22-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import differ.math.*;
44
import differ.shapes.*;
55
import differ.data.*;
66

7+
/** A ray with a start, end, direction
8+
and infinite state for collision queries. */
79
class Ray {
810

911
/** The start point of the ray. */
@@ -15,16 +17,16 @@ class Ray {
1517
Updates only when the dir value is accessed. */
1618
public var dir (get, never):Vector;
1719
/** Whether or not the ray is infinite. */
18-
public var infinite:Bool;
20+
public var infinite:InfiniteState;
1921

2022
/** Create a new ray with the start and end point,
2123
which determine the direction of the ray, and optionally specifying
22-
that this ray is an infinite one. */
23-
public function new(_start:Vector, _end:Vector, _infinite:Bool = true) {
24+
that this ray is infinite in some way. */
25+
public function new(_start:Vector, _end:Vector, ?_infinite:InfiniteState) {
2426

2527
start = _start;
2628
end = _end;
27-
infinite = _infinite;
29+
infinite = _infinite == null ? not_infinite : _infinite;
2830

2931
//internal
3032
dir_cache = new Vector(end.x - start.x, end.y - start.y);
@@ -40,4 +42,19 @@ class Ray {
4042
return dir_cache;
4143
}
4244

43-
}
45+
}
46+
47+
/** A flag for the infinite state of a Ray. */
48+
enum InfiniteState {
49+
50+
/** The line is a fixed length
51+
between the start and end points. */
52+
not_infinite;
53+
/** The line is infinite
54+
from it's starting point. */
55+
infinite_from_start;
56+
/** The line is infinite in both
57+
directions from it's starting point. */
58+
infinite;
59+
60+
} //InfiniteState

‎tests/usage0/assets/.keep

Whitespace-only changes.

‎tests/usage0/src/Main.hx

+37-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import luxe.Text;
55

66
import differ.shapes.Shape;
77
import differ.shapes.Ray;
8+
import differ.math.Util;
89
import phoenix.Batcher;
910

1011
class Main extends luxe.Game {
@@ -44,13 +45,13 @@ class Main extends luxe.Game {
4445
rays = [];
4546

4647
desc = new Text({
47-
pos: new Vector(10,10),
48+
pos: new Vector(10, 10),
4849
point_size: 18,
4950
text: 'differ usage examples, press 9 or 0 to cycle'
5051
});
5152

5253
disp = new Text({
53-
pos: new Vector(10, 30),
54+
pos: new Vector(10, 40),
5455
point_size: 15,
5556
text: 'usage text goes here'
5657
});
@@ -98,9 +99,42 @@ class Main extends luxe.Game {
9899

99100
} //onkeyup
100101

102+
inline static var big_number : Int = 0xFFFFFF;
103+
101104
override function onrender() {
102105
for(shape in shapes) drawer.drawShape(shape);
103-
for(ray in rays) drawer.drawLine(ray.start.x, ray.start.y, ray.end.x, ray.end.y);
106+
for(ray in rays) {
107+
var start_x = ray.start.x;
108+
var start_y = ray.start.y;
109+
var end_x = ray.end.x;
110+
var end_y = ray.end.y;
111+
112+
//get the direction of the ray
113+
var dir_x = end_x - start_x;
114+
var dir_y = end_y - start_y;
115+
//normalize it
116+
var len = Util.vec_length(dir_x, dir_y);
117+
dir_x = Util.vec_normalize(len, dir_x);
118+
dir_y = Util.vec_normalize(len, dir_y);
119+
//scale it way up
120+
dir_x *= big_number;
121+
dir_y *= big_number;
122+
123+
switch(ray.infinite) {
124+
case infinite:
125+
start_x -= dir_x;
126+
start_y -= dir_y;
127+
end_x += dir_x;
128+
end_y += dir_y;
129+
case infinite_from_start:
130+
end_x += dir_x;
131+
end_y += dir_y;
132+
case not_infinite:
133+
//do nothing, the line is fixed
134+
}
135+
136+
drawer.drawLine(start_x, start_y, end_x, end_y);
137+
}
104138
}
105139

106140
} //Main

‎tests/usage0/src/states/Polygons.hx

+6-3
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,18 @@ class Polygons extends luxe.States.State {
3535

3636

3737
moverA = Polygon.square(10, 100, 50);
38-
moverB = new Circle(10, 100, 30);
38+
moverB = new Circle(100, 100, 30);
3939
mover = moverA;
4040

4141
for(fix in fixed) Main.shapes.push(fix);
4242
Main.shapes.push(moverA);
4343
Main.shapes.push(moverB);
4444

45-
var text = '\nThe white polygon is the position the separation would result in.\n';
46-
text += 'Hold down left or right mouse to rotate the box.';
45+
var text = 'The white polygon is the position the separation would result in.\n';
46+
text += 'The dim polygon is the alternate position based on the unit normal.\n';
47+
text += 'Colored collisions is when there are multiple collisions.\n\n';
48+
text += 'Hold down left or right mouse to rotate the box.\n';
49+
text += 'Press M to toggle the shape on the mouse';
4750

4851
Main.display(text);
4952

‎tests/usage0/src/states/RayAndShape.hx

+50-14
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,24 @@ class RayAndShape extends luxe.States.State {
2020
var intersect:LineGeometry;
2121
var before:LineGeometry;
2222
var after:LineGeometry;
23+
var colors:Array<Color>;
2324

2425
override function onenter<T>(_:T) {
2526

26-
Main.display('pink = ray\ngreen = before hit\nwhite = intersection\npurple = after hit');
27+
Main.display('press space to toggle infinite state\npress 1 to move the beam start');
2728

28-
beam = new Ray( new V(450,300), new V(400,100), false );
29+
beam = new Ray( new V(420,300), new V(400,100), not_infinite );
2930

3031
Main.rays.push(beam);
3132
Main.shapes.push(new Circle(600,400,50));
3233
Main.shapes.push(new Circle(200,400,50));
33-
Main.shapes.push( Polygon.rectangle(600,200,50,50));
34-
Main.shapes.push( Polygon.rectangle(200,200,50,50));
34+
Main.shapes.push(Polygon.rectangle(600,200,50,50));
35+
Main.shapes.push(Polygon.rectangle(200,200,50,50));
36+
37+
colors = [
38+
new Color().rgb(0xffffff),
39+
new Color(1,1,1,0.5)
40+
];
3541

3642
intersect = Luxe.draw.line({ depth:100, batcher: Main.thicker, p0:new Vector(), p1:new Vector(), color:new Color().rgb(0xffffff) });
3743
before = Luxe.draw.line({ depth:100, batcher: Main.thicker, p0:new Vector(), p1:new Vector(), color:new Color().rgb(0x00f67b) });
@@ -54,15 +60,32 @@ class RayAndShape extends luxe.States.State {
5460

5561
override function onkeyup(e:KeyEvent) {
5662

63+
if(e.keycode == Key.key_1) {
64+
if(beam.start.y == 300) {
65+
beam.start.y = 200;
66+
} else if(beam.start.y == 200) {
67+
beam.start.y = 380;
68+
} else {
69+
beam.start.y = 300;
70+
}
71+
}
72+
5773
if(e.keycode == Key.space) {
58-
if(beam != null) beam.infinite = !beam.infinite;
74+
if(beam != null) {
75+
//cycle infinite mode
76+
beam.infinite = switch(beam.infinite) {
77+
case not_infinite: infinite_from_start;
78+
case infinite_from_start: infinite;
79+
case infinite: not_infinite;
80+
}
81+
}
5982
}
6083

6184
} //onkeyup
6285

6386
override function onmousemove( e:MouseEvent ) {
6487
if(beam != null) {
65-
if(beam.infinite) {
88+
if(beam.infinite == infinite || beam.infinite == infinite_from_start) { //:todo: check later if correct behaviour
6689
var end = new Vector(e.pos.x, e.pos.y);
6790
end.subtract_xyz(beam.start.x, beam.start.y);
6891
end.normalize();
@@ -98,14 +121,27 @@ class RayAndShape extends luxe.States.State {
98121
var hitendx = c.hitEndX();
99122
var hitendy = c.hitEndY();
100123

101-
intersect.p0 = new Vector(hitstartx, hitstarty);
102-
intersect.p1 = new Vector(hitendx, hitendy);
103-
104-
before.p0 = new Vector(c.ray.start.x, c.ray.start.y);
105-
before.p1 = new Vector(hitstartx, hitstarty);
106-
107-
after.p0 = new Vector(hitendx, hitendy);
108-
after.p1 = new Vector(c.ray.end.x, c.ray.end.y);
124+
Luxe.draw.ring({ immediate:true, x:hitstartx, y:hitstarty, r:4, color:colors[1] });
125+
Luxe.draw.ring({ immediate:true, x:hitendx, y:hitendy, r:4, color:colors[1] });
126+
127+
if(c.end >= 1.0) {
128+
Luxe.draw.line({
129+
p0: new Vector(hitstartx, hitstarty),
130+
p1: new Vector(c.ray.end.x, c.ray.end.y),
131+
color: colors[0],
132+
batcher: Main.thicker,
133+
immediate: true
134+
});
135+
} else {
136+
Luxe.draw.line({
137+
p0: new Vector(hitstartx, hitstarty),
138+
p1: new Vector(hitendx, hitendy),
139+
color: colors[0],
140+
batcher: Main.thicker,
141+
immediate: true
142+
});
143+
}
144+
109145

110146
Luxe.draw.text({
111147
point_size:13,

‎tests/usage0/src/states/Rays.hx

+52-15
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,18 @@ class Rays extends luxe.States.State {
2828
new Color().rgb(0xa0e300)
2929
];
3030

31-
Main.display('move the mouse around');
31+
var message = 'press F to flip start point\n';
32+
message += 'press 1 to toggle the beam infinite state\n';
33+
message += 'press 2 to toggle the other infinite states\n';
34+
message += 'press 3 to toggle the first infinite state\n';
3235

33-
beam = new Ray( new V(50,300), new V(600,400), false );
36+
Main.display(message);
37+
38+
beam = new Ray( new V(50,300), new V(600,400), not_infinite );
3439

3540
for(i in 0 ... colors.length) {
3641
var sx = (i+1) * 120;
37-
var ray = new Ray( new V(sx, 100), new V(sx, 500), false );
42+
var ray = new Ray( new V(sx, 100), new V(sx, 500), not_infinite );
3843
others.push(ray);
3944
Main.rays.push(ray);
4045
}
@@ -55,24 +60,56 @@ class Rays extends luxe.States.State {
5560

5661
override function onmousemove( e:MouseEvent ) {
5762
if(beam != null) {
58-
if(beam.infinite) {
59-
var end = new Vector(e.pos.x, e.pos.y);
60-
end.subtract_xyz(beam.start.x, beam.start.y);
61-
end.normalize();
62-
end.multiplyScalar(9999);
63-
beam.end.x = end.x;
64-
beam.end.y = end.y;
65-
} else {
66-
beam.end.x = e.pos.x;
67-
beam.end.y = e.pos.y;
63+
beam.end.x = e.pos.x;
64+
beam.end.y = e.pos.y;
65+
}
66+
}
67+
68+
function print_infinite(label:String, ray:Ray) {
69+
switch(ray.infinite) {
70+
case not_infinite:
71+
trace('`$label` infinite: nope');
72+
case infinite_from_start:
73+
trace('`$label` infinite: from start');
74+
case infinite:
75+
trace('`$label` infinite: in both directions');
76+
}
77+
}
78+
79+
function toggle_infinite(ray:Ray) {
80+
if(ray != null) {
81+
ray.infinite = switch(ray.infinite) {
82+
case not_infinite:
83+
infinite_from_start;
84+
case infinite_from_start:
85+
infinite;
86+
case infinite:
87+
not_infinite;
6888
}
6989
}
7090
}
7191

7292
override function onkeyup(e:KeyEvent) {
7393

74-
if(e.keycode == Key.space) {
75-
if(beam != null) beam.infinite = !beam.infinite;
94+
if(e.keycode == Key.key_1) {
95+
toggle_infinite(beam);
96+
print_infinite('beam', beam);
97+
}
98+
99+
if(e.keycode == Key.key_2) {
100+
var first = true;
101+
for(o in others) {
102+
toggle_infinite(o);
103+
if(first) {
104+
print_infinite('others', others[0]);
105+
first = false;
106+
}
107+
}
108+
}
109+
110+
if(e.keycode == Key.key_3) {
111+
toggle_infinite(others[0]);
112+
print_infinite('others', others[0]);
76113
}
77114

78115
if(e.keycode == Key.key_f) {

0 commit comments

Comments
 (0)
Please sign in to comment.