use crate::sim::config::{SimConfig, Softness};
use crate::sim::contact::Manifold;
use crate::sim::joint::{JointSolver, Prepared, Push};
use crate::sim::math::vec3;
use super::bodies::Bodies;
use super::contact::{self, ContactConstraint};
#[derive(Default)]
pub(crate) struct Chunk<'a> {
pub(crate) bodies: Bodies<'a>,
pub(crate) active: &'a [u32],
pub(crate) constraints: &'a mut [ContactConstraint],
pub(crate) contact_source: &'a [u32],
pub(crate) joints: &'a mut [Prepared],
}
pub(crate) struct Tuning<'a> {
pub(crate) manifolds: &'a [Manifold],
pub(crate) config: &'a SimConfig,
pub(crate) substeps: u32,
pub(crate) h: f32,
pub(crate) inv_h: f32,
pub(crate) soft: Softness,
pub(crate) joint_biased: Push,
pub(crate) joint_rigid: Push,
}
pub(crate) fn run(chunk: &mut Chunk<'_>, tuning: &Tuning<'_>) {
contact::prepare(
chunk.constraints,
chunk.contact_source,
tuning.manifolds,
&chunk.bodies,
);
for _ in 0..tuning.substeps {
integrate_velocities(chunk, tuning.config.gravity, tuning.h);
JointSolver::warm_start(chunk.joints, &mut chunk.bodies);
contact::warm_start(chunk.constraints, &mut chunk.bodies);
JointSolver::solve(
chunk.joints,
&mut chunk.bodies,
&tuning.joint_biased,
tuning.h,
);
contact::solve(
chunk.constraints,
&mut chunk.bodies,
&tuning.soft,
tuning.config,
tuning.inv_h,
true,
);
integrate_positions(chunk, tuning.h);
JointSolver::refresh(chunk.joints, &chunk.bodies);
JointSolver::solve(
chunk.joints,
&mut chunk.bodies,
&tuning.joint_rigid,
tuning.h,
);
contact::solve(
chunk.constraints,
&mut chunk.bodies,
&Softness::RIGID,
tuning.config,
tuning.inv_h,
false,
);
}
contact::apply_restitution(chunk.constraints, &mut chunk.bodies, tuning.config);
}
fn integrate_velocities(chunk: &mut Chunk<'_>, gravity: f32, h: f32) {
let pull = vec3(0.0, -gravity, 0.0);
let Chunk { bodies, active, .. } = chunk;
for &slot in active.iter() {
let body = bodies.get_mut(slot);
body.linear_velocity += pull * (body.gravity_scale * h);
let decay = 1.0 / (1.0 + h * body.damping);
body.linear_velocity = body.linear_velocity * decay;
body.angular_velocity = body.angular_velocity * decay;
}
}
fn integrate_positions(chunk: &mut Chunk<'_>, h: f32) {
let Chunk { bodies, active, .. } = chunk;
for &slot in active.iter() {
bodies.get_mut(slot).integrate_position(h);
}
}