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

Unsupported collisions between Trimesh and Custom #773

Open
kvark opened this issue Dec 10, 2024 · 5 comments
Open

Unsupported collisions between Trimesh and Custom #773

kvark opened this issue Dec 10, 2024 · 5 comments

Comments

@kvark
Copy link
Contributor

kvark commented Dec 10, 2024

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 kvark/vandals-and-heroes#3.

@Vrixyz Vrixyz transferred this issue from dimforge/rapier Dec 10, 2024
@Vrixyz Vrixyz transferred this issue from dimforge/parry Dec 10, 2024
@Vrixyz
Copy link
Contributor

Vrixyz commented Dec 10, 2024

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 ⬇️

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.

@kvark
Copy link
Contributor Author

kvark commented Dec 10, 2024

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.

@Vrixyz
Copy link
Contributor

Vrixyz commented Dec 10, 2024

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.

@kvark
Copy link
Contributor Author

kvark commented Dec 11, 2024

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.

@kvark
Copy link
Contributor Author

kvark commented Dec 11, 2024

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

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

No branches or pull requests

2 participants