Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions src/dynamics/solver/contact_constraint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,86 @@ mod two_body_constraint;
mod two_body_constraint_element;
#[cfg(feature = "simd-is-enabled")]
mod two_body_constraint_simd;

#[cfg(feature = "dim2")]
#[cfg(test)]
mod test {
use crate::prelude::{
BroadPhaseMultiSap, CCDSolver, ColliderBuilder, ColliderSet, ImpulseJointSet,
IntegrationParameters, IslandManager, MultibodyJointSet, NarrowPhase, PhysicsPipeline,
RigidBodyBuilder, RigidBodySet,
};
use na::{vector, Vector};

#[test]
fn tangent_not_nan_818() {
/*
* World
*/

let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let mut impulse_joints = ImpulseJointSet::new();
let mut multibody_joints = MultibodyJointSet::new();
let mut pipeline = PhysicsPipeline::new();
let mut bf = BroadPhaseMultiSap::new();
let mut nf = NarrowPhase::new();
let mut islands = IslandManager::new();

/*
* The ground
*/
let ground_size = 20.0;
let ground_height = 1.0;

let rigid_body = RigidBodyBuilder::fixed().translation(vector![0.0, -3.0]);
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(ground_size, ground_height)
.rotation((0.25 as crate::math::Real).to_radians())
.friction(0.9);
colliders.insert_with_parent(collider, handle, &mut bodies);

/*
* A tilted capsule that cannot rotate.
*/
let rigid_body = RigidBodyBuilder::dynamic()
.translation(vector![0.0, 4.0])
.lock_rotations();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::capsule_y(2.0, 1.0).friction(0.9);
colliders.insert_with_parent(collider, handle, &mut bodies);

// Steps
let gravity = Vector::y() * -9.81;

for _ in 0..50 {
pipeline.step(
&gravity,
&IntegrationParameters::default(),
&mut islands,
&mut bf,
&mut nf,
&mut bodies,
&mut colliders,
&mut impulse_joints,
&mut multibody_joints,
&mut CCDSolver::new(),
None,
&(),
&(),
);
}
let pairs: Vec<_> = nf.contact_pairs().collect();
println!("contact pairs: {:?}", pairs);
for contact in pairs {
for manifold in contact.manifolds.iter() {
for point in manifold.points.iter() {
assert!(
point.data.tangent_impulse.index(0).is_finite(),
"tangent impulse from a contact pair point data should be normal."
);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ impl OneBodyConstraintBuilder {
{
constraint.elements[k].tangent_part.impulse =
manifold_point.warmstart_tangent_impulse;
constraint.elements[k].tangent_part.impulse_accumulator = na::zero();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two body constraints and generic body constraints may benefit from the same reset. Also, a deconstructing pattern may help with making sure we don't forget to reset any fields.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same should be done for Simd constraints, as the impulse accumulators in the tangent part are also never re-set from NaN


for j in 0..DIM - 1 {
let gcross2 = mprops2
Expand Down
11 changes: 11 additions & 0 deletions src/geometry/contact_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,17 @@ pub struct ContactPair {
pub(crate) workspace: Option<ContactManifoldsWorkspace>,
}

impl std::fmt::Debug for ContactPair {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContactPair")
.field("collider1", &self.collider1)
.field("collider2", &self.collider2)
.field("manifolds", &self.manifolds)
.field("has_any_active_contact", &self.has_any_active_contact)
.finish()
}
}

impl ContactPair {
pub(crate) fn new(collider1: ColliderHandle, collider2: ColliderHandle) -> Self {
Self {
Expand Down