Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Until MechanicalWorld::step is called, GeometricalWorld::interferences_with_point uses old collider positions #279

Open
zachreizner opened this issue Sep 5, 2020 · 1 comment

Comments

@zachreizner
Copy link

For context, I am writing a level editor that uses interferences_with_point to determine the entities the user are clicking on. When the user moves an entity, the underlying body's position is moved. However, the call to interferences_with_point still seems to be using the old object's position until the next time step is called. I have tried both updating the collider position along with the body and using GeometricalWorld::sync_colliders, which has had no effect. Reading through the source of step, I have taken a few stabs in the dark on what will finally allow interferences_with_point to work (without actually calling step), culminating with this:

mech: DefaultMechanicalWorld<f32>,
geo: DefaultGeometricalWorld<f32>,
bodies: DefaultBodySet<f32>,
colliders: DefaultColliderSet<f32>,
joints: DefaultJointConstraintSet<f32>,
forces: DefaultForceGeneratorSet<f32>,
...
self.mech.maintain(&mut self.geo, &mut self.bodies, &mut self.colliders, &mut self.joints);
self.geo.clear_events();
self.geo.sync_colliders(&self.bodies, &mut self.colliders);
self.geo.perform_broad_phase(&self.colliders);
self.geo.perform_narrow_phase(&self.colliders);
self.colliders.foreach_mut(|_, c| c.clear_update_flags());

Still, this did not work. In the end, my workaround was this:

let old_timestep = self.mech.timestep();
self.mech.set_timestep(0.0);
self.mech.step(
    &mut self.geo,
    &mut self.bodies,
    &mut self.colliders,
    &mut self.joints,
    &mut self.forces,
);
self.mech.set_timestep(old_timestep);

This feels like a bit of a hack, especially in the presence of all those other functions which I expected to work, having read the source, but I am all out of leads.

Is there a specific algorithm that users of nphysics are supposed to use to ensure interferences_with_point is querying an up to date world, or is this perhaps a bug in the library?

@zachreizner
Copy link
Author

My workaround of using a timestep of 0.0 ended up not being so good because it would cause dynamic bodies that are temporarily colliding with static bodies to be forced apart, which is not viable behavior for an editor. Therefore I took another look at what made step work for interferences_with_point by removing chunks of MechanicalWorld::step until the editor exhibited the original issue.

After some false positives, I narrowed it to this chunk:

bodies.foreach_mut(&mut |_, b: &mut dyn Body<N>| {
    b.clear_forces();
    b.validate_advancement();
});

I transplanted this into my sync with step function and it works! My theory is that even though I was setting the body and collider position to the new position, the old body position is temporarily cached and used to reset the attached collider position before the broad phase based point interference is run. The call to Body::validate_advancement clears out the old position allowing the broad phase to work as expected with the new collider position. After simplifying my sync function looks like this:

pub fn sync(&mut self) {
    self.mech.maintain(&mut self.geo, &mut self.bodies, &mut self.colliders, &mut self.joints);
    self.bodies.foreach_mut(&mut |_, b| {
        b.validate_advancement();
    });
    self.geo.sync_colliders(&self.bodies, &mut self.colliders);
    self.geo.perform_broad_phase(&self.colliders);
}

I'm not sure if this is a supported use case or if it will continue to work, so it would be nice to get some input from a maintainer, but I'm basically happy with my solution. Thanks for taking a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant