< Summary

Information
Class: Gravitas.CollisionHandling.ExactContactLever2D
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Response/2D/ExactContactLever2D.cs
Line coverage
100%
Covered lines: 140
Uncovered lines: 0
Coverable lines: 140
Total lines: 250
Line coverage: 100%
Branch coverage
100%
Covered branches: 20
Total branches: 20
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
CanUseCompactResponse(...)100%44100%
CreateResponseOperand(...)100%44100%
TryGetNormalResponse(...)100%11100%
TryGetAccumulatedNormalResponse(...)100%11100%
ToSpatial(...)100%11100%
ToPlanar(...)100%11100%
ToPlanarAngular(...)100%11100%
TryGetImpulseVelocityDeltas(...)100%11100%
TryGetParticipantVelocityDeltas(...)100%88100%
CreateInverseInertia(...)100%44100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Response/2D/ExactContactLever2D.cs

#LineLine coverage
 1//=======================================================================
 2// ExactContactLever2D.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2026-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using FixedMathSharp;
 9using FixedMathSharp.Geometry;
 10
 11namespace Gravitas.CollisionHandling;
 12
 13/// <summary>
 14/// Adapts planar body mobility and signed yaw to the shared exact 3D response
 15/// kernel.
 16/// </summary>
 17internal static class ExactContactLever2D
 18{
 19    internal static bool CanUseCompactResponse(
 20        SolidBody2D? bodyA,
 21        Vector2d linearVelocityA,
 22        Fixed64 angularVelocityA,
 23        Vector2d relativeContactPointA,
 24        SolidBody2D? bodyB,
 25        Vector2d linearVelocityB,
 26        Fixed64 angularVelocityB,
 27        Vector2d relativeContactPointB,
 28        Vector2d axis)
 29    {
 201130        Vector3d spatialAxis = ToSpatial(axis);
 201131        Vector3d leverA = ToSpatial(relativeContactPointA);
 201132        Vector3d leverB = ToSpatial(relativeContactPointB);
 201133        return ContactResponseArithmetic3D.CanUseFastPointVelocity(
 201134                ToSpatial(linearVelocityA),
 201135                new Vector3d(
 201136                    Fixed64.Zero,
 201137                    -angularVelocityA,
 201138                    Fixed64.Zero),
 201139                leverA,
 201140                ToSpatial(linearVelocityB),
 201141                new Vector3d(
 201142                    Fixed64.Zero,
 201143                    -angularVelocityB,
 201144                    Fixed64.Zero),
 201145                leverB,
 201146                spatialAxis)
 201147            && ContactResponseArithmetic3D.CanUseFastAngularResponse(
 201148                leverA,
 201149                spatialAxis,
 201150                CreateInverseInertia(bodyA))
 201151            && ContactResponseArithmetic3D.CanUseFastAngularResponse(
 201152                leverB,
 201153                spatialAxis,
 201154                CreateInverseInertia(bodyB));
 55    }
 56
 57    internal static ExactContactResponseOperand3D CreateResponseOperand(
 58        SolidBody2D? body,
 59        Vector2d linearVelocity,
 60        Fixed64 angularVelocity,
 61        in ExactLever3D lever,
 62        Vector3d signedAxis) =>
 46063        new(
 46064            lever,
 46065            ToSpatial(linearVelocity),
 46066            new Vector3d(
 46067                Fixed64.Zero,
 46068                -angularVelocity,
 46069                Fixed64.Zero),
 46070            body == null
 46071                ? Vector3d.Zero
 46072                : ToSpatial(body.ProjectLinearMotion(ToPlanar(signedAxis))),
 46073            body?.EffectiveInverseMass ?? Fixed64.Zero,
 46074            CreateInverseInertia(body));
 75
 76    internal static bool TryGetNormalResponse(
 77        SolidBody2D? bodyA,
 78        Vector2d linearVelocityA,
 79        Fixed64 angularVelocityA,
 80        in ExactLever3D relativeContactPointA,
 81        SolidBody2D? bodyB,
 82        Vector2d linearVelocityB,
 83        Fixed64 angularVelocityB,
 84        in ExactLever3D relativeContactPointB,
 85        Vector2d normal,
 86        Fixed64 restitution,
 87        Fixed64 restitutionVelocityThreshold,
 88        out ExactNormalResponse3D response)
 89    {
 2690        Vector3d spatialNormal = ToSpatial(normal);
 2691        ExactContactResponseOperand3D first = CreateResponseOperand(
 2692            bodyA,
 2693            linearVelocityA,
 2694            angularVelocityA,
 2695            relativeContactPointA,
 2696            -spatialNormal);
 2697        ExactContactResponseOperand3D second = CreateResponseOperand(
 2698            bodyB,
 2699            linearVelocityB,
 26100            angularVelocityB,
 26101            relativeContactPointB,
 26102            spatialNormal);
 26103        return ExactContactResponseKernel.TryGetNormalResponse(
 26104            first,
 26105            second,
 26106            spatialNormal,
 26107            restitution,
 26108            restitutionVelocityThreshold,
 26109            out response);
 110    }
 111
 112    internal static bool TryGetAccumulatedNormalResponse(
 113        SolidBody2D? bodyA,
 114        Vector2d linearVelocityA,
 115        Fixed64 angularVelocityA,
 116        in ExactLever3D relativeContactPointA,
 117        SolidBody2D? bodyB,
 118        Vector2d linearVelocityB,
 119        Fixed64 angularVelocityB,
 120        in ExactLever3D relativeContactPointB,
 121        Vector2d normal,
 122        Fixed64 restitution,
 123        Fixed64 restitutionVelocityThreshold,
 124        Fixed64 accumulatedImpulse,
 125        Fixed64 positiveImpulseScale,
 126        Fixed64 negativeImpulseScale,
 127        out ExactNormalResponse3D response)
 128    {
 38129        Vector3d spatialNormal = ToSpatial(normal);
 38130        ExactContactResponseOperand3D first = CreateResponseOperand(
 38131            bodyA,
 38132            linearVelocityA,
 38133            angularVelocityA,
 38134            relativeContactPointA,
 38135            -spatialNormal);
 38136        ExactContactResponseOperand3D second = CreateResponseOperand(
 38137            bodyB,
 38138            linearVelocityB,
 38139            angularVelocityB,
 38140            relativeContactPointB,
 38141            spatialNormal);
 38142        return ExactContactResponseKernel.TryGetAccumulatedNormalResponse(
 38143            first,
 38144            second,
 38145            spatialNormal,
 38146            restitution,
 38147            restitutionVelocityThreshold,
 38148            accumulatedImpulse,
 38149            positiveImpulseScale,
 38150            negativeImpulseScale,
 38151            out response);
 152    }
 153
 154    internal static Vector3d ToSpatial(Vector2d vector) =>
 21145155        new(vector.X, Fixed64.Zero, vector.Y);
 156
 157    internal static Vector2d ToPlanar(Vector3d vector) =>
 700158        new(vector.X, vector.Z);
 159
 160    internal static Fixed64 ToPlanarAngular(Vector3d vector) =>
 306161        -vector.Y;
 162
 163    internal static bool TryGetImpulseVelocityDeltas(
 164        SolidBody2D? bodyA,
 165        in ExactLever3D relativeContactPointA,
 166        SolidBody2D? bodyB,
 167        in ExactLever3D relativeContactPointB,
 168        Vector2d firstAxis,
 169        Fixed64 firstScale,
 170        Vector2d secondAxis,
 171        Fixed64 secondScale,
 172        out Vector2d linearVelocityDeltaA,
 173        out Fixed64 angularVelocityDeltaA,
 174        out Vector2d linearVelocityDeltaB,
 175        out Fixed64 angularVelocityDeltaB)
 176    {
 3177        Vector3d first = ToSpatial(firstAxis);
 3178        Vector3d second = ToSpatial(secondAxis);
 3179        bool firstResolved = TryGetParticipantVelocityDeltas(
 3180            bodyA,
 3181            relativeContactPointA,
 3182            -first,
 3183            firstScale,
 3184            -second,
 3185            secondScale,
 3186            out linearVelocityDeltaA,
 3187            out angularVelocityDeltaA);
 3188        bool secondResolved = TryGetParticipantVelocityDeltas(
 3189            bodyB,
 3190            relativeContactPointB,
 3191            first,
 3192            firstScale,
 3193            second,
 3194            secondScale,
 3195            out linearVelocityDeltaB,
 3196            out angularVelocityDeltaB);
 3197        return firstResolved & secondResolved;
 198    }
 199
 200    internal static bool TryGetParticipantVelocityDeltas(
 201        SolidBody2D? body,
 202        in ExactLever3D lever,
 203        Vector3d firstAxis,
 204        Fixed64 firstScale,
 205        Vector3d secondAxis,
 206        Fixed64 secondScale,
 207        out Vector2d linearVelocityDelta,
 208        out Fixed64 angularVelocityDelta)
 209    {
 10210        linearVelocityDelta = Vector2d.Zero;
 10211        angularVelocityDelta = Fixed64.Zero;
 10212        if (body?.HasSolverMobility != true)
 5213            return true;
 214
 5215        Vector3d spatialLinear = Vector3d.Zero;
 5216        bool linearResolved = !body.CanTranslate
 5217            || Vector3d.TryScaledLinearCombination(
 5218                ToSpatial(body.ProjectLinearMotion(ToPlanar(firstAxis))),
 5219                firstScale,
 5220                ToSpatial(body.ProjectLinearMotion(ToPlanar(secondAxis))),
 5221                secondScale,
 5222                Vector3d.Zero,
 5223                Fixed64.Zero,
 5224                body.EffectiveInverseMass,
 5225                out spatialLinear);
 5226        Vector3d spatialAngular = Vector3d.Zero;
 5227        bool angularResolved = !body.CanRotate
 5228            || ExactLever3D.TryGetTransformedWeightedCrossProduct(
 5229                lever,
 5230                firstAxis,
 5231                firstScale,
 5232                secondAxis,
 5233                secondScale,
 5234                Vector3d.Zero,
 5235                Fixed64.Zero,
 5236                CreateInverseInertia(body),
 5237                out spatialAngular);
 5238        linearVelocityDelta = ToPlanar(spatialLinear);
 5239        angularVelocityDelta = ToPlanarAngular(spatialAngular);
 5240        return linearResolved & angularResolved;
 241    }
 242
 243    internal static Fixed3x3 CreateInverseInertia(SolidBody2D? body) =>
 4805244        body?.CanRotate == true
 4805245            ? new Fixed3x3(
 4805246                Fixed64.Zero, Fixed64.Zero, Fixed64.Zero,
 4805247                Fixed64.Zero, body.EffectiveInverseMomentOfInertia, Fixed64.Zero,
 4805248                Fixed64.Zero, Fixed64.Zero, Fixed64.Zero)
 4805249            : Fixed3x3.Zero;
 250}

