public string ApproachPrediction(string moonName)
    {
        // @TODO: Too much C&P!
        // Step 1: Determine the patched conic xfer
        OrbitData shipOrbit = new OrbitData();
        NBody     shipNbody = spaceshipCtrl.GetNBody();

        shipOrbit.SetOrbit(shipNbody, centralMass);
        OrbitData moonOrbit = new OrbitData();
        NBody     moonNbody = GetTargetByName(moonName);

        moonOrbit.SetOrbit(moonNbody, centralMass);
        //Make a copy of the universe state and evolve forward to find min distance to
        // moon.
        GravityEngine ge = GravityEngine.Instance();
        GravityState  gs = ge.GetGravityStateCopy();
        // run a simulation and find the closest approach (Expensive!)
        LunarCourseCorrection lcc = new LunarCourseCorrection(shipNbody, moonNbody);

        // want to be within 10% of Earth-Moon distance, before start checking
        courseCorrectionData = new LunarCourseCorrection.CorrectionData();
        courseCorrectionData.gravityState     = gs;
        courseCorrectionData.approachDistance = 0.1f * moonOrbit.a;;
        courseCorrectionData.correction       = 0;
        courseCorrectionData.maxPhysTime      = time_to_moon_phys;
        lcc.ClosestApproachAsync(courseCorrectionData, MoonPreviewCompleted);
        return("Calculation started...\n");
    }
Beispiel #2
0
 public void PreEvolve(GravityState gravityState, ref byte[] info)
 {
     double[] mass = gravityState.m;
     double[,] pos = gravityState.r;
     Get_acc_jerk_pot_coll(ref mass, ref pos, ref info);
     initialEnergy = NUtils.GetEnergy(numBodies, ref mass, ref pos, ref vel);
 }
    private void GravitySetter()
    {
        if (IsOnFloor())
        {
            gravityState = GravityState.NORMAL;
        }

        if (rb.velocity.y < 0)
        {
            gravityState = GravityState.FALL;
        }
        if (rb.velocity.y > 0 && !(Input.GetButton("Jump")))
        {
            gravityState = GravityState.LOWJUMP;
        }

        switch (gravityState)
        {
        case GravityState.NORMAL:
            gravityMultiplier = 1.0f;
            break;

        case GravityState.FALL:
            gravityMultiplier = fallMultiplier;
            break;

        case GravityState.LOWJUMP:
            gravityMultiplier = lowJumpMultiplier;
            break;
        }

        rb.velocity += Vector2.up * Physics2D.gravity.y * (gravityMultiplier - 1.0f) * Time.deltaTime;
    }
Beispiel #4
0
    // Game wrapper to limit number of evolution loops

    public double Evolve(double time, GravityState gravityState, ref byte[] info)
    {
        double[] mass = gravityState.m;
        double[,] pos = gravityState.r;
        double t      = 0;
        double maxDt  = time / 5.0f;     // minimum of 5 evolutions per update
        double minDt  = time / 1000.0f;  // maximum of 1000 evolutions per update
        int    nloops = 0;

        while (t < time)
        {
            // If only one body collision time will be MAXFLOAT
            t += dt;
            Evolve_step(ref mass, ref pos, ref info);
            dt = dtInitial * coll_time;
            if (dt > maxDt)
            {
                dt = maxDt;
            }
            if (dt < minDt)
            {
                dt = minDt;
            }
            nloops++;
        }
        return(t);
    }
