188 lines
5.9 KiB
C#
188 lines
5.9 KiB
C#
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Subsurface
|
|
{
|
|
static class MathUtils
|
|
{
|
|
public static Vector2 SmoothStep(Vector2 v1, Vector2 v2, float amount)
|
|
{
|
|
return new Vector2(
|
|
MathHelper.SmoothStep(v1.X, v2.X, amount),
|
|
MathHelper.SmoothStep(v1.Y, v2.Y, amount));
|
|
}
|
|
|
|
public static float Round(float value, float div)
|
|
{
|
|
return (float)Math.Floor(value / div) * div;
|
|
}
|
|
|
|
public static float RandomFloat(int minimum, int maximum)
|
|
{
|
|
return RandomFloat((float)minimum, (float)maximum);
|
|
}
|
|
|
|
public static float RandomFloat(float minimum, float maximum)
|
|
{
|
|
return (float)Game1.random.NextDouble() * (maximum - minimum) + minimum;
|
|
}
|
|
|
|
public static int RandomInt(int minimum, int maximum)
|
|
{
|
|
return Game1.random.Next(maximum - minimum) + minimum;
|
|
}
|
|
|
|
public static float RandomFloatLocal(float minimum, float maximum)
|
|
{
|
|
return (float)Game1.localRandom.NextDouble() * (maximum - minimum) + minimum;
|
|
}
|
|
|
|
public static int RandomIntLocal(int minimum, int maximum)
|
|
{
|
|
return Game1.localRandom.Next(maximum - minimum) + minimum;
|
|
}
|
|
|
|
public static float VectorToAngle(Vector2 vector)
|
|
{
|
|
return (float)Math.Atan2(vector.Y, vector.X);
|
|
}
|
|
|
|
public static float CurveAngle(float from, float to, float step)
|
|
{
|
|
// Ensure that 0 <= angle < 2pi for both "from" and "to"
|
|
while (from < 0)
|
|
from += MathHelper.TwoPi;
|
|
while (from >= MathHelper.TwoPi)
|
|
from -= MathHelper.TwoPi;
|
|
|
|
while (to < 0)
|
|
to += MathHelper.TwoPi;
|
|
while (to >= MathHelper.TwoPi)
|
|
to -= MathHelper.TwoPi;
|
|
|
|
if (Math.Abs(from - to) < MathHelper.Pi)
|
|
{
|
|
// The simple case - a straight lerp will do.
|
|
return MathHelper.Lerp(from, to, step);
|
|
}
|
|
|
|
// If we get here we have the more complex case.
|
|
// First, increment the lesser value to be greater.
|
|
if (from < to)
|
|
from += MathHelper.TwoPi;
|
|
else
|
|
to += MathHelper.TwoPi;
|
|
|
|
float retVal = MathHelper.Lerp(from, to, step);
|
|
|
|
// Now ensure the return value is between 0 and 2pi
|
|
if (retVal >= MathHelper.TwoPi)
|
|
retVal -= MathHelper.TwoPi;
|
|
return retVal;
|
|
}
|
|
|
|
public static float WrapAngleTwoPi(float angle)
|
|
{
|
|
// Ensure that 0 <= angle < 2pi for both "from" and "to"
|
|
while (angle < 0)
|
|
angle += MathHelper.TwoPi;
|
|
while (angle >= MathHelper.TwoPi)
|
|
angle -= MathHelper.TwoPi;
|
|
|
|
return angle;
|
|
}
|
|
|
|
public static float WrapAnglePi(float angle)
|
|
{
|
|
// Ensure that -pi <= angle < pi for both "from" and "to"
|
|
while (angle < -MathHelper.Pi)
|
|
angle += MathHelper.TwoPi;
|
|
while (angle >= MathHelper.Pi)
|
|
angle -= MathHelper.TwoPi;
|
|
|
|
return angle;
|
|
}
|
|
|
|
public static float GetShortestAngle(float from, float to)
|
|
{
|
|
// Ensure that 0 <= angle < 2pi for both "from" and "to"
|
|
from = WrapAngleTwoPi(from);
|
|
to = WrapAngleTwoPi(to);
|
|
|
|
if (Math.Abs(from - to) < MathHelper.Pi)
|
|
{
|
|
return to - from;
|
|
}
|
|
|
|
// If we get here we have the more complex case.
|
|
// First, increment the lesser value to be greater.
|
|
if (from < to)
|
|
from += MathHelper.TwoPi;
|
|
else
|
|
to += MathHelper.TwoPi;
|
|
|
|
return to - from;
|
|
}
|
|
|
|
/// <summary>
|
|
/// solves the angle opposite to side a (parameters: lengths of each side)
|
|
/// </summary>
|
|
public static float SolveTriangleSSS(float a, float b, float c)
|
|
{
|
|
float A = (float)Math.Acos((b * b + c * c - a * a) / (2 * b * c));
|
|
|
|
if (float.IsNaN(A)) A = 1.0f;
|
|
|
|
return A;
|
|
}
|
|
|
|
public static byte AngleToByte(float angle)
|
|
{
|
|
angle = WrapAngleTwoPi(angle);
|
|
angle = angle * (255.0f / MathHelper.TwoPi);
|
|
return Convert.ToByte(angle);
|
|
}
|
|
|
|
public static float ByteToAngle(byte b)
|
|
{
|
|
float angle = (float)b;
|
|
angle = angle * (MathHelper.TwoPi / 255.0f);
|
|
return angle;
|
|
}
|
|
}
|
|
|
|
class CompareCCW : IComparer<Vector2>
|
|
{
|
|
private Vector2 center;
|
|
|
|
public CompareCCW(Vector2 center)
|
|
{
|
|
this.center = center;
|
|
}
|
|
public int Compare(Vector2 a, Vector2 b)
|
|
{
|
|
if (a.X - center.X >= 0 && b.X - center.X < 0) return -1;
|
|
if (a.X - center.X < 0 && b.X - center.X >= 0) return 1;
|
|
if (a.X - center.X == 0 && b.X - center.X == 0)
|
|
{
|
|
if (a.Y - center.Y >= 0 || b.Y - center.Y >= 0) return Math.Sign(b.Y - a.Y);
|
|
return Math.Sign(a.Y - b.Y);
|
|
}
|
|
|
|
// compute the cross product of vectors (center -> a) x (center -> b)
|
|
float det = (a.X - center.X) * (b.Y - center.Y) - (b.X - center.X) * (a.Y - center.Y);
|
|
if (det < 0) return -1;
|
|
if (det > 0) return 1;
|
|
|
|
// points a and b are on the same line from the center
|
|
// check which point is closer to the center
|
|
float d1 = (a.X - center.X) * (a.X - center.X) + (a.Y - center.Y) * (a.Y - center.Y);
|
|
float d2 = (b.X - center.X) * (b.X - center.X) + (b.Y - center.Y) * (b.Y - center.Y);
|
|
return Math.Sign(d2 - d1);
|
|
}
|
|
}
|
|
}
|