public static void RK4Integrate(ref Vector3d position, ref Vector3d velocity, double dt, PlanetRigidbody self, PlanetAggregator aggr) { Vector3d p1, p2, p3, p4; Vector3d v1, v2, v3, v4; Vector3d a1, a2, a3, a4; p1 = position; v1 = velocity; a1 = aggr.ComputeNetGravity(p1, self); p2 = position + 0.5 * v1 * dt; v2 = velocity + 0.5 * a1 * dt; a2 = aggr.ComputeNetGravity(p2, self); p3 = position + 0.5 * v2 * dt; v3 = velocity + 0.5 * a2 * dt; a3 = aggr.ComputeNetGravity(p3, self); p4 = position + v3 * dt; v4 = velocity + a3 * dt; a4 = aggr.ComputeNetGravity(p4, self); position += (dt / 6.0) * (v1 + 2.0 * v2 + 2.0 * v3 + v4); velocity += (dt / 6.0) * (a1 + 2.0 * a2 + 2.0 * a3 + a4); }
public static void MeanAccelerationIntegrate(ref Vector3d position, ref Vector3d velocity, Vector3d acceleration, double dt, PlanetRigidbody self, PlanetAggregator aggr) { Vector3d expected_position = position + (velocity * dt); Vector3d expected_acceleration = aggr.ComputeNetGravity(expected_position, self); Vector3d new_velocity = velocity + (0.5 * (acceleration + expected_acceleration) * dt); position += 0.5 * (velocity + new_velocity) * dt; velocity = new_velocity; }
public Vector3d ComputeNetGravity(Vector3d position, PlanetRigidbody self) { Vector3d net = Vector3d.zero; foreach (PlanetRigidbody body in bodies) { if (body != self) { net += ComputeGravityForce(position, body); } } return(net); }
void Draw() { // do this kind of iterative thing to do the arc sweeps List <Vector3> positions = new List <Vector3>(); Vector3d position = new Vector3d(transform.position); Vector3d velocity = new Vector3d(transform.forward * speed); Vector3d acceleration = Vector3d.zero; positions.Add(position.ToVector3()); for (int i = 0; i < steps; i++) { //acceleration = aggregator.ComputeNetGravity(position, planet); PlanetRigidbody.RK4Integrate(ref position, ref velocity, timestep, planet, aggregator); positions.Add(position.ToVector3()); } trajectory.positionCount = positions.Count; trajectory.SetPositions(positions.ToArray()); }
public Vector3d ComputeGravityForce(Vector3d position, PlanetRigidbody body) { Vector3d body_pos = new Vector3d( (double)body.transform.position.x, (double)body.transform.position.y, (double)body.transform.position.z ); double r = Vector3d.SqrDistance(position, body_pos); // I'm fine with this approximation because it solves the problem of the div by zero of // objects trying to attract themselves, and two objects centers overlapping is pretty nonsense // conceptually if (r <= Vector3d.MIN_DOUBLE) { return(Vector3d.zero); } double a = (double)body.mass / r; return((body_pos - position).normalized * a); }
void Awake() { aggregator = GameObject.Find("Planet Aggregator").GetComponent <PlanetAggregator>(); planet = GetComponent <PlanetRigidbody>(); trajectory = GetComponent <LineRenderer>(); }
// Here we assume constant acceleration for the duration of the timestep public static void EulerIntegrate(ref Vector3d position, ref Vector3d velocity, Vector3d acceleration, double dt, PlanetRigidbody self, PlanetAggregator aggr) { velocity += acceleration * dt; position += velocity * dt; }