godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.07k stars 69 forks source link

Add per-shape physics materials to the 3D physics system #7401

Open aaronfranke opened 11 months ago

aaronfranke commented 11 months ago

Describe the project you are working on

I am working on GLTF support in Godot.

Describe the problem or limitation you are having in your project

The Khronos group had a meeting about physics the day I am writing this proposal, and decided that GLTF physics materials should be per-shape. The opinion of the Khronos group is that per-shape physics materials are important, should be in the base GLTF physics extension spec, and the spec should require implementations to support them.

Godot currently only has per-body physics materials, so if a GLTF file has a body with multiple shapes and each has per-shape physics materials, it's not possible to import that file and have it behave the same. Technically you could import the data as multiple bodies, but that would likely break other things.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The enhancement is to add physics materials to the CollisionShape3D node. This would allow us to have per-shape physics materials, which allows us to import the Khronos group's proposed GLTF physics materials.

Note that aside from GLTF compatibility, per-shape physics materials may also be useful for Godot users in general. Many other engines have per-shape physics materials, including Jolt, so adding this to Godot's physics nodes would help with using the full capabilities of third-party physics engines in Godot. During the Khronos group meeting they mentioned that most engines they've worked with had this feature and Godot is the odd one out here.

An example use-case of per-shape physics materials would be a hammer. The handle of the hammer is made out of a different physics material from the head of the hammer. It is not possible to simulate a hammer's materials correctly in Godot's current physics system, unless you used 2 bodies with a weld joint holding them together, but that would be likely to cause other issues.

We may wish to do the same in 2D as well for feature parity - but for the moment, I am primarily interested in 3D.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Add a new property to CollisionShape3D: physics_material. These would work similarly to the properties on RigidBody3D. The per-body physics material can be kept to keep simple use cases simple. If the shape's physics material is set, it will take priority over the body's physics material.

Note: RigidBody3D's physics material is currently called physics_material_override, but as far as I can tell this is a mistake. It doesn't actually override anything, this is the only physics material property I can see. I think this should be renamed to physics_material in Godot 5.0 (and move the property to PhysicsBody3D instead of RigidBody3D, actually considering the name difference this part could be done during Godot 4.x).

If this enhancement will not be used often, can it be worked around with a few lines of script?

It can't be worked around in script - at least, not without multiple bodies, which would likely break other things.

Is there a reason why this should be core and not an add-on in the asset library?

This is a core part of the physics system.

xzbobzx commented 9 months ago

I just wrote a similar proposal (https://github.com/godotengine/godot-proposals/issues/7923) before finding this one.

I'd suggest the PhysicsMaterial workflow from Jolt (per-shape physics materials) should become the PhysicsMaterial workflow of Godot as well.

It's already implemented in the physics engine and it's less restrictive than the current implementation.

yankscally commented 2 weeks ago

Working on a 3D spatial audio plugin with a few collaborators and we wanted to apply PhysicsMaterials to each surface for occlusion and reflection to correctly process the audio when it happens to shoot some raycasts at it. Spitting meshes into bodies is the only way, and even then, its a heavy process with MeshDataTool to check the surface etc.

I think another important part of this workflow is that more than often you will want the textures and the collisions to "match up" with an easy way to check that so that you can get footstepping sounds. I don't really have any good ideas for how that could work in practicality though. It's quite difficult when the collision shapes don't always necesserily equal the mesh shape.

For now we will try and find a way around this as elegantly as we can, but this is something that would make this much much easier to work on.