Files
2026-01-19 09:50:54 +09:00

173 lines
5.8 KiB
C#

using System;
namespace Nanomesh
{
public readonly struct Vector3F : IEquatable<Vector3F>, IInterpolable<Vector3F>
{
public readonly float x;
public readonly float y;
public readonly float z;
public Vector3F(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public Vector3F(float x, float y)
{
this.x = x;
this.y = y;
z = 0F;
}
public float this[int index]
{
get
{
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
default:
throw new IndexOutOfRangeException("Invalid Vector3F index!");
}
}
}
public override int GetHashCode()
{
return Vector3FComparer.Default.GetHashCode(this);
//return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2);
}
public override bool Equals(object other)
{
if (!(other is Vector3F))
{
return false;
}
return Equals((Vector3F)other);
}
public bool Equals(Vector3F other)
{
return Vector3FComparer.Default.Equals(this, other);
//return x == other.x && y == other.y && z == other.z;
}
public static Vector3F operator +(in Vector3F a, in Vector3F b) { return new Vector3F(a.x + b.x, a.y + b.y, a.z + b.z); }
public static Vector3F operator -(in Vector3F a, in Vector3F b) { return new Vector3F(a.x - b.x, a.y - b.y, a.z - b.z); }
public static Vector3F operator -(in Vector3F a) { return new Vector3F(-a.x, -a.y, -a.z); }
public static Vector3F operator *(in Vector3F a, float d) { return new Vector3F(a.x * d, a.y * d, a.z * d); }
public static Vector3F operator *(float d, in Vector3F a) { return new Vector3F(a.x * d, a.y * d, a.z * d); }
public static Vector3 operator *(double d, in Vector3F a) { return new Vector3(a.x * d, a.y * d, a.z * d); }
public static Vector3F operator /(in Vector3F a, float d) { return new Vector3F(MathUtils.DivideSafe(a.x, d), MathUtils.DivideSafe(a.y, d), MathUtils.DivideSafe(a.z, d)); }
public static bool operator ==(in Vector3F lhs, in Vector3F rhs)
{
float diff_x = lhs.x - rhs.x;
float diff_y = lhs.y - rhs.y;
float diff_z = lhs.z - rhs.z;
float sqrmag = diff_x * diff_x + diff_y * diff_y + diff_z * diff_z;
return sqrmag < MathUtils.EpsilonFloat;
}
public static bool operator !=(in Vector3F lhs, in Vector3F rhs)
{
return !(lhs == rhs);
}
public static Vector3F Cross(in Vector3F lhs, in Vector3F rhs)
{
return new Vector3F(
lhs.y * rhs.z - lhs.z * rhs.y,
lhs.z * rhs.x - lhs.x * rhs.z,
lhs.x * rhs.y - lhs.y * rhs.x);
}
public static float Dot(in Vector3F lhs, in Vector3F rhs)
{
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
}
public static Vector3F Normalize(in Vector3F value)
{
float mag = Magnitude(value);
return value / mag;
}
public Vector3F Normalized => Vector3F.Normalize(this);
public static float Distance(in Vector3F a, in Vector3F b)
{
float diff_x = a.x - b.x;
float diff_y = a.y - b.y;
float diff_z = a.z - b.z;
return MathF.Sqrt(diff_x * diff_x + diff_y * diff_y + diff_z * diff_z);
}
public static float Magnitude(in Vector3F vector)
{
return MathF.Sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
}
public float SqrMagnitude => x * x + y * y + z * z;
public static Vector3F Min(in Vector3F lhs, in Vector3F rhs)
{
return new Vector3F(MathF.Min(lhs.x, rhs.x), MathF.Min(lhs.y, rhs.y), MathF.Min(lhs.z, rhs.z));
}
public static Vector3F Max(in Vector3F lhs, in Vector3F rhs)
{
return new Vector3F(MathF.Max(lhs.x, rhs.x), MathF.Max(lhs.y, rhs.y), MathF.Max(lhs.z, rhs.z));
}
public static readonly Vector3F zeroVector = new Vector3F(0f, 0f, 0f);
public static readonly Vector3F oneVector = new Vector3F(1f, 1f, 1f);
public static readonly Vector3F positiveInfinityVector = new Vector3F(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
public static readonly Vector3F negativeInfinityVector = new Vector3F(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
public static Vector3F Zero => zeroVector;
public static Vector3F One => oneVector;
public static Vector3F PositiveInfinity => positiveInfinityVector;
public static Vector3F NegativeInfinity => negativeInfinityVector;
public static float AngleRadians(in Vector3F from, in Vector3F to)
{
float denominator = MathF.Sqrt(from.SqrMagnitude * to.SqrMagnitude);
if (denominator < 1e-15F)
{
return 0F;
}
float dot = MathF.Clamp(Dot(from, to) / denominator, -1F, 1F);
return MathF.Acos(dot);
}
public static float AngleDegrees(in Vector3F from, in Vector3F to)
{
return AngleRadians(from, to) / MathF.PI * 180f;
}
public override string ToString()
{
return $"{x}, {y}, {z}";
}
public Vector3F Interpolate(Vector3F other, double ratio) => (ratio * this + (1 - ratio) * other).Normalized;
}
}