using System; namespace slash; 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, float cap = 1.0f) => min(cap, max(0.0f, x)); public static double u_clamp(double x, double cap = 1.0) => min(cap, max(0.0, x)); public static float s_clamp(float x, float cap = 1.0f) => min(cap, max(-cap, x)); public static double s_clamp(double x, double cap = 1.0) => min(cap, max(-cap, 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 public class SpatialArray { 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; } } } } }