< Summary

Information
Class: Gravitas.CollisionHandling.CollisionResponse
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Response/3D/CollisionResponse.cs
Line coverage
100%
Covered lines: 787
Uncovered lines: 0
Coverable lines: 787
Total lines: 1240
Line coverage: 100%
Branch coverage
100%
Covered branches: 216
Total branches: 216
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
CalculateImpulse(...)100%11100%
CalculateImpulse(...)100%4242100%
TryCreateBodyPair(...)100%1212100%
BuildContactBuffer(...)100%44100%
TryCreateContact(...)100%1010100%
TryCalculateExactNormalResult(...)100%11100%
ApplyPositionCorrection(...)100%44100%
TryApplyCachedImpulse(...)100%66100%
TryApplyContactImpulseCombination(...)100%44100%
TryApplyContactImpulse(...)100%66100%
TryApplyContactImpulseExact(...)100%11100%
TryApplyContactImpulseCombinationExact(...)100%22100%
TryApplyNormalImpulse(...)100%1616100%
TrySolveFrictionImpulse(...)100%1212100%
TryGetCompactFrictionResponse(...)100%2626100%
TrySolveFrictionImpulseExact(...)100%44100%
TryGetCompactTangentImpulseDelta(...)100%1212100%
TryGetCompactConstrainedInverseMass(...)100%44100%
TryGetFrictionLimit(...)100%66100%
TryGetMagnitudeSquared(...)100%22100%
TryGetSquare(...)100%44100%
ResolveLinearVelocity(...)100%22100%
ResolveAngularVelocity(...)100%22100%
TryApplyExactImpulse(...)100%22100%
TryApplyCompactImpulse(...)100%22100%
CanNegate(...)100%44100%
TryGetLinearVelocityDelta(...)100%44100%
TryGetAngularVelocityDelta(...)100%1010100%
TryPrepareVelocityStates(...)100%11100%
TryApplyVelocityDeltas(...)100%22100%
ApplyVelocityStates(...)100%11100%
GetExactLevers(...)100%11100%
HasFailedResponse(...)100%11100%
RejectResponse(...)100%22100%
ClearWarmStartImpulse(...)100%11100%
IsWarmStartCompatible(...)100%11100%
ResolveContactNormal(...)100%1010100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Response/3D/CollisionResponse.cs

