Example #1
0
    /// <summary>
    /// Calculates the force necessary to avoid the closest spherical obstacle
    /// </summary>
    /// <returns>
    /// Force necessary to avoid an obstacle, or Vector3.zero
    /// </returns>
    /// <remarks>
    /// This method will iterate through all detected spherical obstacles that
    /// are within MinTimeToCollision, and steer to avoid the closest one to the
    /// vehicle.  It's not ideal, as that means the vehicle might crash into
    /// another obstacle while avoiding the closest one, but it'll do.
    /// </remarks>
    protected override Vector3 CalculateForce()
    {
        Vector3 avoidance = Vector3.zero;

        if (Vehicle.Radar.Obstacles == null || Vehicle.Radar.Obstacles.Count == 0)
        {
            return(avoidance);
        }

        PathIntersection nearest = new PathIntersection(null);

        /*
         * While we could just calculate line as (Velocity * predictionTime)
         * and save ourselves the substraction, this allows other vehicles to
         * override PredictFuturePosition for their own ends.
         */
        Vector3 futurePosition = Vehicle.PredictFuturePosition(_minTimeToCollision);
        Vector3 line           = (futurePosition - Vehicle.Position);

        // test all obstacles for intersection with my forward axis,
        // select the one whose point of intersection is nearest
        Profiler.BeginSample("Find nearest intersection");
        foreach (var o in Vehicle.Radar.Obstacles)
        {
            SphericalObstacle sphere = o as SphericalObstacle;
            PathIntersection  next   = FindNextIntersectionWithSphere(sphere, line);
            if (!nearest.intersect ||
                (next.intersect &&
                 next.distance < nearest.distance))
            {
                nearest = next;
            }
        }
        Profiler.EndSample();


        // when a nearest intersection was found
        Profiler.BeginSample("Calculate avoidance");
        if (nearest.intersect &&
            nearest.distance < line.magnitude)
        {
                        #if ANNOTATE_AVOIDOBSTACLES
            Debug.DrawLine(Vehicle.Position, nearest.obstacle.center, Color.red);
                        #endif

            // 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 = Vehicle.Position - nearest.obstacle.center;
            avoidance = OpenSteerUtility.perpendicularComponent(offset, transform.forward);

            avoidance.Normalize();
            avoidance *= Vehicle.MaxForce;
            avoidance += transform.forward * Vehicle.MaxForce * _avoidanceForceFactor;
        }
        Profiler.EndSample();

        return(avoidance);
    }
Example #2
0
    /// <summary>
    /// Checks for sphere collision.
    /// </summary>
    /// <param name="obstacle">The obstacle.</param>
    /// <param name="tolerance">The tolerance.</param>
    /// <returns>
    ///   <c>true</c> if it collides, <c>false</c> otherwise.
    /// </returns>
    public bool CollidesWith(SphericalObstacle obstacle, double tolerance = 0.0d)
    {
        Vector3 difference = Center - obstacle.Center;
        double  distance   =
            System.Math.Sqrt(System.Math.Pow(difference.X, 2) + System.Math.Pow(difference.Y, 2) + System.Math.Pow(difference.Z, 2));
        double sumRadius = Radius + obstacle.Radius;

        return(distance < (sumRadius + tolerance));
    }
Example #3
0
 private void OnDrawGizmos()
 {
     if (base.Vehicle != null)
     {
         using (IEnumerator <Obstacle> enumerator = base.Vehicle.Radar.Obstacles.GetEnumerator())
         {
             while (enumerator.MoveNext())
             {
                 Obstacle          current           = enumerator.get_Current();
                 SphericalObstacle sphericalObstacle = current as SphericalObstacle;
                 Gizmos.set_color(Color.get_red());
                 Gizmos.DrawWireSphere(sphericalObstacle.center, sphericalObstacle.radius);
             }
         }
     }
 }
