Fixed 3D rendering
This commit is contained in:
parent
adf53b7703
commit
6d9bdae160
@ -1,5 +1,5 @@
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use cgmath::Vector3;
|
use cgmath::{InnerSpace, Vector3};
|
||||||
use crate::body::Body;
|
use crate::body::Body;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
@ -11,10 +11,9 @@ pub struct Simulator {
|
|||||||
timewarp: u32
|
timewarp: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn distance_squared(a: [f64; 2], b: [f64; 2]) -> f64 {
|
pub fn distance_squared(a: Vector3<f64>, b: Vector3<f64>) -> f64 {
|
||||||
let dx = a[0] - b[0];
|
let d = a - b;
|
||||||
let dy = a[1] - b[1];
|
d.magnitude2()
|
||||||
dx * dx + dy * dy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_TIMEWARP: u32 = 536870912;
|
const MAX_TIMEWARP: u32 = 536870912;
|
||||||
@ -52,78 +51,62 @@ impl Simulator {
|
|||||||
|
|
||||||
let masses: Vec<f64> = self.bodies.iter().map(|b| b.mass).collect();
|
let masses: Vec<f64> = self.bodies.iter().map(|b| b.mass).collect();
|
||||||
|
|
||||||
fn compute_accelerations(states: &[State], masses: &[f64]) -> Vec<[f64; 2]> {
|
fn compute_accelerations(states: &[State], masses: &[f64]) -> Vec<Vector3<f64>> {
|
||||||
let n = states.len();
|
let n = states.len();
|
||||||
let accels = (0..n).map(|_| Mutex::new([0.0, 0.0])).collect::<Vec<_>>();
|
let accels = (0..n).map(|_| Mutex::new(Vector3::new(0.0, 0.0, 0.0))).collect::<Vec<_>>();
|
||||||
|
|
||||||
(0..n).into_par_iter().for_each(|i| {
|
(0..n).into_par_iter().for_each(|i| {
|
||||||
for j in (i + 1)..n {
|
for j in (i + 1)..n {
|
||||||
let dx = states[j].position[0] - states[i].position[0];
|
let r = states[j].position - states[i].position;
|
||||||
let dy = states[j].position[1] - states[i].position[1];
|
let dist_sq = r.magnitude2();
|
||||||
let dist_sq = dx * dx + dy * dy;
|
|
||||||
let dist = dist_sq.sqrt();
|
let dist = dist_sq.sqrt();
|
||||||
|
|
||||||
if dist < 1e-3 {
|
if dist < 1e-8 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let force = G * masses[i] * masses[j] / dist_sq;
|
let force = G * masses[i] * masses[j] / dist_sq;
|
||||||
let ax = force * dx / dist;
|
let accel = force * r / (dist * masses[i]);
|
||||||
let ay = force * dy / dist;
|
let accel_j = -force * r / (dist * masses[j]);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut a_i_lock = accels[i].lock().unwrap();
|
let mut a_i_lock = accels[i].lock().unwrap();
|
||||||
a_i_lock[0] += ax / masses[i];
|
*a_i_lock += accel;
|
||||||
a_i_lock[1] += ay / masses[i];
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut a_j_lock = accels[j].lock().unwrap();
|
let mut a_j_lock = accels[j].lock().unwrap();
|
||||||
a_j_lock[0] -= ax / masses[j];
|
*a_j_lock += accel_j;
|
||||||
a_j_lock[1] -= ay / masses[j];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
accels
|
accels.into_iter().map(|mutex| mutex.into_inner().unwrap()).collect()
|
||||||
.into_iter()
|
|
||||||
.map(|mutex| mutex.into_inner().unwrap())
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let k1_pos = original_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
let k1_pos = original_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
||||||
let k1_vel = compute_accelerations(&original_states, &masses);
|
let k1_vel = compute_accelerations(&original_states, &masses);
|
||||||
|
|
||||||
let mut temp_states = original_states
|
let mut temp_states: Vec<State> = original_states.iter().enumerate().map(|(i, s)| {
|
||||||
.iter()
|
State {
|
||||||
.enumerate()
|
position: s.position + k1_pos[i] * (dt / 2.0),
|
||||||
.map(|(i, s)| State {
|
velocity: s.velocity + k1_vel[i] * (dt / 2.0),
|
||||||
position: Vector3::new(s.position[0], s.position[1], 0.0),
|
}
|
||||||
velocity: Vector3::new(
|
}).collect();
|
||||||
s.velocity[0] + k1_vel[i][0] * dt / 2.0,
|
|
||||||
s.velocity[1] + k1_vel[i][1] * dt / 2.0,
|
|
||||||
0.0,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let k2_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
let k2_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
||||||
let k2_vel = compute_accelerations(&temp_states, &masses);
|
let k2_vel = compute_accelerations(&temp_states, &masses);
|
||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
temp_states[i].position[0] = original_states[i].position[0] + k2_pos[i][0] * dt / 2.0;
|
temp_states[i].position = original_states[i].position + k2_pos[i] * (dt / 2.0);
|
||||||
temp_states[i].position[1] = original_states[i].position[1] + k2_pos[i][1] * dt / 2.0;
|
temp_states[i].velocity = original_states[i].velocity + k2_vel[i] * (dt / 2.0);
|
||||||
temp_states[i].velocity[0] = original_states[i].velocity[0] + k2_vel[i][0] * dt / 2.0;
|
|
||||||
temp_states[i].velocity[1] = original_states[i].velocity[1] + k2_vel[i][1] * dt / 2.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let k3_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
let k3_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
||||||
let k3_vel = compute_accelerations(&temp_states, &masses);
|
let k3_vel = compute_accelerations(&temp_states, &masses);
|
||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
temp_states[i].position[0] = original_states[i].position[0] + k3_pos[i][0] * dt;
|
temp_states[i].position = original_states[i].position + k3_pos[i] * dt;
|
||||||
temp_states[i].position[1] = original_states[i].position[1] + k3_pos[i][1] * dt;
|
temp_states[i].velocity = original_states[i].velocity + k3_vel[i] * dt;
|
||||||
temp_states[i].velocity[0] = original_states[i].velocity[0] + k3_vel[i][0] * dt;
|
|
||||||
temp_states[i].velocity[1] = original_states[i].velocity[1] + k3_vel[i][1] * dt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let k4_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
let k4_pos = temp_states.iter().map(|s| s.velocity).collect::<Vec<_>>();
|
||||||
@ -132,15 +115,8 @@ impl Simulator {
|
|||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let body = &mut self.bodies[i];
|
let body = &mut self.bodies[i];
|
||||||
|
|
||||||
body.position[0] += (dt / 6.0)
|
body.position += (k1_pos[i] + 2.0 * k2_pos[i] + 2.0 * k3_pos[i] + k4_pos[i]) * (dt / 6.0);
|
||||||
* (k1_pos[i][0] + 2.0 * k2_pos[i][0] + 2.0 * k3_pos[i][0] + k4_pos[i][0]);
|
body.velocity += (k1_vel[i] + 2.0 * k2_vel[i] + 2.0 * k3_vel[i] + k4_vel[i]) * (dt / 6.0);
|
||||||
body.position[1] += (dt / 6.0)
|
|
||||||
* (k1_pos[i][1] + 2.0 * k2_pos[i][1] + 2.0 * k3_pos[i][1] + k4_pos[i][1]);
|
|
||||||
|
|
||||||
body.velocity[0] += (dt / 6.0)
|
|
||||||
* (k1_vel[i][0] + 2.0 * k2_vel[i][0] + 2.0 * k3_vel[i][0] + k4_vel[i][0]);
|
|
||||||
body.velocity[1] += (dt / 6.0)
|
|
||||||
* (k1_vel[i][1] + 2.0 * k2_vel[i][1] + 2.0 * k3_vel[i][1] + k4_vel[i][1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.time += dt;
|
self.time += dt;
|
||||||
@ -170,7 +146,6 @@ impl Simulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn reset_timewarp(&mut self) {
|
pub fn reset_timewarp(&mut self) {
|
||||||
self.timewarp = 1;
|
self.timewarp = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user