comparison ai/steer.d @ 19:08ddf9e71b88

steer to avoid
author zzzzrrr <mason.green@gmail.com>
date Wed, 25 Mar 2009 14:44:47 -0400
parents 7f74e064dad5
children 6efd0830715b
comparison
equal deleted inserted replaced
18:7f74e064dad5 19:08ddf9e71b88
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 module openmelee.ai.steer; 33 module openmelee.ai.steer;
34 34
35 import tango.io.Stdout : Stdout;
36
35 import blaze.common.bzMath: bzDot, bzClamp, bzVec2; 37 import blaze.common.bzMath: bzDot, bzClamp, bzVec2;
38 import blaze.collision.shapes.bzShape : bzShape;
39 import tango.math.Math : sqrt;
36 import blaze.dynamics.bzBody: bzBody; 40 import blaze.dynamics.bzBody: bzBody;
37 41
38 import openmelee.ships.ship : Ship, State; 42 import openmelee.ships.ship : Ship, State;
39 import openmelee.ai.utilities; 43 import openmelee.ai.utilities;
40 44
42 { 46 {
43 // Constructor: initializes state 47 // Constructor: initializes state
44 this (Ship ship) 48 this (Ship ship)
45 { 49 {
46 m_ship = ship; 50 m_ship = ship;
51 m_body = ship.rBody;
52 m_radius = 0.0f;
53
54 // Find radius of body
55 for (bzShape s = m_body.shapeList; s; s = s.next) {
56 if(s.sweepRadius > m_radius) {
57 m_radius = s.sweepRadius;
58 }
59 }
47 } 60 }
48 61
49 struct PathIntersection 62 struct PathIntersection
50 { 63 {
51 bool intersect; 64 bool intersect;
133 bzVec2 steerToAvoidObstacles (float minTimeToCollision, bzBody obstacles) { 146 bzVec2 steerToAvoidObstacles (float minTimeToCollision, bzBody obstacles) {
134 147
135 bzVec2 avoidance; 148 bzVec2 avoidance;
136 PathIntersection nearest, next; 149 PathIntersection nearest, next;
137 float minDistanceToCollision = minTimeToCollision * m_speed; 150 float minDistanceToCollision = minTimeToCollision * m_speed;
138 151
139 next.intersect = false; 152 next.intersect = false;
140 nearest.intersect = false; 153 nearest.intersect = false;
141 154
142 // test all obstacles for intersection with my forward axis, 155 // test all obstacles for intersection with my forward axis,
143 // select the one whose point of intersection is nearest 156 // select the one whose point of intersection is nearest
144 for (bzBody o; o; o = o.next) { 157 for (bzBody o = obstacles; o; o = o.next) {
158
159 if(o is m_body) continue;
160
145 // This code which presumes the obstacle is spherical 161 // This code which presumes the obstacle is spherical
146 //findNextIntersectionWithSphere (o, next); 162 findNextIntersectionWithSphere(o, next);
147 163
148 if (!nearest.intersect || (next.intersect && next.distance < nearest.distance)) { 164 if (!nearest.intersect || (next.intersect && next.distance < nearest.distance)) {
149 nearest = next; 165 nearest = next;
150 } 166 }
151 } 167 }
152 168
153 // when a nearest intersection was found 169 // when a nearest intersection was found
154 if (nearest.intersect && (nearest.distance < minDistanceToCollision)) { 170 if (nearest.intersect && (nearest.distance < minDistanceToCollision)) {
171 Stdout("Distance: ")(nearest.distance).newline;
155 // compute avoidance steering force: take offset from obstacle to me, 172 // compute avoidance steering force: take offset from obstacle to me,
156 // take the component of that which is lateral (perpendicular to my 173 // take the component of that which is lateral (perpendicular to my
157 // forward direction), set length to maxForce, add a bit of forward 174 // forward direction), set length to maxForce, add a bit of forward
158 // component (in capture the flag, we never want to slow down) 175 // component (in capture the flag, we never want to slow down)
159 bzVec2 offset = m_position - nearest.obstacle.position; 176 bzVec2 offset = m_position - nearest.obstacle.position;
160 //avoidance = Vector3Helpers.PerpendicularComponent(offset, this.Forward); 177 avoidance = perpendicularComponent(offset, m_forward);
161 avoidance.normalize; 178 avoidance.normalize;
162 avoidance *= m_maxForce; 179 //avoidance *= m_maxForce;
163 avoidance += m_forward * m_maxForce * 0.75f; 180 //avoidance += m_forward * m_maxForce * 0.75f;
164 } 181 }
165 182
166 return avoidance; 183 return avoidance;
167 } 184 }
185
186 void findNextIntersectionWithSphere(bzBody obs,
187 inout PathIntersection intersection) {
188
189 // This routine is based on the Paul Bourke's derivation in:
190 // Intersection of a Line and a Sphere (or circle)
191 // http://www.swin.edu.au/astronomy/pbourke/geometry/sphereline/
192
193 float b, c, d, p, q, s;
194 bzVec2 lc;
195
196 // initialize pathIntersection object
197 intersection.intersect = false;
198 intersection.obstacle = obs;
199
200 // find "local center" (lc) of sphere in boid's coordinate space
201 lc = m_body.localPoint(obs.position);
202
203 // computer line-sphere intersection parameters
204 b = 0;
205
206 // Find radius of obstacle
207 float obsRadius = 0;
208 for (bzShape shape = obs.shapeList; shape; shape = shape.next) {
209 if(shape.sweepRadius > obsRadius) {
210 obsRadius = shape.sweepRadius;
211 }
212 }
213
214 c = square(lc.x) + square(lc.y) - square(obsRadius + m_radius);
215 d = (b * b) - (4 * c);
216
217 // when the path does not intersect the sphere
218 if (d < 0) return;
219
220 // otherwise, the path intersects the sphere in two points with
221 // parametric coordinates of "p" and "q".
222 // (If "d" is zero the two points are coincident, the path is tangent)
223 s = sqrt(d);
224 p = (-b + s) * 0.5f;
225 q = (-b - s) * 0.5f;
226
227 // both intersections are behind us, so no potential collisions
228 if ((p < 0) && (q < 0)) return;
229
230 // at least one intersection is in front of us
231 intersection.intersect = true;
232 intersection.distance =
233 ((p > 0) && (q > 0)) ?
234 // both intersections are in front of us, find nearest one
235 ((p < q) ? p : q) :
236 // otherwise only one intersections is in front, select it
237 ((p > 0) ? p : q);
238 }
168 239
169 /* 240 /*
170 // ------------------------------------------------------------------------ 241 // ------------------------------------------------------------------------
171 // Unaligned collision avoidance behavior: avoid colliding with other 242 // Unaligned collision avoidance behavior: avoid colliding with other
172 // nearby vehicles moving in unconstrained directions. Determine which 243 // nearby vehicles moving in unconstrained directions. Determine which
461 bzVec2 m_position; 532 bzVec2 m_position;
462 bzVec2 m_velocity; 533 bzVec2 m_velocity;
463 bzVec2 m_up; 534 bzVec2 m_up;
464 bzVec2 m_side; 535 bzVec2 m_side;
465 bzVec2 m_forward; 536 bzVec2 m_forward;
537 float m_radius;
538 bzBody m_body;
466 539
467 float m_speed = 0; 540 float m_speed = 0;
468 float m_maxForce = 0; 541 float m_maxForce = 0;
469 542
470 // Wander behavior 543 // Wander behavior