198 lines
No EOL
5.5 KiB
C#
198 lines
No EOL
5.5 KiB
C#
using System;
|
|
|
|
namespace snake;
|
|
|
|
public static class Maths
|
|
{
|
|
public static int u_length(int s_len) => (1 + s_len) * 2;
|
|
public static int s_length(int u_len) => (u_len - 1) / 2;
|
|
|
|
public static int u_index(int s_index, int s_len) => s_len + s_index;
|
|
public static int s_index(int u_index, int u_len) => u_index - u_len;
|
|
|
|
public static float u_scalar(float s_scalar) => (1.0f + s_scalar) * 0.5f;
|
|
public static float s_scalar(float u_scalar) => (u_scalar * 2.0f) - 1.0f;
|
|
|
|
public static int min(int a, int b) => Math.Min(a, b);
|
|
public static float min(float a, float b) => Math.Min(a, b);
|
|
public static double min(double a, double b) => Math.Min(a, b);
|
|
public static int max(int a, int b) => Math.Max(a, b);
|
|
public static float max(float a, float b) => Math.Max(a, b);
|
|
public static double max(double a, double b) => Math.Max(a, b);
|
|
|
|
public static float u_clamp(float x) => min(1.0f, max(0.0f, x));
|
|
public static double u_clamp(double x) => min(1.0, max(0.0, x));
|
|
public static float s_clamp(float x) => min(1.0f, max(-1.0f, x));
|
|
public static double s_clamp(double x) => min(1.0, max(-1.0, x));
|
|
|
|
public static int abs(int x) => Math.Abs(x);
|
|
public static float abs(float x) => Math.Abs(x);
|
|
public static double abs(double x) => Math.Abs(x);
|
|
|
|
public static int sign(float x) => x < 0 ? -1 : +1;
|
|
|
|
public static float round(float x) => MathF.Round(x);
|
|
// public static int roundi(float value) => MathF.Round(value)
|
|
|
|
public static float precision(float x, float p)
|
|
=> round(x * p) / p;
|
|
|
|
public static float smooth_start(float t) => (t * t * t);
|
|
public static float smooth_stop(float t)
|
|
{
|
|
float s = sign(t);
|
|
return (s - ((s - t) * (s - t) * (s - t)));
|
|
}
|
|
|
|
public static float lerp(float a, float b, float t) => a + (b - a) * t;
|
|
}
|
|
|
|
public class DeltaBool
|
|
{
|
|
public int delta = 0;
|
|
public bool state = false;
|
|
|
|
public DeltaBool(bool state)
|
|
{
|
|
this.state = state;
|
|
}
|
|
|
|
public void Step(bool next_state)
|
|
{
|
|
delta = 0;
|
|
if (next_state != state)
|
|
{
|
|
delta = next_state ? +1 : -1;
|
|
state = next_state;
|
|
}
|
|
}
|
|
}
|
|
|
|
public struct XYZi
|
|
{
|
|
public int x { get; set; }
|
|
public int y { get; set; }
|
|
public int z { get; set; }
|
|
|
|
public XYZi(int x, int y, int z)
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
}
|
|
|
|
public static XYZi operator -(XYZi a, XYZi b)
|
|
=> new(a.x - b.x, a.y - b.y, a.z - b.z);
|
|
public static XYZi operator +(XYZi a, XYZi b)
|
|
=> new(a.x + b.x, a.y + b.y, a.z + b.z);
|
|
|
|
public static bool operator ==(XYZi a, XYZi b)
|
|
=> (a.x == b.x && a.y == b.y && a.z == b.z);
|
|
public static bool operator !=(XYZi a, XYZi b)
|
|
=> (a.x != b.x || a.y != b.y || a.z != b.z);
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj is XYZi other)
|
|
{
|
|
return this == other;
|
|
}
|
|
return false;
|
|
}
|
|
public override int GetHashCode()
|
|
=> HashCode.Combine(x, y, z);
|
|
|
|
public StereoKit.Vec3 ToVec3
|
|
=> StereoKit.V.XYZ(x, y, z);
|
|
|
|
public override string ToString()
|
|
=> string.Format("[{0:0.##}, {1:0.##}, {2:0.##}]", x, y, z);
|
|
}
|
|
|
|
// public class SignedArray<T>
|
|
|
|
public class SpatialArray<T>
|
|
{
|
|
private T[,,] u_array;
|
|
private T default_value;
|
|
private int x_slen; // length past signed zero
|
|
private int y_slen;
|
|
private int z_slen;
|
|
public int Xslen => x_slen;
|
|
public int Yslen => y_slen;
|
|
public int Zslen => z_slen;
|
|
|
|
public SpatialArray(
|
|
int x_slen,
|
|
int y_slen,
|
|
int z_slen,
|
|
T default_value = default(T)
|
|
)
|
|
{
|
|
this.u_array = new T[
|
|
Maths.u_length(x_slen),
|
|
Maths.u_length(y_slen),
|
|
Maths.u_length(z_slen)
|
|
];
|
|
this.x_slen = x_slen;
|
|
this.y_slen = y_slen;
|
|
this.z_slen = z_slen;
|
|
this.default_value = default_value;
|
|
|
|
// initialize the arrays with the default value
|
|
Clear(default_value);
|
|
}
|
|
|
|
public T this[XYZi sv]
|
|
{
|
|
get
|
|
{
|
|
if (InRange(sv))
|
|
{
|
|
return u_array[
|
|
Maths.u_index(sv.x, x_slen),
|
|
Maths.u_index(sv.y, y_slen),
|
|
Maths.u_index(sv.z, z_slen)
|
|
];
|
|
}
|
|
else
|
|
{
|
|
return default_value;
|
|
}
|
|
}
|
|
set
|
|
{
|
|
if (InRange(sv))
|
|
{
|
|
u_array[
|
|
Maths.u_index(sv.x, x_slen),
|
|
Maths.u_index(sv.y, y_slen),
|
|
Maths.u_index(sv.z, z_slen)
|
|
] = value;
|
|
}
|
|
else
|
|
{
|
|
// throw new IndexOutOfRangeException("set index is out of range.");
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool InX(int sx) => !(Math.Abs(sx) > x_slen);
|
|
public bool InY(int sy) => !(Math.Abs(sy) > y_slen);
|
|
public bool InZ(int sz) => !(Math.Abs(sz) > z_slen);
|
|
public bool InRange(int sx, int sy, int sz) => InX(sx) && InY(sy) && InZ(sz);
|
|
public bool InRange(XYZi sv) => InRange(sv.x, sv.y, sv.z);
|
|
|
|
public void Clear(T value)
|
|
{
|
|
for (int ux = 0; ux < u_array.GetLength(0); ux++)
|
|
{
|
|
for (int uy = 0; uy < u_array.GetLength(1); uy++)
|
|
{
|
|
for (int uz = 0; uz < u_array.GetLength(2); uz++)
|
|
{
|
|
u_array[ux, uy, uz] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |