Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,43 @@ public static void ConstraintsTest()
RunGameTest(game);
}

[Fact]
public static void ConstraintsForceTest()
{
var game = new GameTest();
game.Script.AddTask(async () =>
{
game.ScreenShotAutomationEnabled = false;

var e1 = new BodyComponent { Collider = new CompoundCollider { Colliders = { new BoxCollider() } } };
var c = new OneBodyLinearMotorConstraintComponent
{
A = e1,
LocalOffset = Vector3.Zero,
MotorMaximumForce = 3,
MotorDamping = 1,
};

Assert.Equal(0f, c.GetAccumulatedForceMagnitude());

game.SceneSystem.SceneInstance.RootScene.Entities.AddRange(new EntityComponent[] { e1, c }.Select(x => new Entity { x }));

Assert.Equal(0f, c.GetAccumulatedForceMagnitude());

do
{
await e1.Simulation!.AfterUpdate();

// Given current gravity, the constraint should pull the body in under 5 seconds,
// otherwise something is wrong and this loop would likely continue indefinitely
Assert.True(game.UpdateTime.Total.TotalSeconds < 5d);
} while (c.GetAccumulatedForceMagnitude() < float.BitDecrement(c.MotorMaximumForce));

game.Exit();
});
RunGameTest(game);
}

[Fact]
public static void OnContactRemovalTest()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,26 @@ internal void TryUpdateDescription()
}
}

/// <inheritdoc/>
public override float GetAccumulatedImpulseMagnitude()
{
if (_bepuSimulation != null && Attached)
return MathF.Sqrt(_bepuSimulation.Simulation.Solver.GetAccumulatedImpulseMagnitudeSquared(_cHandle));

return 0;
}

/// <inheritdoc/>
public override float GetAccumulatedForceMagnitude()
{
if (_bepuSimulation != null && Attached)
{
float impulses = GetAccumulatedImpulseMagnitude();
return 1f / (float)_bepuSimulation.FixedTimeStep.TotalSeconds * _bepuSimulation.SolverSubStep * impulses;
}

return 0;
}

protected ConstraintComponent(int bodies) : base(bodies) { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,23 @@ protected BodyComponent? this[int i]
/// <remarks> May not be attached if it is not in a scene, when not <see cref="Enabled"/>, when any of its target is null, not in a scene or in a different simulation </remarks>
public abstract bool Attached { get; }

/// <summary>
/// Returns the squared sum of all impulses this constraint applied on the last tick
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit: The doc says "Returns the squared sum of all...", but your implementation above does a MathF.Sqrt(). Is that correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I intended to replicate bepu's api on that front, but ended up forcing a sqrt as I did not see any cases were one would prefer a squared version. I'll make a PR in a bit to fix this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally squared versions are nice for checking relative magnitudes (i.e. checking if not zero, or comparing A > B, or comparing against a precomputed threshold). In those cases, it is sufficient to get the squared magnitude and save a square root.
Anyway, I'm not very into physics simulations these days, so you may know better 😀.

/// </summary>
/// <remarks>
/// Impulses increase depending on <see cref="BepuSimulation.FixedTimeStep"/>, as well as the amount of <see cref="BepuSimulation.SolverSubStep"/>.
/// You may want to use <see cref="GetAccumulatedForceMagnitude"/> instead.
/// </remarks>
public abstract float GetAccumulatedImpulseMagnitude();

/// <summary>
/// Returns the squared sum of all forces this constraint applied on the last tick
/// </summary>
/// <remarks>
/// This can be used to compare with a given motor constraints' MaximumForce property for example.
/// </remarks>
public abstract float GetAccumulatedForceMagnitude();

protected abstract void BodiesChanged();

internal abstract void Activate(BepuConfiguration bepuConfig);
Expand Down
Loading