public override bool PlanTimeToTarget(Projectile3D projectile3D,
                                          Vector3 initialPosition,
                                          Vector3 targetPosition,
                                          ref float timeToTarget)
    {
        if (timeToTarget > 0) return false;

        PrincipalProjectile principalProjectile;
        PrincipalSpace3D principalSpace3D = PrincipalSpace3D.Create(projectile3D,
            initialPosition, targetPosition, out principalProjectile);

        Vector2 principalTargetPosition = principalSpace3D.ToPrincipalPosition(targetPosition);

        float slope = principalSpace3D.ToPrincipalSlope(targetSlope);

        if (!float.IsNaN(slope))
        {
            float newTimeToTarget = PrincipalTimePlanners.GetTimeToTargetRGivenTargetSlopeA(
                principalProjectile, principalTargetPosition, slope);

            if (newTimeToTarget > 0)
            {
                timeToTarget = newTimeToTarget;
                return true;
            }
        }

        return false;
    }
    public override bool PlanTimeToTarget(Projectile3D projectile3D,
                                          Vector3 initialPosition,
                                          Vector3 targetPosition,
                                          ref float timeToTarget)
    {
        // Don't override the timeToTarget if there's already another valid plan.
        if (timeToTarget > 0) return false;

        PrincipalProjectile principalProjectile;
        PrincipalSpace3D principalSpace3D = PrincipalSpace3D.Create(projectile3D,
            initialPosition, targetPosition, out principalProjectile);

        Vector2 principalTargetPosition = principalSpace3D.ToPrincipalPosition(targetPosition);

        float newTimeToTarget = PrincipalTimePlanners.GetTimeToTargetRGivenInitialSpeedS(
            principalProjectile, principalTargetPosition, initialSpeed, highArc);

        if (newTimeToTarget > 0)
        {
            timeToTarget = newTimeToTarget;

            return true;
        }

        return false;
    }
    public override bool PlanTimeToTarget(Projectile3D projectile3D,
                                          Vector3 initialPosition,
                                          Vector3 targetPosition,
                                          ref float timeToTarget)
    {
        // Allow this planner to only modify an already existing plan, not create a new one.
        if (timeToTarget <= 0) return false;

        // Convert the problem to principal space
        PrincipalProjectile principalProjectile;
        PrincipalSpace3D principalSpace3D = PrincipalSpace3D.Create(projectile3D,
            initialPosition, targetPosition, out principalProjectile);

        Vector2 principalTargetPosition = principalSpace3D.ToPrincipalPosition(targetPosition);

        PrincipalTrajectory principalTrajectory = new PrincipalTrajectory(principalProjectile);
        principalTrajectory.v0 = principalTrajectory.GetInitialVelocityGivenRelativeTargetAndTime(
                principalTargetPosition, timeToTarget);

        // notify helper classes/structs of the trajectory to test
        _trajectoryOverGameObjectHelper.SetupTrajectory(principalSpace3D, principalTrajectory, principalTargetPosition, marginDistance);

        // (Re-)check all the gameobjects until no further intersections are detected, or until
        // an intersecting gameobject is found that can't have a trajectory passing over it.
        int lastIntersectingGameObjectIndex = -1;
        //bool foundAnotherIntersection;
        //do
        {
            //foundAnotherIntersection = false;

            for (int index = 0; index < obstacles.Length; ++index)
            {
                if (index != lastIntersectingGameObjectIndex)
                {
                    float foundTimeToTarget = _trajectoryOverGameObjectHelper.GetTimeToTargetOverGameObject(obstacles[index]);
                    if (foundTimeToTarget >= 0) // found intersection
                    {
                        //foundAnotherIntersection = true;
                        lastIntersectingGameObjectIndex = index;
                        timeToTarget = foundTimeToTarget;
                        if (timeToTarget == 0)
                        {
                            return true; // trajectory over the object is impossible, so give up
                        }

                        // use the new initial velocity in the tested trajecory
                        principalTrajectory.v0 = principalTrajectory.GetInitialVelocityGivenRelativeTargetAndTime(
                                principalTargetPosition, timeToTarget);
                        // notify helper classes/structs of the new trajectory to test
                        _trajectoryOverGameObjectHelper.SetupTrajectory(principalSpace3D,
                            principalTrajectory, principalTargetPosition, marginDistance);
                    }
                }
            }
        }
        //while (foundAnotherIntersection);

        return lastIntersectingGameObjectIndex >= 0; // true iff the plan changed
    }
    // See the base class for an explanation of the parameters.
    public override bool PlanTimeToTarget(Projectile3D projectile3D,
                                          Vector3 initialPosition,
                                          Vector3 targetPosition,
                                          ref float timeToTarget)
    {
        // Don't override the timeToTarget if there's already another valid plan.
        if (timeToTarget > 0) return false;

        timeToTarget = this.timeToTarget;
        return true;
    }
        // projectile in principal space
        // Create a principalSpace3D and PrincipalTrajectory from a given Projectile3D,
        // the launch position and another point on the plane (e.g. a 3d target).
        // Implements Equation 10 from the paper.
        public static PrincipalSpace3D Create(
            Projectile3D projectile3D,      // projectile in world space
            Vector3 worldP0,  	            // the launch position
            Vector3 worldP1,                // any other position on the principal plane
            out PrincipalProjectile principalProjectile)
        {
            principalProjectile = new PrincipalProjectile(
                projectile3D.k, projectile3D.vInfinity.magnitude);
            Vector3 yAxis = projectile3D.vInfinity / -principalProjectile.vInfinity;

            Vector3 deltaPos = worldP1 - worldP0;
            Vector3 xAxis = deltaPos - Vector3.Dot(yAxis, deltaPos) * yAxis;
            float squaredXScale = xAxis.sqrMagnitude;
            if (squaredXScale == 0)
            {
                xAxis = Misc.GetAnyVector3PerpendicularTo(yAxis);
                squaredXScale = xAxis.sqrMagnitude;
            }
            xAxis /= Mathf.Sqrt(squaredXScale);

            return new PrincipalSpace3D(worldP0, xAxis, yAxis);
        }
