< Summary

Information
Class: Gravitas.Constraints.JointSolver3D
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/Constraints/3D/JointSolver3D.cs
Line coverage
100%
Covered lines: 256
Uncovered lines: 0
Coverable lines: 256
Total lines: 461
Line coverage: 100%
Branch coverage
100%
Covered branches: 76
Total branches: 76
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%
Solve(...)100%1414100%
BuildRows(...)100%1010100%
AddLinearAnchorRow(...)100%11100%
AddAngularRows(...)100%44100%
AddMotorRows(...)100%22100%
AddAxisAlignmentRows(...)100%22100%
AddHingeLimitRow(...)100%66100%
AddConeTwistRows(...)100%1010100%
AddAngularErrorRows(...)100%11100%
AddMotorErrorRows(...)100%11100%
AddAngularRow(...)100%44100%
AddMotorRow(...)100%22100%
GetAngularError(...)100%11100%
GetSignedTwistAngle(...)100%44100%
NormalizeAngle(...)100%44100%
Perpendicular(...)100%22100%
SolveRow(...)100%44100%
ComputeRelativeVelocity(...)100%22100%
ComputeDenominator(...)100%22100%
ApplyImpulse(...)100%44100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Constraints/3D/JointSolver3D.cs

#LineLine coverage
 1//=======================================================================
 2// JointSolver3D.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.CollisionHandling;
 10using System;
 11
 12namespace Gravitas.Constraints;
 13
 14internal static class JointSolver3D
 15{
 16    internal const int MaxRowsPerJoint = 12;
 117    private static readonly Fixed64 BiasFactor = Fixed64.One / (Fixed64)5;
 118    private static readonly Fixed64 RowEpsilon = Fixed64.Epsilon;
 19    // 4,096 raw Q32.32 units, approximately 9.536743e-7 radians.
 120    private static readonly Fixed64 QuaternionTwistVectorEpsilon = Fixed64.FromRaw(4_096);
 21
 22    internal static void Solve(Joint3D joint, bool applyCachedImpulse)
 23    {
 4973024        Span<JointConstraintRow3D> rows = stackalloc JointConstraintRow3D[MaxRowsPerJoint];
 4973025        int rowCount = BuildRows(
 4973026            joint,
 4973027            rows,
 4973028            out Fixed64 linearAnchorErrorMagnitude,
 4973029            out Fixed64 angularLimitErrorMagnitude,
 4973030            out Fixed64 motorErrorMagnitude);
 31
 4973032        Fixed64 incrementalImpulseMagnitude = Fixed64.Zero;
 4973033        Fixed64 motorImpulseMagnitude = Fixed64.Zero;
 4973034        int clampedRowCount = 0;
 42140435        for (int i = 0; i < rowCount; i++)
 36        {
 16097237            JointConstraintRow3D row = rows[i];
 16097238            if (applyCachedImpulse)
 39            {
 1628740                row.AccumulatedImpulse = joint.GetCachedImpulse(row.CacheIndex);
 1628741                ApplyImpulse(joint.BodyA, joint.BodyB, row, row.AccumulatedImpulse);
 42            }
 43
 16097244            Fixed64 impulse = SolveRow(joint.BodyA, joint.BodyB, row, out bool clamped);
 16097245            row.AccumulatedImpulse += impulse;
 16097246            rows[i] = row;
 16097247            joint.SetCachedImpulse(row.CacheIndex, row.AccumulatedImpulse);
 16097248            Fixed64 rowImpulseMagnitude = impulse.Abs();
 16097249            incrementalImpulseMagnitude += rowImpulseMagnitude;
 16097250            if (row.Kind == JointConstraintRowKind3D.Motor)
 309651                motorImpulseMagnitude += rowImpulseMagnitude;
 16097252            if (clamped)
 118053                clampedRowCount++;
 54        }
 55
 4973056        Fixed64 impulseMagnitude = Fixed64.Zero;
 42140457        for (int i = 0; i < rowCount; i++)
 16097258            impulseMagnitude += rows[i].AccumulatedImpulse.Abs();
 59
 97103660        for (int i = rowCount; i < MaxRowsPerJoint; i++)
 43578861            joint.SetCachedImpulse(i, Fixed64.Zero);
 62
 4973063        joint.LastSolvedRowCount = rowCount;
 4973064        joint.AccumulatedImpulseMagnitude += incrementalImpulseMagnitude;
 4973065        joint.LastSolveMetrics = new JointSolveMetrics3D(
 4973066            rowCount,
 4973067            linearAnchorErrorMagnitude,
 4973068            angularLimitErrorMagnitude,
 4973069            impulseMagnitude,
 4973070            incrementalImpulseMagnitude,
 4973071            motorImpulseMagnitude,
 4973072            motorErrorMagnitude,
 4973073            clampedRowCount);
 4973074        if (incrementalImpulseMagnitude > Fixed64.Zero)
 4806975            joint.Context.Diagnostics.EmitJointImpulse(joint, joint.LastSolveMetrics);
 4973076    }
 77
 78    private static int BuildRows(
 79        Joint3D joint,
 80        Span<JointConstraintRow3D> rows,
 81        out Fixed64 linearAnchorErrorMagnitude,
 82        out Fixed64 angularLimitErrorMagnitude,
 83        out Fixed64 motorErrorMagnitude)
 84    {
 4973085        int count = 0;
 4973086        angularLimitErrorMagnitude = Fixed64.Zero;
 4973087        motorErrorMagnitude = Fixed64.Zero;
 4973088        SolidBody bodyA = joint.BodyA;
 4973089        SolidBody bodyB = joint.BodyB;
 90
 4973091        FixedQuaternion worldRotationA = (bodyA.Rotation * joint.LocalFrameA.Rotation).Normalized;
 4973092        FixedQuaternion worldRotationB = (bodyB.Rotation * joint.LocalFrameB.Rotation).Normalized;
 4973093        if (!bodyA.Rotation.TryRotate(
 4973094                joint.LocalFrameA.Position,
 4973095                out Vector3d anchorOffsetA)
 4973096            || !bodyB.Rotation.TryRotate(
 4973097                joint.LocalFrameB.Position,
 4973098                out Vector3d anchorOffsetB)
 4973099            || !bodyA.TryGetOffsetFromCenterOfMass(
 49730100                new ContactAnchor(bodyA.Position3d, anchorOffsetA),
 49730101                out Vector3d relativeAnchorA)
 49730102            || !bodyB.TryGetOffsetFromCenterOfMass(
 49730103                new ContactAnchor(bodyB.Position3d, anchorOffsetB),
 49730104                out Vector3d relativeAnchorB)
 49730105            || !Vector3d.TrySubtractSums(
 49730106                bodyB.Position3d,
 49730107                anchorOffsetB,
 49730108                bodyA.Position3d,
 49730109                anchorOffsetA,
 49730110                out Vector3d anchorError))
 111        {
 30112            linearAnchorErrorMagnitude = Fixed64.Zero;
 30113            GravitasLogger.Channel.Write(
 30114                DiagnosticLevel.Error,
 30115                "A 3D joint's anchors cannot be represented in response space.",
 30116                nameof(JointSolver3D));
 30117            return 0;
 118        }
 119
 49700120        linearAnchorErrorMagnitude = anchorError.Magnitude;
 121
 49700122        AddLinearAnchorRow(rows, ref count, Vector3d.Right, anchorError, relativeAnchorA, relativeAnchorB);
 49700123        AddLinearAnchorRow(rows, ref count, Vector3d.Up, anchorError, relativeAnchorA, relativeAnchorB);
 49700124        AddLinearAnchorRow(rows, ref count, Vector3d.Forward, anchorError, relativeAnchorA, relativeAnchorB);
 125
 49700126        AddAngularRows(joint, rows, ref count, worldRotationA, worldRotationB, ref angularLimitErrorMagnitude);
 49700127        AddMotorRows(joint, rows, ref count, worldRotationA, worldRotationB, out motorErrorMagnitude);
 49700128        return count;
 129    }
 130
 131    private static void AddLinearAnchorRow(
 132        Span<JointConstraintRow3D> rows,
 133        ref int count,
 134        Vector3d axis,
 135        Vector3d anchorError,
 136        Vector3d relativeAnchorA,
 137        Vector3d relativeAnchorB)
 138    {
 149100139        Fixed64 error = Vector3d.Dot(anchorError, axis);
 149100140        rows[count] = new JointConstraintRow3D(
 149100141            JointConstraintRowKind3D.Linear,
 149100142            axis,
 149100143            relativeAnchorA,
 149100144            relativeAnchorB,
 149100145            error * BiasFactor,
 149100146            Fixed64.Zero,
 149100147            Fixed64.MinValue,
 149100148            Fixed64.MaxValue,
 149100149            count);
 149100150        count++;
 149100151    }
 152
 153    private static void AddAngularRows(
 154        Joint3D joint,
 155        Span<JointConstraintRow3D> rows,
 156        ref int count,
 157        FixedQuaternion worldRotationA,
 158        FixedQuaternion worldRotationB,
 159        ref Fixed64 angularLimitErrorMagnitude)
 160    {
 49700161        Vector3d error = GetAngularError(worldRotationA, worldRotationB);
 49700162        switch (joint.Type)
 163        {
 164            case JointType3D.Fixed:
 168165                AddAngularErrorRows(rows, ref count, error, Fixed64.Zero, Fixed64.MaxValue);
 168166                break;
 167            case JointType3D.Hinge:
 8824168                AddAxisAlignmentRows(rows, ref count, worldRotationA * Vector3d.Right, worldRotationB * Vector3d.Right);
 8824169                AddHingeLimitRow(joint, rows, ref count, error, worldRotationA * Vector3d.Right, ref angularLimitErrorMa
 8824170                break;
 171            case JointType3D.ConeTwist:
 72172                AddConeTwistRows(joint, rows, ref count, worldRotationA, worldRotationB, ref angularLimitErrorMagnitude)
 173                break;
 174        }
 72175    }
 176
 177    private static void AddMotorRows(
 178        Joint3D joint,
 179        Span<JointConstraintRow3D> rows,
 180        ref int count,
 181        FixedQuaternion worldRotationA,
 182        FixedQuaternion worldRotationB,
 183        out Fixed64 motorErrorMagnitude)
 184    {
 49700185        motorErrorMagnitude = Fixed64.Zero;
 49700186        JointMotor3D motor = joint.Motor;
 49700187        if (!motor.IsEnabled)
 46180188            return;
 189
 3520190        FixedQuaternion targetWorldB = (worldRotationA * motor.TargetLocalRotation).Normalized;
 3520191        Vector3d motorError = GetAngularError(targetWorldB, worldRotationB);
 3520192        motorErrorMagnitude = motorError.Magnitude;
 3520193        AddMotorErrorRows(rows, ref count, motorError, motor.AngularDriveStrength, motor.AngularDriveDamping, motor.Maxi
 3520194    }
 195
 196    private static void AddAxisAlignmentRows(
 197        Span<JointConstraintRow3D> rows,
 198        ref int count,
 199        Vector3d axisA,
 200        Vector3d axisB)
 201    {
 8824202        Vector3d cross = Vector3d.Cross(axisA.Normalized, axisB.Normalized);
 8824203        Fixed64 magnitude = cross.Magnitude;
 8824204        if (magnitude <= RowEpsilon)
 296205            return;
 206
 8528207        AddAngularRow(rows, ref count, cross / magnitude, magnitude, Fixed64.Zero, Fixed64.MaxValue);
 8528208    }
 209
 210    private static void AddHingeLimitRow(
 211        Joint3D joint,
 212        Span<JointConstraintRow3D> rows,
 213        ref int count,
 214        Vector3d angularError,
 215        Vector3d hingeAxis,
 216        ref Fixed64 angularLimitErrorMagnitude)
 217    {
 8824218        if (joint.Limits.Kind != JointLimitKind3D.Hinge)
 8219            return;
 220
 8816221        Vector3d axis = hingeAxis.Normalized;
 8816222        Fixed64 twist = Vector3d.Dot(angularError, axis);
 8816223        Fixed64 max = joint.Limits.MaxHingeAngle;
 8816224        if (twist.Abs() <= max)
 8784225            return;
 226
 32227        Fixed64 limitedError = twist > Fixed64.Zero ? twist - max : twist + max;
 32228        angularLimitErrorMagnitude += limitedError.Abs();
 32229        AddAngularRow(rows, ref count, axis, limitedError, Fixed64.Zero, Fixed64.MaxValue);
 32230        joint.Context.Diagnostics.EmitJointLimitReached(joint, limitedError);
 32231    }
 232
 233    private static void AddConeTwistRows(
 234        Joint3D joint,
 235        Span<JointConstraintRow3D> rows,
 236        ref int count,
 237        FixedQuaternion worldRotationA,
 238        FixedQuaternion worldRotationB,
 239        ref Fixed64 angularLimitErrorMagnitude)
 240    {
 72241        Vector3d forwardA = (worldRotationA * Vector3d.Forward).Normalized;
 72242        Vector3d forwardB = (worldRotationB * Vector3d.Forward).Normalized;
 72243        if (joint.Limits.Kind != JointLimitKind3D.ConeTwist)
 8244            return;
 245
 64246        Fixed64 dot = FixedMath.Clamp(Vector3d.Dot(forwardA, forwardB), -Fixed64.One, Fixed64.One);
 64247        Fixed64 swing = FixedMath.Acos(dot);
 64248        if (swing > joint.Limits.MaxConeAngle)
 249        {
 18250            Vector3d swingAxis = Vector3d.Cross(forwardA, forwardB);
 18251            if (swingAxis.MagnitudeSquared <= RowEpsilon)
 2252                swingAxis = Perpendicular(forwardA);
 253
 18254            Fixed64 limitedError = swing - joint.Limits.MaxConeAngle;
 18255            angularLimitErrorMagnitude += limitedError.Abs();
 18256            AddAngularRow(rows, ref count, swingAxis.Normalized, limitedError, Fixed64.Zero, Fixed64.MaxValue);
 18257            joint.Context.Diagnostics.EmitJointLimitReached(joint, limitedError);
 258        }
 259
 64260        Fixed64 twist = GetSignedTwistAngle(worldRotationA, worldRotationB, forwardA);
 64261        Fixed64 maxTwist = joint.Limits.MaxTwistAngle;
 64262        if (twist.Abs() > maxTwist)
 263        {
 38264            Fixed64 limitedError = twist > Fixed64.Zero ? twist - maxTwist : twist + maxTwist;
 38265            angularLimitErrorMagnitude += limitedError.Abs();
 38266            AddAngularRow(rows, ref count, forwardA, limitedError, Fixed64.Zero, Fixed64.MaxValue);
 38267            joint.Context.Diagnostics.EmitJointLimitReached(joint, limitedError);
 268        }
 64269    }
 270
 271    private static void AddAngularErrorRows(
 272        Span<JointConstraintRow3D> rows,
 273        ref int count,
 274        Vector3d error,
 275        Fixed64 damping,
 276        Fixed64 maxImpulse)
 277    {
 168278        AddAngularRow(rows, ref count, Vector3d.Right, Vector3d.Dot(error, Vector3d.Right), damping, maxImpulse);
 168279        AddAngularRow(rows, ref count, Vector3d.Up, Vector3d.Dot(error, Vector3d.Up), damping, maxImpulse);
 168280        AddAngularRow(rows, ref count, Vector3d.Forward, Vector3d.Dot(error, Vector3d.Forward), damping, maxImpulse);
 168281    }
 282
 283    private static void AddMotorErrorRows(
 284        Span<JointConstraintRow3D> rows,
 285        ref int count,
 286        Vector3d error,
 287        Fixed64 strength,
 288        Fixed64 damping,
 289        Fixed64 maxImpulse)
 290    {
 3520291        AddMotorRow(rows, ref count, Vector3d.Right, Vector3d.Dot(error, Vector3d.Right) * strength, damping, maxImpulse
 3520292        AddMotorRow(rows, ref count, Vector3d.Up, Vector3d.Dot(error, Vector3d.Up) * strength, damping, maxImpulse);
 3520293        AddMotorRow(rows, ref count, Vector3d.Forward, Vector3d.Dot(error, Vector3d.Forward) * strength, damping, maxImp
 3520294    }
 295
 296    private static void AddAngularRow(
 297        Span<JointConstraintRow3D> rows,
 298        ref int count,
 299        Vector3d axis,
 300        Fixed64 error,
 301        Fixed64 damping,
 302        Fixed64 maxImpulse)
 303    {
 9120304        if (error.Abs() <= RowEpsilon || axis.MagnitudeSquared <= RowEpsilon)
 344305            return;
 306
 8776307        rows[count] = new JointConstraintRow3D(
 8776308            JointConstraintRowKind3D.Angular,
 8776309            axis.Normalized,
 8776310            Vector3d.Zero,
 8776311            Vector3d.Zero,
 8776312            error * BiasFactor,
 8776313            damping,
 8776314            -maxImpulse,
 8776315            maxImpulse,
 8776316            count);
 8776317        count++;
 8776318    }
 319
 320    private static void AddMotorRow(
 321        Span<JointConstraintRow3D> rows,
 322        ref int count,
 323        Vector3d axis,
 324        Fixed64 biasVelocity,
 325        Fixed64 damping,
 326        Fixed64 maxImpulse)
 327    {
 10560328        if (biasVelocity.Abs() <= RowEpsilon)
 7464329            return;
 330
 3096331        rows[count] = new JointConstraintRow3D(
 3096332            JointConstraintRowKind3D.Motor,
 3096333            axis,
 3096334            Vector3d.Zero,
 3096335            Vector3d.Zero,
 3096336            biasVelocity,
 3096337            damping,
 3096338            -maxImpulse,
 3096339            maxImpulse,
 3096340            count);
 3096341        count++;
 3096342    }
 343
 344    private static Vector3d GetAngularError(FixedQuaternion reference, FixedQuaternion current)
 345    {
 53220346        FixedQuaternion error = (current * reference.Inverse()).Normalized;
 53220347        return FixedQuaternion.QuaternionLog(error);
 348    }
 349
 350    private static Fixed64 GetSignedTwistAngle(
 351        FixedQuaternion worldRotationA,
 352        FixedQuaternion worldRotationB,
 353        Vector3d twistAxis)
 354    {
 64355        FixedQuaternion relative = (worldRotationB * worldRotationA.Inverse()).Normalized;
 64356        Vector3d relativeVector = new(relative.X, relative.Y, relative.Z);
 64357        Fixed64 projectedTwist = Vector3d.Dot(relativeVector, twistAxis);
 64358        if (projectedTwist.Abs() < QuaternionTwistVectorEpsilon
 64359            && relative.W.Abs() < QuaternionTwistVectorEpsilon)
 360        {
 2361            return Fixed64.Zero;
 362        }
 363
 62364        return NormalizeAngle(Fixed64.Two * FixedMath.Atan2(projectedTwist, relative.W));
 365    }
 366
 367    private static Fixed64 NormalizeAngle(Fixed64 angle)
 368    {
 62369        angle %= Fixed64.TwoPi;
 62370        if (angle < -Fixed64.Pi)
 1371            angle += Fixed64.TwoPi;
 61372        else if (angle >= Fixed64.Pi)
 2373            angle -= Fixed64.TwoPi;
 62374        return angle;
 375    }
 376
 377    private static Vector3d Perpendicular(Vector3d axis)
 378    {
 2379        Vector3d candidate = Vector3d.Cross(axis, Vector3d.Up);
 2380        return candidate.MagnitudeSquared > RowEpsilon
 2381            ? candidate
 2382            : Vector3d.Cross(axis, Vector3d.Right);
 383    }
 384
 385    private static Fixed64 SolveRow(
 386        SolidBody bodyA,
 387        SolidBody bodyB,
 388        JointConstraintRow3D row,
 389        out bool clampedToBounds)
 390    {
 160972391        clampedToBounds = false;
 160972392        Fixed64 denominator = ComputeDenominator(bodyA, bodyB, row);
 160972393        if (denominator <= Fixed64.Epsilon)
 32394            return Fixed64.Zero;
 395
 160940396        Fixed64 velocity = ComputeRelativeVelocity(bodyA, bodyB, row);
 160940397        Fixed64 lambda = -(velocity + row.BiasVelocity + velocity * row.Damping) / denominator;
 160940398        Fixed64 unclamped = row.AccumulatedImpulse + lambda;
 160940399        Fixed64 clamped = FixedMath.Clamp(unclamped, row.LowerImpulse, row.UpperImpulse);
 160940400        clampedToBounds = clamped != unclamped;
 160940401        lambda = clamped - row.AccumulatedImpulse;
 160940402        if (lambda == Fixed64.Zero)
 45639403            return Fixed64.Zero;
 404
 115301405        ApplyImpulse(bodyA, bodyB, row, lambda);
 115301406        return lambda;
 407    }
 408
 409    private static Fixed64 ComputeRelativeVelocity(SolidBody bodyA, SolidBody bodyB, JointConstraintRow3D row)
 410    {
 160940411        if (row.Kind == JointConstraintRowKind3D.Linear)
 412        {
 149100413            Vector3d velocityA = bodyA.LinearVelocity + Vector3d.Cross(bodyA.AngularVelocity, row.RelativeAnchorA);
 149100414            Vector3d velocityB = bodyB.LinearVelocity + Vector3d.Cross(bodyB.AngularVelocity, row.RelativeAnchorB);
 149100415            return Vector3d.Dot(velocityB - velocityA, row.Axis);
 416        }
 417
 11840418        return Vector3d.Dot(bodyB.AngularVelocity - bodyA.AngularVelocity, row.Axis);
 419    }
 420
 421    private static Fixed64 ComputeDenominator(SolidBody bodyA, SolidBody bodyB, JointConstraintRow3D row)
 422    {
 160972423        if (row.Kind != JointConstraintRowKind3D.Linear)
 424        {
 11872425            Vector3d angularA = bodyA.ApplyConstrainedInverseInertia(row.Axis);
 11872426            Vector3d angularB = bodyB.ApplyConstrainedInverseInertia(row.Axis);
 11872427            return Vector3d.Dot(row.Axis, angularA + angularB);
 428        }
 429
 149100430        Fixed64 inverseMass = bodyA.GetConstrainedInverseMass(row.Axis) + bodyB.GetConstrainedInverseMass(row.Axis);
 149100431        Vector3d torqueA = Vector3d.Cross(row.RelativeAnchorA, row.Axis);
 149100432        Vector3d torqueB = Vector3d.Cross(row.RelativeAnchorB, row.Axis);
 149100433        Vector3d linearAngularA = bodyA.ApplyConstrainedInverseInertia(torqueA);
 149100434        Vector3d linearAngularB = bodyB.ApplyConstrainedInverseInertia(torqueB);
 149100435        return inverseMass
 149100436            + Vector3d.Dot(torqueA, linearAngularA)
 149100437            + Vector3d.Dot(torqueB, linearAngularB);
 438    }
 439
 440    private static void ApplyImpulse(SolidBody bodyA, SolidBody bodyB, JointConstraintRow3D row, Fixed64 lambda)
 441    {
 131588442        if (lambda == Fixed64.Zero)
 5145443            return;
 444
 126443445        Vector3d impulse = row.Axis * lambda;
 126443446        if (row.Kind == JointConstraintRowKind3D.Linear)
 447        {
 113998448            bodyA.ApplyCollisionLinearVelocityDelta(-impulse * bodyA.GetConstrainedInverseMass(row.Axis));
 113998449            bodyB.ApplyCollisionLinearVelocityDelta(impulse * bodyB.GetConstrainedInverseMass(row.Axis));
 450
 113998451            Vector3d angularImpulseA = bodyA.ApplyConstrainedInverseInertia(Vector3d.Cross(row.RelativeAnchorA, -impulse
 113998452            Vector3d angularImpulseB = bodyB.ApplyConstrainedInverseInertia(Vector3d.Cross(row.RelativeAnchorB, impulse)
 113998453            bodyA.ApplyCollisionAngularVelocityDelta(angularImpulseA);
 113998454            bodyB.ApplyCollisionAngularVelocityDelta(angularImpulseB);
 113998455            return;
 456        }
 457
 12445458        bodyA.ApplyCollisionAngularVelocityDelta(bodyA.ApplyConstrainedInverseInertia(-impulse));
 12445459        bodyB.ApplyCollisionAngularVelocityDelta(bodyB.ApplyConstrainedInverseInertia(impulse));
 12445460    }
 461}

Methods/Properties

.cctor()
Solve(Gravitas.Constraints.Joint3D,System.Boolean)
BuildRows(Gravitas.Constraints.Joint3D,System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&,FixedMathSharp.Fixed64&)
AddLinearAnchorRow(System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
AddAngularRows(Gravitas.Constraints.Joint3D,System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.FixedQuaternion,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64&)
AddMotorRows(Gravitas.Constraints.Joint3D,System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.FixedQuaternion,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64&)
AddAxisAlignmentRows(System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d)
AddHingeLimitRow(Gravitas.Constraints.Joint3D,System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64&)
AddConeTwistRows(Gravitas.Constraints.Joint3D,System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.FixedQuaternion,FixedMathSharp.FixedQuaternion,FixedMathSharp.Fixed64&)
AddAngularErrorRows(System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AddMotorErrorRows(System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AddAngularRow(System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
AddMotorRow(System.Span`1<Gravitas.Constraints.JointConstraintRow3D>,System.Int32&,FixedMathSharp.Vector3d,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64,FixedMathSharp.Fixed64)
GetAngularError(FixedMathSharp.FixedQuaternion,FixedMathSharp.FixedQuaternion)
GetSignedTwistAngle(FixedMathSharp.FixedQuaternion,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d)
NormalizeAngle(FixedMathSharp.Fixed64)
Perpendicular(FixedMathSharp.Vector3d)
SolveRow(Gravitas.SolidBody,Gravitas.SolidBody,Gravitas.Constraints.JointConstraintRow3D,System.Boolean&)
ComputeRelativeVelocity(Gravitas.SolidBody,Gravitas.SolidBody,Gravitas.Constraints.JointConstraintRow3D)
ComputeDenominator(Gravitas.SolidBody,Gravitas.SolidBody,Gravitas.Constraints.JointConstraintRow3D)
ApplyImpulse(Gravitas.SolidBody,Gravitas.SolidBody,Gravitas.Constraints.JointConstraintRow3D,FixedMathSharp.Fixed64)