physics2d 0.6.0

Yet another 2D physics engine, but with Iron power.
Documentation
mod transform;
mod collections;
mod body;
pub mod debug;

pub use self::body::{Body, BodyId, Material};
pub use self::transform::Transform;
pub(crate) use self::body::BodyPair;
pub(crate) use self::collections::{Bodies, ConstraintsMap};

use self::collections::{ConstraintSolverMap};
use collision::{ContactConstraint, collide};
use collision::broad_phase::{BroadPhase, NaiveBroadPhase, BoundsTreeBroadPhase};
use joint::Joint;

pub struct World {
    bodies: Bodies,
    
    broad_phase: BoundsTreeBroadPhase,
    
    contact_constraints: ConstraintsMap<ContactConstraint>,
    joints: ConstraintsMap<Joint>,
    
    pub velocity_iterations: u8,
    pub position_iterations: u8,
}

impl Default for World {
    fn default() -> World {
        World::new(8, 2)
    }
}

impl World {
    pub fn new(velocity_iterations: u8, position_iterations: u8) -> World {
        World {
            bodies: Bodies::default(),
            broad_phase: BoundsTreeBroadPhase::new(),
            contact_constraints: ConstraintsMap::default(),
            joints: ConstraintsMap::default(),
            velocity_iterations,
            position_iterations,
        }
    }
    
    pub fn add_body(&mut self, mut body: Body) -> BodyId {
        body.proxy_id = self.broad_phase.create_proxy(&body);
        self.bodies.add(body)
    }
    
    pub fn add_joint(&mut self, bodies: (BodyId, BodyId), joint: Joint) {
        let bodies = BodyPair::new(bodies.0, bodies.1);
        let body_joints = self.joints.entry(bodies).or_insert(Vec::new());
        body_joints.push(joint);
    }
    
    pub fn get_joints(&self, bodies: (BodyId, BodyId)) -> Option<&Vec<Joint>> {
        let bodies = BodyPair::new(bodies.0, bodies.1);
        self.joints.get(&bodies)
    }
    
    pub fn get_joints_mut(&mut self, bodies: (BodyId, BodyId)) -> Option<&mut Vec<Joint>> {
        let bodies = BodyPair::new(bodies.0, bodies.1);
        self.joints.get_mut(&bodies)
    }
    
    pub fn get_body(&self, body_id: BodyId) -> &Body {
        &self.bodies[body_id]
    }
    
    pub fn get_body_mut(&mut self, body_id: BodyId) -> &mut Body {
        self.bodies.get_mut(body_id).unwrap()
    }
    
    pub fn bodies_iter(&self) -> impl Iterator<Item=&Body> {
        self.bodies.iter()
    }

    pub fn body_count(&self) -> usize {
        self.bodies.len()
    }
    
    pub fn update(&mut self, dt: f32) {
        for body in self.bodies.iter_mut() {
            body.update(dt);
            self.broad_phase.update_proxy(body.proxy_id, body);
        }
        
        {
            let bodies = &self.bodies;
            self.contact_constraints.retain(|pair, _|
                pair.with(bodies, |a, b| a.bounds.intersects(&b.bounds))
            );
        }
        
        self.broad_phase.new_potential_pairs(&self.bodies, &mut self.contact_constraints);
        
        self.broad_phase.post_update();
        
        {
            let bodies = &self.bodies;
            self.contact_constraints.retain(|pair, constraints| {
                let body_a = &bodies[pair.0];
                let body_b = &bodies[pair.1];
                
                if let Some(new_contacts) = collide(body_a, body_b) {
                    let new_constraints =
                        if !constraints.is_empty() {
                            ContactConstraint::with_persistent_contacts(constraints, &new_contacts)
                        } else {
                            ContactConstraint::with_contacts(&new_contacts)
                        };
                    
                    *constraints = new_constraints;
                    
                    true
                } else {
                    false
                }
            });
        }
        
        for body in self.bodies.iter_mut() {
            body.integrate_force(dt);
        }
        
        self.contact_constraints.initialize_velocity(&mut self.bodies, dt);
        self.contact_constraints.warm_start_velocity(&mut self.bodies, dt);
        
        self.joints.initialize_velocity(&mut self.bodies, dt);
        self.joints.warm_start_velocity(&mut self.bodies, dt);
        
        for _ in 0..self.velocity_iterations {
            self.joints.solve_velocity(&mut self.bodies, dt);
            
            self.contact_constraints.solve_velocity(&mut self.bodies, dt);
        }
        
        for body in self.bodies.iter_mut() {
            body.integrate_velocity(dt);
        }
        
        self.contact_constraints.warm_start_position(&mut self.bodies, dt);
    
        for _ in 0..self.position_iterations {
            self.joints.solve_position(&mut self.bodies, dt);
            
            self.contact_constraints.solve_position(&mut self.bodies, dt);
        }
    }
}