Ambient icon indicating copy to clipboard operation
Ambient copied to clipboard

dynamic collisions on Prefab entities

Open kevzettler opened this issue 1 year ago • 10 comments

I have an entity that is is loaded as a prefab from the pipeline like:

[[pipelines]]
type = "Models"
sources = ["*.glb"]

[pipelines.collider]
type = "FromModel"

The entity looks like

            let player_mesh_id = Entity::new()
                .with(name(), "PlayerMesh".to_string())
                .with(parent(), player_controller_id)
                .with(local_to_parent(), Default::default())
                .with(local_to_world(), Default::default())
                .with_merge(make_transformable())
                .with(prefab_from_url(), assets::url("fighter01.glb"))
                .with(scale(), Vec3::ONE * 0.3)
                // rotate blender mesh to fit world coordinates
                .with(
                    rotation(),
                    Quat::from_rotation_z(-std::f32::consts::FRAC_PI_2)
                        * Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2),
                )
                .spawn();

I dynamically move this entity from parent transformations, It's collision is updated like: https://github.com/AmbientRun/Ambient/pull/885

I noticed when moving this entity through other collision bodies it doesn't register collisions. I dug into the physxs components a bit more and found that by default the entity is treated as a 'static' body and collisions don't get registered unless its a 'dynamic' entity. I tried adding the dynamic component to this entity .with(dynamic(), true) . This did nothing.

I built another test case in which I tried on another non-prefab collision body and the dynamic component worked as expected.

Entity::new()
                    .with(name(), "Bullet".to_string())
                    .with(bullet_owner_ref(), player_id)
                    .with_merge(make_sphere())
                    .with(sphere_collider(), 1.0)
                    .with(dynamic(), true)
                    .with(scale(), vec3(0.1, 0.7, 1.0))
                    .with(self::color(), vec4(1., 0.1, 1., 1.))
                    .with_merge(make_transformable())
                    .with(
                        translation(),
                        ship_position + (bullet_heading.normalize() * 1.3),
                    )
                    .with(bullet_target(), bullet_heading.normalize())
                    .spawn();

I saw in the asset pipeline docs there's flag to specify collision type. I updated the pipeline to add the collision type like:

[[pipelines]]
type = "Models"
sources = ["*.glb"]
collider_type = "Dynamic" 

[pipelines.collider]
type = "FromModel"

The prefab entity is now correctly registered as a "Dynamic" Physics body and collisions get registered. But there is undesired behavior now in which the physx engine transformation updates override the custom transformations I have built. Essentially I have lost control of the entities translation and rotation because its receiving its updates from the physics engine.

How can I get collision behavior similar to the Bullet entity ? Also could somebody point me to where the physics components like dynamic are applied during the prefab_from_url construction?

kevzettler avatar Sep 19 '23 23:09 kevzettler