Beispiel #5
0
    //    void Jump()
    //    {
    //        if (isgrounded) // can remoce "True" because just saying it means its true.. "!" before will make it opposite (false).. "!=" means opposite of current result (isDead example with Time)
    //        {
    //            if (Input.GetButtonDown("Jump"))
    //            {
    //
    //                rb.AddForce(0, jumpforce, 0, ForceMode.Impulse); //I can jump one and dash forever, I might keep that
    //
    //
    //            }
    //
    //        }
    //    }

    //    void Dash() // This feature punishes players that use it too much. It gets harder to control
    //    {
    //        if (isgrounded)
    //        {
    //            if (Input.GetButtonDown("Dash"))
    //            {
    //                rb.AddForce(direction * dashforce, ForceMode.Impulse); // because in this case direction is a Vector3
    //
    //            }
    //
    //            Debug.Log(rb.velocity);
    //
    //            rb.velocity -= rb.velocity * Time.deltaTime * decceleration;
    //
    //
    //        }
    //    }

    //    void GetDirectionInput()
    //    {
    //        float horizontalAxis =
    //            Input.GetAxisRaw("Horizontal"); //this variable collects the value of the button pressed (1,0, or -1)
    //
    //        float verticalAxis = Input.GetAxisRaw("Vertical");
    //
    //
    //
    //        Vector3 moveForward = transform.forward * verticalAxis;
    //        Vector3 moveSide = transform.right * horizontalAxis;
    //
    //
    //
    //        direction = (moveForward + moveSide);
    //
    //    }

    //    private void OnCollisionEnter(Collision collision)
    //    {
    //        if (collision.gameObject.tag == "Ground")
    //        {
    //            isgrounded = true;
    //
    //        }
    //
    //
    //    }


    void characterStateMethod()
    {
        RaycastHit hit;

        // Does the ray intersect any objects excluding the player layer
        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, Mathf.Infinity))
        {
            if (hit.distance > 0.5f)
            {
                //canJump = false;
                characterState = GravityState.Flying;
                print("State " + characterState);
            }


            //will check the hit distance and verify if we can jump or not
            if (hit.distance < 0.5f)
            {
                //canJump = true;
                characterState = GravityState.Ground;
                print("State " + characterState);
            }


            Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.down) * hit.distance, Color.yellow);
        }
        else
        {
            characterState = GravityState.Flying;

            Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.down) * hit.distance, Color.white);
        }
        // print("distance "+ hit.distance);
    }
 private void Awake()
 {
     gravityState = GravityState.NORMAL;
     rb           = GetComponent <Rigidbody2D>();
     animator     = GetComponent <Animator>();
     player       = GetComponent <PlayerScript>();
 }
    void Awake()
    {
        // Convert from real world units
        // Rocket engine thrust is given in SI units, so acceleration is in SI units
        // For Orbital scale need to convert to km/hr^2
        accelerationConversion = GravityScaler.AccelSItoGEUnits();
        // and convert to the physics scale used in the engine
        accelerationConversion = accelerationConversion * GravityScaler.AccelGEtoInternalUnits();

        burnStart     = new double[MAX_STAGES];
        burnRateScale = GravityScaler.GetGameSecondPerPhysicsSecond();

        fuelLevel = new double[MAX_STAGES];
        for (int i = 0; i < numStages; i++)
        {
            fuelLevel[i] = massFuel[i];
        }

        // acceleration will be opposite to thrust direction
        accelDirection = -thrustAxis;
        activeStage    = 0;

        activeState = GravityEngine.Instance().GetWorldState();

        SetEngine(engineOn);
    }
Beispiel #8
0
 /// <summary>
 /// Sets the gravity state for a certain duration.
 /// </summary>
 /// <param name="state">New state to set.</param>
 /// <param name="duration">Optional delay until the new state is set.</param>
 public void SetGravityState(GravityState state, float duration = 1f)
 {
     currentState = state;
     SetRigidbodyGravity();
     // TODO - Glow animation?
     returnToInitial = true;
     timer           = duration;
 }
Beispiel #9
0
 // Checks if check for ground is needed
 protected void CheckIfGrounded()
 {
     if (checkForGround)
     {
         if (Physics.CheckSphere(groundCheck.position, groundDistance, groundMask))
         {
             currentGravityState = GravityState.Grounded;
             currentFallSpeed    = gravityOnGround;
         }
     }
 }
    public override double[] acceleration(double time, GravityState gravityState, ref double massKg)
    {
        // a(t) = Thrust/m(t)
        // Called on every integration timestep - so favour speed over beauty
        // Will be called by both trajectory prediction and game evolution, so needs to be a function of time
        // (i.e. cannot reduce fuel each time this routine is called!)
        double[] a = new double[3] {
            0, 0, 0
        };
        double activeFuel = 0;

        // always need the mass for drag calc (even if engine is off)
        massKg = payloadMass;
        // TODO - could optimize and precompute (mass per stage - fuel) in that stage
        // add stage masses
        for (int i = activeStage; i < numStages; i++)
        {
            massKg += massStageEmpty[i];
        }
        // add fuel of unused stages
        for (int i = activeStage + 1; i < numStages; i++)
        {
            massKg += massFuel[i];
        }
        // thrust
        if (engineOn && (fuelLevel[activeStage] > 0))
        {
            if (gravityState == activeState)
            {
                fuelLevel[activeStage] -= throttle * burnRateScale * burnRate[activeStage] * (time - lastTime);
                if (fuelLevel[activeStage] < 0)
                {
                    fuelLevel[activeStage] = 0;
                }
                activeFuel = fuelLevel[activeStage];
                lastTime   = time;
            }
            else
            {
                activeFuel = fuelLevel[activeStage] - throttle * burnRateScale * burnRate[activeStage] * (time - lastTime);
            }
            if (activeFuel > 0)
            {
                massKg += activeFuel;
                double a_scalar = accelerationConversion * thrust[activeStage] * throttle / massKg;
                a[0] = a_scalar * accelDirection.x;
                a[1] = a_scalar * accelDirection.y;
                a[2] = a_scalar * accelDirection.z;
            }
        }

        return(a);
    }