#LineLine coverage
 1//=======================================================================
 2// CollisionResponse.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;
 10using Gravitas.Materials;
 11using System.Runtime.CompilerServices;
 12
 13namespace Gravitas.CollisionHandling;
 14
 15/// <summary>
 16/// Solves deterministic contact response for one collision pair manifold.
 17/// </summary>
 18public static class CollisionResponse
 19{
 20    /// <summary>
 21    /// Penetration depth below this value is treated as contact slop and does not
 22    /// produce positional correction.
 23    /// </summary>
 124    public static readonly Fixed64 PenetrationSlop = (Fixed64)0.01f;
 25
 26    /// <summary>
 27    /// Fraction of penetration above slop corrected per solver call.
 28    /// </summary>
 129    public static readonly Fixed64 PenetrationCorrectionPercent = (Fixed64)0.8f;
 30
 131    private static readonly Fixed64 WarmStartNormalCompatibilityThreshold = Fixed64.FromFraction(63, 64);
 32
 33    /// <summary>
 34    /// Applies positional correction, normal impulses, and Coulomb friction for
 35    /// the collision pair's current deterministic contact manifold.
 36    /// </summary>
 37    public static void CalculateImpulse(CollisionPair pair) =>
 15538        CalculateImpulse(
 15539            pair,
 15540            applyCachedImpulse: true,
 15541            applyPositionCorrection: true);
 42
 43    internal static void CalculateImpulse(
 44        CollisionPair pair,
 45        bool applyCachedImpulse,
 46        bool applyPositionCorrection)
 47    {
 884248        if (!TryCreateBodyPair(pair, out ResponseBody bodyA, out ResponseBody bodyB))
 449            return;
 50
 883851        ContactAnchor responseCenterA = bodyA.Body.GetCenterOfMassAnchor();
 883852        ContactAnchor responseCenterB = bodyB.Body.GetCenterOfMassAnchor();
 883853        SolverContactBuffer contacts = BuildContactBuffer(
 883854            pair,
 883855            bodyA,
 883856            bodyB,
 883857            responseCenterA,
 883858            responseCenterB);
 883859        if (contacts.Count == 0)
 160            return;
 61
 883762        Vector3d responsePositionA = bodyA.Body.Position3d;
 883763        Vector3d responsePositionB = bodyB.Body.Position3d;
 883764        byte failedResponseMask = 0;
 883765        Fixed64 contactShare = Fixed64.One / (Fixed64)contacts.Count;
 883766        if (applyPositionCorrection)
 67        {
 370068            for (int i = 0; i < contacts.Count; i++)
 97069                ApplyPositionCorrection(contacts.GetContact(i), contactShare);
 70        }
 71
 883772        if (applyCachedImpulse)
 73        {
 88874            bool rebuildContacts = false;
 373275            for (int i = 0; i < contacts.Count; i++)
 76            {
 97877                SolverContact contact = contacts.GetContact(i);
 97878                if (!TryApplyCachedImpulse(
 97879                        pair,
 97880                        contact,
 97881                        responsePositionA,
 97882                        responsePositionB))
 83                {
 784                    ClearWarmStartImpulse(pair, contact);
 785                    rebuildContacts = true;
 86                }
 87            }
 88
 88889            if (rebuildContacts)
 90            {
 791                contacts = BuildContactBuffer(
 792                    pair,
 793                    bodyA,
 794                    bodyB,
 795                    responseCenterA,
 796                    responseCenterB);
 97            }
 98        }
 99
 8837100        Fixed64 restitutionVelocityThreshold = pair.Context.Settings.RestitutionVelocityThreshold;
 35828101        for (int i = 0; i < contacts.Count; i++)
 102        {
 9077103            SolverContact contact = contacts.GetContact(i);
 104            bool normalResolved;
 105            ContactNormalImpulseResult3D normalResult;
 9077106            if (contact.RelativeA.IsExact || contact.RelativeB.IsExact)
 107            {
 34108                normalResolved = TryCalculateExactNormalResult(
 34109                    pair,
 34110                    contact,
 34111                    responsePositionA,
 34112                    responsePositionB,
 34113                    restitutionVelocityThreshold,
 34114                    contactShare,
 34115                    out normalResult);
 116            }
 117            else
 118            {
 9043119                normalResolved = ContactNormalImpulse3D.TryCalculateAccumulatedDelta(
 9043120                    contact.A.Body,
 9043121                    ResolveLinearVelocity(contact.A.Body),
 9043122                    ResolveAngularVelocity(contact.A.Body),
 9043123                    contact.RelativeA.Vector,
 9043124                    contact.B.Body,
 9043125                    ResolveLinearVelocity(contact.B.Body),
 9043126                    ResolveAngularVelocity(contact.B.Body),
 9043127                    contact.RelativeB.Vector,
 9043128                    contact.Normal,
 9043129                    contact.Restitution,
 9043130                    restitutionVelocityThreshold,
 9043131                    contact.CachedNormalImpulse,
 9043132                    contactShare,
 9043133                    Fixed64.One,
 9043134                    out normalResult);
 9043135                if (!normalResolved)
 136                {
 1353137                    normalResolved = TryCalculateExactNormalResult(
 1353138                        pair,
 1353139                        contact,
 1353140                        responsePositionA,
 1353141                        responsePositionB,
 1353142                        restitutionVelocityThreshold,
 1353143                        contactShare,
 1353144                        out normalResult);
 145                }
 146            }
 147
 9077148            if (!normalResolved)
 149            {
 2150                RejectResponse(pair, contact, i, ref failedResponseMask);
 2151                continue;
 152            }
 153
 154            // The kernel preflights this same cache-plus-delta sum.
 9075155            Fixed64 normalImpulse =
 9075156                contact.CachedNormalImpulse
 9075157                + normalResult.ImpulseScalar;
 9075158            contacts.SetNormalImpulse(i, normalImpulse, normalResult);
 159        }
 160
 35828161        for (int i = 0; i < contacts.Count; i++)
 162        {
 9077163            if (HasFailedResponse(failedResponseMask, i))
 164                continue;
 165
 9075166            SolverContact contact = contacts.GetContact(i);
 9075167            if (!TryApplyNormalImpulse(
 9075168                    pair,
 9075169                    contact,
 9075170                    contacts.GetNormalResult(i)))
 171            {
 1172                RejectResponse(pair, contact, i, ref failedResponseMask);
 173            }
 174        }
 175
 35828176        for (int i = 0; i < contacts.Count; i++)
 177        {
 9077178            if (HasFailedResponse(failedResponseMask, i))
 179                continue;
 180
 9074181            SolverContact contact = contacts.GetContact(i);
 9074182            if (!TrySolveFrictionImpulse(
 9074183                    pair,
 9074184                    contact,
 9074185                    responsePositionA,
 9074186                    responsePositionB,
 9074187                    FixedMath.Max(contacts.GetNormalImpulse(i), contact.CachedNormalImpulse),
 9074188                    out Fixed64 tangentImpulse,
 9074189                    out Fixed64 secondaryTangentImpulse))
 190            {
 1191                RejectResponse(pair, contact, i, ref failedResponseMask);
 1192                continue;
 193            }
 194
 9073195            contacts.SetTangentImpulse(i, tangentImpulse, secondaryTangentImpulse);
 196        }
 197
 35828198        for (int i = 0; i < contacts.Count; i++)
 199        {
 9077200            if (HasFailedResponse(failedResponseMask, i))
 201                continue;
 202
 9073203            SolverContact contact = contacts.GetContact(i);
 9073204            pair.StoreWarmStartImpulse(
 9073205                contact.ContactId,
 9073206                contact.Normal,
 9073207                contacts.GetNormalImpulse(i),
 9073208                contacts.GetTangentImpulse(i),
 9073209                contacts.GetSecondaryTangentImpulse(i));
 210        }
 8837211    }
 212
 213    private static bool TryCreateBodyPair(CollisionPair pair, out ResponseBody bodyA, out ResponseBody bodyB)
 214    {
 8842215        bodyA = default;
 8842216        bodyB = default;
 217
 8842218        if (pair.ColliderA.IsTrigger || pair.ColliderB.IsTrigger)
 1219            return false;
 220
 8841221        if (pair.ColliderA.Body == null || pair.ColliderB.Body == null)
 1222            return false;
 223
 8840224        if (!pair.Manifold.HasContact)
 1225            return false;
 226
 8839227        bodyA = ResponseBody.Create(pair.ColliderA);
 8839228        bodyB = ResponseBody.Create(pair.ColliderB);
 8839229        return bodyA.HasSolverMobility || bodyB.HasSolverMobility;
 230    }
 231
 232    private static SolverContactBuffer BuildContactBuffer(
 233        CollisionPair pair,
 234        ResponseBody bodyA,
 235        ResponseBody bodyB,
 236        in ContactAnchor responseCenterA,
 237        in ContactAnchor responseCenterB)
 238    {
 8845239        SolverContactBuffer contacts = default;
 35860240        for (int i = 0; i < pair.Manifold.Count; i++)
 241        {
 9085242            if (TryCreateContact(
 9085243                    pair,
 9085244                    bodyA,
 9085245                    bodyB,
 9085246                    responseCenterA,
 9085247                    responseCenterB,
 9085248                    i,
 9085249                    out SolverContact contact))
 250            {
 9084251                contacts.Add(contact);
 252            }
 253        }
 254
 8845255        return contacts;
 256    }
 257
 258    private static bool TryCreateContact(
 259        CollisionPair pair,
 260        ResponseBody bodyA,
 261        ResponseBody bodyB,
 262        in ContactAnchor responseCenterA,
 263        in ContactAnchor responseCenterB,
 264        int contactIndex,
 265        out SolverContact contact)
 266    {
 9085267        contact = default;
 9085268        ManifoldContact manifoldContact = pair.Manifold[contactIndex];
 9085269        Vector3d normal = ResolveContactNormal(manifoldContact.Normal, pair.ColliderB.Center - pair.ColliderA.Center);
 9085270        if (normal == Vector3d.Zero)
 1271            return false;
 9084272        ContactLever3D relativeA = ContactLever3D.Create(
 9084273            manifoldContact.AnchorA,
 9084274            responseCenterA);
 9084275        ContactLever3D relativeB = ContactLever3D.Create(
 9084276            manifoldContact.AnchorB,
 9084277            responseCenterB);
 9084278        PhysicsMaterial materialA = manifoldContact.HasMaterialOverride
 9084279            ? manifoldContact.MaterialA
 9084280            : pair.ColliderA.Material;
 9084281        PhysicsMaterial materialB = manifoldContact.HasMaterialOverride
 9084282            ? manifoldContact.MaterialB
 9084283            : pair.ColliderB.Material;
 284
 9084285        Fixed64 cachedNormalImpulse = Fixed64.Zero;
 9084286        Fixed64 cachedTangentImpulse = Fixed64.Zero;
 9084287        Fixed64 cachedSecondaryTangentImpulse = Fixed64.Zero;
 9084288        if (pair.TryGetWarmStartImpulse(manifoldContact.ContactId, out ContactWarmStartImpulse cached))
 289        {
 8053290            if (IsWarmStartCompatible(cached.Normal, normal))
 291            {
 8050292                cachedNormalImpulse = cached.NormalImpulse;
 8050293                cachedTangentImpulse = cached.TangentImpulse;
 8050294                cachedSecondaryTangentImpulse = cached.SecondaryTangentImpulse;
 295            }
 296        }
 297
 9084298        contact = new SolverContact(
 9084299            contactIndex,
 9084300            manifoldContact.ContactId,
 9084301            bodyA,
 9084302            bodyB,
 9084303            relativeA,
 9084304            relativeB,
 9084305            manifoldContact.Depth,
 9084306            normal,
 9084307            materialA,
 9084308            materialB,
 9084309            cachedNormalImpulse,
 9084310            cachedTangentImpulse,
 9084311            cachedSecondaryTangentImpulse);
 9084312        return true;
 313    }
 314
 315    [MethodImpl(MethodImplOptions.NoInlining)]
 316    private static bool TryCalculateExactNormalResult(
 317        CollisionPair pair,
 318        SolverContact contact,
 319        Vector3d responsePositionA,
 320        Vector3d responsePositionB,
 321        Fixed64 restitutionVelocityThreshold,
 322        Fixed64 contactShare,
 323        out ContactNormalImpulseResult3D result)
 324    {
 1387325        result = default;
 1387326        GetExactLevers(
 1387327            pair,
 1387328            contact,
 1387329            responsePositionA,
 1387330            responsePositionB,
 1387331            out ExactLever3D exactA,
 1387332            out ExactLever3D exactB);
 1387333        return ContactNormalImpulse3D.TryCalculateAccumulatedDeltaExact(
 1387334            contact.A.Body,
 1387335            ResolveLinearVelocity(contact.A.Body),
 1387336            ResolveAngularVelocity(contact.A.Body),
 1387337            exactA,
 1387338            contact.B.Body,
 1387339            ResolveLinearVelocity(contact.B.Body),
 1387340            ResolveAngularVelocity(contact.B.Body),
 1387341            exactB,
 1387342            contact.Normal,
 1387343            contact.Restitution,
 1387344            restitutionVelocityThreshold,
 1387345            contact.CachedNormalImpulse,
 1387346            contactShare,
 1387347            Fixed64.One,
 1387348            out result);
 349    }
 350
 351    private static void ApplyPositionCorrection(SolverContact contact, Fixed64 contactShare)
 352    {
 970353        Fixed64 correctionDepth = contact.Depth - PenetrationSlop;
 970354        if (correctionDepth <= Fixed64.Zero)
 436355            return;
 356
 534357        Fixed64 inverseMassA = contact.A.GetConstrainedInverseMass(contact.Normal);
 534358        Fixed64 inverseMassB = contact.B.GetConstrainedInverseMass(contact.Normal);
 534359        Fixed64 totalInverseMass = inverseMassA + inverseMassB;
 534360        if (totalInverseMass <= Fixed64.Zero)
 1361            return;
 362
 533363        Vector3d correction = contact.Normal
 533364            * (correctionDepth * PenetrationCorrectionPercent * contactShare / totalInverseMass);
 533365        contact.A.Body.ApplyCollisionPositionCorrection(-correction * inverseMassA);
 533366        contact.B.Body.ApplyCollisionPositionCorrection(correction * inverseMassB);
 533367    }
 368
 369    private static bool TryApplyCachedImpulse(
 370        CollisionPair pair,
 371        SolverContact contact,
 372        Vector3d responsePositionA,
 373        Vector3d responsePositionB)
 374    {
 978375        if (contact.CachedNormalImpulse == Fixed64.Zero
 978376            && contact.CachedTangentImpulse == Fixed64.Zero
 978377            && contact.CachedSecondaryTangentImpulse == Fixed64.Zero)
 378        {
 956379            return true;
 380        }
 381
 22382        return TryApplyContactImpulseCombination(
 22383            pair,
 22384            contact,
 22385            responsePositionA,
 22386            responsePositionB,
 22387            contact.Normal,
 22388            contact.CachedNormalImpulse,
 22389            contact.Tangent,
 22390            contact.CachedTangentImpulse,
 22391            contact.SecondaryTangent,
 22392            contact.CachedSecondaryTangentImpulse);
 393    }
 394
 395    private static bool TryApplyContactImpulseCombination(
 396        CollisionPair pair,
 397        SolverContact contact,
 398        Vector3d responsePositionA,
 399        Vector3d responsePositionB,
 400        Vector3d firstAxis,
 401        Fixed64 firstScale,
 402        Vector3d secondAxis,
 403        Fixed64 secondScale,
 404        Vector3d thirdAxis,
 405        Fixed64 thirdScale)
 406    {
 6173407        if (ContactResponseArithmetic3D.TryLinearCombination(
 6173408                firstAxis,
 6173409                firstScale,
 6173410                secondAxis,
 6173411                secondScale,
 6173412                thirdAxis,
 6173413                thirdScale,
 6173414                out Vector3d impulse)
 6173415            && CanNegate(impulse))
 416        {
 6168417            return TryApplyContactImpulse(
 6168418                pair,
 6168419                contact,
 6168420                responsePositionA,
 6168421                responsePositionB,
 6168422                impulse);
 423        }
 424
 5425        return TryApplyContactImpulseCombinationExact(
 5426            pair,
 5427            contact,
 5428            responsePositionA,
 5429            responsePositionB,
 5430            firstAxis,
 5431            firstScale,
 5432            secondAxis,
 5433            secondScale,
 5434            thirdAxis,
 5435            thirdScale);
 436    }
 437
 438    private static bool TryApplyContactImpulse(
 439        CollisionPair pair,
 440        SolverContact contact,
 441        Vector3d responsePositionA,
 442        Vector3d responsePositionB,
 443        Vector3d impulse)
 444    {
 6168445        if (!contact.RelativeA.IsExact
 6168446            && !contact.RelativeB.IsExact
 6168447            && TryApplyCompactImpulse(contact, impulse))
 448        {
 6120449            return true;
 450        }
 451
 48452        return TryApplyContactImpulseExact(
 48453            pair,
 48454            contact,
 48455            responsePositionA,
 48456            responsePositionB,
 48457            impulse);
 458    }
 459
 460    [MethodImpl(MethodImplOptions.NoInlining)]
 461    private static bool TryApplyContactImpulseExact(
 462        CollisionPair pair,
 463        SolverContact contact,
 464        Vector3d responsePositionA,
 465        Vector3d responsePositionB,
 466        Vector3d impulse)
 467    {
 48468        GetExactLevers(
 48469            pair,
 48470            contact,
 48471            responsePositionA,
 48472            responsePositionB,
 48473            out ExactLever3D exactA,
 48474            out ExactLever3D exactB);
 48475        return TryApplyExactImpulse(
 48476            contact,
 48477            exactA,
 48478            exactB,
 48479            impulse);
 480    }
 481
 482    [MethodImpl(MethodImplOptions.NoInlining)]
 483    private static bool TryApplyContactImpulseCombinationExact(
 484        CollisionPair pair,
 485        SolverContact contact,
 486        Vector3d responsePositionA,
 487        Vector3d responsePositionB,
 488        Vector3d firstAxis,
 489        Fixed64 firstScale,
 490        Vector3d secondAxis,
 491        Fixed64 secondScale,
 492        Vector3d thirdAxis,
 493        Fixed64 thirdScale)
 494    {
 5495        GetExactLevers(
 5496            pair,
 5497            contact,
 5498            responsePositionA,
 5499            responsePositionB,
 5500            out ExactLever3D exactA,
 5501            out ExactLever3D exactB);
 5502        if (!ExactContactLever3D
 5503                .TryGetImpulseCombinationVelocityDeltas(
 5504                    contact.A.Body,
 5505                    exactA,
 5506                    contact.B.Body,
 5507                    exactB,
 5508                    firstAxis,
 5509                    firstScale,
 5510                    secondAxis,
 5511                    secondScale,
 5512                    thirdAxis,
 5513                    thirdScale,
 5514                    out Vector3d linearA,
 5515                    out Vector3d angularA,
 5516                    out Vector3d linearB,
 5517                    out Vector3d angularB))
 518        {
 3519            return false;
 520        }
 521
 2522        return TryApplyVelocityDeltas(
 2523            contact,
 2524            linearA,
 2525            angularA,
 2526            linearB,
 2527            angularB);
 528    }
 529
 530    private static bool TryApplyNormalImpulse(
 531        CollisionPair pair,
 532        SolverContact contact,
 533        ContactNormalImpulseResult3D result)
 534    {
 9075535        if (result.LinearVelocityDeltaA == Vector3d.Zero
 9075536            && result.AngularVelocityDeltaA == Vector3d.Zero
 9075537            && result.LinearVelocityDeltaB == Vector3d.Zero
 9075538            && result.AngularVelocityDeltaB == Vector3d.Zero)
 539        {
 2243540            return true;
 541        }
 542
 6832543        if (!TryPrepareVelocityStates(
 6832544                contact,
 6832545                result.LinearVelocityDeltaA,
 6832546                result.AngularVelocityDeltaA,
 6832547                result.LinearVelocityDeltaB,
 6832548                result.AngularVelocityDeltaB,
 6832549                out Vector3d linearA,
 6832550                out Vector3d angularA,
 6832551                out Vector3d linearB,
 6832552                out Vector3d angularB))
 553        {
 1554            return false;
 555        }
 556
 6831557        if (result.HasRepresentableAppliedImpulse
 6831558            && result.HasRepresentableNormalVelocity
 6831559            && result.AppliedImpulseScalar != Fixed64.Zero)
 560        {
 6826561            Vector3d impulse =
 6826562                contact.Normal * result.AppliedImpulseScalar;
 6826563            pair.Context.Diagnostics.EmitResponseImpulse(
 6826564                pair,
 6826565                impulse,
 6826566                result.NormalVelocity);
 567        }
 6831568        ApplyVelocityStates(
 6831569            contact,
 6831570            linearA,
 6831571            angularA,
 6831572            linearB,
 6831573            angularB);
 6831574        return true;
 575    }
 576
 577    private static bool TrySolveFrictionImpulse(
 578        CollisionPair pair,
 579        SolverContact contact,
 580        Vector3d responsePositionA,
 581        Vector3d responsePositionB,
 582        Fixed64 normalImpulseScalar,
 583        out Fixed64 tangentImpulse,
 584        out Fixed64 secondaryTangentImpulse)
 585    {
 9074586        if (!contact.RelativeA.IsExact
 9074587            && !contact.RelativeB.IsExact
 9074588            && TryGetCompactFrictionResponse(
 9074589                contact,
 9074590                normalImpulseScalar,
 9074591                out tangentImpulse,
 9074592                out secondaryTangentImpulse,
 9074593                out Fixed64 tangentDelta,
 9074594                out Fixed64 secondaryTangentDelta)
 9074595            && ((tangentDelta == Fixed64.Zero
 9074596                    && secondaryTangentDelta == Fixed64.Zero)
 9074597                || TryApplyContactImpulseCombination(
 9074598                    pair,
 9074599                    contact,
 9074600                    responsePositionA,
 9074601                    responsePositionB,
 9074602                    contact.Normal,
 9074603                    Fixed64.Zero,
 9074604                    contact.Tangent,
 9074605                    tangentDelta,
 9074606                    contact.SecondaryTangent,
 9074607                    secondaryTangentDelta)))
 608        {
 8690609            return true;
 610        }
 611
 384612        return TrySolveFrictionImpulseExact(
 384613            pair,
 384614            contact,
 384615            responsePositionA,
 384616            responsePositionB,
 384617            normalImpulseScalar,
 384618            out tangentImpulse,
 384619            out secondaryTangentImpulse);
 620    }
 621
 622    private static bool TryGetCompactFrictionResponse(
 623        SolverContact contact,
 624        Fixed64 normalImpulseScalar,
 625        out Fixed64 tangentImpulse,
 626        out Fixed64 secondaryTangentImpulse,
 627        out Fixed64 tangentDelta,
 628        out Fixed64 secondaryTangentDelta)
 629    {
 9042630        tangentImpulse = default;
 9042631        secondaryTangentImpulse = default;
 9042632        tangentDelta = default;
 9042633        secondaryTangentDelta = default;
 9042634        bool limitsResolved = TryGetFrictionLimit(
 9042635            normalImpulseScalar,
 9042636            contact.StaticFriction,
 9042637            out Fixed64 staticFrictionLimit);
 9042638        limitsResolved &= TryGetFrictionLimit(
 9042639            normalImpulseScalar,
 9042640            contact.DynamicFriction,
 9042641            out Fixed64 dynamicFrictionLimit);
 9042642        if (!limitsResolved)
 2643            return false;
 644
 9040645        if (staticFrictionLimit == Fixed64.Zero
 9040646            && dynamicFrictionLimit == Fixed64.Zero)
 647        {
 2207648            return Fixed64.TrySubtract(
 2207649                    Fixed64.Zero,
 2207650                    contact.CachedTangentImpulse,
 2207651                    out tangentDelta)
 2207652                & Fixed64.TrySubtract(
 2207653                    Fixed64.Zero,
 2207654                    contact.CachedSecondaryTangentImpulse,
 2207655                    out secondaryTangentDelta);
 656        }
 657
 6833658        Vector3d linearA = ResolveLinearVelocity(contact.A.Body);
 6833659        Vector3d angularA = ResolveAngularVelocity(contact.A.Body);
 6833660        Vector3d linearB = ResolveLinearVelocity(contact.B.Body);
 6833661        Vector3d angularB = ResolveAngularVelocity(contact.B.Body);
 6833662        if (!ContactResponseArithmetic3D.TryGetRelativePointVelocity(
 6833663                linearA,
 6833664                angularA,
 6833665                contact.RelativeA.Vector,
 6833666                linearB,
 6833667                angularB,
 6833668                contact.RelativeB.Vector,
 6833669                contact.Tangent,
 6833670                out Vector3d relativeVelocity))
 671        {
 338672            return false;
 673        }
 674
 6495675        bool deltasResolved = TryGetCompactTangentImpulseDelta(
 6495676            contact,
 6495677            relativeVelocity,
 6495678            contact.Tangent,
 6495679            out Fixed64 desiredTangentDelta);
 6495680        deltasResolved &= TryGetCompactTangentImpulseDelta(
 6495681            contact,
 6495682            relativeVelocity,
 6495683            contact.SecondaryTangent,
 6495684            out Fixed64 desiredSecondaryTangentDelta);
 6495685        bool diskResolved = Fixed64.TryAdd(
 6495686                contact.CachedTangentImpulse,
 6495687                desiredTangentDelta,
 6495688                out tangentImpulse)
 6495689            & Fixed64.TryAdd(
 6495690                contact.CachedSecondaryTangentImpulse,
 6495691                desiredSecondaryTangentDelta,
 6495692                out secondaryTangentImpulse)
 6495693            & TryGetMagnitudeSquared(
 6495694                tangentImpulse,
 6495695                secondaryTangentImpulse,
 6495696                out Fixed64 desiredMagnitudeSquared)
 6495697            & TryGetSquare(
 6495698                staticFrictionLimit,
 6495699                out Fixed64 staticLimitSquared);
 6495700        if (!(deltasResolved & diskResolved))
 701        {
 9702            return false;
 703        }
 704
 6486705        if (desiredMagnitudeSquared > staticLimitSquared)
 706        {
 4358707            Fixed64 magnitude = FixedMath.Sqrt(desiredMagnitudeSquared);
 4358708            Fixed64 scale = dynamicFrictionLimit / magnitude;
 4358709            if (dynamicFrictionLimit != Fixed64.Zero
 4358710                && scale == Fixed64.Zero)
 711            {
 1712                return false;
 713            }
 714
 4357715            Fixed64 desiredTangentImpulse = tangentImpulse;
 4357716            Fixed64 desiredSecondaryTangentImpulse =
 4357717                secondaryTangentImpulse;
 4357718            tangentImpulse *= scale;
 4357719            secondaryTangentImpulse *= scale;
 4357720            if (dynamicFrictionLimit != Fixed64.Zero
 4357721                && ((desiredTangentImpulse != Fixed64.Zero
 4357722                        && tangentImpulse == Fixed64.Zero)
 4357723                    || (desiredSecondaryTangentImpulse != Fixed64.Zero
 4357724                        && secondaryTangentImpulse == Fixed64.Zero)))
 725            {
 1726                return false;
 727            }
 728        }
 729
 6484730        return Fixed64.TrySubtract(
 6484731                tangentImpulse,
 6484732                contact.CachedTangentImpulse,
 6484733                out tangentDelta)
 6484734            & Fixed64.TrySubtract(
 6484735                secondaryTangentImpulse,
 6484736                contact.CachedSecondaryTangentImpulse,
 6484737                out secondaryTangentDelta);
 738    }
 739
 740    [MethodImpl(MethodImplOptions.NoInlining)]
 741    private static bool TrySolveFrictionImpulseExact(
 742        CollisionPair pair,
 743        SolverContact contact,
 744        Vector3d responsePositionA,
 745        Vector3d responsePositionB,
 746        Fixed64 normalImpulseScalar,
 747        out Fixed64 tangentImpulse,
 748        out Fixed64 secondaryTangentImpulse)
 749    {
 384750        GetExactLevers(
 384751            pair,
 384752            contact,
 384753            responsePositionA,
 384754            responsePositionB,
 384755            out ExactLever3D exactA,
 384756            out ExactLever3D exactB);
 384757        Vector3d linearA = ResolveLinearVelocity(contact.A.Body);
 384758        Vector3d angularA = ResolveAngularVelocity(contact.A.Body);
 384759        Vector3d linearB = ResolveLinearVelocity(contact.B.Body);
 384760        Vector3d angularB = ResolveAngularVelocity(contact.B.Body);
 384761        ExactContactResponseOperand3D primaryFirst =
 384762            ExactContactLever3D.CreateResponseOperand(
 384763                contact.A.Body,
 384764                linearA,
 384765                angularA,
 384766                exactA,
 384767                -contact.Tangent);
 384768        ExactContactResponseOperand3D primarySecond =
 384769            ExactContactLever3D.CreateResponseOperand(
 384770                contact.B.Body,
 384771                linearB,
 384772                angularB,
 384773                exactB,
 384774                contact.Tangent);
 384775        ExactContactResponseOperand3D secondaryFirst =
 384776            ExactContactLever3D.CreateResponseOperand(
 384777                contact.A.Body,
 384778                linearA,
 384779                angularA,
 384780                exactA,
 384781                -contact.SecondaryTangent);
 384782        ExactContactResponseOperand3D secondarySecond =
 384783            ExactContactLever3D.CreateResponseOperand(
 384784                contact.B.Body,
 384785                linearB,
 384786                angularB,
 384787                exactB,
 384788                contact.SecondaryTangent);
 384789        if (!ExactContactResponseKernel.TryGetCoulombDiskResponse(
 384790                contact.Normal,
 384791                normalImpulseScalar,
 384792                primaryFirst,
 384793                primarySecond,
 384794                contact.Tangent,
 384795                contact.CachedTangentImpulse,
 384796                secondaryFirst,
 384797                secondarySecond,
 384798                contact.SecondaryTangent,
 384799                contact.CachedSecondaryTangentImpulse,
 384800                contact.StaticFriction,
 384801                contact.DynamicFriction,
 384802                out ExactCoulombResponse3D response))
 803        {
 1804            tangentImpulse = default;
 1805            secondaryTangentImpulse = default;
 1806            return false;
 807        }
 808
 383809        _ = response.TryGetPrimaryAccumulatedImpulse(out tangentImpulse);
 383810        _ = response.TryGetSecondaryAccumulatedImpulse(
 383811            out secondaryTangentImpulse);
 383812        return !response.HasAppliedImpulse
 383813            || TryApplyVelocityDeltas(
 383814                contact,
 383815                response.FirstLinearVelocityDelta,
 383816                response.FirstAngularVelocityDelta,
 383817                response.SecondLinearVelocityDelta,
 383818                response.SecondAngularVelocityDelta);
 819    }
 820
 821    private static bool TryGetCompactTangentImpulseDelta(
 822        SolverContact contact,
 823        Vector3d relativeVelocity,
 824        Vector3d tangent,
 825        out Fixed64 impulseDelta)
 826    {
 12990827        impulseDelta = Fixed64.Zero;
 12990828        if (!ContactResponseArithmetic3D.TryDot(
 12990829                relativeVelocity,
 12990830                tangent,
 12990831                out Fixed64 tangentVelocity))
 832        {
 1833            return false;
 834        }
 835
 12989836        if (tangentVelocity >= -Fixed64.Epsilon
 12989837            && tangentVelocity <= Fixed64.Epsilon)
 838        {
 6768839            return true;
 840        }
 841
 6221842        bool denominatorsResolved =
 6221843            ContactNormalImpulse3D.TryComputeAngularDenominator(
 6221844                contact.A.Body,
 6221845                contact.RelativeA.Vector,
 6221846                tangent,
 6221847                out Fixed64 angularA);
 6221848        denominatorsResolved &=
 6221849            ContactNormalImpulse3D.TryComputeAngularDenominator(
 6221850                contact.B.Body,
 6221851                contact.RelativeB.Vector,
 6221852                tangent,
 6221853                out Fixed64 angularB);
 6221854        denominatorsResolved &= TryGetCompactConstrainedInverseMass(
 6221855            contact.A,
 6221856            tangent,
 6221857            out Fixed64 linearA);
 6221858        denominatorsResolved &= TryGetCompactConstrainedInverseMass(
 6221859            contact.B,
 6221860            tangent,
 6221861            out Fixed64 linearB);
 6221862        var denominatorTerms = new ContactEffectiveMassTerms3D(
 6221863            linearA,
 6221864            linearB,
 6221865            angularA,
 6221866            angularB);
 6221867        bool denominatorResolved = denominatorsResolved
 6221868            & denominatorTerms.TryGetValue(out Fixed64 denominator);
 6221869        if (!denominatorResolved)
 870        {
 2871            return false;
 872        }
 873
 6219874        if (denominator <= Fixed64.Epsilon)
 1875            return true;
 876
 6218877        return Fixed64.TryMultiplyDivide(
 6218878                tangentVelocity,
 6218879                -Fixed64.One,
 6218880                denominator,
 6218881                out impulseDelta)
 6218882            && impulseDelta != Fixed64.Zero;
 883    }
 884
 885    private static bool TryGetCompactConstrainedInverseMass(
 886        ResponseBody body,
 887        Vector3d axis,
 888        out Fixed64 inverseMass)
 889    {
 12442890        inverseMass = body.GetConstrainedInverseMass(axis);
 12442891        return inverseMass != Fixed64.Zero
 12442892            || body.InverseMass == Fixed64.Zero
 12442893            || body.Body.ProjectLinearMotion(axis) == Vector3d.Zero;
 894    }
 895
 896    private static bool TryGetFrictionLimit(
 897        Fixed64 normalImpulse,
 898        Fixed64 friction,
 899        out Fixed64 limit)
 900    {
 18084901        if (normalImpulse <= Fixed64.Zero || friction <= Fixed64.Zero)
 902        {
 4415903            limit = Fixed64.Zero;
 4415904            return true;
 905        }
 906
 13669907        return Fixed64.TryMultiplyDivide(
 13669908                normalImpulse,
 13669909                friction,
 13669910                Fixed64.One,
 13669911                out limit)
 13669912            && limit != Fixed64.Zero;
 913    }
 914
 915    private static bool TryGetMagnitudeSquared(
 916        Fixed64 first,
 917        Fixed64 second,
 918        out Fixed64 result)
 919    {
 6495920        bool resolved = TryGetSquare(first, out Fixed64 firstSquared)
 6495921            & TryGetSquare(second, out Fixed64 secondSquared);
 6495922        if (!resolved)
 923        {
 3924            result = default;
 3925            return false;
 926        }
 927
 6492928        return Fixed64.TryAdd(
 6492929            firstSquared,
 6492930            secondSquared,
 6492931            out result);
 932    }
 933
 934    private static bool TryGetSquare(Fixed64 value, out Fixed64 square) =>
 19485935        Fixed64.TryMultiplyDivide(
 19485936            value,
 19485937            value,
 19485938            Fixed64.One,
 19485939            out square)
 19485940        && (value == Fixed64.Zero || square != Fixed64.Zero);
 941
 942    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 943    private static Vector3d ResolveLinearVelocity(SolidBody body) =>
 35294944        body.ProjectLinearMotion(
 35294945            body.IsKinematic
 35294946                ? body.SampleContinuousCollisionLinearVelocity(Fixed64.One)
 35294947                : body.LinearVelocity);
 948
 949    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 950    private static Vector3d ResolveAngularVelocity(SolidBody body) =>
 35294951        body.ProjectAngularMotion(
 35294952            body.IsKinematic
 35294953                ? body.SampleContinuousCollisionAngularVelocity(Fixed64.One)
 35294954                : body.AngularVelocity);
 955
 956    private static bool TryApplyExactImpulse(
 957        SolverContact contact,
 958        in ExactLever3D exactA,
 959        in ExactLever3D exactB,
 960        Vector3d impulseB)
 961    {
 48962        Vector3d impulseA = -impulseB;
 48963        bool linearAResolved = TryGetLinearVelocityDelta(
 48964            contact.A,
 48965            impulseA,
 48966            out Vector3d linearA);
 48967        bool angularAResolved =
 48968            ExactContactLever3D.TryGetAngularVelocityDelta(
 48969            contact.A.Body,
 48970            exactA,
 48971            impulseA,
 48972            out Vector3d angularA);
 48973        bool linearBResolved = TryGetLinearVelocityDelta(
 48974            contact.B,
 48975            impulseB,
 48976            out Vector3d linearB);
 48977        bool angularBResolved =
 48978            ExactContactLever3D.TryGetAngularVelocityDelta(
 48979            contact.B.Body,
 48980            exactB,
 48981            impulseB,
 48982            out Vector3d angularB);
 48983        if (!(linearAResolved
 48984            & angularAResolved
 48985            & linearBResolved
 48986            & angularBResolved))
 987        {
 4988            return false;
 989        }
 990
 44991        return TryApplyVelocityDeltas(
 44992            contact,
 44993            linearA,
 44994            angularA,
 44995            linearB,
 44996            angularB);
 997    }
 998
 999    private static bool TryApplyCompactImpulse(
 1000        SolverContact contact,
 1001        Vector3d impulseB)
 1002    {
 61651003        Vector3d impulseA = -impulseB;
 61651004        bool linearAResolved = TryGetLinearVelocityDelta(
 61651005            contact.A,
 61651006            impulseA,
 61651007            out Vector3d linearA);
 61651008        bool angularAResolved = TryGetAngularVelocityDelta(
 61651009            contact.A,
 61651010            contact.RelativeA.Vector,
 61651011            impulseA,
 61651012            out Vector3d angularA);
 61651013        bool linearBResolved = TryGetLinearVelocityDelta(
 61651014            contact.B,
 61651015            impulseB,
 61651016            out Vector3d linearB);
 61651017        bool angularBResolved = TryGetAngularVelocityDelta(
 61651018            contact.B,
 61651019            contact.RelativeB.Vector,
 61651020            impulseB,
 61651021            out Vector3d angularB);
 61651022        if (!(linearAResolved
 61651023            & angularAResolved
 61651024            & linearBResolved
 61651025            & angularBResolved))
 1026        {
 451027            return false;
 1028        }
 1029
 61201030        return TryApplyVelocityDeltas(
 61201031            contact,
 61201032            linearA,
 61201033            angularA,
 61201034            linearB,
 61201035            angularB);
 1036    }
 1037
 1038    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1039    private static bool CanNegate(Vector3d value) =>
 61691040        value.X != Fixed64.MinValue
 61691041        && value.Y != Fixed64.MinValue
 61691042        && value.Z != Fixed64.MinValue;
 1043
 1044    private static bool TryGetLinearVelocityDelta(
 1045        ResponseBody body,
 1046        Vector3d impulse,
 1047        out Vector3d velocityDelta)
 1048    {
 124261049        if (!body.HasSolverMobility || !body.Body.CanTranslate)
 1050        {
 301051            velocityDelta = Vector3d.Zero;
 301052            return true;
 1053        }
 1054
 123961055        return ContinuousCollisionImpulsePolicy.TryResolveVelocityDelta(
 123961056            body.Body.ProjectLinearMotion(impulse),
 123961057            Fixed64.One,
 123961058            body.InverseMass,
 123961059            Fixed64.One,
 123961060            out velocityDelta);
 1061    }
 1062
 1063    private static bool TryGetAngularVelocityDelta(
 1064        ResponseBody body,
 1065        Vector3d relativeContactPoint,
 1066        Vector3d impulse,
 1067        out Vector3d velocityDelta)
 1068    {
 123301069        velocityDelta = Vector3d.Zero;
 123301070        if (!body.HasSolverMobility || !body.CanRotate)
 411071            return true;
 1072
 122891073        Fixed3x3 inverseInertia =
 122891074            body.Body.GetConstrainedInverseInertiaTensor();
 122891075        if (ContactResponseArithmetic3D.CanUseFastAngularResponse(
 122891076                relativeContactPoint,
 122891077                impulse,
 122891078                inverseInertia))
 1079        {
 122851080            Vector3d fastTorqueAxis =
 122851081                Vector3d.Cross(relativeContactPoint, impulse);
 122851082            velocityDelta = Fixed3x3.TransformDirection(
 122851083                inverseInertia,
 122851084                fastTorqueAxis);
 122851085            return ContactResponseArithmetic3D
 122851086                    .PreservesNonzeroCrossProduct(
 122851087                        relativeContactPoint,
 122851088                        impulse,
 122851089                        fastTorqueAxis)
 122851090                && ContactResponseArithmetic3D
 122851091                    .PreservesNonzeroTransformDirection(
 122851092                        inverseInertia,
 122851093                        fastTorqueAxis,
 122851094                        velocityDelta);
 1095        }
 1096
 41097        if (!ContactResponseArithmetic3D.TryCross(
 41098                relativeContactPoint,
 41099                impulse,
 41100                out Vector3d torqueAxis))
 1101        {
 11102            return false;
 1103        }
 1104
 31105        return ContactResponseArithmetic3D.TryTransformDirection(
 31106            inverseInertia,
 31107            torqueAxis,
 31108            out velocityDelta);
 1109    }
 1110
 1111    private static bool TryPrepareVelocityStates(
 1112        SolverContact contact,
 1113        Vector3d linearA,
 1114        Vector3d angularA,
 1115        Vector3d linearB,
 1116        Vector3d angularB,
 1117        out Vector3d preparedLinearA,
 1118        out Vector3d preparedAngularA,
 1119        out Vector3d preparedLinearB,
 1120        out Vector3d preparedAngularB)
 1121    {
 133501122        bool firstPrepared =
 133501123            contact.A.Body.TryPrepareCollisionVelocityState(
 133501124                linearA,
 133501125                angularA,
 133501126                out preparedLinearA,
 133501127                out preparedAngularA);
 133501128        bool secondPrepared =
 133501129            contact.B.Body.TryPrepareCollisionVelocityState(
 133501130                linearB,
 133501131                angularB,
 133501132                out preparedLinearB,
 133501133                out preparedAngularB);
 133501134        return firstPrepared & secondPrepared;
 1135    }
 1136
 1137    private static bool TryApplyVelocityDeltas(
 1138        SolverContact contact,
 1139        Vector3d linearA,
 1140        Vector3d angularA,
 1141        Vector3d linearB,
 1142        Vector3d angularB)
 1143    {
 65181144        if (!TryPrepareVelocityStates(
 65181145                contact,
 65181146                linearA,
 65181147                angularA,
 65181148                linearB,
 65181149                angularB,
 65181150                out Vector3d preparedLinearA,
 65181151                out Vector3d preparedAngularA,
 65181152                out Vector3d preparedLinearB,
 65181153                out Vector3d preparedAngularB))
 1154        {
 11155            return false;
 1156        }
 1157
 65171158        ApplyVelocityStates(
 65171159            contact,
 65171160            preparedLinearA,
 65171161            preparedAngularA,
 65171162            preparedLinearB,
 65171163            preparedAngularB);
 65171164        return true;
 1165    }
 1166
 1167    private static void ApplyVelocityStates(
 1168        SolverContact contact,
 1169        Vector3d linearA,
 1170        Vector3d angularA,
 1171        Vector3d linearB,
 1172        Vector3d angularB)
 1173    {
 133481174        contact.A.Body.ApplyCollisionVelocityState(linearA, angularA);
 133481175        contact.B.Body.ApplyCollisionVelocityState(linearB, angularB);
 133481176    }
 1177
 1178    private static void GetExactLevers(
 1179        CollisionPair pair,
 1180        SolverContact contact,
 1181        Vector3d responsePositionA,
 1182        Vector3d responsePositionB,
 1183        out ExactLever3D exactA,
 1184        out ExactLever3D exactB)
 1185    {
 18241186        ManifoldContact manifoldContact =
 18241187            pair.Manifold[contact.ManifoldIndex];
 18241188        var centerA = new ContactAnchor(
 18241189            responsePositionA,
 18241190            contact.A.Body.Rotation,
 18241191            contact.A.Body.LocalCenterOfMassOffset);
 18241192        var centerB = new ContactAnchor(
 18241193            responsePositionB,
 18241194            contact.B.Body.Rotation,
 18241195            contact.B.Body.LocalCenterOfMassOffset);
 18241196        exactA = manifoldContact.AnchorA.GetLeverFrom(centerA);
 18241197        exactB = manifoldContact.AnchorB.GetLeverFrom(centerB);
 18241198    }
 1199
 1200    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 1201    private static bool HasFailedResponse(byte failedResponseMask, int contactIndex) =>
 272311202        (failedResponseMask & (1 << contactIndex)) != 0;
 1203
 1204    private static void RejectResponse(
 1205        CollisionPair pair,
 1206        SolverContact contact,
 1207        int contactIndex,
 1208        ref byte failedResponseMask)
 1209    {
 41210        failedResponseMask |= (byte)(1 << contactIndex);
 41211        ClearWarmStartImpulse(pair, contact);
 41212        GravitasLogger.Channel.Error(
 41213            $"Contact response is outside the representable velocity domain.");
 41214    }
 1215
 1216    private static void ClearWarmStartImpulse(
 1217        CollisionPair pair,
 1218        SolverContact contact) =>
 111219        pair.RemoveWarmStartImpulse(contact.ContactId);
 1220
 1221    private static bool IsWarmStartCompatible(Vector3d cachedNormal, Vector3d normal) =>
 80531222        Vector3d.Dot(cachedNormal, normal) >= WarmStartNormalCompatibilityThreshold;
 1223
 1224    private static Vector3d ResolveContactNormal(Vector3d normal, Vector3d fallbackDirection)
 1225    {
 90851226        Vector3d resolved = normal.MagnitudeSquared > Fixed64.Epsilon
 90851227            ? normal.Normalized
 90851228            : fallbackDirection.MagnitudeSquared > Fixed64.Epsilon
 90851229                ? fallbackDirection.Normalized
 90851230                : Vector3d.Zero;
 1231
 90851232        if (resolved == Vector3d.Zero)
 11233            return resolved;
 1234
 90841235        return fallbackDirection.MagnitudeSquared > Fixed64.Epsilon
 90841236            && Vector3d.Dot(resolved, fallbackDirection) < Fixed64.Zero
 90841237                ? -resolved
 90841238                : resolved;
 1239    }
 1240}

