use crate::b2_body::*;
use crate::b2_timer::*;
use crate::b2_world_callbacks::*;
use crate::b2_math::*;
use crate::b2_time_step::*;
use crate::b2_common::*;
use crate::b2rs_common::UserDataType;
use super::b2_island::*;
use crate::private::dynamics::b2_contact_solver::*;
pub(crate) fn solve<D: UserDataType>(self_: &mut B2island<D>, profile: &mut B2Profile, step: &B2timeStep, gravity: B2vec2, allow_sleep: bool)
{
let mut timer = B2timer::default();
let h: f32 = step.dt;
for (i, b) in (&self_.m_bodies).iter().enumerate()
{
let mut b = b.borrow_mut();
let c: B2vec2 = b.m_sweep.c;
let a:f32 = b.m_sweep.a;
let mut v:B2vec2 = b.m_linear_velocity;
let mut w:f32 = b.m_angular_velocity;
b.m_sweep.c0 = b.m_sweep.c;
b.m_sweep.a0 = b.m_sweep.a;
if b.m_type == B2bodyType::B2DynamicBody
{
v += h * b.m_inv_mass * (b.m_gravity_scale * b.m_mass * gravity + b.m_force);
w += h * b.m_inv_i * b.m_torque;
v *= 1.0 / (1.0 + h * b.m_linear_damping);
w *= 1.0 / (1.0 + h * b.m_angular_damping);
}
self_.m_positions[i].c = c;
self_.m_positions[i].a = a;
self_.m_velocities[i].v = v;
self_.m_velocities[i].w = w;
}
timer.reset();
let mut solver_data = B2solverData{
step : *step,
};
let contact_solver_def = B2contactSolverDef
{
step : *step,
};
let mut contact_solver = B2contactSolver::new::<D>(&contact_solver_def, &self_.m_contacts);
contact_solver.initialize_velocity_constraints(&self_.m_positions, &self_.m_velocities, &self_.m_contacts);
if step.warm_starting
{
contact_solver.warm_start(&mut self_.m_velocities);
}
for j in &self_.m_joints
{
j.borrow_mut().init_velocity_constraints(&mut solver_data, &mut self_.m_positions, &mut self_.m_velocities);
}
profile.solve_init = timer.get_milliseconds();
timer.reset();
for _i in 0..step.velocity_iterations
{
for joint in &self_.m_joints
{
joint.borrow_mut().solve_velocity_constraints(&mut solver_data, &mut self_.m_velocities);
}
contact_solver.solve_velocity_constraints(&mut self_.m_velocities);
}
contact_solver.store_impulses(&self_.m_contacts);
profile.solve_velocity = timer.get_milliseconds();
for i in 0..self_.m_bodies.len()
{
let mut c:B2vec2 = self_.m_positions[i].c;
let mut a:f32 = self_.m_positions[i].a;
let mut v:B2vec2 = self_.m_velocities[i].v;
let mut w:f32 = self_.m_velocities[i].w;
let translation:B2vec2 = h * v;
if b2_dot(translation, translation) > B2_MAX_TRANSLATION_SQUARED
{
let ratio:f32 = B2_MAX_TRANSLATION / translation.length();
v *= ratio;
}
let rotation:f32 = h * w;
if rotation * rotation > B2_MAX_ROTATION_SQUARED
{
let ratio:f32 = B2_MAX_ROTATION / b2_abs(rotation);
w *= ratio;
}
c += h * v;
a += h * w;
self_.m_positions[i].c = c;
self_.m_positions[i].a = a;
self_.m_velocities[i].v = v;
self_.m_velocities[i].w = w;
}
timer.reset();
let mut position_solved:bool = false;
for _i in 0..step.position_iterations
{
let contacts_okay: bool = contact_solver.solve_position_constraints(&mut self_.m_positions);
let mut joints_okay: bool = true;
for joint in &self_.m_joints
{
let joint_okay: bool = joint.borrow_mut().solve_position_constraints(&mut solver_data, &mut self_.m_positions);
joints_okay = joints_okay && joint_okay;
}
if contacts_okay && joints_okay
{
position_solved = true;
break;
}
}
for (i,body) in (&self_.m_bodies).iter().enumerate()
{
let mut body = body.borrow_mut();
body.m_sweep.c = self_.m_positions[i].c;
body.m_sweep.a = self_.m_positions[i].a;
body.m_linear_velocity = self_.m_velocities[i].v;
body.m_angular_velocity = self_.m_velocities[i].w;
body.synchronize_transform();
}
profile.solve_position = timer.get_milliseconds();
self_.report(&contact_solver.m_velocity_constraints);
if allow_sleep
{
let mut min_sleep_time:f32 = B2_MAX_FLOAT;
let lin_tol_sqr:f32 = B2_LINEAR_SLEEP_TOLERANCE * B2_LINEAR_SLEEP_TOLERANCE;
let ang_tol_sqr:f32 = B2_ANGULAR_SLEEP_TOLERANCE * B2_ANGULAR_SLEEP_TOLERANCE;
for b in &self_.m_bodies
{
let mut b = b.borrow_mut();
if b.get_type() == B2bodyType::B2StaticBody
{
continue;
}
if !b.m_flags.contains(BodyFlags::E_AUTO_SLEEP_FLAG) ||
b.m_angular_velocity * b.m_angular_velocity > ang_tol_sqr ||
b2_dot(b.m_linear_velocity, b.m_linear_velocity) > lin_tol_sqr
{
b.m_sleep_time = 0.0;
min_sleep_time = 0.0;
}
else
{
b.m_sleep_time += h;
min_sleep_time = b2_min(min_sleep_time, b.m_sleep_time);
}
}
if min_sleep_time >= B2_TIME_TO_SLEEP && position_solved
{
for b in &self_.m_bodies
{
b.borrow_mut().set_awake(false);
}
}
}
}
pub(crate) fn solve_toi<D: UserDataType>(self_: &mut B2island<D>, sub_step: &B2timeStep, toi_index_a: i32, toi_index_b: i32)
{
for (i,b) in self_.m_bodies.iter().enumerate()
{
let b = b.borrow();
self_.m_positions[i].c = b.m_sweep.c;
self_.m_positions[i].a = b.m_sweep.a;
self_.m_velocities[i].v = b.m_linear_velocity;
self_.m_velocities[i].w = b.m_angular_velocity;
}
let contact_solver_def = B2contactSolverDef{
step : *sub_step
};
let mut contact_solver = B2contactSolver::new::<D>(&contact_solver_def, &self_.m_contacts);
for _i in 0..sub_step.position_iterations
{
let contacts_okay:bool = contact_solver.solve_toiposition_constraints(toi_index_a, toi_index_b, &mut self_.m_positions);
if contacts_okay
{
break;
}
}
self_.m_bodies[toi_index_a as usize].borrow_mut().m_sweep.c0 = self_.m_positions[toi_index_a as usize].c;
self_.m_bodies[toi_index_a as usize].borrow_mut().m_sweep.a0 = self_.m_positions[toi_index_a as usize].a;
self_.m_bodies[toi_index_b as usize].borrow_mut().m_sweep.c0 = self_.m_positions[toi_index_b as usize].c;
self_.m_bodies[toi_index_b as usize].borrow_mut().m_sweep.a0 = self_.m_positions[toi_index_b as usize].a;
contact_solver.initialize_velocity_constraints(&self_.m_positions, &self_.m_velocities, &self_.m_contacts);
for _i in 0..sub_step.velocity_iterations
{
contact_solver.solve_velocity_constraints(&mut self_.m_velocities);
}
let h: f32 = sub_step.dt;
for i in 0..self_.m_bodies.len()
{
let mut c:B2vec2 = self_.m_positions[i].c;
let mut a:f32 = self_.m_positions[i].a;
let mut v:B2vec2 = self_.m_velocities[i].v;
let mut w:f32 = self_.m_velocities[i].w;
let translation:B2vec2 = h * v;
if b2_dot(translation, translation) > B2_MAX_TRANSLATION_SQUARED
{
let ratio:f32 = B2_MAX_TRANSLATION / translation.length();
v *= ratio;
}
let rotation:f32 = h * w;
if rotation * rotation > B2_MAX_ROTATION_SQUARED
{
let ratio:f32 = B2_MAX_ROTATION / b2_abs(rotation);
w *= ratio;
}
c += h * v;
a += h * w;
self_.m_positions[i].c = c;
self_.m_positions[i].a = a;
self_.m_velocities[i].v = v;
self_.m_velocities[i].w = w;
let mut body = self_.m_bodies[i].borrow_mut();
body.m_sweep.c = c;
body.m_sweep.a = a;
body.m_linear_velocity = v;
body.m_angular_velocity = w;
body.synchronize_transform();
}
self_.report(&contact_solver.m_velocity_constraints);
}
pub(crate) fn report<D: UserDataType>(self_: &B2island<D>, constraints: &[B2contactVelocityConstraint])
{
if self_.m_listener.is_none()
{
return;
}
let listener = self_.m_listener.as_ref().unwrap();
assert_eq!(self_.m_contacts.len(), constraints.len());
for (i,c) in (&self_.m_contacts).iter().enumerate()
{
let mut c = c.borrow_mut();
let vc = &constraints[i];
let mut impulse = B2contactImpulse::default();
impulse.count = vc.point_count;
for j in 0..vc.point_count
{
impulse.normal_impulses[j as usize] = vc.points[j as usize].normal_impulse;
impulse.tangent_impulses[j as usize] = vc.points[j as usize].tangent_impulse;
}
listener.borrow_mut().post_solve(&mut *c, &impulse);
}
}