use dynamics::solver::solver_body::SolverBody;
use crate::{dynamics::solver::solver_body::SolverBodyInertia, prelude::*};
pub trait PositionConstraint {
fn apply_positional_impulse(
&self,
body1: &mut SolverBody,
body2: &mut SolverBody,
inertia1: &SolverBodyInertia,
inertia2: &SolverBodyInertia,
impulse: Vector,
r1: Vector,
r2: Vector,
) {
let inv_mass1 = inertia1.effective_inv_mass();
let inv_mass2 = inertia2.effective_inv_mass();
let inv_angular_inertia1 = inertia1.effective_inv_angular_inertia();
let inv_angular_inertia2 = inertia2.effective_inv_angular_inertia();
body1.delta_position += impulse * inv_mass1;
#[cfg(feature = "2d")]
{
let delta_angle = Self::get_delta_rot(inv_angular_inertia1, r1, impulse);
body1.delta_rotation = body1.delta_rotation.add_angle_fast(delta_angle);
}
#[cfg(feature = "3d")]
{
let delta_quat = Self::get_delta_rot(inv_angular_inertia1, r1, impulse);
body1.delta_rotation.0 = delta_quat * body1.delta_rotation.0;
}
body2.delta_position -= impulse * inv_mass2;
#[cfg(feature = "2d")]
{
let delta_angle = Self::get_delta_rot(inv_angular_inertia2, r2, -impulse);
body2.delta_rotation = body2.delta_rotation.add_angle_fast(delta_angle);
}
#[cfg(feature = "3d")]
{
let delta_quat = Self::get_delta_rot(inv_angular_inertia2, r2, -impulse);
body2.delta_rotation.0 = delta_quat * body2.delta_rotation.0;
}
}
#[cfg(feature = "2d")]
fn compute_generalized_inverse_mass(
&self,
inverse_mass: Scalar,
inverse_angular_inertia: SymmetricTensor,
r: Vector,
n: Vector,
) -> Scalar {
inverse_mass + inverse_angular_inertia * r.perp_dot(n).powi(2)
}
#[cfg(feature = "3d")]
fn compute_generalized_inverse_mass(
&self,
inverse_mass: Scalar,
inverse_angular_inertia: SymmetricTensor,
r: Vector,
n: Vector,
) -> Scalar {
let r_cross_n = r.cross(n);
inverse_mass + r_cross_n.dot(inverse_angular_inertia * r_cross_n)
}
#[cfg(feature = "2d")]
fn get_delta_rot(inverse_angular_inertia: SymmetricTensor, r: Vector, p: Vector) -> Scalar {
inverse_angular_inertia * r.perp_dot(p)
}
#[cfg(feature = "3d")]
fn get_delta_rot(inverse_angular_inertia: SymmetricTensor, r: Vector, p: Vector) -> Quaternion {
Quaternion::from_scaled_axis(inverse_angular_inertia * r.cross(p))
}
fn compute_force(&self, lagrange: Scalar, direction: Vector, dt: Scalar) -> Vector {
lagrange * direction / dt.powi(2)
}
}