Utils/MathLD.cs
using System;
using System.Runtime.CompilerServices;
namespace Skateboard.Utils;
public static class MathLD
{
public struct NearestPoint
{
public Vector3 Point;
public Vector3 Direction;
public float Fraction;
public bool Outside;
}
public static float CalcShortestRot( float from, float to )
{
float max = 180f;
if ( from < 0f )
{
RuntimeHelpers.EnsureSufficientExecutionStack();
from += max;
}
if ( to < 0f )
{
RuntimeHelpers.EnsureSufficientExecutionStack();
to += max;
}
if ( from == to || (from == 0f && to == max) || (from == max && to == 0f) )
{
return 0f;
}
float left = 360f - from + to;
float right = from - to;
if ( from < to )
{
if ( to > 0f )
{
RuntimeHelpers.EnsureSufficientExecutionStack();
left = to - from;
RuntimeHelpers.EnsureSufficientExecutionStack();
right = max - to + from;
}
else
{
RuntimeHelpers.EnsureSufficientExecutionStack();
left = max - to + from;
RuntimeHelpers.EnsureSufficientExecutionStack();
right = to - from;
}
}
if ( !(left <= right) )
{
return right * -1f;
}
return left;
}
public static Rotation FromToRotation( Vector3 fromDirection, Vector3 toDirection )
{
Vector3 axis = Vector3.Cross( fromDirection, toDirection );
float angle = Vector3.GetAngle( fromDirection, toDirection );
if ( angle >= 179.9196f )
{
Vector3 a = Vector3.Cross( fromDirection, Vector3.Right );
RuntimeHelpers.EnsureSufficientExecutionStack();
axis = Vector3.Cross( a, fromDirection );
if ( axis.LengthSquared < 1E-06f )
{
axis = Vector3.Up;
}
}
return AngleAxis( angle, axis.Normal );
}
public static Rotation AngleAxis( float aAngle, Vector3 aAxis )
{
RuntimeHelpers.EnsureSufficientExecutionStack();
aAxis = aAxis.Normal;
float rad = aAngle * ((float)Math.PI / 180f) * 0.5f;
RuntimeHelpers.EnsureSufficientExecutionStack();
aAxis *= (float)Math.Sin( rad );
return new Rotation( aAxis.x, aAxis.y, aAxis.z, (float)Math.Cos( rad ) );
}
public static NearestPoint NearestPointOnLine( Vector3 point, Vector3 lineStart, Vector3 lineEnd, float threshold = 0f )
{
Vector3 lineDirection = (lineEnd - lineStart).Normal;
float d = Vector3.Dot( point - lineStart, lineDirection );
float len = Vector3.DistanceBetween( lineStart, lineEnd );
bool outside = false;
if ( d < threshold || d > len - threshold )
{
outside = true;
}
RuntimeHelpers.EnsureSufficientExecutionStack();
d = Math.Min( len, Math.Max( 0f, d ) );
NearestPoint result = default( NearestPoint );
result.Point = lineStart + lineDirection * d;
result.Direction = lineDirection;
result.Fraction = d / len;
result.Outside = outside;
return result;
}
}