/// <summary> /// Execute the maneuver. Called automatically by Gravity Engine for maneuvers that /// have been added to the GE via AddManeuver(). /// /// Unusual to call this method directly. /// </summary> /// <param name="ge"></param> public void Execute(GravityState gs) { double[] vel = new double[3] { 0, 0, 0 }; gs.GetVelocityDouble(nbody, ref vel); switch (mtype) { case Mtype.vector: vel[0] += velChange[0]; vel[1] += velChange[1]; vel[2] += velChange[2]; break; case Mtype.scalar: // scalar: adjust existing velocity by dV Vector3d vel3d = new Vector3d(ref vel); Vector3d change = Vector3d.Normalize(vel3d) * dV; vel[0] += change[0]; vel[1] += change[1]; vel[2] += change[2]; break; case Mtype.setv: // direct assignement (this mode normally used for debug) vel[0] = velChange[0]; vel[1] = velChange[1]; vel[2] = velChange[2]; break; } #pragma warning disable 162 // disable unreachable code warning if (GravityEngine.DEBUG) { if (!gs.isAsync) { Debug.Log("Applied manuever: " + LogString() + " engineRef.index=" + nbody.engineRef.index + " engineRef.bodyType=" + nbody.engineRef.bodyType + " timeError=" + (worldTime - gs.time)); Debug.LogFormat("r={0} v=({1},{2},{3}) ", Vector3.Magnitude(nbody.transform.position), vel[0], vel[1], vel[2]); } } #pragma warning restore 162 // enable unreachable code warning gs.SetVelocityDouble(nbody, ref vel); }
/// <summary> /// Determine the acceleration due to atmospheric resistance. /// </summary> /// <param name="time">(not used)</param> /// <param name="gravityState"></param> /// <param name="massKg">Updated mass (0 to use the inertial mass from inspector)</param> /// <returns></returns> public double[] acceleration(double time, GravityState gravityState, ref double massKg) { bool isLiveState = (gravityState == liveState); accel[0] = 0; accel[1] = 0; accel[2] = 0; if (impact) { return(accel); } if (massKg < 1E-9) { massKg = inertialMassKg; } // determine height above Earth's surface in km // due to dynamic add/delete cannot in general keep a cached value of the index for ship or Earth // @TODO: Pass in this objects position to save a lookup Vector3d earthPos = gravityState.GetPhysicsPositionDouble(earth); Vector3d shipPos = gravityState.GetPhysicsPositionDouble(spaceship); double h = Vector3d.Distance(earthPos, shipPos) * geDistanceToKm - heightEarthSurface; if (h < 0) { if (isLiveState) { impact = true; Debug.LogFormat("Impact of {0} at h={1} shipPos={2}", gameObject.name, h, shipPos); if (impactTrigger != null) { impactTrigger.Impact(spaceship, gravityState); } return(accel); } else { return(accel); } } // retrieve the density from the pre-calculated table double hdiv10 = h / 10.0; int densityIndex = (int)hdiv10; if (densityIndex > densityTablePer10km.Length - 2) { // too far away, no drag return(accel); } // interpolate. double density = densityTablePer10km[densityIndex] + (hdiv10 - (double)densityIndex) * (densityTablePer10km[densityIndex + 1] - densityTablePer10km[densityIndex]); // determine accel due to drag gravityState.GetVelocityDouble(spaceship, ref v_ship); gravityState.GetVelocityDouble(earth, ref v_earth); // convert to SI v_rel[0] = (v_ship[0] - v_earth[0]) * velocityScaleInternalToSI; v_rel[1] = (v_ship[1] - v_earth[1]) * velocityScaleInternalToSI; v_rel[2] = (v_ship[2] - v_earth[2]) * velocityScaleInternalToSI; double v_rel_sq = (v_rel[0] * v_rel[0]) + (v_rel[1] * v_rel[1]) + (v_rel[2] * v_rel[2]); // guard against divide by zero for norm if (v_rel_sq < 1E-9) { return(accel); } double v_rel_mag = System.Math.Sqrt(v_rel_sq); double a_mag = 0.5 * coeefDrag * crossSectionalArea * density * v_rel_sq / inertialMassKg; // save the last live value for shipInfo etc. if (isLiveState) { accel_last = a_mag; } // convert to GE scale a_mag *= accelSItoGE; // in the -ve direction of v_rel v_rel[0] = -v_rel[0] / v_rel_mag; v_rel[1] = -v_rel[1] / v_rel_mag; v_rel[2] = -v_rel[2] / v_rel_mag; accel[0] = a_mag * v_rel[0]; accel[1] = a_mag * v_rel[1]; accel[2] = a_mag * v_rel[2]; //if (logCount++ > LOG_INTERVAL) { // logCount = 0; // Debug.LogFormat("h={0} accel = ({1}, {2}, {3}) |a|={4} (m/s^2) -|v_rel|=({5},{6},{7}) v_rel = {8} m/s", // h, accel[0], accel[1], accel[2], a_mag/accelSItoGE, // v_rel[0], v_rel[1], v_rel[2], v_rel_mag); //} return(accel); }