diff options
| author | Sébastien Crozet <sebcrozet@dimforge.com> | 2024-01-21 21:02:23 +0100 |
|---|---|---|
| committer | Sébastien Crozet <sebcrozet@dimforge.com> | 2024-01-21 21:02:27 +0100 |
| commit | 9b87f06a856c4d673642e210f8b0986cfdbac3af (patch) | |
| tree | b4f4eaac0e5004f8ba3fccd42e5aea4fd565dcc6 /src/dynamics/solver/generic_velocity_constraint_element.rs | |
| parent | 9ac3503b879f95fcdf5414470ba5aedf195b9a97 (diff) | |
| download | rapier-9b87f06a856c4d673642e210f8b0986cfdbac3af.tar.gz rapier-9b87f06a856c4d673642e210f8b0986cfdbac3af.tar.bz2 rapier-9b87f06a856c4d673642e210f8b0986cfdbac3af.zip | |
feat: implement new "small-steps" solver + joint improvements
Diffstat (limited to 'src/dynamics/solver/generic_velocity_constraint_element.rs')
| -rw-r--r-- | src/dynamics/solver/generic_velocity_constraint_element.rs | 349 |
1 files changed, 0 insertions, 349 deletions
diff --git a/src/dynamics/solver/generic_velocity_constraint_element.rs b/src/dynamics/solver/generic_velocity_constraint_element.rs deleted file mode 100644 index 19fba43..0000000 --- a/src/dynamics/solver/generic_velocity_constraint_element.rs +++ /dev/null @@ -1,349 +0,0 @@ -use super::DeltaVel; -use crate::dynamics::solver::{ - VelocityConstraintElement, VelocityConstraintNormalPart, VelocityConstraintTangentPart, -}; -use crate::math::{AngVector, Real, Vector, DIM}; -use crate::utils::WDot; -use na::DVector; -#[cfg(feature = "dim2")] -use {crate::utils::WBasis, na::SimdPartialOrd}; - -pub(crate) enum GenericRhs { - DeltaVel(DeltaVel<Real>), - GenericId(usize), -} - -// Offset between the jacobians of two consecutive constraints. -#[inline(always)] -fn j_step(ndofs1: usize, ndofs2: usize) -> usize { - (ndofs1 + ndofs2) * 2 -} - -#[inline(always)] -fn j_id1(j_id: usize, _ndofs1: usize, _ndofs2: usize) -> usize { - j_id -} - -#[inline(always)] -fn j_id2(j_id: usize, ndofs1: usize, _ndofs2: usize) -> usize { - j_id + ndofs1 * 2 -} - -#[inline(always)] -fn normal_j_id(j_id: usize, _ndofs1: usize, _ndofs2: usize) -> usize { - j_id -} - -#[inline(always)] -fn tangent_j_id(j_id: usize, ndofs1: usize, ndofs2: usize) -> usize { - j_id + (ndofs1 + ndofs2) * 2 -} - -impl GenericRhs { - #[inline(always)] - fn dvel( - &self, - j_id: usize, - ndofs: usize, - jacobians: &DVector<Real>, - dir: &Vector<Real>, - gcross: &AngVector<Real>, - mj_lambdas: &DVector<Real>, - ) -> Real { - match self { - GenericRhs::DeltaVel(rhs) => dir.dot(&rhs.linear) + gcross.gdot(rhs.angular), - GenericRhs::GenericId(mj_lambda) => { - let j = jacobians.rows(j_id, ndofs); - let rhs = mj_lambdas.rows(*mj_lambda, ndofs); - j.dot(&rhs) - } - } - } - - #[inline(always)] - fn apply_impulse( - &mut self, - j_id: usize, - ndofs: usize, - impulse: Real, - jacobians: &DVector<Real>, - dir: &Vector<Real>, - gcross: &AngVector<Real>, - mj_lambdas: &mut DVector<Real>, - inv_mass: &Vector<Real>, - ) { - match self { - GenericRhs::DeltaVel(rhs) => { - rhs.linear += dir.component_mul(inv_mass) * impulse; - rhs.angular += gcross * impulse; - } - GenericRhs::GenericId(mj_lambda) => { - let wj_id = j_id + ndofs; - let wj = jacobians.rows(wj_id, ndofs); - let mut rhs = mj_lambdas.rows_mut(*mj_lambda, ndofs); - rhs.axpy(impulse, &wj, 1.0); - } - } - } -} - -impl VelocityConstraintTangentPart<Real> { - #[inline] - pub fn generic_solve( - &mut self, - j_id: usize, - jacobians: &DVector<Real>, - tangents1: [&Vector<Real>; DIM - 1], - im1: &Vector<Real>, - im2: &Vector<Real>, - ndofs1: usize, - ndofs2: usize, - limit: Real, - mj_lambda1: &mut GenericRhs, - mj_lambda2: &mut GenericRhs, - mj_lambdas: &mut DVector<Real>, - ) { - let j_id1 = j_id1(j_id, ndofs1, ndofs2); - let j_id2 = j_id2(j_id, ndofs1, ndofs2); - #[cfg(feature = "dim3")] - let j_step = j_step(ndofs1, ndofs2); - - #[cfg(feature = "dim2")] - { - let dvel_0 = mj_lambda1.dvel( - j_id1, - ndofs1, - jacobians, - &tangents1[0], - &self.gcross1[0], - mj_lambdas, - ) + mj_lambda2.dvel( - j_id2, - ndofs2, - jacobians, - &-tangents1[0], - &self.gcross2[0], - mj_lambdas, - ) + self.rhs[0]; - - let new_impulse = (self.impulse[0] - self.r[0] * dvel_0).simd_clamp(-limit, limit); - let dlambda = new_impulse - self.impulse[0]; - self.impulse[0] = new_impulse; - - mj_lambda1.apply_impulse( - j_id1, - ndofs1, - dlambda, - jacobians, - &tangents1[0], - &self.gcross1[0], - mj_lambdas, - im1, - ); - mj_lambda2.apply_impulse( - j_id2, - ndofs2, - dlambda, - jacobians, - &-tangents1[0], - &self.gcross2[0], - mj_lambdas, - im2, - ); - } - - #[cfg(feature = "dim3")] - { - let dvel_0 = mj_lambda1.dvel( - j_id1, - ndofs1, - jacobians, - &tangents1[0], - &self.gcross1[0], - mj_lambdas, - ) + mj_lambda2.dvel( - j_id2, - ndofs2, - jacobians, - &-tangents1[0], - &self.gcross2[0], - mj_lambdas, - ) + self.rhs[0]; - let dvel_1 = mj_lambda1.dvel( - j_id1 + j_step, - ndofs1, - jacobians, - &tangents1[1], - &self.gcross1[1], - mj_lambdas, - ) + mj_lambda2.dvel( - j_id2 + j_step, - ndofs2, - jacobians, - &-tangents1[1], - &self.gcross2[1], - mj_lambdas, - ) + self.rhs[1]; - - let new_impulse = na::Vector2::new( - self.impulse[0] - self.r[0] * dvel_0, - self.impulse[1] - self.r[1] * dvel_1, - ); - let new_impulse = new_impulse.cap_magnitude(limit); - - let dlambda = new_impulse - self.impulse; - self.impulse = new_impulse; - - mj_lambda1.apply_impulse( - j_id1, - ndofs1, - dlambda[0], - jacobians, - &tangents1[0], - &self.gcross1[0], - mj_lambdas, - im1, - ); - mj_lambda1.apply_impulse( - j_id1 + j_step, - ndofs1, - dlambda[1], - jacobians, - &tangents1[1], - &self.gcross1[1], - mj_lambdas, - im1, - ); - - mj_lambda2.apply_impulse( - j_id2, - ndofs2, - dlambda[0], - jacobians, - &-tangents1[0], - &self.gcross2[0], - mj_lambdas, - im2, - ); - mj_lambda2.apply_impulse( - j_id2 + j_step, - ndofs2, - dlambda[1], - jacobians, - &-tangents1[1], - &self.gcross2[1], - mj_lambdas, - im2, - ); - } - } -} - -impl VelocityConstraintNormalPart<Real> { - #[inline] - pub fn generic_solve( - &mut self, - cfm_factor: Real, - j_id: usize, - jacobians: &DVector<Real>, - dir1: &Vector<Real>, - im1: &Vector<Real>, - im2: &Vector<Real>, - ndofs1: usize, - ndofs2: usize, - mj_lambda1: &mut GenericRhs, - mj_lambda2: &mut GenericRhs, - mj_lambdas: &mut DVector<Real>, - ) { - let j_id1 = j_id1(j_id, ndofs1, ndofs2); - let j_id2 = j_id2(j_id, ndofs1, ndofs2); - - let dvel = mj_lambda1.dvel(j_id1, ndofs1, jacobians, &dir1, &self.gcross1, mj_lambdas) - + mj_lambda2.dvel(j_id2, ndofs2, jacobians, &-dir1, &self.gcross2, mj_lambdas) - + self.rhs; - - let new_impulse = cfm_factor * (self.impulse - self.r * dvel).max(0.0); - let dlambda = new_impulse - self.impulse; - self.impulse = new_impulse; - - mj_lambda1.apply_impulse( - j_id1, - ndofs1, - dlambda, - jacobians, - &dir1, - &self.gcross1, - mj_lambdas, - im1, - ); - mj_lambda2.apply_impulse( - j_id2, - ndofs2, - dlambda, - jacobians, - &-dir1, - &self.gcross2, - mj_lambdas, - im2, - ); - } -} - -impl VelocityConstraintElement<Real> { - #[inline] - pub fn generic_solve_group( - cfm_factor: Real, - elements: &mut [Self], - jacobians: &DVector<Real>, - dir1: &Vector<Real>, - #[cfg(feature = "dim3")] tangent1: &Vector<Real>, - im1: &Vector<Real>, - im2: &Vector<Real>, - limit: Real, - // ndofs is 0 for a non-multibody body, or a multibody with zero - // degrees of freedom. - ndofs1: usize, - ndofs2: usize, - // Jacobian index of the first constraint. - j_id: usize, - mj_lambda1: &mut GenericRhs, - mj_lambda2: &mut GenericRhs, - mj_lambdas: &mut DVector<Real>, - solve_restitution: bool, - solve_friction: bool, - ) { - let j_step = j_step(ndofs1, ndofs2) * DIM; - - // Solve penetration. - if solve_restitution { - let mut nrm_j_id = normal_j_id(j_id, ndofs1, ndofs2); - - for element in elements.iter_mut() { - element.normal_part.generic_solve( - cfm_factor, nrm_j_id, jacobians, &dir1, im1, im2, ndofs1, ndofs2, mj_lambda1, - mj_lambda2, mj_lambdas, - ); - nrm_j_id += j_step; - } - } - - // Solve friction. - if solve_friction { - #[cfg(feature = "dim3")] - let tangents1 = [tangent1, &dir1.cross(&tangent1)]; - #[cfg(feature = "dim2")] - let tangents1 = [&dir1.orthonormal_vector()]; - let mut tng_j_id = tangent_j_id(j_id, ndofs1, ndofs2); - - for element in elements.iter_mut() { - let limit = limit * element.normal_part.impulse; - let part = &mut element.tangent_part; - part.generic_solve( - tng_j_id, jacobians, tangents1, im1, im2, ndofs1, ndofs2, limit, mj_lambda1, - mj_lambda2, mj_lambdas, - ); - tng_j_id += j_step; - } - } - } -} |
