/*
kiss3d = "0.27"
rapier3d = "0.4"
*/
use kiss3d::nalgebra::Point3;
use rapier3d::{
dynamics::{IntegrationParameters, JointSet, RigidBodyBuilder, RigidBodyHandle, RigidBodySet},
geometry::{BroadPhase, ColliderBuilder, ColliderHandle, ColliderSet, NarrowPhase},
math::Vector,
pipeline::PhysicsPipeline,
};
struct World {
pipeline: PhysicsPipeline,
gravity: Vector<f32>,
integration_parameters: IntegrationParameters,
broad_phase: BroadPhase,
narrow_phase: NarrowPhase,
bodies: RigidBodySet,
colliders: ColliderSet,
joints: JointSet,
event_handler: (),
}
#[derive(Debug)]
enum Mass {
BodyMass(f32),
ColliderDensity(f32),
}
impl World {
fn new() -> Self {
Self {
pipeline: PhysicsPipeline::new(),
gravity: Vector::new(0.0, -9.81, 0.0),
integration_parameters: IntegrationParameters::default(),
broad_phase: BroadPhase::new(),
narrow_phase: NarrowPhase::new(),
bodies: RigidBodySet::new(),
colliders: ColliderSet::new(),
joints: JointSet::new(),
event_handler: (),
}
}
fn create_ground(&mut self, hx: f32, hy: f32, hz: f32) -> (RigidBodyHandle, ColliderHandle) {
let body = self.bodies.insert(
RigidBodyBuilder::new_static()
.translation(0.0, -hy, 0.0)
.build(),
);
let collider = self.colliders.insert(
ColliderBuilder::cuboid(hx, hy, hz)
.friction(0.5)
.restitution(0.0)
.build(),
body,
&mut self.bodies,
);
(body, collider)
}
fn create_cuboid(
&mut self,
hx: f32,
hy: f32,
hz: f32,
mass: &Mass,
) -> (RigidBodyHandle, ColliderHandle) {
let (body_mass, collider_contribution, collider_density) = match mass {
Mass::BodyMass(mass) => (*mass, false, None),
Mass::ColliderDensity(density) => (0.0, true, Some(*density)),
};
let body = self.bodies.insert(
RigidBodyBuilder::new_dynamic()
.translation(0.0, hy * 2.0, 0.0)
.rotation(Vector::new(0.0, 0.0, std::f32::consts::FRAC_PI_4 * 0.9))
.mass(body_mass, collider_contribution)
.build(),
);
let mut collider = ColliderBuilder::cuboid(hx, hz, hz)
.friction(0.5)
.restitution(0.0);
if let Some(density) = collider_density {
collider = collider.density(density);
};
let collider = self
.colliders
.insert(collider.build(), body, &mut self.bodies);
(body, collider)
}
fn step(&mut self) {
self.pipeline.step(
&self.gravity,
&self.integration_parameters,
&mut self.broad_phase,
&mut self.narrow_phase,
&mut self.bodies,
&mut self.colliders,
&mut self.joints,
None,
None,
&self.event_handler,
);
}
}
fn main() {
let (floor_hx, floor_hy, floor_hz) = (5.0, 0.5, 5.0);
let (cube_hx, cube_hy, cube_hz) = (0.5, 0.5, 0.5);
let mut window = kiss3d::window::Window::new("");
window.set_light(kiss3d::light::Light::StickToCamera);
let mut camera =
kiss3d::camera::FirstPerson::new(Point3::new(0.0, 1.0, -5.0), Point3::new(0.0, 1.0, 0.0));
let mut floor = window.add_cube(floor_hx * 2.0, floor_hy * 2.0, floor_hz * 2.0);
floor.set_color(0.5, 0.0, 0.0);
let mut cuboid = window.add_cube(cube_hx * 2.0, cube_hy * 2.0, cube_hz * 2.0);
cuboid.set_color(0.0, 0.5, 0.0);
for mass in vec![
Mass::ColliderDensity(0.1),
Mass::BodyMass(0.1),
Mass::ColliderDensity(1.0),
Mass::BodyMass(1.0),
Mass::ColliderDensity(10.0),
Mass::BodyMass(10.0),
Mass::ColliderDensity(100.0),
Mass::BodyMass(100.0),
Mass::ColliderDensity(1000.0),
Mass::BodyMass(1000.0),
] {
println!("starting test with mass {:?}", mass);
let mut world = World::new();
let (floor_body, _) = world.create_ground(floor_hx, floor_hy, floor_hz);
let (cuboid_body, _) = world.create_cuboid(cube_hx, cube_hy, cube_hz, &mass);
let mut step = 0;
loop {
world.step();
window.render_with_camera(&mut camera);
floor.set_local_transformation(*world.bodies.get(floor_body).unwrap().position());
cuboid.set_local_transformation(*world.bodies.get(cuboid_body).unwrap().position());
step += 1;
let body = world.bodies.get(cuboid_body).unwrap();
if !body.is_moving() {
println!("object is resting after {} steps\n", step);
break;
}
if step >= 1000 {
println!("cancelling because still moving after {} steps\n", step);
break;
}
}
}
}