shape-runtime 0.3.0

Bytecode compiler, builtins, and runtime infrastructure for Shape
Documentation
/// @module std::physics::mechanics
/// Physics Mechanics
///
/// Basic step functions for common mechanics systems.

function vec_add(a, b) {
    let mut out = [];
    for i in range(0, a.len()) {
        out.push(a[i] + b[i]);
    }
    out
}

function vec_scale(a, s) {
    let mut out = [];
    for i in range(0, a.len()) {
        out.push(a[i] * s);
    }
    out
}

/// Projectile step (no drag)
///
/// @param state - ProjectileState
/// @param dt - time step
/// @param g - gravity (positive, downward)
pub fn projectile_step(state, dt, g = 9.81) {
    let new_x = state.x + state.vx * dt;
    let new_y = state.y + state.vy * dt - 0.5 * g * dt * dt;
    let new_vy = state.vy - g * dt;

    {
        x: new_x,
        y: new_y,
        vx: state.vx,
        vy: new_vy,
        t: state.t + dt
    }
}

/// Spring-mass oscillator step (1D)
///
/// @param state - OscillatorState
/// @param k - spring constant
/// @param m - mass
/// @param dt - time step
/// @param damping - damping coefficient
pub fn spring_mass_step(state, k, m, dt, damping = 0.0) {
    let a = -(k / m) * state.x - (damping / m) * state.v;
    let v_next = state.v + a * dt;
    let x_next = state.x + v_next * dt;

    {
        x: x_next,
        v: v_next
    }
}

/// Single step for n-body gravitational system
///
/// @param particles - array of Particle
/// @param dt - time step
/// @param G - gravitational constant
pub fn n_body_step(particles, dt, G = 1.0) {
    let n = particles.len();
    let mut acc = [];

    for i in range(0, n) {
        acc.push([0.0, 0.0, 0.0]);
    }

    // Compute pairwise accelerations
    for i in range(0, n) {
        for j in range(i + 1, n) {
            let pi = particles[i];
            let pj = particles[j];
            let dx = pj.position[0] - pi.position[0];
            let dy = pj.position[1] - pi.position[1];
            let dz = pj.position[2] - pi.position[2];
            let dist2 = dx * dx + dy * dy + dz * dz + 0.000000001;
            let dist = sqrt(dist2);
            let inv = G / (dist2 * dist);

            let ax = inv * pj.mass * dx;
            let ay = inv * pj.mass * dy;
            let az = inv * pj.mass * dz;

            acc[i] = vec_add(acc[i], [ax, ay, az]);
            acc[j] = vec_add(acc[j], [-inv * pi.mass * dx, -inv * pi.mass * dy, -inv * pi.mass * dz]);
        }
    }

    let mut updated = [];
    for i in range(0, n) {
        let p = particles[i];
        let v_next = vec_add(p.velocity, vec_scale(acc[i], dt));
        let pos_next = vec_add(p.position, vec_scale(v_next, dt));
        updated.push({
            position: pos_next,
            velocity: v_next,
            mass: p.mass
        });
    }

    updated
}