1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#![allow(clippy::new_without_default)]

pub use vek2d;
pub mod contact_generators;
mod contact_resolver;
pub mod force_generators;
mod force_registry;
pub mod particle;
pub mod world;

#[cfg(not(feature = "high_precision"))]
use std::f32::MAX as F32_MAX;
#[cfg(feature = "high_precision")]
use std::f64::MAX as F64_MAX;

#[cfg(not(feature = "high_precision"))]
pub type FP = f32;
#[cfg(not(feature = "high_precision"))]
pub const FP_MAX: f32 = F32_MAX;

#[cfg(feature = "high_precision")]
pub type FP = f64;
#[cfg(feature = "high_precision")]
pub const FP_MAX: f64 = F64_MAX;

#[cfg(test)]
mod tests {
    use crate::contact_generators::GroundContact;
    use crate::force_generators::{AnchoredSpring, Drag, Gravity};
    use crate::particle::Particle;
    use crate::vek2d::Vec2d;
    use crate::world::World;

    #[test]
    fn setup() {
        // max_contacts, iterations
        let mut world = World::new(100, 1000, None);

        let mut particle = Particle::new(1.0, 0.3);
        particle.set_position(Vec2d::new(1.0, 100.0));
        let pid1 = world.add_particle(particle).unwrap();
        let ptr1 = world.get_particle_ptr(pid1).unwrap();

        let mut particle = Particle::new(1.0, 0.3);
        particle.set_position(Vec2d::new(1.0, 100.0));
        let pid2 = world.add_particle(particle).unwrap();
        let ptr2 = world.get_particle_ptr(pid2).unwrap();

        let mut particle = Particle::new(1.0, 0.2);
        particle.set_position(Vec2d::new(1.0, 100.0));
        let pid3 = world.add_particle(particle).unwrap();
        let ptr3 = world.get_particle_ptr(pid3).unwrap();

        // Insert force gen
        world.add_force_generator(Gravity::new(ptr1, -9.81));
        world.add_force_generator(Drag::new(ptr1, 1.0, 1.0));

        world.add_force_generator(Gravity::new(ptr2, -9.81));
        world.add_force_generator(Drag::new(ptr2, 1.0, 1.0));

        world.add_force_generator(Gravity::new(ptr3, -9.81));
        world.add_force_generator(Drag::new(ptr3, 1.0, 1.0));

        // Insert contact gen
        world.add_contact_generator(GroundContact::new());

        // RUN
        for _ in 0..10000 {
            world.start_frame();
            world.run_physics(0.01);
        }

        //assert_eq!(bodies[&0].position, bodies[&1].position);
        assert_ne!(
            world.get_particle_position(pid2).unwrap(),
            world.get_particle_position(pid3).unwrap()
        );
        let floor = world.get_particle_position(pid1).unwrap().y().floor();
        assert!(floor >= 0.0 && floor < f64::EPSILON);
    }

    #[test]
    fn test_springs() {
        // max_contacts, iterations
        let mut world = World::new(100, 1000, None);

        let mut particle = Particle::new(1.0, 0.3);
        particle.set_position(Vec2d::new(2.0, 1000.0));
        let pid1 = world.add_particle(particle).unwrap();
        let ptr1 = world.get_particle_ptr(pid1).unwrap();

        // Insert force gen
        world.add_force_generator(AnchoredSpring::new(
            ptr1,
            Vec2d::new(2.0, 100.0),
            1.0,
            100.0,
        ));

        // RUN
        for _ in 0..500 {
            world.start_frame();
            world.run_physics(0.1);
        }

        assert!(
            world.get_particle_position(pid1).unwrap().y() < 201.0
                && world.get_particle_position(pid1).unwrap().y() > 199.0
        );
    }
}