public Vector3d ComputeForces(double altitude, Vector3d airVelocity, Vector3d vup, double angleOfAttack)
{
if (!vessel_.mainBody.atmosphere)
return Vector3d.zero;
if (altitude >= body_.atmosphereDepth)
return Vector3d.zero;
Transform vesselTransform = vessel_.ReferenceTransform;
// this is weird, but the vessel orientation does not match the reference transform (up is forward), this code fixes it but I don't know if it'll work in all cases
Vector3d vesselBackward = (Vector3d)(-vesselTransform.up.normalized);
Vector3d vesselForward = -vesselBackward;
Vector3d vesselUp = (Vector3d)(-vesselTransform.forward.normalized);
Vector3d vesselRight = Vector3d.Cross(vesselUp, vesselBackward).normalized;
Vector3d airVelocityForFixedAoA = (vesselForward * Math.Cos(-angleOfAttack) + vesselUp * Math.Sin(-angleOfAttack)) * airVelocity.magnitude;
Vector3d totalForce = ComputeForces_Model(airVelocityForFixedAoA, altitude);
if (Double.IsNaN(totalForce.x) || Double.IsNaN(totalForce.y) || Double.IsNaN(totalForce.z))
{
Debug.Log(string.Format("Trajectories: WARNING: {0} totalForce is NAN (altitude={1}, airVelocity={2}, angleOfAttack={3}", AerodynamicModelName, altitude, airVelocity.magnitude, angleOfAttack));
return Vector3d.zero; // Don't send NaN into the simulation as it would cause bad things (infinite loops, crash, etc.). I think this case only happens at the atmosphere edge, so the total force should be 0 anyway.
}
// convert the force computed by the model (depends on the current vessel orientation, which is irrelevant for the prediction) to the predicted vessel orientation (which depends on the predicted velocity)
Vector3d localForce = new Vector3d(Vector3d.Dot(vesselRight, totalForce), Vector3d.Dot(vesselUp, totalForce), Vector3d.Dot(vesselBackward, totalForce));
//if (Double.IsNaN(localForce.x) || Double.IsNaN(localForce.y) || Double.IsNaN(localForce.z))
// throw new Exception("localForce is NAN");
Vector3d velForward = airVelocity.normalized;
Vector3d velBackward = -velForward;
Vector3d velRight = Vector3d.Cross(vup, velBackward);
if (velRight.sqrMagnitude < 0.001)
{
velRight = Vector3d.Cross(vesselUp, velBackward);
if (velRight.sqrMagnitude < 0.001)
{
velRight = Vector3d.Cross(vesselBackward, velBackward).normalized;
}
else
{
velRight = velRight.normalized;
}
}
else
velRight = velRight.normalized;
Vector3d velUp = Vector3d.Cross(velBackward, velRight).normalized;
Vector3d predictedVesselForward = velForward * Math.Cos(angleOfAttack) + velUp * Math.Sin(angleOfAttack);
Vector3d predictedVesselBackward = -predictedVesselForward;
Vector3d predictedVesselRight = velRight;
Vector3d predictedVesselUp = Vector3d.Cross(predictedVesselBackward, predictedVesselRight).normalized;
Vector3d res = predictedVesselRight * localForce.x + predictedVesselUp * localForce.y + predictedVesselBackward * localForce.z;
if (Double.IsNaN(res.x) || Double.IsNaN(res.y) || Double.IsNaN(res.z))
{
Debug.Log("Trajectories: res is NaN (altitude=" + altitude + ", airVelocity=" + airVelocity.magnitude + ", angleOfAttack=" + angleOfAttack);
return new Vector3d(0, 0, 0); // Don't send NaN into the simulation as it would cause bad things (infinite loops, crash, etc.). I think this case only happens at the atmosphere edge, so the total force should be 0 anyway.
}
return res;
}