Beispiel #11
0
    public void PreEvolve(GravityState gravityState, ref byte[] info)
    {
        double[] m = gravityState.m;
        double[,] r = gravityState.r;
        // Precalc initial acceleration
        double[] rji = new double[GravityEngine.NDIM];
        double   r2;
        double   r3;
        double   r_sep;
        double   accel;

        for (int i = 0; i < numBodies; i++)
        {
            for (int k = 0; k < GravityEngine.NDIM; k++)
            {
                a[i, k] = 0.0;
            }
        }
        for (int i = 0; i < numBodies; i++)
        {
            for (int j = i + 1; j < numBodies; j++)
            {
                r2 = 0;
                for (int k = 0; k < GravityEngine.NDIM; k++)
                {
                    rji[k] = r[j, k] - r[i, k];
                    r2    += rji[k] * rji[k];
                }
                if (forceDelegate == null)
                {
                    r3 = r2 * System.Math.Sqrt(r2) + EPSILON;
                    for (int k = 0; k < GravityEngine.NDIM; k++)
                    {
                        a[i, k] += m[j] * rji[k] / r3;
                        a[j, k] -= m[i] * rji[k] / r3;
                    }
                }
                else
                {
                    r_sep = System.Math.Sqrt(r2) + EPSILON;
                    accel = forceDelegate.CalcF(r_sep);
                    for (int k = 0; k < GravityEngine.NDIM; k++)
                    {
                        a[i, k] += m[j] * accel * (rji[k] / r_sep);
                        a[j, k] -= m[i] * accel * (rji[k] / r_sep);
                    }
                }
            }
        }

        initialEnergy = NUtils.GetEnergy(numBodies, ref m, ref r, ref v);
    }
Beispiel #12
0
    private void SetGravityState(GravityState state)
    {
        gravState = state;
        switch (gravState)
        {
        case GravityState.AIRBORN:
            SetAirbornPhysics();
            break;

        case GravityState.GROUND:
            SetGroundPhysics();
            break;
        }
    }
    void Start()
    {
        SetEngine(engineOn);
        // Convert from real world units
        // Rocket engine thrust is given in SI units, so acceleration is in SI units
        // For Orbital scale need to convert to km/hr^2
        accelerationConversion = GravityScaler.AccelSItoGEUnits();
        // and convert to the physics scale used in the engine
        accelerationConversion = accelerationConversion * GravityScaler.AccelGEtoInternalUnits();

        burnRateScaled  = burnRate * GravityScaler.GetGameSecondPerPhysicsSecond();
        thrustDirection = thrustAxis;
        fuelLevel       = massFuel;
        activeState     = GravityEngine.Instance().GetWorldState();
    }
    public void Impact(NBody nbody, GravityState gravityState)
    {
        if (!impactFlag)
        {
            Vector3 vel = GravityEngine.Instance().GetScaledVelocity(nbody);
            Vector3 pos = gravityState.GetPhysicsPosition(nbody);
            pos = GravityEngine.Instance().physToWorldFactor *pos;
            Debug.LogFormat("Set pos={0} |pos| = {1}", pos, pos.magnitude);
            GravityEngine.Instance().InactivateBody(nbody.gameObject);
            nbody.GEUpdate(pos, vel, GravityEngine.Instance());

            this.nbody = nbody;
            impactFlag = true;
        }
    }
    // Called by Evolve after particles have been inited.
    // - calculate the current acceleration on each particle so that on first LF step will evolve smoothly
    private void PreEvolve(int fromP, int toP, int numBodies, GravityState gravityState, ref byte[] info)
    {
        double[] m = gravityState.m;
        double[,] r_m = gravityState.r;
        // Precalc initial acceleration
        double[] rji = new double[GravityState.NDIM];
        double   r2;
        double   r3;

        for (int i = fromP; i < toP; i++)
        {
            for (int k = 0; k < GravityState.NDIM; k++)
            {
                a[i, k] = 0.0;
            }
        }
        // evolve over all massive objects
        for (int i = 0; i < numBodies; i++)
        {
            if ((info[i] & GravityEngine.INACTIVE) == 0)
            {
                for (int j = fromP; j < toP; j++)
                {
                    for (int k = 0; k < GravityState.NDIM; k++)
                    {
                        rji[k] = r[j, k] - r_m[i, k];
                    }
                    r2 = 0;
                    for (int k = 0; k < GravityState.NDIM; k++)
                    {
                        r2 += rji[k] * rji[k];
                    }
                    r3 = r2 * System.Math.Sqrt(r2) + EPSILON;
                    for (int k = 0; k < GravityState.NDIM; k++)
                    {
                        a[j, k] += m[i] * rji[k] / r3;
                    }
                                        #pragma warning disable 162, 429                // disable unreachable code warning
                    if (debugLogs && j == 0)
                    {
                        Debug.Log(string.Format("PreEvolve : Initial a={0} {1} {2} rji={3} {4} {5} body={6} m={7}",
                                                a[0, 0], a[0, 1], a[0, 2], rji[0], rji[1], rji[2], i, m[i]));
                    }
                                        #pragma warning restore 162, 429
                }
            }
        }
    }
