That can’t be right. If there’s t*t in the formula, the solution needs to contain a square root. And where did the S go? Not sure what you are doing here.

Can’t you just do this:
Assuming the bullet is much faster than the planes you can calculate the time to impact:

timeToImpact = distanceToTarget / bulletSpeed

Then plug that time into your formula and calculate where the target will be:

Left and side of the equation, bullet
Right hand side of the equation, aircraft

Distance goes because we are solving for the TIME when bullet and plane will be the same distance from the origin

The square root goes when you divide both sides of the equation by T

I don’t want the distance to target, as the target will not be at that point when the bullet gets there.

Pointless shooting at where the plane was.

I thought about it more last night and I think I am on the correct track. At this point in the solver I don’t care where the convergence point is, just how long it will take to reach convergence.

So the 3 dimensional nature of the equation is meaningless. I am just solving for two changing velocities converging at a distance.

Ah I see, I understand your approach now. You started with this and solved for t:

v1*t + 0.5*a1*t*t = v2*t + 0.5*a2*t*t

You are missing the starting positions though, don’t you? I think it needs to be:

s1 + v1*t + 0.5*a1*t*t = s2 + v2*t + 0.5*a2*t*t

Which makes it more difficult to solve, as you are not getting rid of the t^2 anymore.

Why? There’s 4 unknown variables: time and bullet velocity.xyz, right? So you need all 3 dimensions, if you want to solve this.

In case this get’s too complicated I think you could use the method I proposed and run multiple iterations of it. It should converge to the same result. So futureTargetPosition from the first iteration would be the first rough approximation. You can then use this position to get a better estimate for distanceToTarget and calculate a more accurate futureTargetPosition. With every iteration you should get closer to the correct result.

///
///
/// From target manager
/// Aircraft velocity
/// From BulletPropertiesComponent
/// Time step
/// Inverted local world
///
public static Vector3 GetAimDirection(AITarget target, Vector3 velocity, float muzzlevelocity, float dt, Matrix inWorld)
{
// First work out the time it will take to get to the targets current position
Vector3 relative_current_position = Vector3.Transform(target.Position, inWorld);
float bullet_velocity = velocity.Length() + muzzlevelocity;
float time1 = relative_current_position.Length() / bullet_velocity;

// work out instantaneous acceleration and velocity for target
Vector3 ivel = (target.Position - target.OldPosition) / dt;
Vector3 iaccel = (target.Velocity - target.OldVelocity) / dt;
// move instantaneous values into local world space
ivel = Vector3.Transform(ivel, inWorld);
iaccel = Vector3.Transform(iaccel, inWorld);
// move target to where it will be after time1
Vector3 predict1 = relative_current_position + (ivel * time1) + (0.5f * iaccel * time1 * time1);
// work out time a bullet would take to go there
float time2 = predict1.Length() / bullet_velocity;
// work out how far the bullet will go in time2
float dist1 = bullet_velocity * time2;
// how far is the bullet from the predicted position
float dist2 = predict1.Length() - dist1;
// adjust the time based on this distance to get our time estimation.
float time3 = time2 + (dist2 / bullet_velocity);
// work out bullet drop due to gravity
float drop = 0.5f * 9.81f * time3 * time3;
// Adjust time for bullet drop
time3 += drop / bullet_velocity;
// work out the target position using time3
Vector3 predict2 = relative_current_position + (ivel * time3) + (0.5f * iaccel * time3 * time3);
drop = 0.5f * 9.81f * time3 * time3;
// move aim point up to compensate
predict2.Y += drop;
predict2.Normalize();
#if DEBUG
if (DebugRenderSettings.RenderAimPoints)
{
ivel = (target.Position - target.OldPosition) / dt;
iaccel = (target.Velocity - target.OldVelocity) / dt;
Vector3 dp = target.Position + (ivel * time3) + (0.5f * iaccel * time3 * time3);
dp.Y += drop;
DebugLineDraw.DrawTarget(dp, Color.Red, 1);
}
#endif
return predict2;
}`

This is a 2d quadratic solution i keep.
Making it 3d is trivial just add in the z.

This finds the normalized directional vector a bullet that has a given speed must head in to intercept a target with a given velocity from it’s current position.

Note there exists the possibility that you cannot actually hit the target say its moving away from the bullet faster then the bullet, this accounts for that.

/// <summary>
/// Given a object with a speed we will find what direction it must head (in normalized velocity form)
/// to intercept the given target with a given velocity from its current position
/// </summary>
/// <returns>The normal vector the object or bullet must head in to intercept</returns>
public static Vector2 QuadricIntercept(Vector2 obj_position, float obj_speed, Vector2 target_position,Vector2 target_velocity)
{
float tvx = target_velocity.X;
float tvy = target_velocity.Y;
float pdx = target_position.X - obj_position.X;
float pdy = target_position.Y - obj_position.Y;
float d = pdx * pdx + pdy * pdy;
float s = (tvx * tvx + tvy * tvy) - obj_speed * obj_speed;
float q = (tvx * pdx + tvy * pdy);
float disc = (q * q) - s * d; // simplify get rid of the fluff
float disclen = (float)Math.Sqrt(disc);
float t = (-q + disclen) / s;
float t2 = (-q - disclen) / s;
if (t < 0.0f)
t = t2;
Vector2 aimpoint = Vector2.Zero;
if (t > 0.0f)
{
aimpoint.X = t * tvx + target_position.X;
aimpoint.Y = t * tvy + target_position.Y;
}
return aimpoint; // returns Vector2.Zero if no positive future time to fire exists
}

The actual collision code is trivial, simple ray cast for broadphase , then a more detailed raytrace for actual location.

The aim off angle for gunners is a really complex and interesting problem.

The things I am ignoring that I would like to include are …

Bullet drag

Magnus effect

Altitude effects

Bullet drag is obvious, but quite expensive to code
Magnus effect is actually quite cheap to calculate, but makes the cheap prediction code above fall apart
Altitude effects drag and the magnus effect and should be included really

I would be very interested to see how other people have modelled this, but so far all I can find is that Fortran code from 1974 which has the nasty assumption that bullet and target are on a fixed plane

Ah i would say the forces like drag and even gravity in that context that cause a fall off can be considered from a different point of view such that for a distance the angle of aim is adjusted as a constant with the distance.

Think about it like in a real life example say in ww1 or ww2 for aa gunners or artillery.
Remember they didn’t have calculators or computers back then on the ground.

They had a simple table to adjust for these things like wind and distance.
That told them the amount of lead aim angle required.
They adjusted for a lead angle and height depending on distance wind and the enemy’s estimated target velocity basically they had to guess the intercept then adjust for wind drag and gravity.

Here once we have the direct intercept, the other two are trivial in comparison simple linear functions of drag and or gravity ect on the bullet over distance you could even just make a table to adjust the gun aim for those forces over distance.