< Summary

Line coverage
100%
Covered lines: 998
Uncovered lines: 0
Coverable lines: 998
Total lines: 1644
Line coverage: 100%
Branch coverage
100%
Covered branches: 235
Total branches: 235
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: TryCompoundEmbedded2D(...)100%1010100%
File 1: TryMeshEmbedded2D(...)100%1616100%
File 1: TryGetTriangleFiniteSurfaceContact(...)100%44100%
File 2: TryCollide(...)100%1313100%
File 2: TryEmbeddedCompound2D(...)100%1010100%
File 2: TrySphereEmbedded2D(...)100%2020100%
File 2: TryCapsuleEmbedded2D(...)100%1010100%
File 2: TryCylinderEmbedded2D(...)100%1010100%
File 2: TryConeEmbedded2D(...)100%1010100%
File 2: TryTestCapsuleCircleSlab(...)100%66100%
File 2: TryTestCylinderCircleSlab(...)100%66100%
File 2: TryTestConeCircleSlab(...)100%66100%
File 2: TryTestCapsuleCapsuleSlab(...)100%1212100%
File 2: TryTestCylinderCapsuleSlab(...)100%1212100%
File 2: TryTestConeCapsuleSlab(...)100%1010100%
File 2: CheckCapsuleCircleSlabAxis(...)100%88100%
File 2: CheckCylinderCircleSlabAxis(...)100%44100%
File 2: CheckConeCircleSlabAxis(...)100%44100%
File 2: CheckCapsulePrismAxis(...)100%44100%
File 2: CheckCylinderPrismAxis(...)100%44100%
File 2: CheckConePrismAxis(...)100%44100%
File 2: KeepAxisPenetration(...)100%44100%
File 2: CheckEmbeddedCapsuleAxes(...)100%22100%
File 2: CheckEmbeddedCapsuleAxes(...)100%22100%
File 2: CheckEmbeddedCapsuleAxes(...)100%22100%
File 2: CheckCapsuleEmbeddedCapsuleEdgeAxis(...)100%11100%
File 2: CheckCylinderEmbeddedCapsuleEdgeAxis(...)100%11100%
File 2: CheckConeEmbeddedCapsuleEdgeAxis(...)100%11100%
File 2: BuildCapsuleContact(...)100%11100%
File 2: BuildCylinderContact(...)100%11100%
File 2: BuildConeContact(...)100%11100%
File 2: BuildCanonicalSupportContact(...)100%11100%
File 3: TryCuboidEmbedded2D(...)100%66100%
File 3: TryGetCuboidPrismContact(...)100%11100%
File 3: TryGetCuboidRelationContact(...)100%22100%
File 3: TryGetTriangleConvexPrismContact(...)100%11100%
File 3: TryGetSphereConvexPrismContact(...)100%11100%
File 3: TryGetCapsuleConvexPrismContact(...)100%11100%
File 3: TryGetCylinderConvexPrismContact(...)100%11100%
File 3: TryGetConeConvexPrismContact(...)100%11100%
File 3: GetConvexPrismOffsets(...)100%22100%
File 3: TryBuildFinitePrismContact(...)100%22100%
File 4: TryGetRotationalSeparationGap(...)100%88100%
File 4: TryGetSpherePolygonSlabSeparationGap(...)100%66100%
File 4: TryGetPolygonExteriorGap(...)100%66100%
File 4: TryGetPointIntervalGap(...)100%11100%
File 4: TryGetIntervalGap(...)100%44100%
File 5: TryNormalizeAxis(...)100%22100%
File 5: GetEmbeddedCenter3D(...)100%11100%
File 5: GetEmbeddedCapsuleAxes(...)100%22100%
File 5: GetRigidUpAxis(...)100%11100%
File 5: ResolveFallbackNormal(...)100%22100%
File 5: NoContact(...)100%11100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Detection/Mixed/CollisionDetectionMixed.Complex.cs