Beispiel #16
0
    /// <summary>
    /// Pre-evolve the massless bodies based in the array information about the massive bodies in the
    /// system.
    /// </summary>
    /// <param name="numMasses">Number masses.</param>
    /// <param name="m">Mass array for massive bodies</param>
    /// <param name="r_m">Position array for massive bodies.</param>
    public void PreEvolve(int numMasses, GravityState gravityState)
    {
        double[] m = gravityState.m;
        double[,] r_m = gravityState.r;
        if (numMasses == 0 && numBodies == 0)
        {
            return;
        }
        // Precalc initial acceleration
        double[] rji = new double[GravityEngine.NDIM];
        double   r2;
        double   r3;

        for (int i = 0; i < numBodies; i++)
        {
            a[i, 0] = 0.0;
            a[i, 1] = 0.0;
            a[i, 2] = 0.0;
        }
        // precalc initial acceleration due to massive bodies
        for (int i = 0; i < numMasses; i++)
        {
            for (int j = 0; j < numBodies; j++)
            {
                for (int k = 0; k < GravityEngine.NDIM; k++)
                {
                    rji[k] = r[j, k] - r_m[i, k];
                }
                r2 = 0;
                for (int k = 0; k < GravityEngine.NDIM; k++)
                {
                    r2 += rji[k] * rji[k];
                }
                r3 = r2 * System.Math.Sqrt(r2) + EPSILON;
                for (int k = 0; k < GravityEngine.NDIM; k++)
                {
                    a[j, k] += m[i] * rji[k] / r3;
                }
            }
        }
                #pragma warning disable 162             // disable unreachable code warning
        if (GravityEngine.DEBUG)
        {
            Debug.Log(string.Format("PreEvolve: Initial a={0} {1} {2}", a[0, 0], a[0, 1], a[0, 2]));
        }
                #pragma warning restore 162
    }
Beispiel #17
0
    private void SetGravity(GravityState gstate)
    {
        gravityState = gstate;

        switch (GravityState)
        {
            case GravityState.Moon:
                Current = moonGrav;
                break;
            case GravityState.Earth:
                Current = earthGrav;
                break;
            default:
                Current = Vector2.zero;
                break;
        }
    }
Beispiel #18
0
    public double Evolve(double time, GravityState gravityState, ref byte[] info)
    {
        double[] mass = gravityState.m;
        double[,] pos     = gravityState.r;
        this.gravityState = gravityState;
        t_offset          = 0;
        t_evolveStart     = gravityState.GetPhysicsTime();

        int nloops = 0;

        if (dt > time)
        {
            dt = time;
        }

        while (t_offset < time)
        {
            // If only one body collision time will be MAXFLOAT
            t_offset += dt;
            Evolve_step(ref mass, ref pos, ref info);
            // timestep adjustement, relative to initial collision time
            coll_time_avg = COLL_AVERAGE_FACTOR * coll_time_avg + (1 - COLL_AVERAGE_FACTOR) * coll_time;
            dt            = dtInitial * coll_time_avg / coll_time_initial;
            if (dt > maxDt)
            {
                dt = maxDt;
            }
            else if (dt < minDt)
            {
                dt = minDt;
            }
            nloops++;
        }
#pragma warning disable 162        // disable unreachable code warning
        if (GravityEngine.DEBUG)
        {
            if (logCount++ > LOG_INTERVAL)
            {
                logCount = 0;
                Debug.LogFormat("time={0} dt={1} coll_time={2} coll_factor={3} coll_time_initial={4} nloops={5} numbodies={6}",
                                time, dt, coll_time, coll_time_avg / coll_time_initial, coll_time_initial, nloops, numBodies);
            }
        }
#pragma warning restore 162
        return(t_offset);
    }
Beispiel #19
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);
    }
Beispiel #20
0
    private void SetGravity(GravityState gstate)
    {
        gravityState = gstate;

        switch (GravityState)
        {
        case GravityState.Low:
            Current = lowGrav;
            break;

        case GravityState.Normal:
            Current = normalGrav;
            break;

        default:
            Current = Vector2.zero;
            break;
        }
    }
Beispiel #21
0
    /// <summary>
    /// Returns the gravity value for a given state.
    /// </summary>
    /// <param name="state">State to get gravity value from.</param>
    /// <returns>Gravity value of the state.</returns>
    public static float GetStateGravity(GravityState state)
    {
        switch (state)
        {
        case GravityState.NormalGravity:
            return(normalGravity);

        case GravityState.MoonGravity:
            return(moonGravity);

        case GravityState.GroundedGravity:
            return(groundedGravity);

        case GravityState.Weightless:
            return(zeroGravity);

        default:
            return(normalGravity);
        }
    }