Example #4
0
    protected override Vector3 CalculateForce()
    {
        Vector3 vector = Vector3.get_zero();

        if (base.Vehicle.Radar.Obstacles == null || base.Vehicle.Radar.Obstacles.Count == 0)
        {
            return(vector);
        }
        SteerForSphericalObstacleAvoidance.PathIntersection pathIntersection = new SteerForSphericalObstacleAvoidance.PathIntersection(null);
        Vector3 vector2 = base.Vehicle.PredictFuturePosition(this._minTimeToCollision);
        Vector3 line    = vector2 - base.Vehicle.Position;

        using (IEnumerator <Obstacle> enumerator = base.Vehicle.Radar.Obstacles.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                Obstacle          current = enumerator.get_Current();
                SphericalObstacle obs     = current as SphericalObstacle;
                SteerForSphericalObstacleAvoidance.PathIntersection pathIntersection2 = this.FindNextIntersectionWithSphere(obs, line);
                if (!pathIntersection.intersect || (pathIntersection2.intersect && pathIntersection2.distance < pathIntersection.distance))
                {
                    pathIntersection = pathIntersection2;
                }
            }
        }
        if (pathIntersection.intersect && pathIntersection.distance < line.get_magnitude())
        {
            Debug.DrawLine(base.Vehicle.Position, pathIntersection.obstacle.center, Color.get_red());
            Vector3 source = base.Vehicle.Position - pathIntersection.obstacle.center;
            vector = OpenSteerUtility.perpendicularComponent(source, base.get_transform().get_forward());
            vector.Normalize();
            vector *= base.Vehicle.MaxForce;
            vector += base.get_transform().get_forward() * base.Vehicle.MaxForce * this._avoidanceForceFactor;
        }
        return(vector);
    }
        /// <summary>
        /// Load content for the screen.
        /// </summary>
        /// <param name="GraphicInfo"></param>
        /// <param name="factory"></param>
        /// <param name="contentManager"></param>
        protected override void LoadContent(GraphicInfo GraphicInfo, GraphicFactory factory, IContentManager contentManager)
        {
            base.LoadContent(GraphicInfo, factory, contentManager);

            RegisterDebugDrawCommand rc = new RegisterDebugDrawCommand(ddrawer);

            CommandProcessor.getCommandProcessor().SendCommandAssyncronous(rc);

            path.AddCircularObstacle(Vector3.Zero, 10);

            path.AddCircularObstacle(new Vector3(0, 20, 0), 15);

            path.AddCircularObstacle(new Vector3(200), 10);

            foreach (var item in path.Obstacles)
            {
                SphericalObstacle SphericalObstacle = item as SphericalObstacle;
                DebugSphere       s = new DebugSphere(SphericalObstacle.Center, SphericalObstacle.Radius, Color.Blue);
                ddrawer.AddShape(s);
            }
            //DebugSphere.WireFrameEnabled = true;

            DebugLines dls = new DebugLines();

            ddrawer.AddShape(dls);
            for (int i = 0; i < path.PolyPath.pointCount - 1; i++)
            {
                dls.AddLine(path.PolyPath.points[i], path.PolyPath.points[i] + Vector3.Up * 200, Color.Brown);
                dls.AddLine(path.PolyPath.points[i], path.PolyPath.points[i + 1], Color.Red);
            }
            dls.AddLine(path.PolyPath.points[path.PolyPath.pointCount - 1], path.PolyPath.points[path.PolyPath.pointCount - 1] + Vector3.Up * 200, Color.Brown);

            PlugIn = new PedestrianPlugIn(this.World, path,
                                          (pd) =>
            {
                SimpleModel simpleModel = new SimpleModel(factory, "Model//block");
                simpleModel.SetTexture(factory.CreateTexture2DColor(1, 1, Color.Green), TextureType.DIFFUSE);
                ///Physic info (position, rotation and scale are set here)
                GhostObject tmesh = new GhostObject();
                ///Forward Shader (look at this shader construction for more info)
                ForwardXNABasicShader shader = new ForwardXNABasicShader();
                ///Deferred material
                ForwardMaterial fmaterial = new ForwardMaterial(shader);
                ///The object itself
                IObject obj = new IObject(fmaterial, simpleModel, tmesh);
                obj.IObjectAttachment.Add(new SteerAtachment(pd));
                return(obj);
            });

            PlugIn.Init();

            {
                SimpleModel simpleModel = new SimpleModel(factory, "Model//block");
                simpleModel.SetTexture(factory.CreateTexture2DColor(1, 1, Color.White), TextureType.DIFFUSE);
                ///Physic info (position, rotation and scale are set here)
                BoxObject tmesh = new BoxObject(Vector3.Zero, 1, 1, 1, 10, new Vector3(1000, 1, 1000), Matrix.Identity, MaterialDescription.DefaultBepuMaterial());
                tmesh.isMotionLess = true;
                ///Forward Shader (look at this shader construction for more info)
                ForwardXNABasicShader shader = new ForwardXNABasicShader();
                ///Deferred material
                ForwardMaterial fmaterial = new ForwardMaterial(shader);
                ///The object itself
                this.World.AddObject(new IObject(fmaterial, simpleModel, tmesh));
            }

            ///add a camera
            this.World.CameraManager.AddCamera(new CameraFirstPerson(GraphicInfo));
        }