示例#6
0
        // Call all planners in order and return the flightTime if at least one planner
        // found a solution. The return value is only true if the last planner that found a
        // plan had mayLaunch = true.
        private static bool RunPlanners(ICollection <TrajectoryPlannerBase> planners,
                                        ProjectileKinematics projectileKinematics,
                                        Vector3 predictedLauncherPosition,
                                        Vector3 predictedTargetPosition,
                                        out float flightTime)
        {
            Projectile3D projectile3D = projectileKinematics.Projectile3D;

            flightTime = 0;
            bool mayLaunch = false;

            foreach (TrajectoryPlannerBase planner in planners)
            {
                if (planner.PlanTimeToTarget(projectile3D, predictedLauncherPosition,
                                             predictedTargetPosition, ref flightTime))
                {
                    mayLaunch = planner.mayLaunch;
                }
            }

            return(mayLaunch);
        }
示例#7
0
        // Based on the incoming positions, velocities and timing information, this function
        // uses dead reckoning to work out the TrajectoryXXXPlanner inputs to plan plan the
        // next projectile's trajectory with. The planners are called from lo to high
        // PlanNumber. If any (future) plan is available, it returns the initial velocity for
        // that plan. Otherwise, it returns Vector3.Zero. Furthermore, if a future plan is
        // found AND it allows launching AND the target is within reach AND
        // minimumTimeToNextLaunch <= 0, then shouldLaunch = true.
        public static Vector3 UpdatePlan(ICollection <TrajectoryPlannerBase> planners,
                                         ProjectileKinematics projectileKinematics,
                                         Vector3 launcherPosition,
                                         Vector3 launcherVelocity,
                                         Vector3 targetPosition,
                                         Vector3 targetVelocity,
                                         float minimumTimeToNextLaunch,
                                         ref float lastFlightTime,
                                         out bool shouldLaunch)
        {
            // Work out where the launcher and the target are most likely to be when
            // minimumTimeToNextLaunch becomes zero again.
            minimumTimeToNextLaunch = Mathf.Max(0.0f, minimumTimeToNextLaunch);
            float   timeToTarget = minimumTimeToNextLaunch + lastFlightTime;
            Vector3 predictedLauncherPosition = launcherPosition + launcherVelocity *
                                                minimumTimeToNextLaunch;
            Vector3 predictedTargetPosition = targetPosition + targetVelocity * timeToTarget;

            // Run the planners
            bool mayLaunch = RunPlanners(planners, projectileKinematics,
                                         predictedLauncherPosition, predictedTargetPosition, out lastFlightTime);

            // Calculate the projectile spawn velocity if a flight time estimate is available
            Vector3 projectileVelocity = Vector3.zero;

            if (lastFlightTime > 0)
            {
                Projectile3D projectile3D = projectileKinematics.Projectile3D;

                projectileVelocity =
                    projectile3D.GetInitialVelocityGivenRelativeTargetAndTime(
                        predictedTargetPosition - predictedLauncherPosition, lastFlightTime);
            }

            // Set shouldLaunch to true iff the planners presented a plan and
            // the time is right.
            shouldLaunch = mayLaunch && minimumTimeToNextLaunch <= 0;
            return(projectileVelocity);
        }
        // Create a principalSpace3D and PrincipalTrajectory from a given Projectile3D, 
        // the launch position and another point on the plane (e.g. a 3d target).
		// Implements Equation 10 from the paper.		
        public static PrincipalSpace3D Create(
            Projectile3D projectile3D,      // projectile in world space
            Vector3 worldP0,  	            // the launch position
            Vector3 worldP1,                // any other position on the principal plane
            out PrincipalProjectile principalProjectile) // projectile in principal space
        {

			principalProjectile = new PrincipalProjectile(
                projectile3D.k, projectile3D.vInfinity.magnitude);
            Vector3 yAxis = projectile3D.vInfinity / -principalProjectile.vInfinity;

            Vector3 deltaPos = worldP1 - worldP0;
            Vector3 xAxis = deltaPos - Vector3.Dot(yAxis, deltaPos) * yAxis;
            float squaredXScale = xAxis.sqrMagnitude;
            if (squaredXScale == 0)
            {
                xAxis = Misc.GetAnyVector3PerpendicularTo(yAxis);
                squaredXScale = xAxis.sqrMagnitude;
            }
            xAxis /= Mathf.Sqrt(squaredXScale);

            return new PrincipalSpace3D(worldP0, xAxis, yAxis);
        }
 public Projectile3D(Projectile3D projectile3D)
 {
     this.k         = projectile3D.k;
     this.vInfinity = projectile3D.vInfinity;
 }
 public Trajectory3D(Projectile3D projectile3D, Vector3 p0, Vector3 v0)
     : base(projectile3D)
 {
     this.p0 = p0;
     this.v0 = v0;
 }
 public Trajectory3D(Projectile3D projectile3D)
     : base(projectile3D)
 {
 }
 public Projectile3D(Projectile3D projectile3D)
 {
     this.k = projectile3D.k;
     this.vInfinity = projectile3D.vInfinity;
 }
 // Plan a trajectory in terms of flight time from initialPosition and targetPosition
 // using the settings in projectile3D. It's the responsibility of each implementated
 // subclass to decide whether or not to override provided timeToTarget, making it
 // possible to use the same interface for simple planners, backup planning and plan
 // modifiers. The function returns true if it modified the timeToTarget. To convert
 // the (new) timeToTarget to a 3D initial velocity use the projectile3D's
 // GetInitialVelocityGivenRelativeTargetAndTime() function.
 public abstract bool PlanTimeToTarget(Projectile3D projectile3D,
                                       Vector3 initialPosition,
                                       Vector3 targetPosition,
                                       ref float timeToTarget);
示例#14
0
 public Trajectory3D(Projectile3D projectile3D, Vector3 p0, Vector3 v0) :
     base(projectile3D)
 {
     this.p0 = p0;
     this.v0 = v0;
 }
示例#15
0
 public Trajectory3D(Projectile3D projectile3D) :
     base(projectile3D)
 {
 }