Repository: godotengine/godot (language: cpp)

Issue:
0 units-thin BoxShape3D has no working collision when using Jolt
### Tested versions

- Reproducible in: 4.4.beta1

### System information

Godot v4.4.dev (24d74510e) - Fedora Linux 41 (KDE Plasma) on X11 - X11 display driver, Multi-window, 1 monitor - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4090 (nvidia; 565.77) - 13th Gen Intel(R) Core(TM) i9-13900K (32 threads)

### Issue description

A slow-moving RigidBody3D with a SphereShape fails to collide with a BoxShape that has its height set to 0 (essentially a quad collision shape). The RigidBody3D will fall straight through it as if the box didn't exist.

In contrast, it works when using GodotPhysics3D or against very thin CylinderShape3D (see below).

This may not be fixable on the Jolt side, so maybe it should just be worked around by disallowing the use of `0.0` in the BoxShape3D inspector and requiring it to be at least `0.001` like CylinderShape3D.

https://github.com/user-attachments/assets/5c9b9ee3-1b9f-4da7-8365-83f7fc71b44e

### Steps to reproduce

- Create a StaticBody3D with a BoxShape3D that has its Y component set to `0.0`.
- Add a RigidBody3D with a collision shape and make it fall on the BoxShape3D.
- Notice how the rigid body collides properly as long as its speed is not too high.
- Set the 3D physics engine to Jolt in the Project Settings and try again.
- Notice how the rigid body now phases through the box.

### Minimal reproduction project (MRP)

[test_box_thin.zip](https://github.com/user-attachments/files/18497769/test_box_thin.zip)


Discussion / hints:
Not only does it not behave as with Godot Physics, but (as you can see in your MRP) you get met with an error in the Output pane saying:

```
Failed to build Jolt Physics box shape with {half_extents=(1.000000, 0.000000, 1.000000) margin=0.040000}. It returned the following error: 'Invalid convex radius'. This shape belongs to 'StaticBody3D:<StaticBody3D#2444876660670>' and 2 other object(s).
```

I could have sworn I had code to replace this `Invalid convex radius` Jolt error with one that mentioned collision margins instead, at least for the simpler primitive shapes, but as it turns out that particular code went away in godot-jolt/godot-jolt#406, when we added the dynamic scaling of the collision margin instead, which to some degree fills the same function, but doesn't cover the zero case. I guess I somehow never encountered a zero-sized box since then, nor ever had this error reported to me, because that will indeed trigger this error.

Either way, as it turns out, setting the cylinders to all have a zero height through a script (and thus a calculated collision margin of zero as well) does still seem to make Jolt behave the same as with Godot Physics, where the shape turns into a plane of sorts, which I'm surprised by.

When looking at the code for `JPH::CylinderShape` and `JPH::BoxShape` it would seem that there's a discrepancy within their error-checking, where `JPH::BoxShape` effectively checks for `min_half_extent <= collision_margin` (see [here](https://github.com/jrouwe/JoltPhysics/blob/748edb70ed2f16b95af52f046781d57c242656a5/Jolt/Physics/Collision/Shape/BoxShape.cpp#L62)) whereas `JPH::CylinderShape` does `min_half_extent < collision_margin` (see [here](https://github.com/jrouwe/JoltPhysics/blob/748edb70ed2f16b95af52f046781d57c242656a5/Jolt/Physics/Collision/Shape/CylinderShape.cpp#L96-L106)). And indeed, changing the error-checking in `JPH::BoxShape` to also use `<` instead of `<=` resolves this problem and makes things behave as with Godot Physics (at least in this basic scene).

@jrouwe Is there some particular reason for this discrepancy in the error-checking? Are there other problems one can expect from a zero-sized shape like this, besides the obvious problem of having a convex radius of zero? I would imagine that dynamic bodies will be janky at best, but maybe it's fine-ish for static bodies, like in this MRP? Maybe we're better off just disallowing zero-sized shapes altogether?
@mihe No there's no particular reason for this. I've updated the code to change `<=` into `<`. 

I cannot recommend creating scenes like this though as these really thin objects make it easy for objects to tunnel through them.

Fix patch:
diff --git a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/BoxShape.cpp b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/BoxShape.cpp
index dc7ea4828575..fc2281252f05 100644
--- a/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/BoxShape.cpp
+++ b/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/BoxShape.cpp
@@ -59,7 +59,7 @@ BoxShape::BoxShape(const BoxShapeSettings &inSettings, ShapeResult &outResult) :
 {
 	// Check convex radius
 	if (inSettings.mConvexRadius < 0.0f
-		|| inSettings.mHalfExtent.ReduceMin() <= inSettings.mConvexRadius)
+		|| inSettings.mHalfExtent.ReduceMin() < inSettings.mConvexRadius)
 	{
 		outResult.SetError("Invalid convex radius");
 		return;
@@ -278,7 +278,7 @@ void BoxShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg
 
 void BoxShape::GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const
 {
-	new (&ioContext) GetTrianglesContextVertexList(inPositionCOM, inRotation, inScale, Mat44::sScale(mHalfExtent), sUnitBoxTriangles, sizeof(sUnitBoxTriangles) / sizeof(Vec3), GetMaterial());
+	new (&ioContext) GetTrianglesContextVertexList(inPositionCOM, inRotation, inScale, Mat44::sScale(mHalfExtent), sUnitBoxTriangles, std::size(sUnitBoxTriangles), GetMaterial());
 }
 
 int BoxShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials) const


Test patch: