659 lines
24 KiB
C#
659 lines
24 KiB
C#
using UnityEngine;
|
|
|
|
|
|
namespace FIMSpace
|
|
{
|
|
/// <summary>
|
|
/// FM: Class which contains many helpful methods which operates on Vectors and Quaternions or some other floating point maths
|
|
/// </summary>
|
|
public static class FEngineering
|
|
{
|
|
|
|
|
|
#region Rotations and directions
|
|
|
|
|
|
public static bool VIsZero( this Vector3 vec )
|
|
{
|
|
if( vec.sqrMagnitude == 0f ) return true; return false;
|
|
//if (vec.x != 0f) return false; if (vec.y != 0f) return false; if (vec.z != 0f) return false; return true;
|
|
}
|
|
|
|
public static bool VIsSame( this Vector3 vec1, Vector3 vec2 )
|
|
{
|
|
if( vec1.x != vec2.x ) return false; if( vec1.y != vec2.y ) return false; if( vec1.z != vec2.z ) return false; return true;
|
|
}
|
|
|
|
|
|
public static Vector3 TransformVector( this Quaternion parentRot, Vector3 parentLossyScale, Vector3 childLocalPos )
|
|
{
|
|
return parentRot * Vector3.Scale( childLocalPos, parentLossyScale );
|
|
}
|
|
|
|
/// <summary> Same like transform vector but without scaling but also supporting negative scale </summary>
|
|
public static Vector3 TransformInDirection( this Quaternion childRotation, Vector3 parentLossyScale, Vector3 childLocalPos )
|
|
{
|
|
return childRotation * Vector3.Scale( childLocalPos, new Vector3( parentLossyScale.x > 0 ? 1 : -1, parentLossyScale.y > 0 ? 1 : -1, parentLossyScale.y > 0 ? 1 : -1 ) );
|
|
}
|
|
|
|
public static Vector3 InverseTransformVector( this Quaternion tRotation, Vector3 tLossyScale, Vector3 worldPos )
|
|
{
|
|
worldPos = Quaternion.Inverse( tRotation ) * worldPos;
|
|
return new Vector3( worldPos.x / tLossyScale.x, worldPos.y / tLossyScale.y, worldPos.z / tLossyScale.z );
|
|
}
|
|
|
|
|
|
/// <summary> Instance for 2D Axis limit calculations </summary>
|
|
private static Plane axis2DProjection;
|
|
|
|
/// <summary>
|
|
/// Calculating offset (currentPos -= Axis2DLimit...) to prevent object from moving in provided axis
|
|
/// </summary>
|
|
/// <param name="axis">1 is X 2 is Y 3 is Z</param>
|
|
public static Vector3 VAxis2DLimit( this Transform parent, Vector3 parentPos, Vector3 childPos, int axis = 3 )
|
|
{
|
|
if( axis == 3 ) // Z is depth
|
|
axis2DProjection.SetNormalAndPosition( parent.forward, parentPos );
|
|
else
|
|
if( axis == 2 ) // Y
|
|
axis2DProjection.SetNormalAndPosition( parent.up, parentPos );
|
|
else // X is depth
|
|
axis2DProjection.SetNormalAndPosition( parent.right, parentPos );
|
|
|
|
return axis2DProjection.normal * axis2DProjection.GetDistanceToPoint( childPos );
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region Just Rotations related
|
|
|
|
/// <summary>
|
|
/// Locating world rotation in local space of parent transform
|
|
/// </summary>
|
|
public static Quaternion QToLocal( this Quaternion parentRotation, Quaternion worldRotation )
|
|
{
|
|
return Quaternion.Inverse( parentRotation ) * worldRotation;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Locating local rotation of child local space to world
|
|
/// </summary>
|
|
public static Quaternion QToWorld( this Quaternion parentRotation, Quaternion localRotation )
|
|
{
|
|
return parentRotation * localRotation;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Offsetting rotation of child transform with defined axis orientation
|
|
/// </summary>
|
|
public static Quaternion QRotateChild( this Quaternion offset, Quaternion parentRot, Quaternion childLocalRot )
|
|
{
|
|
return ( offset * parentRot ) * childLocalRot;
|
|
}
|
|
|
|
public static Quaternion ClampRotation( this Vector3 current, Vector3 bounds )
|
|
{
|
|
WrapVector( current );
|
|
|
|
if( current.x < -bounds.x ) current.x = -bounds.x; else if( current.x > bounds.x ) current.x = bounds.x;
|
|
if( current.y < -bounds.y ) current.y = -bounds.y; else if( current.y > bounds.y ) current.y = bounds.y;
|
|
if( current.z < -bounds.z ) current.z = -bounds.z; else if( current.z > bounds.z ) current.z = bounds.z;
|
|
|
|
return Quaternion.Euler( current );
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// For use with rigidbody.angularVelocity (Remember to set "rigidbody.maxAngularVelocity" higher)
|
|
/// </summary>
|
|
/// <param name="deltaRotation"> Create with [TargetRotation] * Quaternion.Inverse([CurrentRotation]) </param>
|
|
/// <returns> Multiply this value by rotation speed parameter like QToAngularVelocity(deltaRot) * RotationSpeed </returns>
|
|
public static Vector3 QToAngularVelocity( this Quaternion deltaRotation, bool fix = false )
|
|
{
|
|
return QToAngularVelocity( deltaRotation, fix ? ( 1f / Time.fixedDeltaTime ) : 1f );
|
|
}
|
|
|
|
/// <summary>
|
|
/// For use with rigidbody.angularVelocity (Remember to set "rigidbody.maxAngularVelocity" higher)
|
|
/// </summary>
|
|
/// <param name="deltaRotation"> Create with [TargetRotation] * Quaternion.Inverse([CurrentRotation]) </param>
|
|
/// <returns> Multiply this value by rotation speed parameter like QToAngularVelocity(deltaRot) * RotationSpeed </returns>
|
|
public static Vector3 QToAngularVelocity( this Quaternion deltaRotation, float multiplyAngle )
|
|
{
|
|
float angle; Vector3 axis;
|
|
deltaRotation.ToAngleAxis( out angle, out axis );
|
|
if( angle != 0f ) angle = Mathf.DeltaAngle( 0f, angle );
|
|
else return Vector3.zero;
|
|
|
|
axis = axis * ( angle * Mathf.Deg2Rad * multiplyAngle );
|
|
|
|
#if UNITY_2018_4_OR_NEWER
|
|
if( axis.x is float.NaN ) return Vector3.zero;
|
|
if( axis.y is float.NaN ) return Vector3.zero;
|
|
if( axis.z is float.NaN ) return Vector3.zero;
|
|
#endif
|
|
|
|
return axis;
|
|
}
|
|
|
|
public static Vector3 QToAngularVelocity( this Quaternion currentRotation, Quaternion targetRotation, bool fix = false )
|
|
{
|
|
return QToAngularVelocity( targetRotation * Quaternion.Inverse( currentRotation ), fix );
|
|
}
|
|
|
|
public static Vector3 QToAngularVelocity( this Quaternion currentRotation, Quaternion targetRotation, float multiply )
|
|
{
|
|
return QToAngularVelocity( targetRotation * Quaternion.Inverse( currentRotation ), multiply );
|
|
}
|
|
|
|
public static bool QIsZero( this Quaternion rot )
|
|
{
|
|
if( rot.x != 0f ) return false; if( rot.y != 0f ) return false; if( rot.z != 0f ) return false; return true;
|
|
}
|
|
|
|
public static bool QIsSame( this Quaternion rot1, Quaternion rot2 )
|
|
{
|
|
if( rot1.x != rot2.x ) return false; if( rot1.y != rot2.y ) return false; if( rot1.z != rot2.z ) return false; if( rot1.w != rot2.w ) return false; return true;
|
|
}
|
|
|
|
|
|
/// <summary> Wrapping angle (clamping in +- 360) </summary>
|
|
public static float WrapAngle( float angle )
|
|
{
|
|
angle %= 360;
|
|
if( angle > 180 ) return angle - 360;
|
|
return angle;
|
|
}
|
|
|
|
public static Vector3 WrapVector( Vector3 angles )
|
|
{ return new Vector3( WrapAngle( angles.x ), WrapAngle( angles.y ), WrapAngle( angles.z ) ); }
|
|
|
|
/// <summary> Unwrapping angle </summary>
|
|
public static float UnwrapAngle( float angle )
|
|
{
|
|
if( angle >= 0 ) return angle;
|
|
angle = -angle % 360;
|
|
return 360 - angle;
|
|
}
|
|
|
|
public static Vector3 UnwrapVector( Vector3 angles )
|
|
{ return new Vector3( UnwrapAngle( angles.x ), UnwrapAngle( angles.y ), UnwrapAngle( angles.z ) ); }
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Animation Related
|
|
|
|
|
|
public static Quaternion SmoothDampRotation( this Quaternion current, Quaternion target, ref Quaternion velocityRef, float duration, float delta )
|
|
{
|
|
return SmoothDampRotation( current, target, ref velocityRef, duration, Mathf.Infinity, delta );
|
|
}
|
|
|
|
public static Quaternion SmoothDampRotation( this Quaternion current, Quaternion target, ref Quaternion velocityRef, float duration, float maxSpeed, float delta )
|
|
{
|
|
float dot = Quaternion.Dot( current, target );
|
|
float sign = dot > 0f ? 1f : -1f;
|
|
target.x *= sign;
|
|
target.y *= sign;
|
|
target.z *= sign;
|
|
target.w *= sign;
|
|
|
|
Vector4 smoothVal = new Vector4(
|
|
Mathf.SmoothDamp( current.x, target.x, ref velocityRef.x, duration, maxSpeed, delta ),
|
|
Mathf.SmoothDamp( current.y, target.y, ref velocityRef.y, duration, maxSpeed, delta ),
|
|
Mathf.SmoothDamp( current.z, target.z, ref velocityRef.z, duration, maxSpeed, delta ),
|
|
Mathf.SmoothDamp( current.w, target.w, ref velocityRef.w, duration, maxSpeed, delta ) ).normalized;
|
|
|
|
Vector4 correction = Vector4.Project( new Vector4( velocityRef.x, velocityRef.y, velocityRef.z, velocityRef.w ), smoothVal );
|
|
velocityRef.x -= correction.x;
|
|
velocityRef.y -= correction.y;
|
|
velocityRef.z -= correction.z;
|
|
velocityRef.w -= correction.w;
|
|
|
|
return new Quaternion( smoothVal.x, smoothVal.y, smoothVal.z, smoothVal.w );
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Helper Maths
|
|
|
|
public static float PerlinNoise3D( float x, float y, float z )
|
|
{
|
|
y += 1;
|
|
z += 2;
|
|
float xy = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( x, y ) );
|
|
float xz = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( x, z ) );
|
|
float yz = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( y, z ) );
|
|
float yx = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( y, x ) );
|
|
float zx = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( z, x ) );
|
|
float zy = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( z, y ) );
|
|
|
|
return xy * xz * yz * yx * zx * zy;
|
|
}
|
|
|
|
public static float PerlinNoise3D( Vector3 pos )
|
|
{
|
|
return PerlinNoise3D( pos.x, pos.y, pos.z );
|
|
}
|
|
|
|
public static bool SameDirection( this float a, float b )
|
|
{
|
|
return ( a > 0 && b > 0 ) || ( a < 0f && b < 0f );
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Using Halton Sequence to choose propabilistic coords for example for raycasts
|
|
/// !!!! baseV must be greater than one > 1
|
|
/// </summary>
|
|
public static float PointDisperse01( int index, int baseV = 2 )
|
|
{
|
|
float sum = 0f; float functionV = 1f / baseV; int i = index;
|
|
while( i > 0 ) { sum += functionV * ( i % baseV ); i = Mathf.FloorToInt( i / baseV ); functionV /= baseV; }
|
|
return sum;
|
|
}
|
|
|
|
public static float PointDisperse( int index, int baseV = 2 )
|
|
{
|
|
float sum = 0f; float functionV = 1f / baseV; int i = index;
|
|
while( i > 0 ) { sum += functionV * ( i % baseV ); i = Mathf.FloorToInt( i / baseV ); functionV /= baseV; }
|
|
return ( sum - 0.5f );
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Matrixes
|
|
|
|
|
|
/// <summary>
|
|
/// Getting scalling axis lossy scale value if object changes it's size by transform scale
|
|
/// </summary>
|
|
public static float GetScaler( this Transform transform )
|
|
{
|
|
float scaler;
|
|
if( transform.lossyScale.x > transform.lossyScale.y )
|
|
{
|
|
if( transform.lossyScale.y > transform.lossyScale.z )
|
|
scaler = transform.lossyScale.y;
|
|
else
|
|
scaler = transform.lossyScale.z;
|
|
}
|
|
else
|
|
scaler = transform.lossyScale.x;
|
|
|
|
return scaler;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extracting position from Matrix
|
|
/// </summary>
|
|
public static Vector3 PosFromMatrix( this Matrix4x4 m )
|
|
{
|
|
return m.GetColumn( 3 );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extracting rotation from Matrix
|
|
/// </summary>
|
|
public static Quaternion RotFromMatrix( this Matrix4x4 m )
|
|
{
|
|
return Quaternion.LookRotation( m.GetColumn( 2 ), m.GetColumn( 1 ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extracting scale from Matrix
|
|
/// </summary>
|
|
public static Vector3 ScaleFromMatrix( this Matrix4x4 m )
|
|
{
|
|
return new Vector3
|
|
(
|
|
m.GetColumn( 0 ).magnitude,
|
|
m.GetColumn( 1 ).magnitude,
|
|
m.GetColumn( 2 ).magnitude
|
|
);
|
|
}
|
|
|
|
public static Bounds TransformBounding( Bounds b, Transform by )
|
|
{
|
|
return TransformBounding( b, by.localToWorldMatrix );
|
|
}
|
|
|
|
public static Bounds TransformBounding( Bounds b, Matrix4x4 mx )
|
|
{
|
|
Vector3 min = mx.MultiplyPoint( b.min );
|
|
Vector3 max = mx.MultiplyPoint( b.max );
|
|
|
|
Vector3 minB = mx.MultiplyPoint( new Vector3( b.max.x, b.center.y, b.min.z ) );
|
|
Vector3 maxB = mx.MultiplyPoint( new Vector3( b.min.x, b.center.y, b.max.z ) );
|
|
|
|
b = new Bounds( min, Vector3.zero );
|
|
|
|
b.Encapsulate( min );
|
|
b.Encapsulate( max );
|
|
b.Encapsulate( minB );
|
|
b.Encapsulate( maxB );
|
|
|
|
return b;
|
|
}
|
|
|
|
#if UNITY_2018_4_OR_NEWER
|
|
public static Bounds RotateBoundsByMatrix( this Bounds b, Quaternion rotation )
|
|
{
|
|
if( QIsZero( rotation ) ) return b;
|
|
|
|
Matrix4x4 rot = Matrix4x4.Rotate( rotation );
|
|
|
|
Bounds newB = new Bounds();
|
|
Vector3 fr1 = rot.MultiplyPoint( new Vector3( b.max.x, b.min.y, b.max.z ) );
|
|
Vector3 br1 = rot.MultiplyPoint( new Vector3( b.max.x, b.min.y, b.min.z ) );
|
|
Vector3 bl1 = rot.MultiplyPoint( new Vector3( b.min.x, b.min.y, b.min.z ) );
|
|
Vector3 fl1 = rot.MultiplyPoint( new Vector3( b.min.x, b.min.y, b.max.z ) );
|
|
newB.Encapsulate( fr1 );
|
|
newB.Encapsulate( br1 );
|
|
newB.Encapsulate( bl1 );
|
|
newB.Encapsulate( fl1 );
|
|
|
|
Vector3 fr = rot.MultiplyPoint( new Vector3( b.max.x, b.max.y, b.max.z ) );
|
|
Vector3 br = rot.MultiplyPoint( new Vector3( b.max.x, b.max.y, b.min.z ) );
|
|
Vector3 bl = rot.MultiplyPoint( new Vector3( b.min.x, b.max.y, b.min.z ) );
|
|
Vector3 fl = rot.MultiplyPoint( new Vector3( b.min.x, b.max.y, b.max.z ) );
|
|
newB.Encapsulate( fr );
|
|
newB.Encapsulate( br );
|
|
newB.Encapsulate( bl );
|
|
newB.Encapsulate( fl );
|
|
|
|
return newB;
|
|
}
|
|
#else
|
|
public static Bounds RotateBoundsByMatrix(this Bounds b, Quaternion rotation)
|
|
{
|
|
if (QIsZero(rotation)) return b;
|
|
|
|
Matrix4x4 rot = Matrix4x4.Rotate(rotation);
|
|
|
|
Bounds newB = new Bounds();
|
|
Vector3 fr1 = rot.MultiplyPoint(new Vector3(b.max.x, b.min.y, b.max.z));
|
|
Vector3 br1 = rot.MultiplyPoint(new Vector3(b.max.x, b.min.y, b.min.z));
|
|
Vector3 bl1 = rot.MultiplyPoint(new Vector3(b.min.x, b.min.y, b.min.z));
|
|
Vector3 fl1 = rot.MultiplyPoint(new Vector3(b.min.x, b.min.y, b.max.z));
|
|
newB.Encapsulate(fr1);
|
|
newB.Encapsulate(br1);
|
|
newB.Encapsulate(bl1);
|
|
newB.Encapsulate(fl1);
|
|
|
|
Vector3 fr = rot.MultiplyPoint(new Vector3(b.max.x, b.max.y, b.max.z));
|
|
Vector3 br = rot.MultiplyPoint(new Vector3(b.max.x, b.max.y, b.min.z));
|
|
Vector3 bl = rot.MultiplyPoint(new Vector3(b.min.x, b.max.y, b.min.z));
|
|
Vector3 fl = rot.MultiplyPoint(new Vector3(b.min.x, b.max.y, b.max.z));
|
|
newB.Encapsulate(fr);
|
|
newB.Encapsulate(br);
|
|
newB.Encapsulate(bl);
|
|
newB.Encapsulate(fl);
|
|
|
|
return newB;
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Roatate by 90, not precise
|
|
/// </summary>
|
|
public static Bounds RotateLocalBounds( this Bounds b, Quaternion rotation )
|
|
{
|
|
float angle = Quaternion.Angle( rotation, Quaternion.identity );
|
|
|
|
if( angle > 45 && angle < 135 ) b.size = new Vector3( b.size.z, b.size.y, b.size.x );
|
|
if( angle < 315 && angle > 225 ) b.size = new Vector3( b.size.z, b.size.y, b.size.x );
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
public static int[] GetLayermaskValues( int mask, int optionsCount )
|
|
{
|
|
System.Collections.Generic.List<int> masks = new System.Collections.Generic.List<int>();
|
|
|
|
for( int i = 0; i < optionsCount; i++ )
|
|
{
|
|
int layer = 1 << i;
|
|
if( ( mask & layer ) != 0 ) masks.Add( i );
|
|
}
|
|
|
|
return masks.ToArray();
|
|
}
|
|
|
|
|
|
#region Physical Materials Stuff
|
|
|
|
|
|
public static LayerMask GetLayerMaskUsingPhysicsProjectSettingsMatrix( int maskForLayer )
|
|
{
|
|
LayerMask layerMask = 0;
|
|
|
|
for( int i = 0; i < 32; i++ )
|
|
{
|
|
if( !Physics.GetIgnoreLayerCollision( maskForLayer, i ) ) layerMask = layerMask | 1 << i;
|
|
}
|
|
|
|
return layerMask;
|
|
}
|
|
|
|
public static PhysicsMaterial PMSliding
|
|
{
|
|
get
|
|
{
|
|
if( _slidingMat ) return _slidingMat;
|
|
else
|
|
{
|
|
_slidingMat = new PhysicsMaterial( "Slide" );
|
|
_slidingMat.frictionCombine = PhysicsMaterialCombine.Minimum;
|
|
_slidingMat.dynamicFriction = 0f;
|
|
_slidingMat.staticFriction = 0f;
|
|
return _slidingMat;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static PhysicsMaterial _slidingMat;
|
|
public static PhysicsMaterial PMFrict
|
|
{
|
|
get
|
|
{
|
|
if( _frictMat ) return _frictMat;
|
|
else
|
|
{
|
|
_frictMat = new PhysicsMaterial( "Friction" );
|
|
_frictMat.frictionCombine = PhysicsMaterialCombine.Maximum;
|
|
_frictMat.dynamicFriction = 10f;
|
|
_frictMat.staticFriction = 10f;
|
|
return _frictMat;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static PhysicsMaterial _frictMat;
|
|
|
|
|
|
public static PhysicsMaterial2D PMSliding2D
|
|
{
|
|
get
|
|
{
|
|
if( _slidingMat2D ) return _slidingMat2D;
|
|
else
|
|
{
|
|
_slidingMat2D = new PhysicsMaterial2D( "Slide2D" );
|
|
_slidingMat2D.friction = 0f;
|
|
return _slidingMat2D;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static PhysicsMaterial2D _slidingMat2D;
|
|
|
|
public static PhysicsMaterial2D PMFrict2D
|
|
{
|
|
get
|
|
{
|
|
if( _frictMat2D ) return _frictMat2D;
|
|
else
|
|
{
|
|
_frictMat2D = new PhysicsMaterial2D( "Friction2D" );
|
|
_frictMat2D.friction = 5f;
|
|
return _frictMat2D;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static PhysicsMaterial2D _frictMat2D;
|
|
|
|
#endregion
|
|
|
|
|
|
#region Extra Quick Trigonometrics and 2D
|
|
|
|
|
|
public static float DistanceTo_2D( Vector3 aPos, Vector3 bPos )
|
|
{
|
|
return Vector2.Distance( new Vector2( aPos.x, aPos.z ), new Vector2( bPos.x, bPos.z ) );
|
|
}
|
|
|
|
public static float DistanceTo_2DSqrt( Vector3 aPos, Vector3 bPos )
|
|
{
|
|
return Vector2.SqrMagnitude( new Vector2( aPos.x, aPos.z ) - new Vector2( bPos.x, bPos.z ) );
|
|
}
|
|
|
|
public static Vector2 GetAngleDirection2D( float angle )
|
|
{
|
|
float degToRad = angle * Mathf.Deg2Rad;
|
|
return new Vector2( Mathf.Sin( degToRad ), Mathf.Cos( degToRad ) );
|
|
}
|
|
|
|
public static Vector3 GetAngleDirection( float angle )
|
|
{
|
|
float degToRad = angle * Mathf.Deg2Rad;
|
|
return new Vector3( Mathf.Sin( degToRad ), 0f, Mathf.Cos( degToRad ) );
|
|
}
|
|
|
|
public static Vector3 GetAngleDirectionXZ( float angle )
|
|
{
|
|
return GetAngleDirection( angle );
|
|
}
|
|
public static Vector3 GetAngleDirectionZX( float angle )
|
|
{
|
|
float degToRad = angle * Mathf.Deg2Rad;
|
|
return new Vector3( Mathf.Cos( degToRad ), 0f, Mathf.Sin( degToRad ) );
|
|
}
|
|
public static Vector3 GetAngleDirectionXY( float angle, float radOffset = 0f, float secAxisRadOffset = 0f )
|
|
{
|
|
float degToRad = angle * Mathf.Deg2Rad;
|
|
return new Vector3( Mathf.Sin( degToRad + radOffset ), Mathf.Cos( degToRad + secAxisRadOffset ), 0f );
|
|
}
|
|
public static Vector3 GetAngleDirectionYX( float angle, float firstAxisRadOffset = 0f, float secAxisRadOffset = 0f )
|
|
{
|
|
float degToRad = angle * Mathf.Deg2Rad;
|
|
return new Vector3( Mathf.Cos( degToRad + secAxisRadOffset ), Mathf.Sin( degToRad + firstAxisRadOffset ), 0f );
|
|
}
|
|
public static Vector3 GetAngleDirectionYZ( float angle )
|
|
{
|
|
float degToRad = angle * Mathf.Deg2Rad;
|
|
return new Vector3( 0f, Mathf.Sin( degToRad ), Mathf.Cos( degToRad ) );
|
|
}
|
|
public static Vector3 GetAngleDirectionZY( float angle )
|
|
{
|
|
float degToRad = angle * Mathf.Deg2Rad;
|
|
return new Vector3( 0f, Mathf.Cos( degToRad ), Mathf.Sin( degToRad ) );
|
|
}
|
|
|
|
public static Vector3 V2ToV3TopDown( Vector2 v )
|
|
{
|
|
return new Vector3( v.x, 0f, v.y );
|
|
}
|
|
|
|
/// <summary> new V2(a.x, a.z) </summary>
|
|
public static Vector2 V3ToV2( Vector3 a )
|
|
{
|
|
return new Vector2( a.x, a.z );
|
|
}
|
|
|
|
public static Vector2 V3TopDownDiff( Vector3 target, Vector3 me )
|
|
{
|
|
return V3ToV2( target ) - V3ToV2( me );
|
|
}
|
|
|
|
/// <summary> Reads x and z value </summary>
|
|
public static float GetAngleDeg( Vector3 v )
|
|
{
|
|
return GetAngleDeg( v.x, v.z );
|
|
}
|
|
public static float GetAngleDeg( Vector2 v )
|
|
{
|
|
return GetAngleDeg( v.x, v.y );
|
|
}
|
|
public static float GetAngleDeg( float x, float z )
|
|
{
|
|
return GetAngleRad( x, z ) * Mathf.Rad2Deg;
|
|
}
|
|
public static float GetAngleRad( float x, float z )
|
|
{
|
|
return Mathf.Atan2( x, z );
|
|
}
|
|
|
|
public static float Rnd( float val, int dec = 0 )
|
|
{
|
|
if( dec <= 0 ) return Mathf.Round( val );
|
|
return (float)System.Math.Round( val, dec );
|
|
}
|
|
|
|
/// <summary> Cheap distance calculation 2D </summary>
|
|
internal static float ManhattanTopDown2D( Vector3 probePos, Vector3 worldPosition )
|
|
{
|
|
float d1 = probePos.x - worldPosition.x;
|
|
if( d1 < 0 ) d1 = -d1;
|
|
|
|
float d2 = probePos.z - worldPosition.z;
|
|
if( d2 < 0 ) d2 = -d2;
|
|
|
|
return d1 + d2;
|
|
}
|
|
|
|
|
|
/// <summary> Cheap check if position is contained in square </summary>
|
|
internal static bool IsInSqureBounds2D( Vector3 probePos, Vector3 boundsPos, float boundsRange )
|
|
{
|
|
if( boundsRange <= 0f ) return false;
|
|
|
|
if( probePos.x > boundsPos.x - boundsRange && probePos.x < boundsPos.x + boundsRange &&
|
|
probePos.z > boundsPos.z - boundsRange && probePos.z < boundsPos.z + boundsRange )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
internal static bool IsInSqureBounds2D( Vector3 boundsAPos, float boundsAHalfRange, Vector3 boundsBPos, float boundsBHRange )
|
|
{
|
|
return ( boundsAPos.x - boundsAHalfRange <= boundsBPos.x + boundsBHRange ) && ( boundsAPos.x + boundsAHalfRange >= boundsBPos.x - boundsBHRange ) &&
|
|
( boundsAPos.z - boundsAHalfRange <= boundsBPos.z + boundsBHRange ) && ( boundsAPos.z + boundsAHalfRange >= boundsBPos.z - boundsBHRange );
|
|
}
|
|
|
|
internal static Vector3 GetDirectionTowards( Vector3 me, Vector3 target )
|
|
{
|
|
return new Vector3( target.x - me.x, 0f, target.z - me.z );
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
} |