Beispiel #22
0
    public double[] acceleration(double time, GravityState gravityState, ref double massKg)
    {
        a_rocket = engine.acceleration(time, gravityState, ref massKg);
        // need to update mass as fuel is consumed
        atmosphere.inertialMassKg = massKg;
        a_atmosphere = atmosphere.acceleration(time, gravityState, ref massKg);

        a[0] = a_rocket[0] + a_atmosphere[0];
        a[1] = a_rocket[1] + a_atmosphere[1];
        a[2] = a_rocket[2] + a_atmosphere[2];
        // cache the last atmosphere accel for world state (need to check since could be trajectories
        // asking for accel as well)
        if (gravityState == worldState)
        {
            a_last[0] = a[0];
            a_last[1] = a[1];
            a_last[2] = a[2];
        }
        return(a);
    }
    public string MoonPreview(string moonName, float lambda1, bool async)
    {
        // Step 1: Determine the patched conic xfer
        OrbitData shipOrbit = new OrbitData();
        NBody     shipNbody = spaceshipCtrl.GetNBody();

        shipOrbit.SetOrbit(shipNbody, centralMass);
        OrbitData moonOrbit = new OrbitData();
        NBody     moonNbody = GetTargetByName(moonName);

        moonOrbit.SetOrbit(moonNbody, centralMass);
        OrbitTransfer xfer = new PatchedConicXfer(shipOrbit, moonOrbit, lambda1);

        // Step 2: Make a copy of the universe state and evolve forward to find min distance to
        // moon.
        GravityEngine ge = GravityEngine.Instance();
        GravityState  gs = ge.GetGravityStateCopy();

        // there is only one maneuver to add
        gs.maneuverMgr.Add(xfer.GetManeuvers()[0]);
        // run a simulation and find the closest approach (Expensive!)
        LunarCourseCorrection lcc = new LunarCourseCorrection(shipNbody, moonNbody);

        // want to be within 10% of Earth-Moon distance, before start checking
        courseCorrectionData = new LunarCourseCorrection.CorrectionData();
        courseCorrectionData.gravityState     = gs;
        courseCorrectionData.approachDistance = 0.1f * moonOrbit.a;;
        courseCorrectionData.correction       = 0;
        courseCorrectionData.maxPhysTime      = time_to_moon_phys;
        // Direct (unthreaded) calculation
        if (async)
        {
            lcc.ClosestApproachAsync(courseCorrectionData, MoonPreviewCompleted);
            return("Calculation started...\n");
        }
        else
        {
            predictedDistance = lcc.ClosestApproach(courseCorrectionData);
            return(string.Format("Patched Conic with lambda={0} => approach={1}\n", lambda1, predictedDistance));
        }
    }
    public override double[] acceleration(double time, GravityState gravityState, ref double massKg)
    {
        // a(t) = Thrust/m(t)
        // Will be called by both trajectory prediction and game evolution, so needs to be a function of time
        // (i.e. cannot reduce fuel each time this routine is called!)
        double[] a = new double[3] {
            0, 0, 0
        };
        double activeFuel = 0;

        if (engineOn)
        {
            massKg = massEmpty;
            if (gravityState == activeState)
            {
                fuelLevel -= throttle * burnRate * burnRateScaled * (time - lastTime);
                if (fuelLevel < 0)
                {
                    fuelLevel = 0;
                }
                activeFuel = fuelLevel;
                lastTime   = time;
            }
            else
            {
                activeFuel = fuelLevel - throttle * burnRate * burnRateScaled * (time - lastTime);
            }
            if (activeFuel > 0)
            {
                massKg += activeFuel;
                double a_scalar = accelerationConversion * thrust / massKg;
                a[0] = a_scalar * thrustDirection.x;
                a[1] = a_scalar * thrustDirection.y;
                a[2] = a_scalar * thrustDirection.z;
            }
            //Debug.Log(string.Format("a=({0}, {1}, {2}) fuel={3}", a[0], a[1], a[2], fuel));
        }

        return(a);
    }
    IEnumerator RotateWorld(bool clockwise)
    {
        rotating         = true;
        movement.gravity = Vector3.zero;

        GravityState oldState = gravityStates[gravityIndex];

        gravityIndex = RangeMath.CycleInt(gravityIndex, gravityStates.Length - 1, clockwise);
        GravityState newState = gravityStates[gravityIndex];

        Quaternion oldRotation = Quaternion.Euler(oldState.objectRotation);
        Quaternion newRotation = Quaternion.Euler(newState.objectRotation);

        float oldZAngle = pivot.localEulerAngles.z;
        float newZAngle = oldZAngle + rotationDegrees * (clockwise ? -1 : 1);

        float timer = 0;

        while (timer < rotationTime)
        {
            timer += Time.deltaTime;
            if (timer > rotationTime)
            {
                timer = rotationTime;
            }

            foreach (Transform rotor in toRotate)
            {
                rotor.rotation = Quaternion.Lerp(oldRotation, newRotation, timer / rotationTime);
            }

            float z = Mathf.Lerp(oldZAngle, newZAngle, timer / rotationTime);
            VectorMath.SetZRotation(pivot, z);

            yield return(null);
        }

        movement.gravity = newState.gravityDirection;
        rotating         = false;
    }
    /// <summary>
    /// Validation:
    /// - confirmed velocity in SI units matches expected orbital velocity of ISS
    /// - checked that SI acceleration = -g at terminal velocity (9.73 m/s^2 at 28 km)
    /// </summary>

    // Use this for initialization
    void Start()
    {
        if (inertialMassKg == 0)
        {
            Debug.LogError("Mass is zero. Drag calculation will fail.");
        }
        if (spaceship == null)
        {
            spaceship = GetComponent <NBody>();
        }

        geDistanceToKm = 1;
        v_ship         = new double[] { 0, 0, 0 };
        v_earth        = new double[] { 0, 0, 0 };

        velocityScaleInternalToSI = GravityScaler.VelocityScaletoSIUnits() / GravityScaler.GetVelocityScale();
        accelSItoGE = GravityScaler.AccelSItoGEUnits() / GravityScaler.AccelerationScaleInternalToGEUnits();

        LoadDensityProfile();

        liveState = GravityEngine.Instance().GetWorldState();
    }
