Closed mihe closed 3 months ago
I’m willing to help troubleshoot this in any way I can!
Thanks, I'll take a look!
I've created a fix for the repro case.
Note that if I uncomment the commented lines, the issue of the ball getting stuck on the slope still happens. This is because in this mode it will only simulate until the first hit (aka time stealing). If:
physics_settings.mPenetrationSlop = 0.0f;
Then it means that it will collide immediately, so will make no progress. Allowing a little slop (10x less than the default):
physics_settings.mPenetrationSlop = 0.002f;
Makes the ball roll down the slope without issues.
I take it (based on #1162) that I should disable the active edge detection for the shape queries in Godot Jolt as well then, when using InternalEdgeRemovingCollector
?
Yes, I think so. Although we might want to verify first that this actually fixes the original reported issue (which I find hard to judge when I compile godot-jolt with this new code and run the BallStuckBug_2.zip repro).
I can confirm that both BallStuckBug.zip
and BallStuckBug_2.zip
are fixed.
Before #1162 TestSceneBall.tscn
in BallStuckBug.zip
shows a significant jump when crossing over the internal edge, with or without mEnhancedInternalEdgeRemoval
, but now it only shows it when mEnhancedInternalEdgeRemoval
is disabled.
BallStuckBug_2.zip
had all the settings applied that we'd talked about, so you'd need to revert those first in order for TestSceneBall.tscn
to do the jump on the internal edge. With those reverted it's the same story as with BallStuckBug.zip
.
As talked about in godot-jolt/godot-jolt#587.
The actual relevant circumstances/properties surrounding this one isn't super clear to me, so I'll just lay out the scenario as shown in the issue linked above.
When a
SphereShape
dynamic body is moving across a staticMeshShape
body, seemingly with a significant angular velocity, the dynamic body will sometimes "catch" on the internal/inactive edges of the static body and jump up as a result.This seems to happen regardless of whether Jolt's active edge detection is enabled, or whether the more recent
mEnhancedInternalEdgeRemoval
is enabled on the dynamic body.The workaround suggested in the issue linked above was to enable
EMotionQuality::LinearCast
on the dynamic body, lower themLinearCastThreshold
setting to something like 25% and set bothmPenetrationSlop
andmSpeculativeContactDistance
to 0. While this does resolve the issue of catching on the internal/inactive edges, this however produces another artifact, namely that the dynamic body will randomly get stuck on the static body, almost as if linearly constrained, while its angular movement remains unconstrained, causing it to spin in-place.I've created a repro for both scenarios in the
Samples
projects, by hijackingSimpleTest
:Header File
```cpp #pragma once #include
#include
class SimpleTest : public Test
{
public:
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SimpleTest)
virtual void Initialize() override;
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
private:
BodyID mLevelBall;
BodyID mSlopeBall;
};
```
Source File
```cpp #include
#include
#include
#include
#include
#include
#include "SimpleTest.h"
JPH_IMPLEMENT_RTTI_VIRTUAL(SimpleTest)
{
JPH_ADD_BASE_CLASS(SimpleTest, Test)
}
void SimpleTest::Initialize()
{
MeshShapeSettings plane_mesh({
{
Float3(-10, 0, -10),
Float3(-10, 0, 10),
Float3(10, 0, 10)
},
{
Float3(-10, 0, -10),
Float3(10, 0, 10),
Float3(10, 0, -10)
},
});
plane_mesh.SetEmbedded();
BodyCreationSettings level_plane(&plane_mesh, RVec3(-10, 0, 0), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING);
level_plane.mFriction = 1;
mBodyInterface->CreateAndAddBody(level_plane, EActivation::DontActivate);
BodyCreationSettings level_ball(new SphereShape(0.5f), RVec3(-10, 1, -9), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
// level_ball.mMotionQuality = EMotionQuality::LinearCast;
level_ball.mEnhancedInternalEdgeRemoval = true;
level_ball.mFriction = 1;
level_ball.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
level_ball.mMassPropertiesOverride.mMass = 1;
mLevelBall = mBodyInterface->CreateAndAddBody(level_ball, EActivation::Activate);
BodyCreationSettings slope_plane(&plane_mesh, RVec3(10, 0, 0), Quat::sRotation(Vec3::sAxisX(), DegreesToRadians(45)), EMotionType::Static, Layers::NON_MOVING);
slope_plane.mFriction = 1;
mBodyInterface->CreateAndAddBody(slope_plane, EActivation::DontActivate);
BodyCreationSettings slope_ball(new SphereShape(0.5f), RVec3(10, 8, -6), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
// slope_ball.mMotionQuality = EMotionQuality::LinearCast;
slope_ball.mEnhancedInternalEdgeRemoval = true;
slope_ball.mFriction = 1;
slope_ball.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
slope_ball.mMassPropertiesOverride.mMass = 1;
mSlopeBall = mBodyInterface->CreateAndAddBody(slope_ball, EActivation::Activate);
PhysicsSettings physics_settings = mPhysicsSystem->GetPhysicsSettings();
// physics_settings.mPenetrationSlop = 0.0f;
// physics_settings.mSpeculativeContactDistance = 0.0f;
// physics_settings.mLinearCastThreshold = 0.25f;
mPhysicsSystem->SetPhysicsSettings(physics_settings);
}
void SimpleTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
{
mBodyInterface->AddTorque(mLevelBall, Vec3(JPH_PI * 4, 0, 0));
}
```
Here's what that repro looks like when just using the enhanced internal edge removal (and friction set to 1 on all bodies):
https://github.com/jrouwe/JoltPhysics/assets/4884246/f7245562-0c78-4404-a59c-ef7067568007
Here's what the repro looks like when uncommenting all the commented lines, meaning enabling CCD and changing
PhysicsSettings
to what was mentioned above:https://github.com/jrouwe/JoltPhysics/assets/4884246/ddd37b4b-11b3-41a1-b69f-06ed1960160b