Methods/Properties

.cctor()
CalculateImpulse(Gravitas.CollisionHandling.CollisionPair)
CalculateImpulse(Gravitas.CollisionHandling.CollisionPair,System.Boolean,System.Boolean)
TryCreateBodyPair(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.ResponseBody&,Gravitas.CollisionHandling.ResponseBody&)
BuildContactBuffer(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.ResponseBody,Gravitas.CollisionHandling.ResponseBody,Gravitas.CollisionHandling.ContactAnchor&,Gravitas.CollisionHandling.ContactAnchor&)
TryCreateContact(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.ResponseBody,Gravitas.CollisionHandling.ResponseBody,Gravitas.CollisionHandling.ContactAnchor&,Gravitas.CollisionHandling.ContactAnchor&,System.Int32,Gravitas.CollisionHandling.SolverContact&)
TryCalculateExactNormalResult(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,Gravitas.CollisionHandling.ContactNormalImpulseResult3D&)
ApplyPositionCorrection(Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Fixed64)
TryApplyCachedImpulse(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
TryApplyContactImpulseCombination(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryApplyContactImpulse(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
TryApplyContactImpulseExact(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
TryApplyContactImpulseCombinationExact(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64)
TryApplyNormalImpulse(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,Gravitas.CollisionHandling.ContactNormalImpulseResult3D)
TrySolveFrictionImpulse(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCompactFrictionResponse(Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TrySolveFrictionImpulseExact(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
TryGetCompactTangentImpulseDelta(Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64&)
TryGetCompactConstrainedInverseMass(Gravitas.CollisionHandling.ResponseBody,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64&)
TryGetFrictionLimit(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetMagnitudeSquared(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetSquare(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
ResolveLinearVelocity(Gravitas.SolidBody)
ResolveAngularVelocity(Gravitas.SolidBody)
TryApplyExactImpulse(Gravitas.CollisionHandling.SolverContact,Gravitas.CollisionHandling.ExactLever3D&,Gravitas.CollisionHandling.ExactLever3D&,FixedMathSharp.Vector3d)
TryApplyCompactImpulse(Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d)
CanNegate(FixedMathSharp.Vector3d)
TryGetLinearVelocityDelta(Gravitas.CollisionHandling.ResponseBody,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryGetAngularVelocityDelta(Gravitas.CollisionHandling.ResponseBody,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
TryPrepareVelocityStates(Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
TryApplyVelocityDeltas(Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
ApplyVelocityStates(Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
GetExactLevers(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.ExactLever3D&,Gravitas.CollisionHandling.ExactLever3D&)
HasFailedResponse(System.Byte,System.Int32)
RejectResponse(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact,System.Int32,System.Byte&)
ClearWarmStartImpulse(Gravitas.CollisionHandling.CollisionPair,Gravitas.CollisionHandling.SolverContact)
IsWarmStartCompatible(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
ResolveContactNormal(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)