using System; using System.Collections.Generic; using System.Linq; using System.Text; using Azimuth; namespace Lodestone { /// /// Basically all bodies which are directly or indirectly constrained /// to each other (eg: touching each other) form an island. /// /// The purpose of an island is to allow all simultaneous collisions to be /// solved jointly, efficiently, and without jitter. /// public class Island { public IList Constraints { get; protected set; } public IList Bodies { get; protected set; } /// /// The center of mass of the island. Barring external forces, this should obey a ballistic trajectory. /// public Vector CenterOfMass { get; protected set; } private ulong _currentTimeUnits = 0; private Scalar _currentTimeFraction = 0; private void UpdateSimulationTime(Scalar deltaTime) { Scalar units = Math.Floor(deltaTime); // This should be safe except for very very very large deltaTime where 1.0 is not representable in the epsilon. Scalar fraction = deltaTime - units; _currentTimeFraction += fraction; while (_currentTimeFraction.Value >= 1.0) // we want an exact check { _currentTimeFraction--; units++; } // This should always be safe _currentTimeUnits += (ulong)units; } /// /// Steps the motion of the island forward by deltaTime. /// public void Step(Scalar deltaTime, Solvers.Solver solver, Scalar stepSize) { if (deltaTime < 0) { throw new Exception("Negative timesteps are not presently supported."); } if (deltaTime == 0) { throw new Exception("Trying to step the island with a timestep that is " + "indistinguishable from 0."); } UpdateSimulationTime(deltaTime); ConstrainAndIntegrateAcceleraton(solver); //Solver.SolveAndIntegrateIsland(this, } public void ConstrainAndIntegrateAcceleraton(Solvers.Solver solver) { // Flush all the accumulated forces to accumulated accelerations. IList deltaLinearVelocity; IList deltaAngularVelocity; // Now solve for delta velocities solver.SolveIsland( Bodies, Constraints, Lodestone.Solvers.SolverLevel.ACCELERATION, out deltaLinearVelocity, out deltaAngularVelocity); // Now update for (int i = 0; i < Bodies.Count; ++i) { //Bodies[i].ResetAccumulatedForcesAndTorques(); Bodies[i].Motion.Velocity += deltaLinearVelocity[i]; Bodies[i].Motion.AngularVelocity += deltaAngularVelocity[i]; } } public void ConstrainVelocity(Scalar deltaTime, IList deltaLinearVelocity, IList deltaAngularVelocity, out IList newLinearVelocity, out IList newAngularVelocity) { newLinearVelocity = new List(deltaLinearVelocity.Count); newAngularVelocity = new List(deltaAngularVelocity.Count); } ///// ///// Will split the given island into smaller child islands ///// if it's possible to do so. ///// //public static IList SplitIslandIfPossible(Island island) //{ // var childIslands = new List(); // while (island.Collisions.Count > 0) // { // List next = new List(); // next.Add(collisions.First()); // collisions.RemoveAt(0); // for (int i = 0; i < next.Count && collisions.Count > 0; i++) // { // for (int x = collisions.Count - 1; x >= 0 && collisions.Count > 0; x--) // { // if(next[i].Related(collisions[x])) // { // next.Add(collisions[x]); // collisions.RemoveAt(x); // } // } // } // islands.Add(next); // } // Island[] value = new Island[islands.Count]; // for (int i = 0; i < value.Length; i++) // { // value[i] = new Island(islands[i]); // } // return value; //} /// /// Will solve the constraints in the island. /// /// NOTE! This is very very slow. /// //public void SolveIslandConstraints() //{ // if(Constrain // //Do collisions here // //Only changes velocity, not position // //Directly modifies the bodies // if (Count < 1) // { // return; // } // //simple collision // if (Count == 1) // { // CollisionPhysics.SimpleCollision(this); // } // else//Multiple collision // { // CollisionPhysics.MultipleCollision(this); // } //} internal int GetIndexOfBody(Body body) { throw new NotImplementedException(); } } }