Example #6
0
    public SteerForSphericalObstacleAvoidance.PathIntersection FindNextIntersectionWithSphere(SphericalObstacle obs, Vector3 line)
    {
        Vector3 vector = base.Vehicle.Position - obs.center;

        SteerForSphericalObstacleAvoidance.PathIntersection result = new SteerForSphericalObstacleAvoidance.PathIntersection(obs);
        obs.annotatePosition();
        Debug.DrawLine(base.Vehicle.Position, base.Vehicle.Position + line, Color.get_cyan());
        float sqrMagnitude = line.get_sqrMagnitude();
        float num          = 2f * Vector3.Dot(line, vector);
        float num2         = obs.center.get_sqrMagnitude();

        num2 += base.Vehicle.Position.get_sqrMagnitude();
        num2 -= 2f * Vector3.Dot(obs.center, base.Vehicle.Position);
        num2 -= Mathf.Pow(obs.radius + base.Vehicle.ScaledRadius, 2f);
        float num3 = num * num - 4f * sqrMagnitude * num2;

        if (num3 >= 0f)
        {
            result.intersect = true;
            Vector3 vector2 = Vector3.get_zero();
            if (num3 == 0f)
            {
                float num4 = -num / (2f * sqrMagnitude);
                vector2 = num4 * line;
            }
            else
            {
                float num5 = (-num + Mathf.Sqrt(num3)) / (2f * sqrMagnitude);
                float num6 = (-num - Mathf.Sqrt(num3)) / (2f * sqrMagnitude);
                if (num5 < 0f && num6 < 0f)
                {
                    result.intersect = false;
                }
                else
                {
                    vector2 = ((Mathf.Abs(num5) >= Mathf.Abs(num6)) ? (num6 * line) : (num5 * line));
                }
            }
            Debug.DrawRay(base.Vehicle.Position, vector2, Color.get_red());
            result.distance = vector2.get_magnitude();
        }
        return(result);
    }
Example #7
0
 public PathIntersection(SphericalObstacle obstacle)
 {
     this.obstacle  = obstacle;
     this.intersect = false;
     this.distance  = 3.40282347E+38f;
 }
Example #8
0
 public PathIntersection(SphericalObstacle obstacle)
 {
     this.obstacle = obstacle;
     intersect     = false;
     distance      = float.MaxValue;
 }
Example #9
0
    /// <summary>
    /// Finds the vehicle's next intersection with a spherical obstacle
    /// </summary>
    /// <param name="obs">
    /// A spherical obstacle to check against <see cref="SphericalObstacle"/>
    /// </param>
    /// <param name="line">
    /// Line that we expect we'll follow to our future destination
    /// </param>
    /// <returns>
    /// A PathIntersection with the intersection details <see cref="PathIntersection"/>
    /// </returns>
    public PathIntersection FindNextIntersectionWithSphere(SphericalObstacle obs, Vector3 line)
    {
        /*
         * This routine is based on the Paul Bourke's derivation in:
         *   Intersection of a Line and a Sphere (or circle)
         *   http://www.swin.edu.au/astronomy/pbourke/geometry/sphereline/
         *
         * Retaining the same variable values used in that description.
         *
         */
        float a, b, c, bb4ac;
        var   toCenter = Vehicle.Position - obs.center;

        // initialize pathIntersection object
        var intersection = new PathIntersection(obs);

                #if ANNOTATE_AVOIDOBSTACLES
        obs.annotatePosition();
        Debug.DrawLine(Vehicle.Position, Vehicle.Position + line, Color.cyan);
                #endif

        // computer line-sphere intersection parameters
        a     = line.sqrMagnitude;
        b     = 2 * Vector3.Dot(line, toCenter);
        c     = obs.center.sqrMagnitude;
        c    += Vehicle.Position.sqrMagnitude;
        c    -= 2 * Vector3.Dot(obs.center, Vehicle.Position);
        c    -= Mathf.Pow(obs.radius + Vehicle.ScaledRadius, 2);
        bb4ac = b * b - 4 * a * c;

        if (bb4ac >= 0)
        {
            intersection.intersect = true;
            Vector3 closest = Vector3.zero;
            if (bb4ac == 0)
            {
                // Only one intersection
                var mu = -b / (2 * a);
                closest = mu * line;
            }
            else
            {
                // More than one intersection
                var mu1 = (-b + Mathf.Sqrt(bb4ac)) / (2 * a);
                var mu2 = (-b - Mathf.Sqrt(bb4ac)) / (2 * a);

                /*
                 * If the results are negative, the obstacle is behind us.
                 *
                 * If one result is negative and the other one positive,
                 * that would indicate that one intersection is behind us while
                 * the other one ahead of us, which would mean that we're
                 * just overlapping the obstacle, so we should still avoid.
                 */
                if (mu1 < 0 && mu2 < 0)
                {
                    intersection.intersect = false;
                }
                else
                {
                    closest = (Mathf.Abs(mu1) < Mathf.Abs(mu2)) ? mu1 * line : mu2 * line;
                }
            }
                        #if ANNOTATE_AVOIDOBSTACLES
            Debug.DrawRay(Vehicle.Position, closest, Color.red);
                        #endif

            intersection.distance = closest.magnitude;
        }
        return(intersection);
    }