Mercurial > projects > openmelee
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 |