Exemple #1
0
    /// <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);
    }