// 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); }
// 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); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that also hits the line exactly 'b' above the // line from the origin to r. This is equivalent to saying that the trajectory // will touch the line y(x) = r.y/r.x * x + b, and that it is exactly contained // by the parallelogram formed by the vectors (0, 0)-(r.x, r.y) and (0, 0)-(0, b) // Uses Equation 27 from the paper. public static float GetTimeToTargetRGivenArcHeightB( PrincipalProjectile projectile, Vector2 r, float b) { return(GetTimeToTargetRGivenArcHeightB( projectile.k, projectile.vInfinity, r.x, r.y, b)); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that also passes through position q. // Uses Equation 23 from the paper. public static float GetTimeToTargetRGivenIntermediatePositionQ( PrincipalProjectile projectile, Vector2 r, Vector2 q) { return(GetTimeToTargetRGivenIntermediatePositionQ( projectile.k, projectile.vInfinity, r.x, r.y, q.x, q.y)); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory with the initial velocity s. When s is too small // to hit r at all, the functions return 0. But when it great enough, the // problem has two solutions: One arc that's higher and one arc that's lower // than the one that's found by GetTimeToTargetRWithMinimalInitialSpeed(). // Use highArc to select which one to return the time for. // Uses Equation 30 from the paper. public static float GetTimeToTargetRGivenInitialSpeedS( PrincipalProjectile projectile, Vector2 r, double s, bool highArc) { return((float)GetTimeToTargetRGivenInitialSpeedS( projectile.k, projectile.vInfinity, r.x, r.y, s, highArc)); }
public PrincipalTrajectory(PrincipalProjectile principalProjectile, Vector2 v0) : base(principalProjectile) { this.v0 = v0; }
public float vInfinity; // velocity of projectile falling indefinitely public PrincipalProjectile(PrincipalProjectile principalProjectile) { k = principalProjectile.k; vInfinity = principalProjectile.vInfinity; }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that has slope a at position r. Use // principalSpace3D.ToPrincipalSlope() to get the principal slope a from // a slope in world space. Uses Equation 26 from the paper. public static float GetTimeToTargetRGivenTargetSlopeA( PrincipalProjectile projectile, Vector2 r, float a) { return(GetTimeToTargetRGivenTargetSlopeA( projectile.k, projectile.vInfinity, r.x, r.y, a)); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that also passes through position q. // Uses Equation 23 from the paper. public static float GetTimeToTargetRGivenIntermediatePositionQ( PrincipalProjectile projectile, Vector2 r, Vector2 q) { return GetTimeToTargetRGivenIntermediatePositionQ( projectile.k, projectile.vInfinity, r.x, r.y, q.x, q.y); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory with the initial velocity s. When s is too small // to hit r at all, the functions return 0. But when it great enough, the // problem has two solutions: One arc that's higher and one arc that's lower // than the one that's found by GetTimeToTargetRWithMinimalInitialSpeed(). // Use highArc to select which one to return the time for. // Uses Equation 30 from the paper. public static float GetTimeToTargetRGivenInitialSpeedS( PrincipalProjectile projectile, Vector2 r, double s, bool highArc) { return (float)GetTimeToTargetRGivenInitialSpeedS( projectile.k, projectile.vInfinity, r.x, r.y, s, highArc); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory with curviness 'h'. h is defined as the ratio between // the height of the parallelogram (as defined in // GetTimeToTargetRGivenArcHeightB()) and the distance to the target. // Consequently, small values result in low arcs, and high values result in high // arcs. h = 0.25 roughly approximates a 'minimal effort' arc. // Uses Equation 27 and 28 from the paper. public static float GetTimeToTargetRGivenCurvinessH( PrincipalProjectile projectile, Vector2 r, float h) { return GetTimeToTargetRGivenCurvinessH( projectile.k, projectile.vInfinity, r.x, r.y, h); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that also hits the line exactly 'b' above the // line from the origin to r. This is equivalent to saying that the trajectory // will touch the line y(x) = r.y/r.x * x + b, and that it is exactly contained // by the parallelogram formed by the vectors (0, 0)-(r.x, r.y) and (0, 0)-(0, b) // Uses Equation 27 from the paper. public static float GetTimeToTargetRGivenArcHeightB( PrincipalProjectile projectile, Vector2 r, float b) { return GetTimeToTargetRGivenArcHeightB( projectile.k, projectile.vInfinity, r.x, r.y, b); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory with the smallest possible initial velocity. // Uses Equation 29 from the paper. public static float GetTimeToTargetRWithMinimalInitialSpeed( PrincipalProjectile projectile, Vector2 r) { return (float)GetTimeToTargetRWithMinimalInitialSpeed( projectile.k, projectile.vInfinity, r.x, r.y); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory with curviness 'h'. h is defined as the ratio between // the height of the parallelogram (as defined in // GetTimeToTargetRGivenArcHeightB()) and the distance to the target. // Consequently, small values result in low arcs, and high values result in high // arcs. h = 0.25 roughly approximates a 'minimal effort' arc. // Uses Equation 27 and 28 from the paper. public static float GetTimeToTargetRGivenCurvinessH( PrincipalProjectile projectile, Vector2 r, float h) { return(GetTimeToTargetRGivenCurvinessH( projectile.k, projectile.vInfinity, r.x, r.y, h)); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that touches the line y(x) = a*x + b. Use // principalSpace3D.ToPrincipalIntersectionLine() to get the (a,b) line // parameters from a world space plane. Uses Equation 24 from the paper. public static float GetTimeToTargetRGivenLineToTouch( PrincipalProjectile projectile, Vector2 r, Vector2 lineAB) { return GetTimeToTargetRGivenLineToTouch( projectile.k, projectile.vInfinity, r.x, r.y, lineAB.x, lineAB.y); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that touches the line y(x) = a*x + b. Use // principalSpace3D.ToPrincipalIntersectionLine() to get the (a,b) line // parameters from a world space plane. Uses Equation 24 from the paper. public static float GetTimeToTargetRGivenLineToTouch( PrincipalProjectile projectile, Vector2 r, Vector2 lineAB) { return(GetTimeToTargetRGivenLineToTouch( projectile.k, projectile.vInfinity, r.x, r.y, lineAB.x, lineAB.y)); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory that has slope a at position r. Use // principalSpace3D.ToPrincipalSlope() to get the principal slope a from // a slope in world space. Uses Equation 26 from the paper. public static float GetTimeToTargetRGivenTargetSlopeA( PrincipalProjectile projectile, Vector2 r, float a) { return GetTimeToTargetRGivenTargetSlopeA( projectile.k, projectile.vInfinity, r.x, r.y, a); }
// Get the time at which the (principal-space) target position r will be hit // as part of a trajectory with the smallest possible initial velocity. // Uses Equation 29 from the paper. public static float GetTimeToTargetRWithMinimalInitialSpeed( PrincipalProjectile projectile, Vector2 r) { return((float)GetTimeToTargetRWithMinimalInitialSpeed( projectile.k, projectile.vInfinity, r.x, r.y)); }
public Vector2 v0; // projectile velocity at t = 0 public PrincipalTrajectory(PrincipalProjectile principalProjectile) : base(principalProjectile) { }
public float vInfinity; // velocity of projectile falling indefinitely #endregion Fields #region Constructors public PrincipalProjectile(PrincipalProjectile principalProjectile) { k = principalProjectile.k; vInfinity = principalProjectile.vInfinity; }
public Vector2 v0; // projectile velocity at t = 0 #endregion Fields #region Constructors public PrincipalTrajectory(PrincipalProjectile principalProjectile) : base(principalProjectile) { }