dofdemo/src/Maths.cs
2024-11-29 13:06:28 -05:00

198 lines
No EOL
5.5 KiB
C#

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<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;
}
}
}
}
}