@kevzettler It sounds like what you want is kinematic (here's the physx docs: https://gameworksdocs.nvidia.com/PhysX/4.1/documentation/physxguide/Manual/RigidBodyDynamics.html#kinematic-actors ).

Also it might be worth to try to dump the server state to make sure the entities have the right components (ambient run --debugger and the click "dump server world")

FredrikNoren avatar Sep 26 '23 06:09 FredrikNoren

I have added the .with(kinematic(), ()) component and this fixes the behavior with the collision body being hijacked and managed by physxs instead of our dynamic updates. Unfortunately it still does not register collision events against other bodies.

kevzettler avatar Oct 15 '23 21:10 kevzettler

@kevzettler Could you try putting a breakpoint of println here and see if the collision is triggered at all from physx? https://github.com/AmbientRun/Ambient/blob/main/crates/physics/src/lib.rs#L73

FredrikNoren avatar Oct 16 '23 13:10 FredrikNoren

From the server dump server_hiearchy.yml

Here is the player mesh prefab that is behaving incorrectly...

        - "id=ZQrAWe9bxjNyWRQfX_4pMQ loc=62:0":
            "ambient_core::app::name": "\"PlayerMesh\""
            "ambient_core::hierarchy::parent": "EntityId(IcWsLFGOhVxDguFC9DCqaw, 143111078922968181966099845513996977441)"
            "ambient_core::model::model_from_url": "\"ambient-assets:/lsvr7wpee4biw3sleyscm7har4xzjvoa/assets/ships/fighter01.glb/models/main.json\""
            "ambient_core::physics::angular_velocity": "Vec3(0.0, 0.0, 0.0)"
            "ambient_core::physics::collider_loaded": ()
            "ambient_core::physics::dynamic": "true"
            "ambient_core::physics::kinematic": ()
            "ambient_core::physics::linear_velocity": "Vec3(0.0, 0.0, 0.0)"
            "ambient_core::prefab::prefab_from_url": "\"ambient-assets:/lsvr7wpee4biw3sleyscm7har4xzjvoa/assets/ships/fighter01.glb\""
            "ambient_core::prefab::spawned": ()
            "ambient_core::transform::local_to_parent": "Mat4 { x_axis: Vec4(1.1920929e-7, -0.9999999, 0.0, 0.0), y_axis: Vec4(0.0, 1.1920929e-7, -0.9999999, 0.0), z_axis: Vec4(0.9999999, 0.0, 1.1920929e-7, 0.0), w_axis: Vec4(0.0, 0.0, 0.0, 1.0) }"
            "ambient_core::transform::local_to_world": "Mat4 { x_axis: Vec4(0.76182234, -0.64778584, 1.1400717e-7, 0.0), y_axis: Vec4(0.5385441, 0.6333498, -0.55573195, 0.0), z_axis: Vec4(0.35999534, 0.423369, 0.8313614, 0.0), w_axis: Vec4(779.1699, 2185.8381, 160.05618, 1.0) }"
            "ambient_core::transform::rotation": "Quat(-0.49999997, 0.49999997, -0.49999997, 0.49999997)"
            "ambient_core::transform::scale": "Vec3(1.0, 1.0, 1.0)"
            "ambient_core::transform::translation": "Vec3(0.0, 0.0, 0.0)"
            "ambient_core::physics::rigid_actor": "..."
            "ambient_core::physics::rigid_dynamic": "..."
            "ambient_core::physics::physics_shape": "..."
            "ambient_core::physics::collider": "Asset { collider: TypedAssetUrl(ambient-assets:/lsvr7wpee4biw3sleyscm7har4xzjvoa/assets/ships/fighter01.glb/colliders/main.json, PhantomData<ambient_native_std::uncategorized::asset_url::ColliderAssetType>) }"
            "ambient_core::physics::collider_type": Dynamic
            "ambient_core::physics::collider_shapes": "..."
            "ambient_core::physics::collider_shapes_convex": "..."
            "lsvr7wpee4biw3sleyscm7har4xzjvoa::owner_player_id": "EntityId(KHqDENPKWRgWP4v1KaajKA, 54018834423678847093558392131707697704)"
          children: []

Here is the bullet mesh that is behaving correctly....

- "id=zxu8sgSKTmMjdfZDbQqFoQ loc=74:0":
    "ambient_core::app::name": "\"Bullet\""
    "ambient_core::physics::angular_velocity": "Vec3(0.0, 0.0, 0.0)"
    "ambient_core::physics::collider_loaded": ()
    "ambient_core::physics::dynamic": "true"
    "ambient_core::physics::linear_velocity": "Vec3(0.0, 0.0, 0.0)"
    "ambient_core::physics::mass": "5.57528"
    "ambient_core::physics::physics_controlled": ()
    "ambient_core::physics::sphere_collider": "1.0"
    "ambient_core::physics::visualize_collider": ()
    "ambient_core::primitives::sphere": ()
    "ambient_core::primitives::sphere_radius": "0.5"
    "ambient_core::primitives::sphere_sectors": "36"
    "ambient_core::primitives::sphere_stacks": "18"
    "ambient_core::rendering::color": "Vec4(1.0, 0.1, 1.0, 1.0)"
    "ambient_core::transform::local_to_world": "Mat4 { x_axis: Vec4(1.1, 0.0, 0.0, 0.0), y_axis: Vec4(0.0, 1.7, 0.0, 0.0), z_axis: Vec4(0.0, 0.0, 2.0, 0.0), w_axis: Vec4(1227.4658, 3602.9219, -546.807, 1.0) }"
    "ambient_core::transform::rotation": "Quat(0.0, 0.0, 0.0, 1.0)"
    "ambient_core::transform::scale": "Vec3(1.1, 1.7, 2.0)"
    "ambient_core::transform::translation": "Vec3(1228.5403, 3605.1194, -547.6371)"
    "ambient_core::gizmos::local_gizmos": "[Sphere { origin: Vec3(1227.4658, 3602.9219, -546.807), radius: 0.15, color: Vec3(1.0, 0.0, 0.0), border_width: 0.15 }, Sphere { origin: Vec3(1227.4658, 3602.9219, -546.807), radius: 0.1, color: Vec3(0.0, 1.0, 0.0), border_width: 0.1 }]"
    "ambient_core::physics::rigid_actor": "..."
    "ambient_core::physics::rigid_dynamic": "..."
    "ambient_core::physics::physics_shape": "..."
    "ambient_core::physics::collider": "Sphere { radius: 1.0, center: Vec3(0.0, 0.0, 0.0) }"
    "ambient_core::physics::collider_type": Dynamic
    "ambient_core::physics::collider_shapes": "..."
    "ambient_core::physics::collider_shapes_convex": "..."
    "lsvr7wpee4biw3sleyscm7har4xzjvoa::bullet_heading": "Vec3(0.41596055, 0.8507181, -0.32133415)"
    "lsvr7wpee4biw3sleyscm7har4xzjvoa::bullet_auto_aim_target": "EntityId(AAAAAAAAAAAAAAAAAAAAAA, 0)"
    "lsvr7wpee4biw3sleyscm7har4xzjvoa::owner_player_id": "EntityId(KHqDENPKWRgWP4v1KaajKA, 54018834423678847093558392131707697704)"
  children: []

kevzettler avatar Oct 17 '23 22:10 kevzettler

@FredrikNoren I tried this

@kevzettler Could you try putting a breakpoint of println here and see if the collision is triggered at all from physx? https://github.com/AmbientRun/Ambient/blob/main/crates/physics/src/lib.rs#L73

The breakpoint was triggered for the primitive Bullet entities but not the prefab entity...

Looking above at the server hierarchy dump the the prefab seems to be missing the "ambient_core::physics::physics_controlled": ()

Where the primitive shape has that. Seems suspicious.

kevzettler avatar Oct 17 '23 22:10 kevzettler

@kevzettler If you look in the prefab file (i.e. assets/your_model.glb/prefabs/main.json), does it have it there? I checked a file here and it didn't seem to have it. Think that might be the problem.

FredrikNoren avatar Oct 19 '23 15:10 FredrikNoren

This is what my prefab json looks like:

{"AQAAAAAAAAAAAAAAAAAAAA":{"ambient_core::hierarchy::children":["9AJ0r_AW2-LkEBvlDIZamA"]},"9AJ0r_AW2-LkEBvlDIZamA":{"ambient_core::model::model_from_url":"../models/main.json","ambient_core::physics::collider":{"Asset":{"collider":"../colliders/main.json"}},"ambient_core::physics::collider_type":"Dynamic"}}%

Not seeing mention of "ambient_core::physics::physics_controlled"

suspicious that there is a reference in the children array. Not sure what the hierarchy is here there is only one mesh in the .glb

The ..colliders/main.json file it references is also there

kevzettler@kevs-mbp-3 aceclone % cat build/lsvr7wpee4biw3sleyscm7har4xzjvoa/assets/ships/fighter01.glb/colliders/main.json
{"concave":[[[1.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,1.0],"../px_triangle_meshes/mesh_0_0.pxtm"]],"convex":[[[-0.9999999,0.0,0.0,0.0,0.0,5.9604645e-8,0.99999994,0.0,0.0,0.99999994,5.9604645e-8,0.0,0.0,0.0,0.0,1.0],"../px_convex_meshes/mesh_0_0_npp.pxcm"]]}%

I've tried adding physics_controlled at runtime like:

            .with(physics_controlled(), ())
            .with(kinematic(), ())
            .with(dynamic(), true)

but it doesn't seem to persist in the server_hierarchy dump..

kevzettler avatar Oct 19 '23 15:10 kevzettler

One detail I don't know if I mentioned is that I can trigger collisions between:

primitve runtime entities -> prefab dynamics So at some level the prefab dynamics are in the physx

Also primitive runtime entities -> prefab statics Works as well

but not

prefab dynamics -> prefab statics

kevzettler avatar Oct 20 '23 00:10 kevzettler

I have added the .with(kinematic(), ()) component and this fixes the behavior with the collision body being hijacked and managed by physxs instead of our dynamic updates. Unfortunately it still does not register collision events against other bodies.

Are these other bodies being dynamic or static? If you look at the documentation of PhysX 4.1 under the kinematic actors, it says:

There is no interaction or collision between kinematic actors and static actors. However, it is possible to request contact information for these cases with the PxSceneDesc::kineKineFilteringMode and PxSceneDesc::staticKineFilteringMode.

It is possible that you are hitting one of those edge cases (by design), as those flags are not set by default because they come with a performance cost. (We may need to expose those somehow).

If one of those actors where actually dynamic bodies, then I would expect the contacts to be reported by the callback.

fabiopolimeni avatar Nov 21 '23 11:11 fabiopolimeni

@fabiopolimeni I built a minimal isolated reproduction case for this issue at:

https://github.com/kevzettler/ambient_collision_bug

you can git clone it and ambient run

cubccollide

It makes 2 cubes. one prefab and one runtime and collides them into the ground. The prefab one exhibits the issue I described above. The collisions are logged with println! the prefab and runtime cubes collide. The runtime and ground collide. The prefab and ground do not collide.

kevzettler avatar Dec 17 '23 19:12 kevzettler