< Summary

Information
Class: Gravitas.CollisionHandling.GjkSimplexPolicy
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Detection/3D/GjkSimplexPolicy.cs
Line coverage
100%
Covered lines: 95
Uncovered lines: 0
Coverable lines: 95
Total lines: 172
Line coverage: 100%
Branch coverage
100%
Covered branches: 34
Total branches: 34
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddPoint(...)100%44100%
Update(...)100%44100%
UpdateLine(...)100%44100%
UpdateTriangle(...)100%1010100%
UpdateTetrahedron(...)100%66100%
SameDirection(...)100%11100%
TripleCross(...)100%11100%
OrientFaceNormal(...)100%22100%
Perpendicular(...)100%44100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/CollisionHandling/Detection/3D/GjkSimplexPolicy.cs

#LineLine coverage
 1//=======================================================================
 2// GjkSimplexPolicy.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 System;
 10using System.Runtime.CompilerServices;
 11
 12namespace Gravitas.CollisionHandling;
 13
 14internal static class GjkSimplexPolicy
 15{
 16    public static void AddPoint(Span<Vector3d> simplex, ref int count, Vector3d point)
 17    {
 897218        for (int i = Math.Min(count, 3); i > 0; i--)
 300919            simplex[i] = simplex[i - 1];
 20
 147721        simplex[0] = point;
 147722        if (count < 4)
 147623            count++;
 147724    }
 25
 26    public static bool Update(Span<Vector3d> simplex, ref int count, ref Vector3d direction)
 27    {
 147628        return count switch
 147629        {
 47530            2 => UpdateLine(simplex, ref count, ref direction),
 47231            3 => UpdateTriangle(simplex, ref count, ref direction),
 52932            _ => UpdateTetrahedron(simplex, ref count, ref direction)
 147633        };
 34    }
 35
 36    public static bool UpdateLine(Span<Vector3d> simplex, ref int count, ref Vector3d direction)
 37    {
 48238        Vector3d a = simplex[0];
 48239        Vector3d b = simplex[1];
 48240        Vector3d ab = b - a;
 48241        Vector3d ao = -a;
 42
 48243        if (SameDirection(ab, ao))
 44        {
 48045            direction = TripleCross(ab, ao, ab);
 48046            if (direction.MagnitudeSquared <= Fixed64.Epsilon)
 22547                direction = Perpendicular(ab);
 48048            return false;
 49        }
 50
 251        simplex[0] = a;
 252        count = 1;
 253        direction = ao;
 254        return false;
 55    }
 56
 57    public static bool UpdateTriangle(Span<Vector3d> simplex, ref int count, ref Vector3d direction)
 58    {
 47859        Vector3d a = simplex[0];
 47860        Vector3d b = simplex[1];
 47861        Vector3d c = simplex[2];
 47862        Vector3d ab = b - a;
 47863        Vector3d ac = c - a;
 47864        Vector3d ao = -a;
 47865        Vector3d abc = Vector3d.Cross(ab, ac);
 66
 47867        Vector3d acPerp = Vector3d.Cross(abc, ac);
 47868        if (SameDirection(acPerp, ao))
 69        {
 770            if (SameDirection(ac, ao))
 71            {
 672                simplex[1] = c;
 673                count = 2;
 674                direction = TripleCross(ac, ao, ac);
 675                if (direction.MagnitudeSquared <= Fixed64.Epsilon)
 176                    direction = Perpendicular(ac);
 677                return false;
 78            }
 79
 180            simplex[1] = b;
 181            count = 2;
 182            return UpdateLine(simplex, ref count, ref direction);
 83        }
 84
 47185        Vector3d abPerp = Vector3d.Cross(ab, abc);
 47186        if (SameDirection(abPerp, ao))
 87        {
 388            simplex[1] = b;
 389            count = 2;
 390            return UpdateLine(simplex, ref count, ref direction);
 91        }
 92
 46893        if (SameDirection(abc, ao))
 94        {
 1295            direction = abc;
 1296            return false;
 97        }
 98
 45699        simplex[1] = c;
 456100        simplex[2] = b;
 456101        direction = -abc;
 456102        return false;
 103    }
 104
 105    public static bool UpdateTetrahedron(Span<Vector3d> simplex, ref int count, ref Vector3d direction)
 106    {
 533107        Vector3d a = simplex[0];
 533108        Vector3d b = simplex[1];
 533109        Vector3d c = simplex[2];
 533110        Vector3d d = simplex[3];
 533111        Vector3d ao = -a;
 112
 533113        Vector3d abc = OrientFaceNormal(a, b, c, d);
 533114        if (SameDirection(abc, ao))
 115        {
 32116            simplex[0] = a;
 32117            simplex[1] = b;
 32118            simplex[2] = c;
 32119            count = 3;
 32120            direction = abc;
 32121            return false;
 122        }
 123
 501124        Vector3d acd = OrientFaceNormal(a, c, d, b);
 501125        if (SameDirection(acd, ao))
 126        {
 23127            simplex[0] = a;
 23128            simplex[1] = c;
 23129            simplex[2] = d;
 23130            count = 3;
 23131            direction = acd;
 23132            return false;
 133        }
 134
 478135        Vector3d adb = OrientFaceNormal(a, d, b, c);
 478136        if (SameDirection(adb, ao))
 137        {
 14138            simplex[0] = a;
 14139            simplex[1] = d;
 14140            simplex[2] = b;
 14141            count = 3;
 14142            direction = adb;
 14143            return false;
 144        }
 145
 464146        return true;
 147    }
 148
 149    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 150    private static bool SameDirection(Vector3d first, Vector3d second) =>
 3418151        Vector3d.Dot(first, second) > Fixed64.Zero;
 152
 153    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 154    private static Vector3d TripleCross(Vector3d first, Vector3d second, Vector3d third) =>
 486155        Vector3d.Cross(Vector3d.Cross(first, second), third);
 156
 157    private static Vector3d OrientFaceNormal(Vector3d a, Vector3d b, Vector3d c, Vector3d opposite)
 158    {
 1512159        Vector3d normal = Vector3d.Cross(b - a, c - a);
 1512160        return Vector3d.Dot(normal, opposite - a) > Fixed64.Zero ? -normal : normal;
 161    }
 162
 163    private static Vector3d Perpendicular(Vector3d vector)
 164    {
 226165        Vector3d candidate = Vector3d.Cross(vector, Vector3d.Up);
 226166        if (candidate.MagnitudeSquared > Fixed64.Epsilon)
 224167            return candidate;
 168
 2169        candidate = Vector3d.Cross(vector, Vector3d.Right);
 2170        return candidate.MagnitudeSquared > Fixed64.Epsilon ? candidate : Vector3d.Forward;
 171    }
 172}