Ejemplo n.º 1
0
    private void EvolveForTimestep(GravityEngine ge, double physicsDt)
    {
        // if everything is on rails, can just jump to the end time
        if (onRails)
        {
            time += physicsDt;
            MoveFixedBodies(time);
            // Keep these up-to-date so can flip to off-rails if needed
            physicalTime[(int)Evolvers.MASSIVE]   = time;
            physicalTime[(int)Evolvers.MASSLESS]  = time;
            physicalTime[(int)Evolvers.PARTICLES] = time;
            return;
        }
        // Objective is to keep physical time proportional to game time
        // Each integrator will run for at least as long as it is told but may overshoot
        // so correct time on next iteration.
        //
        // Keep the current physical time each integrator has reached in physicalTime[integrator_type]
        //
        double engineDt = ge.engineDt;

        if (physicsDt < engineDt)
        {
            return;
        }

        double timeEvolved = 0;

        // Need to move the integrators forward concurrently in steps matching the engineDt
        // - Hermite may be using a different timestep than this
        // - particles likely use a much longer timestep

        while (timeEvolved < physicsDt)
        {
            //==============================
            // Massive bodies
            //==============================
            // evolve all the massive game objects
            double massiveDt = 0.0;
            if (numBodies > fixedBodiesInIntegrator)
            {
                // typical path - have massive bodies: use NBody integration
                massiveDt = integrator.Evolve(engineDt, this, ref info);
                physicalTime[(int)Evolvers.MASSIVE] += massiveDt;
                timeEvolved += massiveDt;
            }
            else
            {
                // all Kepler mode: skip integration
                physicalTime[(int)Evolvers.MASSIVE] += engineDt;
                timeEvolved += engineDt;
            }

            //==============================
            // Fixed Bodies
            //==============================
            // Update fixed update objects (if any)
            // Evolution is to a specific time - so use massive object physical time
            MoveFixedBodies(physicalTime[(int)Evolvers.MASSIVE]);

            // Debug.Log(string.Format("gameDt={0} integated={1} ptime={2} wtime={3}", gameDt, dt, physicalTime, worldTime));
            // LF is built in to particles and massless routines. They have their own DT built in
            // these run on a fixed timestep (if it is varied energy conservation is wrecked)
            // Track their evolution vs wall clock time seperately

            //==============================
            // Particles (should only be present in worldState)
            //==============================
            if (gravityParticles.Count > 0)
            {
                double particle_dt = ge.GetParticleDt();
                if (physicalTime[(int)GravityState.Evolvers.PARTICLES] <
                    physicalTime[(int)GravityState.Evolvers.MASSIVE])
                {
                    double evolvedFor = 0.0;
                    if (forceDelegate != null)
                    {
                        foreach (GravityParticles nbp in gravityParticles)
                        {
                            evolvedFor = nbp.EvolveWithForce(particle_dt, numBodies, this,
                                                             ref size2, ref info, forceDelegate);
                        }
                    }
                    else
                    {
                        foreach (GravityParticles nbp in gravityParticles)
                        {
                            evolvedFor = nbp.Evolve(particle_dt, numBodies, this, ref size2, ref info);
                        }
                    }
                    physicalTime[(int)Evolvers.PARTICLES] += evolvedFor;
                }
            }

            //==============================
            // Massless
            //==============================
            if (masslessEngine != null && masslessEngine.NumBodies() > 0)
            {
                // rockets need the time
                if (physicalTime[(int)Evolvers.MASSLESS] <
                    physicalTime[(int)Evolvers.MASSIVE])
                {
                    if (forceDelegate != null)
                    {
                        physicalTime[(int)Evolvers.MASSLESS] +=
                            masslessEngine.EvolveWithForce(engineDt, time, numBodies, this, ref info, forceDelegate);
                    }
                    else
                    {
                        physicalTime[(int)Evolvers.MASSLESS] +=
                            masslessEngine.Evolve(engineDt, time, numBodies, this, ref info);
                    }
                }
            }
            // must update time so trajectory times are up to date
            time = physicalTime[(int)Evolvers.MASSIVE];
            if (hasTrajectories)
            {
                ge.UpdateTrajectories();
            }
        } // while
    }