< Summary

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

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
CreateTangent(...)100%66100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// SolverContact.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 Gravitas.Materials;
 10
 11namespace Gravitas.CollisionHandling;
 12
 13internal readonly struct ContactLever3D
 14{
 15    private ContactLever3D(Vector3d vector, bool isExact)
 16    {
 17        Vector = vector;
 18        IsExact = isExact;
 19    }
 20
 21    internal bool IsExact { get; }
 22
 23    internal Vector3d Vector { get; }
 24
 25    internal static ContactLever3D Create(
 26        in ContactAnchor point,
 27        in ContactAnchor origin)
 28    {
 29        if (point.TryGetOffsetFrom(origin, out Vector3d vector))
 30            return new ContactLever3D(vector, isExact: false);
 31
 32        return new ContactLever3D(default, isExact: true);
 33    }
 34}
 35
 36/// <summary>
 37/// Solver-ready 3D contact data, including the deterministic tangent frame and cached impulses.
 38/// </summary>
 39internal readonly struct SolverContact
 40{
 41    public SolverContact(
 42        int manifoldIndex,
 43        ulong contactId,
 44        ResponseBody bodyA,
 45        ResponseBody bodyB,
 46        ContactLever3D relativeA,
 47        ContactLever3D relativeB,
 48        Fixed64 depth,
 49        Vector3d normal,
 50        PhysicsMaterial materialA,
 51        PhysicsMaterial materialB,
 52        Fixed64 cachedNormalImpulse,
 53        Fixed64 cachedTangentImpulse,
 54        Fixed64 cachedSecondaryTangentImpulse)
 55    {
 908456        ManifoldIndex = manifoldIndex;
 908457        ContactId = contactId;
 908458        A = bodyA;
 908459        B = bodyB;
 908460        RelativeA = relativeA;
 908461        RelativeB = relativeB;
 908462        Depth = depth;
 908463        Normal = normal;
 908464        MaterialA = materialA;
 908465        MaterialB = materialB;
 908466        PhysicsMaterial.CombineFriction(materialA, materialB, out Fixed64 staticFriction, out Fixed64 dynamicFriction);
 908467        StaticFriction = staticFriction;
 908468        DynamicFriction = dynamicFriction;
 908469        Restitution = PhysicsMaterial.CombineRestitution(materialA, materialB);
 908470        Tangent = CreateTangent(normal);
 908471        SecondaryTangent = Vector3d.Cross(normal, Tangent).Normalized;
 908472        CachedNormalImpulse = cachedNormalImpulse;
 908473        CachedTangentImpulse = cachedTangentImpulse;
 908474        CachedSecondaryTangentImpulse = cachedSecondaryTangentImpulse;
 908475    }
 76
 77    public int ManifoldIndex { get; }
 78
 79    public ulong ContactId { get; }
 80
 81    public ResponseBody A { get; }
 82
 83    public ResponseBody B { get; }
 84
 85    public ContactLever3D RelativeA { get; }
 86
 87    public ContactLever3D RelativeB { get; }
 88
 89    public Fixed64 Depth { get; }
 90
 91    public Vector3d Normal { get; }
 92
 93    public PhysicsMaterial MaterialA { get; }
 94
 95    public PhysicsMaterial MaterialB { get; }
 96
 97    public Fixed64 StaticFriction { get; }
 98
 99    public Fixed64 DynamicFriction { get; }
 100
 101    public Fixed64 Restitution { get; }
 102
 103    public Vector3d Tangent { get; }
 104
 105    public Vector3d SecondaryTangent { get; }
 106
 107    public Fixed64 CachedNormalImpulse { get; }
 108
 109    public Fixed64 CachedTangentImpulse { get; }
 110
 111    public Fixed64 CachedSecondaryTangentImpulse { get; }
 112
 113    internal static Vector3d CreateTangent(Vector3d normal)
 114    {
 9117115        Vector3d absolute = Vector3d.Abs(normal);
 9117116        Vector3d reference = absolute.X <= absolute.Y && absolute.X <= absolute.Z
 9117117            ? Vector3d.Right
 9117118            : absolute.Y <= absolute.Z
 9117119                ? Vector3d.Up
 9117120                : Vector3d.Forward;
 121
 9117122        return Vector3d.Cross(reference, normal).Normalized;
 123    }
 124}