ZeroVR/ZeroPacientVR/Assets/CodeRespawn/DungeonArchitect/ThirdParty/SharpNav/MathHelper.cs

272 lines
8.2 KiB
C#

// Copyright (c) 2013-2015 Robert Rouhani <robert.rouhani@gmail.com> and other contributors (see CONTRIBUTORS file).
// Licensed under the MIT License - https://raw.github.com/Robmaister/SharpNav/master/LICENSE
using SharpNav.Geometry;
#if MONOGAME
using Vector3 = Microsoft.Xna.Framework.Vector3;
#elif OPENTK
using Vector3 = OpenTK.Vector3;
#elif SHARPDX
using Vector3 = SharpDX.Vector3;
#endif
namespace SharpNav
{
/// <summary>
/// A class where all the small, miscellaneous math functions are stored.
/// </summary>
internal static class MathHelper
{
/// <summary>
/// Clamps an integer value to be within a specified range.
/// </summary>
/// <param name="val">The value to clamp.</param>
/// <param name="min">The inclusive minimum of the range.</param>
/// <param name="max">The inclusive maximum of the range.</param>
/// <returns>The clamped value.</returns>
internal static int Clamp(int val, int min, int max)
{
return val < min ? min : (val > max ? max : val);
}
/// <summary>
/// Clamps an integer value to be within a specified range.
/// </summary>
/// <param name="val">The value to clamp.</param>
/// <param name="min">The inclusive minimum of the range.</param>
/// <param name="max">The inclusive maximum of the range.</param>
internal static void Clamp(ref int val, int min, int max)
{
val = val < min ? min : (val > max ? max : val);
}
/// <summary>
/// Clamps an integer value to be within a specified range.
/// </summary>
/// <param name="val">The value to clamp.</param>
/// <param name="min">The inclusive minimum of the range.</param>
/// <param name="max">The inclusive maximum of the range.</param>
/// <returns>The clamped value.</returns>
internal static uint Clamp(uint val, uint min, uint max)
{
return val < min ? min : (val > max ? max : val);
}
/// <summary>
/// Clamps an integer value to be within a specified range.
/// </summary>
/// <param name="val">The value to clamp.</param>
/// <param name="min">The inclusive minimum of the range.</param>
/// <param name="max">The inclusive maximum of the range.</param>
internal static void Clamp(ref uint val, uint min, uint max)
{
val = val < min ? min : (val > max ? max : val);
}
/// <summary>
/// Clamps an integer value to be within a specified range.
/// </summary>
/// <param name="val">The value to clamp.</param>
/// <param name="min">The inclusive minimum of the range.</param>
/// <param name="max">The inclusive maximum of the range.</param>
/// <returns>The clamped value.</returns>
internal static float Clamp(float val, float min, float max)
{
return val < min ? min : (val > max ? max : val);
}
/// <summary>
/// Clamps an integer value to be within a specified range.
/// </summary>
/// <param name="val">The value to clamp.</param>
/// <param name="min">The inclusive minimum of the range.</param>
/// <param name="max">The inclusive maximum of the range.</param>
internal static void Clamp(ref float val, float min, float max)
{
val = val < min ? min : (val > max ? max : val);
}
/// <summary>
/// Normalizes a value in a specified range to be between 0 and 1.
/// </summary>
/// <param name="t">The value</param>
/// <param name="t0">The lower bound of the range.</param>
/// <param name="t1">The upper bound of the range.</param>
/// <returns>A normalized value.</returns>
public static float Normalize(float t, float t0, float t1)
{
return MathHelper.Clamp((t - t0) / (t1 - t0), 0.0f, 1.0f);
}
/// <summary>
/// Calculates the next highest power of two.
/// </summary>
/// <remarks>
/// This is a minimal method meant to be fast. There is a known edge case where an input of 0 will output 0
/// instead of the mathematically correct value of 1. It will not be fixed.
/// </remarks>
/// <param name="v">A value.</param>
/// <returns>The next power of two after the value.</returns>
internal static int NextPowerOfTwo(int v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
/// <summary>
/// Calculates the next highest power of two.
/// </summary>
/// <remarks>
/// This is a minimal method meant to be fast. There is a known edge case where an input of 0 will output 0
/// instead of the mathematically correct value of 1. It will not be fixed.
/// </remarks>
/// <param name="v">A value.</param>
/// <returns>The next power of two after the value.</returns>
internal static uint NextPowerOfTwo(uint v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
/// <summary>
/// Calculates the binary logarithm of the input.
/// </summary>
/// <remarks>
/// Inputs 0 and below have undefined output.
/// </remarks>
/// <param name="v">A value.</param>
/// <returns>The binary logarithm of v.</returns>
internal static int Log2(int v)
{
int r;
int shift;
r = (v > 0xffff) ? 1 << 4 : 0 << 4;
v >>= r;
shift = (v > 0xff) ? 1 << 3 : 0 << 3;
v >>= shift;
r |= shift;
shift = (v > 0xf) ? 1 << 2 : 0 << 2;
v >>= shift;
r |= shift;
shift = (v > 0x3) ? 1 << 1 : 0 << 1;
v >>= shift;
r |= shift;
r |= v >> 1;
return r;
}
/// <summary>
/// Calculates the binary logarithm of the input.
/// </summary>
/// <remarks>
/// An input of 0 has an undefined output.
/// </remarks>
/// <param name="v">A value.</param>
/// <returns>The binary logarithm of v.</returns>
internal static uint Log2(uint v)
{
uint r;
int shift;
r = (uint)((v > 0xffff) ? 1 << 4 : 0 << 4);
v >>= (int)r;
shift = (v > 0xff) ? 1 << 3 : 0 << 3;
v >>= shift;
r |= (uint)shift;
shift = (v > 0xf) ? 1 << 2 : 0 << 2;
v >>= shift;
r |= (uint)shift;
shift = (v > 0x3) ? 1 << 1 : 0 << 1;
v >>= shift;
r |= (uint)shift;
r |= v >> 1;
return r;
}
/// <summary>
/// Clips a polygon to a plane using the Sutherland-Hodgman algorithm.
/// </summary>
/// <param name="inVertices">The input array of vertices.</param>
/// <param name="outVertices">The output array of vertices.</param>
/// <param name="numVerts">The number of vertices to read from the arrays.</param>
/// <param name="planeX">The clip plane's X component.</param>
/// <param name="planeZ">The clip plane's Z component.</param>
/// <param name="planeD">The clip plane's D component.</param>
/// <returns>The number of vertices stored in outVertices.</returns>
internal static int ClipPolygonToPlane(Vector3[] inVertices, Vector3[] outVertices, int numVerts, float planeX, float planeZ, float planeD)
{
float[] distances = new float[12];
return ClipPolygonToPlane(inVertices, outVertices, distances, numVerts, planeX, planeZ, planeD);
}
/// <summary>
/// Clips a polygon to a plane using the Sutherland-Hodgman algorithm.
/// </summary>
/// <param name="inVertices">The input array of vertices.</param>
/// <param name="outVertices">The output array of vertices.</param>
/// <param name="distances">A buffer that stores intermediate data</param>
/// <param name="numVerts">The number of vertices to read from the arrays.</param>
/// <param name="planeX">The clip plane's X component.</param>
/// <param name="planeZ">The clip plane's Z component.</param>
/// <param name="planeD">The clip plane's D component.</param>
/// <returns>The number of vertices stored in outVertices.</returns>
internal static int ClipPolygonToPlane(Vector3[] inVertices, Vector3[] outVertices, float[] distances, int numVerts, float planeX, float planeZ, float planeD)
{
for (int i = 0; i < numVerts; i++)
distances[i] = planeX * inVertices[i].X + planeZ * inVertices[i].Z + planeD;
int m = 0;
Vector3 temp;
for (int i = 0, j = numVerts - 1; i < numVerts; j = i, i++)
{
bool inj = distances[j] >= 0;
bool ini = distances[i] >= 0;
if (inj != ini)
{
float s = distances[j] / (distances[j] - distances[i]);
Vector3.Subtract(ref inVertices[i], ref inVertices[j], out temp);
Vector3.Multiply(ref temp, s, out temp);
Vector3.Add(ref inVertices[j], ref temp, out outVertices[m]);
m++;
}
if (ini)
{
outVertices[m] = inVertices[i];
m++;
}
}
return m;
}
}
}