Beispiel #27
0
    // clone constructor
    public GravityState(GravityState fromState)
    {
        m            = new double[fromState.arraySize];
        r            = new double[fromState.arraySize, GravityEngine.NDIM];
        physicalTime = new double[System.Enum.GetNames(typeof(Evolvers)).Length];
        arraySize    = fromState.arraySize;

        for (int i = 0; i < physicalTime.Length; i++)
        {
            physicalTime[i] = fromState.physicalTime[i];
        }
        time = fromState.time;

        for (int i = 0; i < arraySize; i++)
        {
            m[i] = fromState.m[i];
            for (int j = 0; j < GravityEngine.NDIM; j++)
            {
                r[i, j] = fromState.r[i, j];
            }
        }
    }
Beispiel #28
0
 void Start()
 {
     worldState  = GravityEngine.Instance().GetWorldState();
     accelGEtoSI = GravityScaler.AccelerationScaleInternalToGEUnits() / GravityScaler.AccelSItoGEUnits();
 }
    /// <summary>
    /// Evolves particles using massice bodies the with force delegate provided.
    /// </summary>
    /// <returns>The with force.</returns>
    /// <param name="evolveTime">Evolve time.</param>
    /// <param name="numBodies">Number bodies.</param>
    /// <param name="m">M.</param>
    /// <param name="r_m">R m.</param>
    /// <param name="size2">Size2.</param>
    /// <param name="info">Info.</param>
    /// <param name="force">Force.</param>
    public double EvolveWithForce(double evolveTime,
                                  int numBodies,
                                  GravityState gravityState,
                                  ref double[] size2,
                                  ref byte[] info,
                                  IForceDelegate force)
    {
        // do nothing if all inactive
        if (inactive == null || allInactive)
        {
            return(evolveTime);                 // Particle system has not init-ed yet or is done
        }
        //  (did not work in Start() -> Unity bug? Init sequencing?)
        if (!playing)
        {
            gravityParticles.Play();
            playing = true;
        }
        double[] m = gravityState.m;
        double[,] r_m = gravityState.r;

        ParticleLifeCycleHandler(numBodies, gravityState, ref info);
        //
        // physics integration of particles in the field of the masses passed in by NBE
        //
        double time = 0;

        while (time < evolveTime)
        {
            time += dt;
            // Update v and r
            for (int i = 0; i < particleCount; i++)
            {
                if (!inactive[i])
                {
                    v[i, 0] += a[i, 0] * 0.5 * dt;
                    r[i, 0] += v[i, 0] * dt;
                    v[i, 1] += a[i, 1] * 0.5 * dt;
                    r[i, 1] += v[i, 1] * dt;
                    v[i, 2] += a[i, 2] * 0.5 * dt;
                    r[i, 2] += v[i, 2] * dt;
                }
            }
            // advance acceleration
            double[] rji = new double[GravityState.NDIM];
            double   r2;               // r squared
            double   r_sep;            // r
            double   accel;
            // a = 0
            for (int i = 0; i < particleCount; i++)
            {
                a[i, 0] = 0.0;
                a[i, 1] = 0.0;
                a[i, 2] = 0.0;
            }
            // calc a
            for (int i = 0; i < numBodies; i++)
            {
                // check mass has inactive clear
                if ((info[i] & GravityEngine.INACTIVE) == 0)
                {
                    for (int j = 0; j < particleCount; j++)
                    {
                        // only evolve active particles
                        if (!inactive[j])
                        {
                            rji[0] = r[j, 0] - r_m[i, 0];
                            rji[1] = r[j, 1] - r_m[i, 1];
                            rji[2] = r[j, 2] - r_m[i, 2];
                            // Particles that have moved outside of view are marked inactive

                            r2 = rji[0] * rji[0] + rji[1] * rji[1] + rji[2] * rji[2];
                            // Check for incursion on massive bodies and inactivate particles that have collided
                            // (Do not want to incur collider overhead per particle)
                            if (allowRemoval && r2 < size2[i])
                            {
                                inactive[j] = true;
                                inactiveCount++;
                                                                #pragma warning disable 162             // disable unreachable code warning
                                if (debugLogs)
                                {
                                    Debug.Log(string.Format("Inactivate particle {0} size2={1} due to object at {2} {3} {4} r2={5} count={6} p={7} {8}",
                                                            j, size2[i], r_m[i, 0], r_m[i, 1], r_m[i, 2], r2, inactiveCount, r[j, 0], r[j, 1]));
                                }
                                                                #pragma warning restore 162
                                if (oneTimeBurst)
                                {
                                    r[j, 0] = OUT_OF_VIEW;
                                }
                                else
                                {
                                    particles[j].remainingLifetime = 0;
                                }
                                continue;
                            }
                            r_sep    = System.Math.Sqrt(r2) + EPSILON;
                            accel    = force.CalcPseudoForce(r_sep, i, j);
                            a[j, 0] -= m[i] * accel * (rji[0] / r_sep);
                            a[j, 1] -= m[i] * accel * (rji[1] / r_sep);
                            a[j, 2] -= m[i] * accel * (rji[2] / r_sep);
                        }         // for j
                    }             // info
                }                 // for i
            }
            // update velocity
            for (int i = 0; i < particleCount; i++)
            {
                if (!inactive[i])
                {
                    v[i, 0] += a[i, 0] * 0.5 * dt;
                    v[i, 1] += a[i, 1] * 0.5 * dt;
                    v[i, 2] += a[i, 2] * 0.5 * dt;
                }
            }
        }         // while
        return(time);
    }
    //
    // Emmisive particle management
    // - per cycle look for new particles or cases where particles expired and were shuffled
    //

    void ParticleLifeCycleHandler(int numBodies, GravityState gravityState, ref byte[] info)
    {
        // Particle life cycle management
        // - need GetParticles() call to get the correct number of active particle (p.particleCount did not work)
        // - IIUC this is a re-copy and it would be better to avoid this if possible
        particleCount = gravityParticles.GetParticles(particles);
        if (lastParticleCount < particleCount)
        {
            // there are new particles
            if (particlesInit != null)
            {
                particlesInit.InitNewParticles(lastParticleCount, gravityParticles.particleCount, ref r, ref v);
                // apply mass scale to particle velocities
            }
            else
            {
                NoInitDelegateSetup(lastParticleCount, gravityParticles.particleCount);
            }
            PreEvolve(lastParticleCount, gravityParticles.particleCount, numBodies, gravityState, ref info);
            for (int i = lastParticleCount; i < gravityParticles.particleCount; i++)
            {
                inactive[i] = false;
                seed[i]     = particles[i].randomSeed;
                particleBySeed[particles[i].randomSeed] = i;
            }
            lastParticleCount = gravityParticles.particleCount;
        }
        if (oneTimeBurst)
        {
            // not doing life cycle for this particle system
            return;
        }
        // Check if any existing particles were replaced.
        // As particles expire, Unity will move particles from the end down into their slot and reduce
        // the number of active particles. Need to detect this and move their physics data.
        // This makes emmisive particle systems more CPU intensive.
        for (int i = 0; i < gravityParticles.particleCount; i++)
        {
            if (seed[i] != particles[i].randomSeed)
            {
                                #pragma warning disable 162             // disable unreachable code warning
                if (debugLogs)
                {
                    Debug.Log("Seed changed was:" + seed[i] + " now:" + particles[i].randomSeed);
                }
                                #pragma warning restore 162
                // particle has been replaced
                particleBySeed.Remove(seed [i]);
                // remove old seed from hash
                if (particleBySeed.ContainsKey(particles[i].randomSeed))
                {
                    // particle was moved - copy physical data down
                    int oldIndex = particleBySeed[particles[i].randomSeed];
                    for (int k = 0; k < 3; k++)
                    {
                        r [i, k] = r [oldIndex, k];
                        v [i, k] = v [oldIndex, k];
                        a [i, k] = a [oldIndex, k];
                    }
                    particleBySeed [particles[i].randomSeed] = i;
                                        #pragma warning disable 162             // disable unreachable code warning
                    if (debugLogs)
                    {
                        Debug.Log("Shuffling particle from " + oldIndex + " to " + i + " vel=" + v[i, 0] + " " + v[i, 1]);
                    }
                                        #pragma warning restore 162
                }
                else
                {
                                        #pragma warning disable 162             // disable unreachable code warning
                    if (debugLogs)
                    {
                        Debug.Log("Reusing particle " + i + " vel=" + particles[i].velocity);
                    }
                                        #pragma warning restore 162
                    if (particlesInit != null)
                    {
                        particlesInit.InitNewParticles(i, i + 1, ref r, ref v);
                    }
                    else
                    {
                        NoInitDelegateSetup(i, i + 1);
                    }
                    PreEvolve(i, i + 1, numBodies, gravityState, ref info);
                    particleBySeed[particles[i].randomSeed] = i;
                                        #pragma warning disable 162             // disable unreachable code warning
                    if (debugLogs)
                    {
                        Debug.Log("Post-Setup Reusing particle " + i + " v[i,0]=" + v[i, 0] + " v[i,1]=" + v[i, 1]);
                    }
                                        #pragma warning restore 162
                }
                seed[i]     = particles[i].randomSeed;
                inactive[i] = false;
            }
        }
    }