Methods/Properties

CanUseCompactResponse(Gravitas.SolidBody2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,Gravitas.SolidBody2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Vector2d)
CreateResponseOperand(Gravitas.SolidBody2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ExactLever3D&,FixedMathSharp.Vector3d)
TryGetNormalResponse(Gravitas.SolidBody2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ExactLever3D&,Gravitas.SolidBody2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ExactLever3D&,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ExactNormalResponse3D&)
TryGetAccumulatedNormalResponse(Gravitas.SolidBody2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ExactLever3D&,Gravitas.SolidBody2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ExactLever3D&,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ExactNormalResponse3D&)
ToSpatial(FixedMathSharp.Vector2d)
ToPlanar(FixedMathSharp.Vector3d)
ToPlanarAngular(FixedMathSharp.Vector3d)
TryGetImpulseVelocityDeltas(Gravitas.SolidBody2D,Gravitas.CollisionHandling.ExactLever3D&,Gravitas.SolidBody2D,Gravitas.CollisionHandling.ExactLever3D&,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d&,FixedMathSharp.Fixed64&,FixedMathSharp.Vector2d&,FixedMathSharp.Fixed64&)
TryGetParticipantVelocityDeltas(Gravitas.SolidBody2D,Gravitas.CollisionHandling.ExactLever3D&,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector2d&,FixedMathSharp.Fixed64&)
CreateInverseInertia(Gravitas.SolidBody2D)