// ---------------------------------------------------------------------------- // avoidance of "close neighbors" -- used only by steerToAvoidNeighbors // // XXX Does a hard steer away from any other agent who comes withing a // XXX critical distance. Ideally this should be replaced with a call // XXX to steerForSeparation. public Vector3 steerToAvoidCloseNeighbors(float minSeparationDistance, ArrayList others) { // for each of the other vehicles... //for (AVIterator i = others.begin(); i != others.end(); i++) for (int i = 0; i < others.Count; i++) { AbstractVehicle other = (AbstractVehicle)others[i]; if (other != this) { float sumOfRadii = radius() + other.radius(); float minCenterToCenter = minSeparationDistance + sumOfRadii; Vector3 offset = other.Position - Position; float currentDistance = offset.Length; if (currentDistance < minCenterToCenter) { annotateAvoidCloseNeighbor(other, minSeparationDistance); return(OpenSteerUtility.perpendicularComponent(-offset, forward())); } } } // otherwise return zero return(Vector3.Zero); }
// this version avoids all of the obstacles in an ObstacleGroup // // XXX 9-12-03: note this does NOT use the Obstacle::steerToAvoid protocol // XXX like the older steerToAvoidObstacle does/did. It needs to be fixed public Vector3 steerToAvoidObstacles(float minTimeToCollision, ArrayList obstacles) { Vector3 avoidance = new Vector3(); PathIntersection nearest, next; nearest = new PathIntersection(); next = new PathIntersection(); float minDistanceToCollision = minTimeToCollision * speed(); next.intersect = 0; // false; nearest.intersect = 0; // false; // test all obstacles for intersection with my forward axis, // select the one whose point of intersection is nearest //for (ObstacleIterator o = obstacles.begin(); o != obstacles.end(); o++) for (int i = 0; i < obstacles.Count; i++) { SphericalObstacle o = (SphericalObstacle)obstacles[i]; // xxx this should be a generic call on Obstacle, rather than // xxx this code which presumes the obstacle is spherical findNextIntersectionWithSphere(o, next); if ((nearest.intersect == 0) || ((next.intersect != 0) && (next.distance < nearest.distance))) { nearest = next; } } // when a nearest intersection was found if ((nearest.intersect != 0) && (nearest.distance < minDistanceToCollision)) { // show the corridor that was checked for collisions annotateAvoidObstacle(minDistanceToCollision); // compute avoidance steering force: take offset from obstacle to me, // take the component of that which is lateral (perpendicular to my // forward direction), set length to maxForce, add a bit of forward // component (in capture the flag, we never want to slow down) Vector3 offset = Position - nearest.obstacle.center; //avoidance = offset.perpendicularComponent (forward()); avoidance = OpenSteerUtility.perpendicularComponent(offset, forward()); avoidance.Normalize();//.normalize (); avoidance *= maxForce(); avoidance += forward() * maxForce() * 0.75f; } return(avoidance); }
// ---------------------------------------------------------------------------- // measure path curvature (1/turning-radius), maintain smoothed version void measurePathCurvature(float elapsedTime) { if (elapsedTime > 0) { Vector3 dP = _lastPosition - Position; Vector3 dF = (_lastForward - forward()) / dP.Length; //SI - BIT OF A WEIRD FIX HERE . NOT SURE IF ITS CORRECT //Vector3 lateral = dF.perpendicularComponent (forward ()); Vector3 lateral = OpenSteerUtility.perpendicularComponent(dF, forward()); float sign = (lateral.DotProduct(side()) < 0) ? 1.0f : -1.0f; _curvature = lateral.Length * sign; //OpenSteerUtility.blendIntoAccumulator(elapsedTime * 4.0f, _curvature,_smoothedCurvature); _smoothedCurvature = OpenSteerUtility.blendIntoAccumulator(elapsedTime * 4.0f, _curvature, _smoothedCurvature); _lastForward = forward(); _lastPosition = Position; } }