Beispiel #31
0
    /// <summary>
    /// Evolves using the force delegate. Internals differ slightly and for effeciency do not want
    /// a conditional on forceDelegate in the inner loop.
    ///
    /// </summary>
    /// <returns>The force delegate.</returns>
    /// <param name="time">Time.</param>
    /// <param name="m">M.</param>
    /// <param name="r">The red component.</param>
    /// <param name="info">Info.</param>
    private double EvolveForceDelegate(double time, GravityState gravityState, ref byte[] info)
    {
        int numSteps = 0;

        double[] m = gravityState.m;
        double[,] r = gravityState.r;
        // advance acceleration
        double r2;
        double r_sep;
        double f;

        // If objects are fixed want to use their mass but not update their position
        // Better to calc their acceleration and ignore than add an if statement to core loop.
        for (double t = 0; t < time; t += dt)
        {
            numSteps++;
            // Update v and r
            for (int i = 0; i < numBodies; i++)
            {
                if ((info[i] & GravityEngine.FIXED_MOTION) == 0)
                {
                    v[i, 0] += a[i, 0] * 0.5 * dt;
                    r[i, 0] += v[i, 0] * dt;
                    v[i, 1] += a[i, 1] * 0.5 * dt;
                    r[i, 1] += v[i, 1] * dt;
                    v[i, 2] += a[i, 2] * 0.5 * dt;
                    r[i, 2] += v[i, 2] * dt;
                }
            }

            // a = 0
            for (int i = 0; i < numBodies; i++)
            {
                a[i, 0] = 0.0;
                a[i, 1] = 0.0;
                a[i, 2] = 0.0;
            }
            // calc a
            for (int i = 0; i < numBodies; i++)
            {
                if ((info[i] & GravityEngine.INACTIVE) == 0)
                {
                    for (int j = i + 1; j < numBodies; j++)
                    {
                        if ((info[j] & GravityEngine.INACTIVE) == 0)
                        {
                            // O(N^2) in here, unpack loops to optimize
                            r2       = 0;
                            rji[0]   = r[j, 0] - r[i, 0];
                            r2      += rji[0] * rji[0];
                            rji[1]   = r[j, 1] - r[i, 1];
                            r2      += rji[1] * rji[1];
                            rji[2]   = r[j, 2] - r[i, 2];
                            r2      += rji[2] * rji[2];
                            r_sep    = System.Math.Sqrt(r2) + EPSILON;
                            f        = forceDelegate.CalcF(r_sep);
                            a[i, 0] += m[j] * f * (rji[0] / r_sep);
                            a[i, 1] += m[j] * f * (rji[1] / r_sep);
                            a[i, 2] += m[j] * f * (rji[2] / r_sep);

                            a[j, 0] -= m[i] * f * (rji[0] / r_sep);
                            a[j, 1] -= m[i] * f * (rji[1] / r_sep);
                            a[j, 2] -= m[i] * f * (rji[2] / r_sep);
                        }
                    }
                }
            }
            // update velocity
            for (int i = 0; i < numBodies; i++)
            {
                if ((info[i] & GravityEngine.FIXED_MOTION) == 0)
                {
                    v[i, 0] += a[i, 0] * 0.5 * dt;
                    v[i, 1] += a[i, 1] * 0.5 * dt;
                    v[i, 2] += a[i, 2] * 0.5 * dt;
                    //DebugBody(i, ref m, ref r, "evolve");
                }
            }
            // coll_time code
        }
        return(numSteps * dt);
    }