-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCollisionLibrary.pde
More file actions
198 lines (155 loc) · 5.61 KB
/
CollisionLibrary.pde
File metadata and controls
198 lines (155 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/////////
// Point Intersection Tests
/////////
//Returns true if the point is inside a box
boolean pointInBox(Vec2 boxTopLeft, float boxW, float boxH, Vec2 pointPos){
Vec2 diff = pointPos.minus(boxTopLeft);
if (diff.x > 0 && diff.x < boxW && diff.y > 0 && diff.y < boxH) return true;
return false;
}
//Returns true if the point is inside a circle
boolean pointInCircle(Vec2 center, float r, Vec2 pointPos){
float dist = pointPos.distanceTo(center);
if (dist < r+2){ //small safty factor
return true;
}
return false;
}
//Returns true if the point is inside a list of circle
boolean pointInCircleList(Vec2[] centers, float[] radii, int numObstacles, Vec2 pointPos){
for (int i = 0; i < numObstacles; i++){
Vec2 center = centers[i];
float r = radii[i];
if (pointInCircle(center,r,pointPos)){
return true;
}
}
return false;
}
/////////
// Ray Circle Intersection Tests
/////////
//Returns true if the agent is inside a circle
boolean collisionWithCircle(Vec2 center, float r, Vec2 pointPos, float pointRad){
float dist = pointPos.distanceTo(center);
if (dist < r+pointRad){ //small safty factor
return true;
}
return false;
}
//Returns true if the agent is inside a list of circle
void collisionInCircleList(Vec2[] centers, float[] radii, int numObstacles, Vec2 pointPos, float pointRad){
for (int i = 0; i < numObstacles; i++){
Vec2 center = centers[i];
float r = radii[i];
Vec2 collisionNormal = (agentPos.minus(center)).normalized();
if (collisionWithCircle(center,r,pointPos,pointRad)){
agentPos = center.plus(collisionNormal.times(r + pointRad).times(1.01));
}
if (collisionWithCircle(center,r+10,pointPos,pointRad+10)) {
agentVel = center.plus(collisionNormal.times(r + pointRad + 20).times(3));
}
}
}
/////////
// Ray Intersection Tests
/////////
class hitInfo{
public boolean hit = false;
public float t = 9999999;
}
hitInfo rayBoxIntersect(Vec2 boxTopLeft, float boxW, float boxH, Vec2 ray_start, Vec2 ray_dir, float max_t){
hitInfo hit = new hitInfo();
hit.hit = true;
float t_left_x, t_right_x, t_top_y, t_bot_y;
t_left_x = (boxTopLeft.x - ray_start.x)/ray_dir.x;
t_right_x = (boxTopLeft.x + boxW - ray_start.x)/ray_dir.x;
t_top_y = (boxTopLeft.y - ray_start.y)/ray_dir.y;
t_bot_y = (boxTopLeft.y + boxH - ray_start.y)/ray_dir.y;
float t_max_x = max(t_left_x,t_right_x);
float t_max_y = max(t_top_y,t_bot_y);
float t_max = min(t_max_x,t_max_y); //When the ray exists the box
float t_min_x = min(t_left_x,t_right_x);
float t_min_y = min(t_top_y,t_bot_y);
float t_min = max(t_min_x,t_min_y); //When the ray enters the box
//The the box is behind the ray (negative t)
if (t_max < 0){
hit.hit = false;
hit.t = t_max;
return hit;
}
//The ray never hits the box
if (t_min > t_max){
hit.hit = false;
}
//The ray hits, but further out than max_t
if (t_min > max_t){
hit.hit = false; }
hit.t = t_min;
return hit;
}
hitInfo rayCircleIntersect(Vec2 center, float r, Vec2 l_start, Vec2 l_dir, float max_t){
hitInfo hit = new hitInfo();
//Step 2: Compute W - a displacement vector pointing from the start of the line segment to the center of the circle
Vec2 toCircle = center.minus(l_start);
//Step 3: Solve quadratic equation for intersection point (in terms of l_dir and toCircle)
float a = 1; //Length of l_dir (we normalized it)
float b = -2*dot(l_dir,toCircle); //-2*dot(l_dir,toCircle)
float c = toCircle.lengthSqr() - (r*r); //different of squared distances
float d = b*b - 4*a*c; //discriminant
if (d >=0 ){
//If d is positive we know the line is colliding, but we need to check if the collision line within the line segment
// ... this means t will be between 0 and the length of the line segment
float t1 = (-b - sqrt(d))/(2*a); //Optimization: we only need the first collision
float t2 = (-b + sqrt(d))/(2*a); //Optimization: we only need the first collision
//println(hit.t,t1,t2);
if (t1 > 0 && t1 < max_t){
hit.hit = true;
hit.t = t1;
}
else if (t1 < 0 && t2 > 0){
hit.hit = true;
hit.t = -1;
}
}
return hit;
}
hitInfo rayCircleListIntersect(Vec2[] centers, float[] radii, int numObstacles, Vec2 l_start, Vec2 l_dir, float max_t){
hitInfo hit = new hitInfo();
hit.t = max_t;
for (int i = 0; i < numObstacles; i++){
Vec2 center = centers[i];
float r = radii[i];
hitInfo circleHit = rayCircleIntersect(center, r, l_start, l_dir, hit.t);
if (circleHit.t > 0 && circleHit.t < hit.t){
hit.hit = true;
hit.t = circleHit.t;
}
else if (circleHit.hit && circleHit.t < 0){
hit.hit = true;
hit.t = -1;
}
}
return hit;
}
boolean rayCircleIntersectBool(Vec2 center, float r, Vec2 l_start, Vec2 l_dir, float max_t){
//Compute displacement vector pointing from the start of the line segment to the center of the circle
Vec2 toCircle = center.minus(l_start);
//Solve quadratic equation for intersection point (in terms of l_dir and toCircle)
float a = 1; //Length of l_dir (we normalized it)
float b = -2*dot(l_dir,toCircle); //-2*dot(l_dir,toCircle)
float c = toCircle.lengthSqr() - (r*r); //different of squared distances
float d = b*b - 4*a*c; //discriminant
if (d >=0 ){
float t1 = (-b - sqrt(d))/(2*a);
float t2 = (-b + sqrt(d))/(2*a);
//println(hit.t,t1,t2);
if (t1 > 0 && t1 < max_t){ //We intersect the circle
return true;
}
else if (t1 < 0 && t2 > 0){ //We start in the circle
return true;
}
}
return false;
}