#LineLine coverage
 1//=======================================================================
 2// CollisionDetectionMixed.Complex.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.Colliders;
 11using SwiftCollections;
 12using SwiftCollections.Query;
 13using System;
 14
 15namespace Gravitas.CollisionHandling;
 16
 17public static partial class CollisionDetectionMixed
 18{
 19    private static bool TryCompoundEmbedded2D(LSCompoundCollider compound, LSCollider2D embedded, out MixedContact conta
 20    {
 621        bool found = false;
 622        MixedContact best = default;
 23
 3424        for (int i = 0; i < compound.PartCount; i++)
 25        {
 1126            LSCollider part = compound.GetPartCollider(i);
 1127            if (!part.Bounds.Intersects(embedded.MixedBounds3D)
 1128                || !TryCollide(part, embedded, out MixedContact candidate))
 29            {
 30                continue;
 31            }
 32
 633            candidate = candidate.WithFallbackMaterials(part.Material, embedded.Material);
 34
 635            if (ContactSelectionPolicy.ShouldReplaceWithShallower(candidate, found, best))
 36            {
 537                best = candidate;
 538                found = true;
 39            }
 40        }
 41
 642        if (!found)
 143            return NoContact(out contact);
 44
 545        contact = best;
 546        return true;
 47    }
 48
 49    private static bool TryMeshEmbedded2D(LSMeshCollider mesh, LSCollider2D embedded, out MixedContact contact)
 50    {
 2051        SwiftList<int> triangleBuffer = mesh.Context.CollisionScratch.MeshTriangleCandidatesA;
 2052        FixedBoundVolume embeddedBounds = new(embedded.MixedBounds3D.Min, embedded.MixedBounds3D.Max);
 2053        mesh.GetTrianglesInBounds(embeddedBounds, triangleBuffer);
 54
 2055        bool found = false;
 2056        MixedContact best = default;
 17057        for (int i = 0; i < triangleBuffer.Count; i++)
 58        {
 6559            int triangleIndex = triangleBuffer[i];
 60            MixedContact candidate;
 6561            if (embedded is LSAABBoxCollider2D or LSPolygonCollider2D)
 62            {
 2363                if (!TryGetTriangleConvexPrismContact(
 2364                        mesh,
 2365                        triangleIndex,
 2366                        embedded,
 2367                        out candidate))
 68                {
 1469                    continue;
 70                }
 71            }
 72            else
 73            {
 4274                if (!TryGetTriangleFiniteSurfaceContact(
 4275                        mesh,
 4276                        triangleIndex,
 4277                        embedded,
 4278                        out candidate))
 79                {
 80                    continue;
 81                }
 82            }
 83
 2884            if (ContactSelectionPolicy.ShouldReplaceWithShallower(candidate, found, best))
 85            {
 1086                best = candidate;
 1087                found = true;
 88            }
 89        }
 90
 2091        if (!found)
 1192            return NoContact(out contact);
 93
 994        contact = best;
 995        return true;
 96    }
 97
 98    private static bool TryGetTriangleFiniteSurfaceContact(
 99        LSMeshCollider mesh,
 100        int triangleIndex,
 101        LSCollider2D embedded,
 102        out MixedContact contact)
 103    {
 42104        mesh.Mesh.GetLocalTriangleVertices(
 42105            triangleIndex,
 42106            out Vector3d first,
 42107            out Vector3d second,
 42108            out Vector3d third);
 42109        var triangle = new FixedTriangle(first, second, third);
 42110        Vector3d slabCenter = GetEmbeddedCenter3D(embedded);
 111
 112        bool collided;
 113        FixedContactAnchors relation;
 42114        if (embedded is LSCircleCollider2D circle)
 115        {
 16116            collided = triangle.TryGetCircleSlabContact(
 16117                mesh.Mesh.Origin,
 16118                mesh.Mesh.Rotation,
 16119                slabCenter,
 16120                circle.Rotation,
 16121                circle.MixedHalfThickness,
 16122                circle.ScaledRadius,
 16123                out relation);
 124        }
 26125        else if (embedded is LSCapsuleCollider2D capsule)
 126        {
 14127            collided = triangle.TryGetCenteredCapsuleSlabContact(
 14128                mesh.Mesh.Origin,
 14129                mesh.Mesh.Rotation,
 14130                slabCenter,
 14131                capsule.Rotation,
 14132                Vector2d.Forward,
 14133                capsule.AxisLength,
 14134                capsule.ScaledRadius,
 14135                capsule.MixedHalfThickness,
 14136                out relation);
 137        }
 138        else
 139        {
 12140            return NoContact(out contact);
 141        }
 142
 30143        return TryBuildFinitePrismContact(
 30144            collided,
 30145            relation,
 30146            out contact);
 147    }
 148}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Detection/Mixed/CollisionDetectionMixed.cs

#LineLine coverage
 1//=======================================================================
 2// CollisionDetectionMixed.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.Colliders;
 11using System;
 12using System.Runtime.CompilerServices;
 13
 14namespace Gravitas.CollisionHandling;
 15
 16/// <summary>
 17/// Deterministic mixed 2D/3D narrow-phase collision checks.
 18/// </summary>
 19public static partial class CollisionDetectionMixed
 20{
 21    /// <summary>Tests a 3D collider against an embedded 2D collider.</summary>
 22    public static bool TryCollide(LSCollider collider3D, LSCollider2D collider2D, out MixedContact contact)
 23    {
 804024        SwiftThrowHelper.ThrowIfNull(collider3D, nameof(collider3D));
 804025        SwiftThrowHelper.ThrowIfNull(collider2D, nameof(collider2D));
 26
 804027        if (!collider3D.Bounds.Intersects(collider2D.MixedBounds3D))
 28        {
 315229            contact = default;
 315230            return false;
 31        }
 32
 488833        if (collider2D is LSCompoundCollider2D compound2D)
 634            return TryEmbeddedCompound2D(collider3D, compound2D, out contact);
 35
 488236        return collider3D.Shape switch
 488237        {
 146638            ColliderType.Sphere => TrySphereEmbedded2D((LSSphereCollider)collider3D, collider2D, out contact),
 200339            ColliderType.AABox or ColliderType.OBBox => TryCuboidEmbedded2D((LSCuboidCollider)collider3D, collider2D, ou
 53840            ColliderType.Capsule => TryCapsuleEmbedded2D((LSCapsuleCollider)collider3D, collider2D, out contact),
 41041            ColliderType.Cylinder => TryCylinderEmbedded2D((LSCylinderCollider)collider3D, collider2D, out contact),
 39642            ColliderType.Cone => TryConeEmbedded2D((LSConeCollider)collider3D, collider2D, out contact),
 2043            ColliderType.Mesh => TryMeshEmbedded2D((LSMeshCollider)collider3D, collider2D, out contact),
 644            ColliderType.Compound => TryCompoundEmbedded2D((LSCompoundCollider)collider3D, collider2D, out contact),
 4345            _ => NoContact(out contact)
 488246        };
 47    }
 48
 49    private static bool TryEmbeddedCompound2D(
 50        LSCollider collider3D,
 51        LSCompoundCollider2D compound2D,
 52        out MixedContact contact)
 53    {
 654        bool found = false;
 655        MixedContact best = default;
 56
 3257        for (int i = 0; i < compound2D.PartCount; i++)
 58        {
 1059            LSCollider2D part = compound2D.GetPartCollider(i);
 1060            if (!collider3D.Bounds.Intersects(part.MixedBounds3D)
 1061                || !TryCollide(collider3D, part, out MixedContact candidate))
 62            {
 63                continue;
 64            }
 65
 766            candidate = candidate.WithFallbackMaterials(collider3D.Material, part.Material);
 67
 768            if (ContactSelectionPolicy.ShouldReplaceWithShallower(candidate, found, best))
 69            {
 670                best = candidate;
 671                found = true;
 72            }
 73        }
 74
 675        if (!found)
 176            return NoContact(out contact);
 77
 578        contact = best;
 579        return true;
 80    }
 81
 82    private static bool TrySphereEmbedded2D(LSSphereCollider sphere, LSCollider2D embedded, out MixedContact contact)
 83    {
 146684        if (embedded is LSAABBoxCollider2D or LSPolygonCollider2D)
 118885            return TryGetSphereConvexPrismContact(sphere, embedded, out contact);
 86
 27887        Vector3d sphereCenter = sphere.Center;
 27888        Vector2d planarCenter = new(sphereCenter.X, sphereCenter.Z);
 27889        bool planarInside = embedded.ContainsPoint(planarCenter);
 27890        bool inside = planarInside
 27891            && MixedEmbedded2DGeometry.ContainsPointInSlab(
 27892                embedded,
 27893                sphereCenter.Y);
 27894        ContactAnchor embeddedAnchor =
 27895            MixedEmbedded2DGeometry.GetClosestAnchorOnEmbeddedVolume(
 27896                embedded,
 27897                sphereCenter);
 98        // Broad-phase overlap plus a closest-volume anchor bounds every
 99        // component of this relative offset to the Fixed64 domain.
 278100        _ = embeddedAnchor.TryGetOffsetFrom(
 278101            sphereCenter,
 278102            out Vector3d delta);
 278103        if (!Vector3d.TryGetMagnitude(delta, out Fixed64 distance)
 278104            || (!inside && distance > sphere.ScaledRadius))
 105        {
 8106            contact = default;
 8107            return false;
 108        }
 109
 270110        Vector3d normal = distance > Fixed64.Zero
 270111            ? delta / distance
 270112            : ResolveFallbackNormal(sphereCenter, embedded);
 270113        bool exactDepth = inside
 270114            ? Fixed64.TryAdd(
 270115                sphere.ScaledRadius,
 270116                distance,
 270117                out Fixed64 depth)
 270118            : Fixed64.TrySubtract(
 270119                sphere.ScaledRadius,
 270120                distance,
 270121                out depth);
 270122        if (!exactDepth)
 1123            depth = Fixed64.MaxValue;
 270124        contact = new MixedContact(
 270125            new ContactAnchor(
 270126                sphereCenter,
 270127                normal * sphere.ScaledRadius),
 270128            embeddedAnchor,
 270129            normal,
 270130            depth,
 270131            depthIsClamped: !exactDepth);
 270132        return true;
 133    }
 134
 135    private static bool TryCapsuleEmbedded2D(LSCapsuleCollider capsule, LSCollider2D embedded, out MixedContact contact)
 136    {
 538137        if (embedded is LSAABBoxCollider2D or LSPolygonCollider2D)
 301138            return TryGetCapsuleConvexPrismContact(capsule, embedded, out contact);
 139
 237140        bool collided = embedded.Shape == ColliderType2D.Circle
 237141            ? TryTestCapsuleCircleSlab(capsule, (LSCircleCollider2D)embedded, out AxisPenetration penetration)
 237142            : TryTestCapsuleCapsuleSlab(capsule, (LSCapsuleCollider2D)embedded, out penetration);
 143
 237144        return collided
 237145            ? BuildCapsuleContact(capsule, embedded, penetration, out contact)
 237146            : NoContact(out contact);
 147    }
 148
 149    private static bool TryCylinderEmbedded2D(LSCylinderCollider cylinder, LSCollider2D embedded, out MixedContact conta
 150    {
 410151        if (embedded is LSAABBoxCollider2D or LSPolygonCollider2D)
 239152            return TryGetCylinderConvexPrismContact(cylinder, embedded, out contact);
 153
 171154        bool collided = embedded.Shape == ColliderType2D.Circle
 171155            ? TryTestCylinderCircleSlab(cylinder, (LSCircleCollider2D)embedded, out AxisPenetration penetration)
 171156            : TryTestCylinderCapsuleSlab(cylinder, (LSCapsuleCollider2D)embedded, out penetration);
 157
 171158        return collided
 171159            ? BuildCylinderContact(cylinder, embedded, penetration, out contact)
 171160            : NoContact(out contact);
 161    }
 162
 163    private static bool TryConeEmbedded2D(LSConeCollider cone, LSCollider2D embedded, out MixedContact contact)
 164    {
 396165        if (embedded is LSAABBoxCollider2D or LSPolygonCollider2D)
 230166            return TryGetConeConvexPrismContact(cone, embedded, out contact);
 167
 166168        bool collided = embedded.Shape == ColliderType2D.Circle
 166169            ? TryTestConeCircleSlab(cone, (LSCircleCollider2D)embedded, out AxisPenetration penetration)
 166170            : TryTestConeCapsuleSlab(cone, (LSCapsuleCollider2D)embedded, out penetration);
 171
 166172        return collided
 166173            ? BuildConeContact(cone, embedded, penetration, out contact)
 166174            : NoContact(out contact);
 175    }
 176
 177    private static bool TryTestCapsuleCircleSlab(
 178        LSCapsuleCollider capsule,
 179        LSCircleCollider2D circle,
 180        out AxisPenetration penetration)
 181    {
 96182        penetration = default;
 96183        Vector3d capsuleAxis = GetRigidUpAxis(capsule.Rotation);
 96184        CheckCapsuleCircleSlabAxis(
 96185            capsule,
 96186            circle,
 96187            capsuleAxis,
 96188            Vector3d.Up,
 96189            ref penetration);
 190
 96191        if (!CheckCapsuleCircleSlabAxis(
 96192                capsule,
 96193                circle,
 96194                capsuleAxis,
 96195                capsuleAxis,
 96196                ref penetration))
 1197            return false;
 198
 95199        if (!CheckCapsuleCircleSlabAxis(
 95200                capsule,
 95201                circle,
 95202                capsuleAxis,
 95203                Vector3d.Cross(capsuleAxis, Vector3d.Up),
 95204                ref penetration))
 1205            return false;
 206
 94207        Vector3d closestFeatureAxis =
 94208            FixedSegment.GetClosestDirectionBetweenCenteredAxes(
 94209                capsule.Center,
 94210                capsuleAxis,
 94211                capsule.AxisLength,
 94212                GetEmbeddedCenter3D(circle),
 94213                Vector3d.Up,
 94214                circle.MixedHalfThickness * Fixed64.Two);
 94215        if (!CheckCapsuleCircleSlabAxis(
 94216                capsule,
 94217                circle,
 94218                capsuleAxis,
 94219                closestFeatureAxis,
 94220                ref penetration))
 1221            return false;
 222
 93223        return penetration.HasValue;
 224    }
 225
 226    private static bool TryTestCylinderCircleSlab(
 227        LSCylinderCollider cylinder,
 228        LSCircleCollider2D circle,
 229        out AxisPenetration penetration)
 230    {
 67231        penetration = default;
 67232        Vector3d cylinderAxis = GetRigidUpAxis(cylinder.Rotation);
 67233        if (!CheckCylinderCircleSlabAxis(
 67234                cylinder,
 67235                circle,
 67236                cylinderAxis,
 67237                cylinderAxis,
 67238                ref penetration))
 1239            return false;
 240
 66241        CheckCylinderCircleSlabAxis(
 66242            cylinder,
 66243            circle,
 66244            cylinderAxis,
 66245            Vector3d.Up,
 66246            ref penetration);
 247
 66248        if (!CheckCylinderCircleSlabAxis(
 66249                cylinder,
 66250                circle,
 66251                cylinderAxis,
 66252                Vector3d.Cross(cylinderAxis, Vector3d.Up),
 66253                ref penetration))
 1254            return false;
 255
 65256        Vector3d closestFeatureAxis =
 65257            FixedSegment.GetClosestDirectionBetweenCenteredAxes(
 65258                cylinder.Center,
 65259                cylinderAxis,
 65260                cylinder.Height,
 65261                GetEmbeddedCenter3D(circle),
 65262                Vector3d.Up,
 65263                circle.MixedHalfThickness * Fixed64.Two);
 65264        if (!CheckCylinderCircleSlabAxis(
 65265                cylinder,
 65266                circle,
 65267                cylinderAxis,
 65268                closestFeatureAxis,
 65269                ref penetration))
 1270            return false;
 271
 64272        return penetration.HasValue;
 273    }
 274
 275    private static bool TryTestConeCircleSlab(
 276        LSConeCollider cone,
 277        LSCircleCollider2D circle,
 278        out AxisPenetration penetration)
 279    {
 65280        penetration = default;
 65281        Vector3d coneAxis = GetRigidUpAxis(cone.Rotation);
 282
 65283        if (!CheckConeCircleSlabAxis(cone, circle, coneAxis, ref penetration))
 1284            return false;
 285
 64286        CheckConeCircleSlabAxis(cone, circle, Vector3d.Up, ref penetration);
 287
 64288        if (!CheckConeCircleSlabAxis(
 64289                cone,
 64290                circle,
 64291                Vector3d.Cross(coneAxis, Vector3d.Up),
 64292                ref penetration))
 1293            return false;
 294
 63295        Vector3d circleCenter = GetEmbeddedCenter3D(circle);
 296        // The admitted broad-phase bounds and separating axes guarantee that
 297        // this closest-feature offset is representable in either rigid frame.
 63298        _ = FixedSegment.TryGetClosestCenteredFiniteConeSurfaceAnchor(
 63299            circleCenter,
 63300            cone.Center,
 63301            cone.Rotation,
 63302            Vector3d.Up,
 63303            cone.Height,
 63304            cone.ScaledRadius,
 63305            Vector3d.Right,
 63306            out FixedPointAnchor conePoint,
 63307            out _,
 63308            out _);
 63309        _ = conePoint.TryGetOffsetFrom(
 63310            new FixedPointAnchor(
 63311                circleCenter,
 63312                FixedQuaternion.Identity,
 63313                Vector3d.Zero),
 63314            out Vector3d conePointFromCircle);
 315
 63316        Fixed64 closestCircleY = FixedMath.Clamp(
 63317            conePointFromCircle.Y,
 63318            -circle.MixedHalfThickness,
 63319            circle.MixedHalfThickness);
 63320        _ = Vector3d.TrySubtract(
 63321            new Vector3d(Fixed64.Zero, closestCircleY, Fixed64.Zero),
 63322            conePointFromCircle,
 63323            out Vector3d closestFeatureAxis);
 63324        if (!CheckConeCircleSlabAxis(
 63325                cone,
 63326                circle,
 63327                closestFeatureAxis,
 63328                ref penetration))
 1329            return false;
 330
 62331        return penetration.HasValue;
 332    }
 333
 334    private static bool TryTestCapsuleCapsuleSlab(
 335        LSCapsuleCollider capsule,
 336        LSCapsuleCollider2D prism,
 337        out AxisPenetration penetration)
 338    {
 141339        penetration = default;
 141340        Vector3d capsuleAxis = GetRigidUpAxis(capsule.Rotation);
 141341        GetEmbeddedCapsuleAxes(
 141342            prism,
 141343            out Vector2d prismPlanarAxis,
 141344            out Vector3d prismAxis,
 141345            out Vector3d prismNormal);
 346
 141347        if (!CheckCapsulePrismAxis(
 141348                capsule,
 141349                prism,
 141350                capsuleAxis,
 141351                prismPlanarAxis,
 141352                capsuleAxis,
 141353                ref penetration))
 1354            return false;
 355
 140356        CheckCapsulePrismAxis(
 140357            capsule,
 140358            prism,
 140359            capsuleAxis,
 140360            prismPlanarAxis,
 140361            Vector3d.Up,
 140362            ref penetration);
 363
 140364        if (!CheckCapsulePrismAxis(
 140365                capsule,
 140366                prism,
 140367                capsuleAxis,
 140368                prismPlanarAxis,
 140369                Vector3d.Cross(capsuleAxis, Vector3d.Up),
 140370                ref penetration))
 8371            return false;
 372
 132373        if (!CheckEmbeddedCapsuleAxes(
 132374                capsule,
 132375                capsuleAxis,
 132376                prism,
 132377                prismPlanarAxis,
 132378                prismAxis,
 132379                prismNormal,
 132380                ref penetration)
 132381            || !CheckCapsuleEmbeddedCapsuleEdgeAxis(
 132382                capsule,
 132383                capsuleAxis,
 132384                prism,
 132385                prismPlanarAxis,
 132386                prismAxis,
 132387                ref penetration))
 388        {
 8389            return false;
 390        }
 391
 124392        Vector3d closestFeatureAxis =
 124393            FixedSegment.GetClosestDirectionBetweenCenteredAxes(
 124394                capsule.Center,
 124395                capsuleAxis,
 124396                capsule.AxisLength,
 124397                GetEmbeddedCenter3D(prism),
 124398                prism.AxisLength <= Fixed64.Epsilon
 124399                    ? Vector3d.Up
 124400                    : prismAxis,
 124401                prism.AxisLength);
 124402        if (!CheckCapsulePrismAxis(
 124403                capsule,
 124404                prism,
 124405                capsuleAxis,
 124406                prismPlanarAxis,
 124407                closestFeatureAxis,
 124408                ref penetration))
 1409            return false;
 410
 123411        return penetration.HasValue;
 412    }
 413
 414    private static bool TryTestCylinderCapsuleSlab(
 415        LSCylinderCollider cylinder,
 416        LSCapsuleCollider2D prism,
 417        out AxisPenetration penetration)
 418    {
 104419        penetration = default;
 104420        Vector3d cylinderAxis = GetRigidUpAxis(cylinder.Rotation);
 104421        GetEmbeddedCapsuleAxes(
 104422            prism,
 104423            out Vector2d prismPlanarAxis,
 104424            out Vector3d prismAxis,
 104425            out Vector3d prismNormal);
 426
 104427        if (!CheckCylinderPrismAxis(
 104428                cylinder,
 104429                prism,
 104430                cylinderAxis,
 104431                prismPlanarAxis,
 104432                cylinderAxis,
 104433                ref penetration))
 1434            return false;
 435
 103436        CheckCylinderPrismAxis(
 103437            cylinder,
 103438            prism,
 103439            cylinderAxis,
 103440            prismPlanarAxis,
 103441            Vector3d.Up,
 103442            ref penetration);
 443
 103444        if (!CheckCylinderPrismAxis(
 103445                cylinder,
 103446                prism,
 103447                cylinderAxis,
 103448                prismPlanarAxis,
 103449                Vector3d.Cross(cylinderAxis, Vector3d.Up),
 103450                ref penetration))
 1451            return false;
 452
 102453        if (!CheckEmbeddedCapsuleAxes(
 102454                cylinder,
 102455                cylinderAxis,
 102456                prism,
 102457                prismPlanarAxis,
 102458                prismAxis,
 102459                prismNormal,
 102460                ref penetration)
 102461            || !CheckCylinderEmbeddedCapsuleEdgeAxis(
 102462                cylinder,
 102463                cylinderAxis,
 102464                prism,
 102465                prismPlanarAxis,
 102466                prismAxis,
 102467                ref penetration))
 468        {
 8469            return false;
 470        }
 471
 94472        Vector3d closestFeatureAxis =
 94473            FixedSegment.GetClosestDirectionBetweenCenteredAxes(
 94474                cylinder.Center,
 94475                cylinderAxis,
 94476                cylinder.Height,
 94477                GetEmbeddedCenter3D(prism),
 94478                prism.AxisLength <= Fixed64.Epsilon
 94479                    ? Vector3d.Up
 94480                    : prismAxis,
 94481                prism.AxisLength);
 94482        if (!CheckCylinderPrismAxis(
 94483                cylinder,
 94484                prism,
 94485                cylinderAxis,
 94486                prismPlanarAxis,
 94487                closestFeatureAxis,
 94488                ref penetration))
 1489            return false;
 490
 93491        return penetration.HasValue;
 492    }
 493
 494    private static bool TryTestConeCapsuleSlab(
 495        LSConeCollider cone,
 496        LSCapsuleCollider2D prism,
 497        out AxisPenetration penetration)
 498    {
 101499        penetration = default;
 101500        Vector3d coneAxis = GetRigidUpAxis(cone.Rotation);
 101501        GetEmbeddedCapsuleAxes(
 101502            prism,
 101503            out Vector2d prismPlanarAxis,
 101504            out Vector3d prismAxis,
 101505            out Vector3d prismNormal);
 506
 101507        if (!CheckConePrismAxis(
 101508                cone,
 101509                prism,
 101510                prismPlanarAxis,
 101511                coneAxis,
 101512                ref penetration))
 1513            return false;
 514
 100515        CheckConePrismAxis(
 100516            cone,
 100517            prism,
 100518            prismPlanarAxis,
 100519            Vector3d.Up,
 100520            ref penetration);
 521
 100522        if (!CheckConePrismAxis(
 100523                cone,
 100524                prism,
 100525                prismPlanarAxis,
 100526                Vector3d.Cross(coneAxis, Vector3d.Up),
 100527                ref penetration))
 1528            return false;
 529
 99530        if (!CheckEmbeddedCapsuleAxes(
 99531                cone,
 99532                prism,
 99533                prismPlanarAxis,
 99534                prismAxis,
 99535                prismNormal,
 99536                ref penetration)
 99537            || !CheckConeEmbeddedCapsuleEdgeAxis(
 99538                cone,
 99539                coneAxis,
 99540                prism,
 99541                prismPlanarAxis,
 99542                prismAxis,
 99543                ref penetration))
 544        {
 3545            return false;
 546        }
 547
 96548        ContactAnchor embeddedPoint =
 96549            MixedEmbedded2DGeometry.GetClosestAnchorOnEmbeddedVolume(
 96550                prism,
 96551                cone.Center);
 552        // Earlier exact axes admit a shared finite feature neighborhood, so
 553        // each relative offset remains representable through the cone frame.
 96554        _ = embeddedPoint.TryGetOffsetFrom(
 96555            cone.Center,
 96556            out Vector3d centerToEmbedded);
 96557        _ = cone.Rotation.Inverse().TryRotate(
 96558            centerToEmbedded,
 96559            out Vector3d localEmbeddedPoint);
 96560        _ = FixedSegment.TryGetClosestCenteredFiniteConeSurfaceOffset(
 96561            localEmbeddedPoint,
 96562            Vector3d.Zero,
 96563            Vector3d.Up,
 96564            cone.Height,
 96565            cone.ScaledRadius,
 96566            Vector3d.Right,
 96567            out Vector3d coneSurfaceOffset,
 96568            out _,
 96569            out _);
 96570        _ = embeddedPoint.TryGetOffsetFrom(
 96571            new ContactAnchor(
 96572                cone.Center,
 96573                cone.Rotation,
 96574                coneSurfaceOffset),
 96575            out Vector3d closestFeatureAxis);
 96576        if (!CheckConePrismAxis(
 96577                cone,
 96578                prism,
 96579                prismPlanarAxis,
 96580                closestFeatureAxis,
 96581                ref penetration))
 8582            return false;
 583
 88584        return penetration.HasValue;
 585    }
 586
 587    private static bool CheckCapsuleCircleSlabAxis(
 588        LSCapsuleCollider capsule,
 589        LSCircleCollider2D circle,
 590        Vector3d capsuleAxis,
 591        Vector3d axis,
 592        ref AxisPenetration penetration)
 593    {
 381594        if (!TryNormalizeAxis(axis, out Vector3d normalizedAxis))
 45595            return true;
 596
 336597        if (!FixedSegment.TryGetCenteredFiniteCylinderCapsuleAxisPenetration(
 336598            normalizedAxis,
 336599            GetEmbeddedCenter3D(circle),
 336600            Vector3d.Up,
 336601            circle.MixedHalfThickness * Fixed64.Two,
 336602            circle.ScaledRadius,
 336603            capsule.Center,
 336604            capsuleAxis,
 336605            capsule.AxisLength,
 336606            capsule.ScaledRadius,
 336607            out Vector3d circleToCapsuleAxis,
 336608            out Fixed64 depth,
 336609            out bool depthIsClamped))
 610        {
 3611            return false;
 612        }
 613
 333614        if (!penetration.HasValue || depth < penetration.Depth)
 615        {
 225616            penetration = new AxisPenetration(
 225617                -circleToCapsuleAxis,
 225618                depth,
 225619                depthIsClamped);
 620        }
 621
 333622        return true;
 623    }
 624
 625    private static bool CheckCylinderCircleSlabAxis(
 626        LSCylinderCollider cylinder,
 627        LSCircleCollider2D circle,
 628        Vector3d cylinderAxis,
 629        Vector3d axis,
 630        ref AxisPenetration penetration)
 631    {
 264632        if (!TryNormalizeAxis(axis, out Vector3d normalizedAxis))
 28633            return true;
 634
 236635        if (!FixedSegment.TryGetCenteredFiniteCylinderCapsuleSlabAxisPenetration(
 236636                normalizedAxis,
 236637                cylinder.Center,
 236638                cylinderAxis,
 236639                cylinder.Height,
 236640                cylinder.ScaledRadius,
 236641                GetEmbeddedCenter3D(circle),
 236642                Vector2d.Forward,
 236643                Fixed64.Zero,
 236644                circle.ScaledRadius,
 236645                circle.MixedHalfThickness,
 236646                out Vector3d orientedAxis,
 236647                out Fixed64 depth,
 236648                out bool depthIsClamped))
 649        {
 3650            return false;
 651        }
 652
 233653        return KeepAxisPenetration(
 233654            orientedAxis,
 233655            depth,
 233656            depthIsClamped,
 233657            ref penetration);
 658    }
 659
 660    private static bool CheckConeCircleSlabAxis(
 661        LSConeCollider cone,
 662        LSCircleCollider2D circle,
 663        Vector3d axis,
 664        ref AxisPenetration penetration)
 665    {
 256666        if (!TryNormalizeAxis(axis, out Vector3d normalizedAxis))
 22667            return true;
 668
 234669        if (!FixedSegment.TryGetCenteredFiniteConeCapsuleSlabAxisPenetration(
 234670                normalizedAxis,
 234671                cone.Center,
 234672                GetRigidUpAxis(cone.Rotation),
 234673                cone.Height,
 234674                cone.ScaledRadius,
 234675                GetEmbeddedCenter3D(circle),
 234676                Vector2d.Forward,
 234677                Fixed64.Zero,
 234678                circle.ScaledRadius,
 234679                circle.MixedHalfThickness,
 234680                out Vector3d orientedAxis,
 234681                out Fixed64 depth,
 234682                out bool depthIsClamped))
 683        {
 3684            return false;
 685        }
 686
 231687        return KeepAxisPenetration(
 231688            orientedAxis,
 231689            depth,
 231690            depthIsClamped,
 231691            ref penetration);
 692    }
 693
 694    private static bool CheckCapsulePrismAxis(
 695        LSCapsuleCollider capsule,
 696        LSCapsuleCollider2D prism,
 697        Vector3d capsuleAxis,
 698        Vector2d prismAxis,
 699        Vector3d axis,
 700        ref AxisPenetration penetration)
 701    {
 932702        if (!TryNormalizeAxis(axis, out Vector3d normalizedAxis))
 51703            return true;
 704
 881705        if (!FixedSegment.TryGetCenteredCapsuleCapsuleSlabAxisPenetration(
 881706                normalizedAxis,
 881707                capsule.Center,
 881708                capsuleAxis,
 881709                capsule.AxisLength,
 881710                capsule.ScaledRadius,
 881711                GetEmbeddedCenter3D(prism),
 881712                prismAxis,
 881713                prism.AxisLength,
 881714                prism.ScaledRadius,
 881715                prism.MixedHalfThickness,
 881716                out Vector3d orientedAxis,
 881717                out Fixed64 depth,
 881718                out bool depthIsClamped))
 18719            return false;
 720
 863721        return KeepAxisPenetration(
 863722            orientedAxis,
 863723            depth,
 863724            depthIsClamped,
 863725            ref penetration);
 726    }
 727
 728    private static bool CheckCylinderPrismAxis(
 729        LSCylinderCollider cylinder,
 730        LSCapsuleCollider2D prism,
 731        Vector3d cylinderAxis,
 732        Vector2d prismAxis,
 733        Vector3d axis,
 734        ref AxisPenetration penetration)
 735    {
 701736        if (!TryNormalizeAxis(axis, out Vector3d normalizedAxis))
 43737            return true;
 738
 658739        if (!FixedSegment.TryGetCenteredFiniteCylinderCapsuleSlabAxisPenetration(
 658740                normalizedAxis,
 658741                cylinder.Center,
 658742                cylinderAxis,
 658743                cylinder.Height,
 658744                cylinder.ScaledRadius,
 658745                GetEmbeddedCenter3D(prism),
 658746                prismAxis,
 658747                prism.AxisLength,
 658748                prism.ScaledRadius,
 658749                prism.MixedHalfThickness,
 658750                out Vector3d orientedAxis,
 658751                out Fixed64 depth,
 658752                out bool depthIsClamped))
 11753            return false;
 754
 647755        return KeepAxisPenetration(
 647756            orientedAxis,
 647757            depth,
 647758            depthIsClamped,
 647759            ref penetration);
 760    }
 761
 762    private static bool CheckConePrismAxis(
 763        LSConeCollider cone,
 764        LSCapsuleCollider2D prism,
 765        Vector2d prismAxis,
 766        Vector3d axis,
 767        ref AxisPenetration penetration)
 768    {
 690769        if (!TryNormalizeAxis(axis, out Vector3d normalizedAxis))
 46770            return true;
 771
 644772        if (!FixedSegment.TryGetCenteredFiniteConeCapsuleSlabAxisPenetration(
 644773                normalizedAxis,
 644774                cone.Center,
 644775                GetRigidUpAxis(cone.Rotation),
 644776                cone.Height,
 644777                cone.ScaledRadius,
 644778                GetEmbeddedCenter3D(prism),
 644779                prismAxis,
 644780                prism.AxisLength,
 644781                prism.ScaledRadius,
 644782                prism.MixedHalfThickness,
 644783                out Vector3d orientedAxis,
 644784                out Fixed64 depth,
 644785                out bool depthIsClamped))
 13786            return false;
 787
 631788        return KeepAxisPenetration(
 631789            orientedAxis,
 631790            depth,
 631791            depthIsClamped,
 631792            ref penetration);
 793    }
 794
 795    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 796    private static bool KeepAxisPenetration(
 797        Vector3d axis,
 798        Fixed64 depth,
 799        bool depthIsClamped,
 800        ref AxisPenetration penetration)
 801    {
 2605802        if (!penetration.HasValue || depth < penetration.Depth)
 803        {
 1184804            penetration = new AxisPenetration(
 1184805                axis,
 1184806                depth,
 1184807                depthIsClamped);
 808        }
 809
 2605810        return true;
 811    }
 812
 813    private static bool CheckEmbeddedCapsuleAxes(
 814        LSCapsuleCollider capsule3D,
 815        Vector3d capsule3DAxis,
 816        LSCapsuleCollider2D capsule2D,
 817        Vector2d capsule2DPlanarAxis,
 818        Vector3d capsule2DAxis,
 819        Vector3d capsule2DNormal,
 820        ref AxisPenetration penetration)
 821    {
 132822        return CheckCapsulePrismAxis(
 132823                capsule3D,
 132824                capsule2D,
 132825                capsule3DAxis,
 132826                capsule2DPlanarAxis,
 132827                capsule2DAxis,
 132828                ref penetration)
 132829            && CheckCapsulePrismAxis(
 132830                capsule3D,
 132831                capsule2D,
 132832                capsule3DAxis,
 132833                capsule2DPlanarAxis,
 132834                capsule2DNormal,
 132835                ref penetration);
 836    }
 837
 838    private static bool CheckEmbeddedCapsuleAxes(
 839        LSCylinderCollider cylinder,
 840        Vector3d cylinderAxis,
 841        LSCapsuleCollider2D capsule,
 842        Vector2d capsulePlanarAxis,
 843        Vector3d capsuleAxis,
 844        Vector3d capsuleNormal,
 845        ref AxisPenetration penetration)
 846    {
 102847        return CheckCylinderPrismAxis(
 102848                cylinder,
 102849                capsule,
 102850                cylinderAxis,
 102851                capsulePlanarAxis,
 102852                capsuleAxis,
 102853                ref penetration)
 102854            && CheckCylinderPrismAxis(
 102855                cylinder,
 102856                capsule,
 102857                cylinderAxis,
 102858                capsulePlanarAxis,
 102859                capsuleNormal,
 102860                ref penetration);
 861    }
 862
 863    private static bool CheckEmbeddedCapsuleAxes(
 864        LSConeCollider cone,
 865        LSCapsuleCollider2D capsule,
 866        Vector2d capsulePlanarAxis,
 867        Vector3d capsuleAxis,
 868        Vector3d capsuleNormal,
 869        ref AxisPenetration penetration)
 870    {
 99871        return CheckConePrismAxis(
 99872                cone,
 99873                capsule,
 99874                capsulePlanarAxis,
 99875                capsuleAxis,
 99876                ref penetration)
 99877            && CheckConePrismAxis(
 99878                cone,
 99879                capsule,
 99880                capsulePlanarAxis,
 99881                capsuleNormal,
 99882                ref penetration);
 883    }
 884
 885    private static bool CheckCapsuleEmbeddedCapsuleEdgeAxis(
 886        LSCapsuleCollider capsule3D,
 887        Vector3d capsule3DAxis,
 888        LSCapsuleCollider2D capsule2D,
 889        Vector2d capsule2DPlanarAxis,
 890        Vector3d capsule2DAxis,
 891        ref AxisPenetration penetration)
 892    {
 124893        return CheckCapsulePrismAxis(
 124894            capsule3D,
 124895            capsule2D,
 124896            capsule3DAxis,
 124897            capsule2DPlanarAxis,
 124898            Vector3d.Cross(capsule3DAxis, capsule2DAxis),
 124899            ref penetration);
 900    }
 901
 902    private static bool CheckCylinderEmbeddedCapsuleEdgeAxis(
 903        LSCylinderCollider cylinder,
 904        Vector3d cylinderAxis,
 905        LSCapsuleCollider2D capsule,
 906        Vector2d capsulePlanarAxis,
 907        Vector3d capsuleAxis,
 908        ref AxisPenetration penetration)
 909    {
 94910        return CheckCylinderPrismAxis(
 94911            cylinder,
 94912            capsule,
 94913            cylinderAxis,
 94914            capsulePlanarAxis,
 94915            Vector3d.Cross(cylinderAxis, capsuleAxis),
 94916            ref penetration);
 917    }
 918
 919    private static bool CheckConeEmbeddedCapsuleEdgeAxis(
 920        LSConeCollider cone,
 921        Vector3d coneAxis,
 922        LSCapsuleCollider2D capsule,
 923        Vector2d capsulePlanarAxis,
 924        Vector3d capsuleAxis,
 925        ref AxisPenetration penetration)
 926    {
 96927        return CheckConePrismAxis(
 96928            cone,
 96929            capsule,
 96930            capsulePlanarAxis,
 96931            Vector3d.Cross(coneAxis, capsuleAxis),
 96932            ref penetration);
 933    }
 934
 935    private static bool BuildCapsuleContact(
 936        LSCapsuleCollider capsule,
 937        LSCollider2D embedded,
 938        AxisPenetration penetration,
 939        out MixedContact contact)
 940    {
 216941        contact = BuildCanonicalSupportContact(
 216942            capsule,
 216943            embedded,
 216944            penetration.Axis,
 216945            penetration.Depth,
 216946            penetration.DepthIsClamped);
 216947        return true;
 948    }
 949
 950    private static bool BuildCylinderContact(
 951        LSCylinderCollider cylinder,
 952        LSCollider2D embedded,
 953        AxisPenetration penetration,
 954        out MixedContact contact)
 955    {
 157956        contact = BuildCanonicalSupportContact(
 157957            cylinder,
 157958            embedded,
 157959            penetration.Axis,
 157960            penetration.Depth,
 157961            penetration.DepthIsClamped);
 157962        return true;
 963    }
 964
 965    private static bool BuildConeContact(
 966        LSConeCollider cone,
 967        LSCollider2D embedded,
 968        AxisPenetration penetration,
 969        out MixedContact contact)
 970    {
 150971        contact = BuildCanonicalSupportContact(
 150972            cone,
 150973            embedded,
 150974            penetration.Axis,
 150975            penetration.Depth,
 150976            penetration.DepthIsClamped);
 150977        return true;
 978    }
 979
 980    private static MixedContact BuildCanonicalSupportContact(
 981        LSCollider collider3D,
 982        LSCollider2D embedded,
 983        Vector3d normal3DTo2D,
 984        Fixed64 depth,
 985        bool depthIsClamped)
 986    {
 523987        return new MixedContact(
 523988            new ContactAnchor(
 523989                ConvexColliderSupport.GetSupportAnchor(
 523990                    collider3D,
 523991                    normal3DTo2D,
 523992                    Vector3d.Zero)),
 523993            MixedEmbedded2DGeometry.GetSupportAnchor(embedded, -normal3DTo2D),
 523994            normal3DTo2D,
 523995            depth,
 523996            depthIsClamped);
 997    }
 998
 999}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Detection/Mixed/CollisionDetectionMixed.FinitePrisms.cs

#LineLine coverage
 1//=======================================================================
 2// CollisionDetectionMixed.FinitePrisms.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.Colliders;
 11using System;
 12
 13namespace Gravitas.CollisionHandling;
 14
 15public static partial class CollisionDetectionMixed
 16{
 17    private static bool TryCuboidEmbedded2D(
 18        LSCuboidCollider cuboid,
 19        LSCollider2D embedded,
 20        out MixedContact contact)
 21    {
 200322        if (embedded is LSCircleCollider2D circle)
 23        {
 137224            return TryGetCuboidRelationContact(
 137225                cuboid.OrientedBox.TryGetCircleSlabContact(
 137226                    GetEmbeddedCenter3D(circle),
 137227                    circle.Rotation,
 137228                    circle.MixedHalfThickness,
 137229                    circle.ScaledRadius,
 137230                    out FixedContactAnchors anchors),
 137231                anchors,
 137232                out contact);
 33        }
 34
 63135        if (embedded is LSCapsuleCollider2D capsule)
 36        {
 11937            return TryGetCuboidRelationContact(
 11938                cuboid.OrientedBox.TryGetCenteredCapsuleSlabContact(
 11939                    GetEmbeddedCenter3D(capsule),
 11940                    capsule.Rotation,
 11941                    Vector2d.Forward,
 11942                    capsule.AxisLength,
 11943                    capsule.ScaledRadius,
 11944                    capsule.MixedHalfThickness,
 11945                    out FixedContactAnchors anchors),
 11946                anchors,
 11947                out contact);
 48        }
 49
 51250        if (embedded is LSPolygonCollider2D polygon)
 51        {
 37652            return TryGetCuboidPrismContact(
 37653                cuboid,
 37654                embedded,
 37655                polygon.ScaledLocalVertices,
 37656                out contact);
 57        }
 58
 13659        Vector2d halfExtents =
 13660            ((LSAABBoxCollider2D)embedded).ScaledHalfExtents;
 13661        Span<Vector2d> centerRelativeVertices = stackalloc Vector2d[4];
 13662        centerRelativeVertices[0] = new Vector2d(-halfExtents.X, -halfExtents.Y);
 13663        centerRelativeVertices[1] = new Vector2d(halfExtents.X, -halfExtents.Y);
 13664        centerRelativeVertices[2] = new Vector2d(halfExtents.X, halfExtents.Y);
 13665        centerRelativeVertices[3] = new Vector2d(-halfExtents.X, halfExtents.Y);
 13666        return TryGetCuboidPrismContact(
 13667            cuboid,
 13668            embedded,
 13669            centerRelativeVertices,
 13670            out contact);
 71    }
 72
 73    private static bool TryGetCuboidPrismContact(
 74        LSCuboidCollider cuboid,
 75        LSCollider2D embedded,
 76        ReadOnlySpan<Vector2d> centerRelativeVertices,
 77        out MixedContact contact)
 78    {
 51279        Vector3d embeddedCenter = GetEmbeddedCenter3D(embedded);
 51280        return TryGetCuboidRelationContact(
 51281            cuboid.OrientedBox.TryGetConvexPrismContact(
 51282                embeddedCenter,
 51283                embedded.ConvexRotation,
 51284                centerRelativeVertices,
 51285                embedded.MixedHalfThickness,
 51286                out FixedContactAnchors anchors),
 51287            anchors,
 51288            out contact);
 89    }
 90
 91    private static bool TryGetCuboidRelationContact(
 92        bool collided,
 93        in FixedContactAnchors anchors,
 94        out MixedContact contact)
 95    {
 200396        if (!collided)
 75497            return NoContact(out contact);
 98
 124999        contact = new MixedContact(
 1249100            new ContactAnchor(anchors.FirstAnchor),
 1249101            new ContactAnchor(anchors.SecondAnchor),
 1249102            anchors.Normal,
 1249103            anchors.Depth,
 1249104            anchors.DepthIsClamped);
 1249105        return true;
 106    }
 107
 108    private static bool TryGetTriangleConvexPrismContact(
 109        LSMeshCollider mesh,
 110        int triangleIndex,
 111        LSCollider2D embedded,
 112        out MixedContact contact)
 113    {
 23114        mesh.Mesh.GetLocalTriangleVertices(
 23115            triangleIndex,
 23116            out Vector3d first,
 23117            out Vector3d second,
 23118            out Vector3d third);
 23119        Span<Vector2d> boxOffsets = stackalloc Vector2d[4];
 23120        ReadOnlySpan<Vector2d> prismOffsets = GetConvexPrismOffsets(
 23121            embedded,
 23122            boxOffsets);
 23123        bool collided = FixedConvexPrismRelations.TryGetTriangleContact(
 23124            mesh.Mesh.Origin,
 23125            mesh.Mesh.Rotation,
 23126            new FixedTriangle(first, second, third),
 23127            GetEmbeddedCenter3D(embedded),
 23128            embedded.ConvexRotation,
 23129            prismOffsets,
 23130            embedded.MixedHalfThickness,
 23131            out FixedContactAnchors relation);
 23132        return TryBuildFinitePrismContact(
 23133            collided,
 23134            relation,
 23135            out contact);
 136    }
 137
 138    private static bool TryGetSphereConvexPrismContact(
 139        LSSphereCollider sphere,
 140        LSCollider2D embedded,
 141        out MixedContact contact)
 142    {
 1188143        Span<Vector2d> boxOffsets = stackalloc Vector2d[4];
 1188144        ReadOnlySpan<Vector2d> offsets = GetConvexPrismOffsets(
 1188145            embedded,
 1188146            boxOffsets);
 1188147        bool collided = FixedConvexPrismRelations.TryGetSphereContact(
 1188148            sphere.Center,
 1188149            sphere.ScaledRadius,
 1188150            GetEmbeddedCenter3D(embedded),
 1188151            embedded.ConvexRotation,
 1188152            offsets,
 1188153            embedded.MixedHalfThickness,
 1188154            out FixedContactAnchors relation);
 1188155        return TryBuildFinitePrismContact(
 1188156            collided,
 1188157            relation,
 1188158            out contact);
 159    }
 160
 161    private static bool TryGetCapsuleConvexPrismContact(
 162        LSCapsuleCollider capsule,
 163        LSCollider2D embedded,
 164        out MixedContact contact)
 165    {
 301166        Span<Vector2d> boxOffsets = stackalloc Vector2d[4];
 301167        ReadOnlySpan<Vector2d> offsets = GetConvexPrismOffsets(
 301168            embedded,
 301169            boxOffsets);
 301170        bool collided =
 301171            FixedConvexPrismRelations.TryGetCenteredCapsuleContact(
 301172                capsule.Center,
 301173                capsule.Rotation,
 301174                Vector3d.Up,
 301175                capsule.AxisLength,
 301176                capsule.ScaledRadius,
 301177                GetEmbeddedCenter3D(embedded),
 301178                embedded.ConvexRotation,
 301179                offsets,
 301180                embedded.MixedHalfThickness,
 301181                out FixedContactAnchors relation);
 301182        return TryBuildFinitePrismContact(
 301183            collided,
 301184            relation,
 301185            out contact);
 186    }
 187
 188    private static bool TryGetCylinderConvexPrismContact(
 189        LSCylinderCollider cylinder,
 190        LSCollider2D embedded,
 191        out MixedContact contact)
 192    {
 239193        Span<Vector2d> boxOffsets = stackalloc Vector2d[4];
 239194        ReadOnlySpan<Vector2d> offsets = GetConvexPrismOffsets(
 239195            embedded,
 239196            boxOffsets);
 239197        bool collided =
 239198            FixedConvexPrismRelations.TryGetCenteredCylinderContact(
 239199                cylinder.Center,
 239200                cylinder.Rotation,
 239201                Vector3d.Up,
 239202                cylinder.Height,
 239203                cylinder.ScaledRadius,
 239204                GetEmbeddedCenter3D(embedded),
 239205                embedded.ConvexRotation,
 239206                offsets,
 239207                embedded.MixedHalfThickness,
 239208                out FixedContactAnchors relation);
 239209        return TryBuildFinitePrismContact(
 239210            collided,
 239211            relation,
 239212            out contact);
 213    }
 214
 215    private static bool TryGetConeConvexPrismContact(
 216        LSConeCollider cone,
 217        LSCollider2D embedded,
 218        out MixedContact contact)
 219    {
 230220        Span<Vector2d> boxOffsets = stackalloc Vector2d[4];
 230221        ReadOnlySpan<Vector2d> offsets = GetConvexPrismOffsets(
 230222            embedded,
 230223            boxOffsets);
 230224        bool collided =
 230225            FixedConvexPrismRelations.TryGetCenteredConeContact(
 230226                cone.Center,
 230227                cone.Rotation,
 230228                Vector3d.Up,
 230229                cone.Height,
 230230                cone.ScaledRadius,
 230231                GetEmbeddedCenter3D(embedded),
 230232                embedded.ConvexRotation,
 230233                offsets,
 230234                embedded.MixedHalfThickness,
 230235                out FixedContactAnchors relation);
 230236        return TryBuildFinitePrismContact(
 230237            collided,
 230238            relation,
 230239            out contact);
 240    }
 241
 242    private static ReadOnlySpan<Vector2d> GetConvexPrismOffsets(
 243        LSCollider2D embedded,
 244        Span<Vector2d> boxOffsets)
 245    {
 1981246        if (embedded is LSPolygonCollider2D polygon)
 1580247            return polygon.ScaledLocalVertices;
 248
 401249        Vector2d halfExtents =
 401250            ((LSAABBoxCollider2D)embedded).ScaledHalfExtents;
 401251        boxOffsets[0] = new Vector2d(-halfExtents.X, -halfExtents.Y);
 401252        boxOffsets[1] = new Vector2d(halfExtents.X, -halfExtents.Y);
 401253        boxOffsets[2] = new Vector2d(halfExtents.X, halfExtents.Y);
 401254        boxOffsets[3] = new Vector2d(-halfExtents.X, halfExtents.Y);
 401255        return boxOffsets;
 256    }
 257
 258    private static bool TryBuildFinitePrismContact(
 259        bool collided,
 260        in FixedContactAnchors relation,
 261        out MixedContact contact)
 262    {
 2011263        if (!collided)
 619264            return NoContact(out contact);
 265
 1392266        contact = new MixedContact(
 1392267            new ContactAnchor(relation.FirstAnchor),
 1392268            new ContactAnchor(relation.SecondAnchor),
 1392269            relation.Normal,
 1392270            relation.Depth,
 1392271            relation.DepthIsClamped);
 1392272        return true;
 273    }
 274}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Detection/Mixed/CollisionDetectionMixed.Separation.cs

#LineLine coverage
 1//=======================================================================
 2// CollisionDetectionMixed.Separation.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.Colliders;
 11using System;
 12
 13namespace Gravitas.CollisionHandling;
 14
 15public static partial class CollisionDetectionMixed
 16{
 17    internal static bool TryGetRotationalSeparationGap(
 18        LSCollider collider3D,
 19        LSCollider2D collider2D,
 20        out Fixed64 separationGap,
 21        out bool supported)
 22    {
 467023        separationGap = Fixed64.Zero;
 467024        supported = false;
 25
 467026        if (collider3D is LSSphereCollider sphere
 467027            && collider2D is LSPolygonCollider2D polygon)
 28        {
 178929            supported = true;
 178930            return TryGetSpherePolygonSlabSeparationGap(
 178931                sphere,
 178932                polygon,
 178933                out separationGap);
 34        }
 35
 288136        if (collider3D is LSCuboidCollider cuboid
 288137            && collider2D is LSCircleCollider2D circle)
 38        {
 199739            supported = true;
 199740            separationGap = cuboid.OrientedBox.GetCircleSlabSeparationLowerBound(
 199741                new Vector3d(
 199742                    circle.Center.X,
 199743                    circle.MixedSlabCenterY,
 199744                    circle.Center.Y),
 199745                circle.MixedHalfThickness,
 199746                circle.ScaledRadius);
 199747            return true;
 48        }
 49
 88450        return false;
 51    }
 52
 53    private static bool TryGetSpherePolygonSlabSeparationGap(
 54        LSSphereCollider sphere,
 55        LSPolygonCollider2D polygon,
 56        out Fixed64 separationGap)
 57    {
 178958        Vector3d center3D = sphere.Center;
 178959        Vector2d center2D = new(center3D.X, center3D.Z);
 178960        if (!TryGetPolygonExteriorGap(polygon, center2D, out Fixed64 planarGap)
 178961            || !TryGetPointIntervalGap(
 178962                center3D.Y,
 178963                polygon.MixedBounds3D.Min.Y,
 178964                polygon.MixedBounds3D.Max.Y,
 178965                out Fixed64 verticalGap))
 66        {
 567            separationGap = default;
 568            return false;
 69        }
 70
 71        // Both gaps are non-negative representable distances, so subtracting a
 72        // positive representable radius cannot leave Fixed64's signed domain.
 178473        separationGap = FixedMath.Max(planarGap, verticalGap) - sphere.ScaledRadius;
 178474        if (separationGap < Fixed64.Zero)
 71275            separationGap = Fixed64.Zero;
 178476        return true;
 77    }
 78
 79    private static bool TryGetPolygonExteriorGap(
 80        LSPolygonCollider2D polygon,
 81        Vector2d point,
 82        out Fixed64 exteriorGap)
 83    {
 178984        ReadOnlySpan<Vector2d> offsets = polygon.ScaledLocalVertices;
 178985        if (FixedConvex2dRelations.ContainsPoint(
 178986                point,
 178987                polygon.Center,
 178988                polygon.Rotation,
 178989                offsets))
 90        {
 691            exteriorGap = Fixed64.Zero;
 692            return true;
 93        }
 94
 178395        FixedPointAnchor2d closestPoint =
 178396            FixedConvex2dRelations.GetClosestPointAnchor(
 178397                point,
 178398                polygon.Center,
 178399                polygon.Rotation,
 1783100                offsets);
 1783101        if (!new ContactAnchor2D(closestPoint)
 1783102                .TryGetOffsetFrom(point, out Vector2d difference)
 1783103            || !Vector2d.TryGetMagnitude(difference, out exteriorGap))
 104        {
 3105            exteriorGap = default;
 3106            return false;
 107        }
 108
 1780109        return true;
 110    }
 111
 112    private static bool TryGetPointIntervalGap(
 113        Fixed64 point,
 114        Fixed64 min,
 115        Fixed64 max,
 116        out Fixed64 gap) =>
 1786117        TryGetIntervalGap(point, point, min, max, out gap);
 118
 119    private static bool TryGetIntervalGap(
 120        Fixed64 firstMin,
 121        Fixed64 firstMax,
 122        Fixed64 secondMin,
 123        Fixed64 secondMax,
 124        out Fixed64 gap)
 125    {
 1786126        if (firstMax < secondMin)
 26127            return Fixed64.TrySubtract(secondMin, firstMax, out gap);
 1760128        if (secondMax < firstMin)
 2129            return Fixed64.TrySubtract(firstMin, secondMax, out gap);
 130
 1758131        gap = Fixed64.Zero;
 1758132        return true;
 133    }
 134}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Detection/Mixed/CollisionDetectionMixed.Support.cs

#LineLine coverage
 1//=======================================================================
 2// CollisionDetectionMixed.Support.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.Colliders;
 11using System.Runtime.CompilerServices;
 12
 13namespace Gravitas.CollisionHandling;
 14
 15public static partial class CollisionDetectionMixed
 16{
 17    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 18    private static bool TryNormalizeAxis(
 19        Vector3d axis,
 20        out Vector3d normalizedAxis)
 21    {
 322422        Fixed64 magnitudeSqr = axis.MagnitudeSquared;
 322423        if (magnitudeSqr <= Fixed64.Epsilon)
 24        {
 23525            normalizedAxis = Vector3d.Zero;
 23526            return false;
 27        }
 28
 298929        normalizedAxis = axis.Normalized;
 298930        return true;
 31    }
 32
 33    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 34    private static Vector3d GetEmbeddedCenter3D(LSCollider2D embedded) =>
 745535        MixedEmbedded2DGeometry.GetCenter3D(embedded);
 36
 37    private static void GetEmbeddedCapsuleAxes(
 38        LSCapsuleCollider2D capsule,
 39        out Vector2d planarAxis,
 40        out Vector3d axis,
 41        out Vector3d normal)
 42    {
 34643        if (capsule.AxisLength <= Fixed64.Epsilon)
 44        {
 345            planarAxis = Vector2d.Forward;
 346            axis = Vector3d.Zero;
 347            normal = Vector3d.Zero;
 348            return;
 49        }
 50
 34351        planarAxis = new Vector2d(
 34352            -FixedMath.Sin(capsule.Rotation),
 34353            FixedMath.Cos(capsule.Rotation));
 34354        axis = new Vector3d(
 34355            planarAxis.X,
 34356            Fixed64.Zero,
 34357            planarAxis.Y);
 34358        Vector2d planarNormal = planarAxis.RightHandNormal;
 34359        normal = new Vector3d(
 34360            planarNormal.X,
 34361            Fixed64.Zero,
 34362            planarNormal.Y);
 34363    }
 64
 65    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 66    private static Vector3d GetRigidUpAxis(FixedQuaternion rotation) =>
 145267        (rotation * Vector3d.Up).Normalized;
 68
 69    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 70    private static Vector3d ResolveFallbackNormal(
 71        Vector3d sphereCenter,
 72        LSCollider2D embedded)
 73    {
 474        Vector3d fallback = new(
 475            embedded.Center.X - sphereCenter.X,
 476            embedded.MixedSlabCenterY - sphereCenter.Y,
 477            embedded.Center.Y - sphereCenter.Z);
 478        return fallback.MagnitudeSquared > Fixed64.Epsilon
 479            ? fallback.Normalized
 480            : Vector3d.Right;
 81    }
 82
 83    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 84    private static bool NoContact(out MixedContact contact)
 85    {
 149286        contact = default;
 149287        return false;
 88    }
 89}

Methods/Properties

TryCompoundEmbedded2D(Gravitas.Colliders.LSCompoundCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryMeshEmbedded2D(Gravitas.Colliders.LSMeshCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryGetTriangleFiniteSurfaceContact(Gravitas.Colliders.LSMeshCollider,System.Int32,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryCollide(Gravitas.Colliders.LSCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryEmbeddedCompound2D(Gravitas.Colliders.LSCollider,Gravitas.Colliders.LSCompoundCollider2D,Gravitas.CollisionHandling.MixedContact&)
TrySphereEmbedded2D(Gravitas.Colliders.LSSphereCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryCapsuleEmbedded2D(Gravitas.Colliders.LSCapsuleCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryCylinderEmbedded2D(Gravitas.Colliders.LSCylinderCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryConeEmbedded2D(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryTestCapsuleCircleSlab(Gravitas.Colliders.LSCapsuleCollider,Gravitas.Colliders.LSCircleCollider2D,Gravitas.CollisionHandling.AxisPenetration&)
TryTestCylinderCircleSlab(Gravitas.Colliders.LSCylinderCollider,Gravitas.Colliders.LSCircleCollider2D,Gravitas.CollisionHandling.AxisPenetration&)
TryTestConeCircleSlab(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCircleCollider2D,Gravitas.CollisionHandling.AxisPenetration&)
TryTestCapsuleCapsuleSlab(Gravitas.Colliders.LSCapsuleCollider,Gravitas.Colliders.LSCapsuleCollider2D,Gravitas.CollisionHandling.AxisPenetration&)
TryTestCylinderCapsuleSlab(Gravitas.Colliders.LSCylinderCollider,Gravitas.Colliders.LSCapsuleCollider2D,Gravitas.CollisionHandling.AxisPenetration&)
TryTestConeCapsuleSlab(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCapsuleCollider2D,Gravitas.CollisionHandling.AxisPenetration&)
CheckCapsuleCircleSlabAxis(Gravitas.Colliders.LSCapsuleCollider,Gravitas.Colliders.LSCircleCollider2D,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckCylinderCircleSlabAxis(Gravitas.Colliders.LSCylinderCollider,Gravitas.Colliders.LSCircleCollider2D,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckConeCircleSlabAxis(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCircleCollider2D,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckCapsulePrismAxis(Gravitas.Colliders.LSCapsuleCollider,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector3d,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckCylinderPrismAxis(Gravitas.Colliders.LSCylinderCollider,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector3d,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckConePrismAxis(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
KeepAxisPenetration(FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Boolean,Gravitas.CollisionHandling.AxisPenetration&)
CheckEmbeddedCapsuleAxes(Gravitas.Colliders.LSCapsuleCollider,FixedMathSharp.Vector3d,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckEmbeddedCapsuleAxes(Gravitas.Colliders.LSCylinderCollider,FixedMathSharp.Vector3d,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckEmbeddedCapsuleAxes(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckCapsuleEmbeddedCapsuleEdgeAxis(Gravitas.Colliders.LSCapsuleCollider,FixedMathSharp.Vector3d,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckCylinderEmbeddedCapsuleEdgeAxis(Gravitas.Colliders.LSCylinderCollider,FixedMathSharp.Vector3d,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
CheckConeEmbeddedCapsuleEdgeAxis(Gravitas.Colliders.LSConeCollider,FixedMathSharp.Vector3d,Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Vector3d,Gravitas.CollisionHandling.AxisPenetration&)
BuildCapsuleContact(Gravitas.Colliders.LSCapsuleCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.AxisPenetration,Gravitas.CollisionHandling.MixedContact&)
BuildCylinderContact(Gravitas.Colliders.LSCylinderCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.AxisPenetration,Gravitas.CollisionHandling.MixedContact&)
BuildConeContact(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.AxisPenetration,Gravitas.CollisionHandling.MixedContact&)
BuildCanonicalSupportContact(Gravitas.Colliders.LSCollider,Gravitas.Colliders.LSCollider2D,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,System.Boolean)
TryCuboidEmbedded2D(Gravitas.Colliders.LSCuboidCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryGetCuboidPrismContact(Gravitas.Colliders.LSCuboidCollider,Gravitas.Colliders.LSCollider2D,System.ReadOnlySpan`1<FixedMathSharp.Vector2d>,Gravitas.CollisionHandling.MixedContact&)
TryGetCuboidRelationContact(System.Boolean,FixedMathSharp.Geometry.FixedContactAnchors&,Gravitas.CollisionHandling.MixedContact&)
TryGetTriangleConvexPrismContact(Gravitas.Colliders.LSMeshCollider,System.Int32,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryGetSphereConvexPrismContact(Gravitas.Colliders.LSSphereCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryGetCapsuleConvexPrismContact(Gravitas.Colliders.LSCapsuleCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryGetCylinderConvexPrismContact(Gravitas.Colliders.LSCylinderCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
TryGetConeConvexPrismContact(Gravitas.Colliders.LSConeCollider,Gravitas.Colliders.LSCollider2D,Gravitas.CollisionHandling.MixedContact&)
GetConvexPrismOffsets(Gravitas.Colliders.LSCollider2D,System.Span`1<FixedMathSharp.Vector2d>)
TryBuildFinitePrismContact(System.Boolean,FixedMathSharp.Geometry.FixedContactAnchors&,Gravitas.CollisionHandling.MixedContact&)
TryGetRotationalSeparationGap(Gravitas.Colliders.LSCollider,Gravitas.Colliders.LSCollider2D,FixedMathSharp.Fixed64&,System.Boolean&)
TryGetSpherePolygonSlabSeparationGap(Gravitas.Colliders.LSSphereCollider,Gravitas.Colliders.LSPolygonCollider2D,FixedMathSharp.Fixed64&)
TryGetPolygonExteriorGap(Gravitas.Colliders.LSPolygonCollider2D,FixedMathSharp.Vector2d,FixedMathSharp.Fixed64&)
TryGetPointIntervalGap(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryGetIntervalGap(FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64&)
TryNormalizeAxis(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
GetEmbeddedCenter3D(Gravitas.Colliders.LSCollider2D)
GetEmbeddedCapsuleAxes(Gravitas.Colliders.LSCapsuleCollider2D,FixedMathSharp.Vector2d&,FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
GetRigidUpAxis(FixedMathSharp.FixedQuaternion)
ResolveFallbackNormal(FixedMathSharp.Vector3d,Gravitas.Colliders.LSCollider2D)
NoContact(Gravitas.CollisionHandling.MixedContact&)