rapier
rapier copied to clipboard
Unsupported collisions between Trimesh and Custom
I'm implementing a custom collider, which is essentially a heightmap over a cylinder surface. Got stuck for not seeing project_local_point being called, and decided to debug Rapier a bit. Reached to this step:
parry3d::query::default_query_dispatcher::impl$1::contact_manifold_convex_convex<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>(*mut parry3d::query::default_query_dispatcher::DefaultQueryDispatcher,*mut nalgebra::geometry::isometry::Isometry<f32,nalgebra::base::unit::Unit<nalgebra::geometry::quaternion::Quaternion<f32> >,3>,ref$<dyn$<parry3d::shape::shape::Shape> >,ref$<dyn$<parry3d::shape::shape::Shape> >,enum2$<core::option::Option<ref$<dyn$<parry3d::query::contact_manifolds::normals_constraint::NormalConstraints> > > >,enum2$<core::option::Option<ref$<dyn$<parry3d::query::contact_manifolds::normals_constraint::NormalConstraints> > > >,f32,*mut parry3d::query::contact_manifolds::contact_manifold::ContactManifold<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>) default_query_dispatcher.rs:599
parry3d::query::contact_manifolds::contact_manifolds_trimesh_shape::contact_manifolds_trimesh_shape<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>(ref$<dyn$<parry3d::query::query_dispatcher::PersistentQueryDispatcher<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData> > >,*mut nalgebra::geometry::isometry::Isometry<f32,nalgebra::base::unit::Unit<nalgebra::geometry::quaternion::Quaternion<f32> >,3>,*mut parry3d::shape::trimesh::TriMesh,ref$<dyn$<parry3d::shape::shape::Shape> >,f32,*mut alloc::vec::Vec<parry3d::query::contact_manifolds::contact_manifold::ContactManifold<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>,alloc::alloc::Global>,*mut enum2$<core::option::Option<parry3d::query::contact_manifolds::contact_manifolds_workspace::ContactManifoldsWorkspace> >,bool) contact_manifolds_trimesh_shape.rs:195
parry3d::query::contact_manifolds::contact_manifolds_trimesh_shape::contact_manifolds_trimesh_shape_shapes<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>(ref$<dyn$<parry3d::query::query_dispatcher::PersistentQueryDispatcher<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData> > >,*mut nalgebra::geometry::isometry::Isometry<f32,nalgebra::base::unit::Unit<nalgebra::geometry::quaternion::Quaternion<f32> >,3>,ref$<dyn$<parry3d::shape::shape::Shape> >,ref$<dyn$<parry3d::shape::shape::Shape> >,f32,*mut alloc::vec::Vec<parry3d::query::contact_manifolds::contact_manifold::ContactManifold<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>,alloc::alloc::Global>,*mut enum2$<core::option::Option<parry3d::query::contact_manifolds::contact_manifolds_workspace::ContactManifoldsWorkspace> >) contact_manifolds_trimesh_shape.rs:59
parry3d::query::default_query_dispatcher::impl$1::contact_manifolds<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>(*mut parry3d::query::default_query_dispatcher::DefaultQueryDispatcher,*mut nalgebra::geometry::isometry::Isometry<f32,nalgebra::base::unit::Unit<nalgebra::geometry::quaternion::Quaternion<f32> >,3>,ref$<dyn$<parry3d::shape::shape::Shape> >,ref$<dyn$<parry3d::shape::shape::Shape> >,f32,*mut alloc::vec::Vec<parry3d::query::contact_manifolds::contact_manifold::ContactManifold<rapier3d::geometry::contact_pair::ContactManifoldData,rapier3d::geometry::contact_pair::ContactData>,alloc::alloc::Global>,*mut enum2$<core::option::Option<parry3d::query::contact_manifolds::contact_manifolds_workspace::ContactManifoldsWorkspace> >) default_query_dispatcher.rs:451
rapier3d::geometry::narrow_phase::impl$2::compute_contacts::closure$0(*mut rapier3d::geometry::narrow_phase::impl$2::compute_contacts::closure_env$0,*mut rapier3d::data::graph::Edge<rapier3d::geometry::contact_pair::ContactPair>) narrow_phase.rs:941
core::slice::iter::impl$190::for_each<rapier3d::data::graph::Edge<rapier3d::geometry::contact_pair::ContactPair>,rapier3d::geometry::narrow_phase::impl$2::compute_contacts::closure_env$0>(core::slice::iter::IterMut<rapier3d::data::graph::Edge<rapier3d::geometry::contact_pair::ContactPair> >,rapier3d::geometry::narrow_phase::impl$2::compute_contacts::closure_env$0) macros.rs:254
rapier3d::geometry::narrow_phase::NarrowPhase::compute_contacts(f32,f32,*mut rapier3d::dynamics::rigid_body_set::RigidBodySet,*mut rapier3d::geometry::collider_set::ColliderSet,*mut rapier3d::dynamics::joint::impulse_joint::impulse_joint_set::ImpulseJointSet,*mut rapier3d::dynamics::joint::multibody_joint::multibody_joint_set::MultibodyJointSet,ref$<slice2$<rapier3d::geometry::collider_components::ColliderHandle> >,ref$<dyn$<rapier3d::pipeline::physics_hooks::PhysicsHooks> >,ref$<dyn$<rapier3d::pipeline::event_handler::EventHandler> >) narrow_phase.rs:807
rapier3d::pipeline::physics_pipeline::PhysicsPipeline::detect_collisions(*mut rapier3d::dynamics::integration_parameters::IntegrationParameters,*mut rapier3d::dynamics::island_manager::IslandManager,ref_mut$<dyn$<rapier3d::geometry::broad_phase::BroadPhase> >,*mut rapier3d::geometry::narrow_phase::NarrowPhase,*mut rapier3d::dynamics::rigid_body_set::RigidBodySet,*mut rapier3d::geometry::collider_set::ColliderSet,*mut rapier3d::dynamics::joint::impulse_joint::impulse_joint_set::ImpulseJointSet,*mut rapier3d::dynamics::joint::multibody_joint::multibody_joint_set::MultibodyJointSet,ref$<slice2$<rapier3d::geometry::collider_components::ColliderHandle> >,ref$<slice2$<rapier3d::geometry::collider_components::ColliderHandle> >,ref$<dyn$<rapier3d::pipeline::physics_hooks::PhysicsHooks> >,ref$<dyn$<rapier3d::pipeline::event_handler::EventHandler> >,bool) physics_pipeline.rs:145
rapier3d::pipeline::physics_pipeline::PhysicsPipeline::step(*mut nalgebra::base::matrix::Matrix<f32,nalgebra::base::dimension::Const<3>,nalgebra::base::dimension::Const<1>,nalgebra::base::array_storage::ArrayStorage<f32,3,1> >,*mut rapier3d::dynamics::integration_parameters::IntegrationParameters,*mut rapier3d::dynamics::island_manager::IslandManager,ref_mut$<dyn$<rapier3d::geometry::broad_phase::BroadPhase> >,*mut rapier3d::geometry::narrow_phase::NarrowPhase,*mut rapier3d::dynamics::rigid_body_set::RigidBodySet,*mut rapier3d::geometry::collider_set::ColliderSet,*mut rapier3d::dynamics::joint::impulse_joint::impulse_joint_set::ImpulseJointSet,*mut rapier3d::dynamics::joint::multibody_joint::multibody_joint_set::MultibodyJointSet,*mut rapier3d::dynamics::ccd::ccd_solver::CCDSolver,enum2$<core::option::Option<ref_mut$<rapier3d::pipeline::query_pipeline::QueryPipeline> > >,ref$<dyn$<rapier3d::pipeline::physics_hooks::PhysicsHooks> >,ref$<dyn$<rapier3d::pipeline::event_handler::EventHandler> >) physics_pipeline.rs:478
In this contact_manifold_convex_convex function, we are handling different types of shapes. It has this default handler:
if let (Some(pfm1), Some(pfm2)) = (
shape1.as_polygonal_feature_map(),
shape2.as_polygonal_feature_map(),
) {
contact_manifold_pfm_pfm(
pos12, pfm1.0, pfm1.1, normal_constraints1, pfm2.0, pfm2.1, normal_constraints2, prediction, manifold,
)
} else {
return Err(Unsupported);
}
I'm reading it as: rapier only supports custom shapes that have polygonal features. I.e. it's impossible today to even implement an existing heightmap as a custom shape. Is my reading correct? Are there any plans to support true custom shapes? I'm not asking for crazy things, just at least to have an ability to implement any of the existing shapes myself, if needed.
This is a bit of a blocker for me currently in https://github.com/kvark/vandals-and-heroes/pull/3.
- Thanks for the issue, I added a related issue to parry https://github.com/dimforge/parry/issues/297 as an upstream fix should be discussed.
We can discuss your original problem in this thread:
Root issue
My understanding is that your shape not supporting as_polygonal_feature_map is the root issue.
Could your shape implement this function ?
I.e. it's impossible today to even implement an existing heightmap as a custom shape
I think you're correct, but you might be able to have your custom shape bail out its implementations to HeightField as you did in your PR, + add an approximation of a as_polygonal_feature_map which fits your needs ?
Other ideas
Spoiler for probably not a good attack angle :arrow_down:
That's definitely not an ideal solution, but could help understanding the problem space:
You could implement your own QueryDispatcher and feed it to the different relevant interested containers (ccdsolver, narrowphase).
I'm not sure exactly if we're lacking information from types or if this issue "only" needs a non-invasive implementation effort.
Thank you for the quick response!
Could your shape implement this function ?
I don't this so. The polygonal feature map is for convex objects only.
you might be able to have your custom shape bail out its implementations to HeightField
I'm not quite seeing how this would work. I can't piggy back on the built-in shape because my height field is curved.
You could implement your own QueryDispatcher and feed it to the different relevant interested containers (ccdsolver, narrowphase).
That's a possibility indeed. If rapier/parry doesn't want to have colliders implementable in user space, I'm forced to essentially go this route.
Thanks for the precisions.
If rapier/parry doesn't want to have colliders implementable in user space
I fail to see how an implementation of a collider helps in this case, maybe "true custom shapes contacts" would be a better term ?
To my understanding, this QueryDispatcher (re)implementation on user code is currently the best way then.
The best upstream task I can come up with would be an extensible (Default)QueryDispatcher which could be more easily extended with custom user shapes.
- https://github.com/dimforge/parry/issues/8 might be relevant to our discussion, and there's been some effort on it.
fail to see how an implementation of a collider helps in this case, maybe "true custom shapes contacts" would be a better term ?
Yes, I meant to write "true custom shape contacts". Thanks for correction!
Currently trying to implement a QueryDispatcher, and it's a whole ton of boilerplate I didn't expect to find myself in... About an extra 400 lines of code before I can even start writing my target logic. I really hope there will be a better solution to this.
Actually, the problem might be deeper than we assumed. If we look at the call stack again, we can notice contact_manifolds_trimesh_shape calling into contact_manifold_convex_convex. This itself appears wrong to me, since nowhere we are making sure that shape is actually convex. And in my case - it's not actually convex.
Relevant code - https://github.com/dimforge/parry/blob/aaeb17f9414c2d801d59609bc7d6ec48eda5fe70/src/query/contact_manifolds/contact_manifolds_trimesh_shape.rs#L195-L213
Custom shapes will always require a custom dispatcher, and in most cases work fine once you have one, although due to long-standing design issue https://github.com/dimforge/parry/issues/8 you can't compose custom dispatchers. See https://github.com/Ralith/planetmap/blob/master/src/parry.rs for a real-world example of a custom heightmap-like.