using System; namespace Oni { internal struct Vector4 : IEquatable { public float X; public float Y; public float Z; public float W; public Vector4(float all) { X = all; Y = all; Z = all; W = all; } public Vector4(Vector3 v, float w) { X = v.X; Y = v.Y; Z = v.Z; W = w; } public Vector4(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; } public Vector3 XYZ { get { return new Vector3(X, Y, Z); } set { X = value.X; Y = value.Y; Z = value.Z; } } public static Vector4 operator +(Vector4 v1, Vector4 v2) { v1.X += v2.X; v1.Y += v2.Y; v1.Z += v2.Z; v1.W += v2.W; return v1; } public static Vector4 operator -(Vector4 v1, Vector4 v2) { v1.X -= v2.X; v1.Y -= v2.Y; v1.Z -= v2.Z; v1.W -= v2.W; return v1; } public static Vector4 operator *(Vector4 v, float s) { v.X *= s; v.Y *= s; v.Z *= s; v.W *= s; return v; } public static Vector4 operator *(float s, Vector4 v) => v * s; public static Vector4 operator /(Vector4 v, float s) => v * (1.0f / s); public static float Dot(Vector4 v1, Vector4 v2) => v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z + v1.W * v2.W; public static Vector4 Min(Vector4 v1, Vector4 v2) { v1.X = (v1.X < v2.X) ? v1.X : v2.X; v1.Y = (v1.Y < v2.Y) ? v1.Y : v2.Y; v1.Z = (v1.Z < v2.Z) ? v1.Z : v2.Z; v1.W = (v1.W < v2.W) ? v1.W : v2.W; return v1; } public static Vector4 Max(Vector4 v1, Vector4 v2) { v1.X = (v1.X > v2.X) ? v1.X : v2.X; v1.Y = (v1.Y > v2.Y) ? v1.Y : v2.Y; v1.Z = (v1.Z > v2.Z) ? v1.Z : v2.Z; v1.W = (v1.W > v2.W) ? v1.W : v2.W; return v1; } public static Vector4 Normalize(Vector4 v) => v * (1.0f / v.Length()); public float LengthSquared() => X * X + Y * Y + Z * Z + W * W; public float Length() => FMath.Sqrt(LengthSquared()); public static bool EqualsEps(Vector4 v1, Vector4 v2) { Vector4 d = v2 - v1; float dx = Math.Abs(d.X); float dy = Math.Abs(d.Y); float dz = Math.Abs(d.Z); float dw = Math.Abs(d.W); return (dx < 0.0001f && dy < 0.0001f && dz < 0.0001f && dw < 0.0001f); } public static bool operator ==(Vector4 v1, Vector4 v2) => v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z && v1.W == v2.W; public static bool operator !=(Vector4 v1, Vector4 v2) => v1.X != v2.X || v1.Y != v2.Y || v1.Z != v2.Z || v1.W != v2.W; public bool Equals(Vector4 other) => X == other.X && Y == other.Y && Z == other.Z && W == other.W; public override bool Equals(object obj) => obj is Vector4 && Equals((Vector4)obj); public override int GetHashCode() => X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode(); public override string ToString() => $"{{{X} {Y} {Z} {W}}}"; private static Vector4 zero = new Vector4(); private static Vector4 one = new Vector4(1.0f); private static Vector4 unitX = new Vector4(1.0f, 0.0f, 0.0f, 0.0f); private static Vector4 unitY = new Vector4(0.0f, 1.0f, 0.0f, 0.0f); private static Vector4 unitZ = new Vector4(0.0f, 0.0f, 1.0f, 0.0f); private static Vector4 unitW = new Vector4(0.0f, 0.0f, 0.0f, 1.0f); public static Vector4 Zero => zero; public static Vector4 One => one; public static Vector4 UnitX => unitX; public static Vector4 UnitY => unitY; public static Vector4 UnitZ => unitZ; public static Vector4 UnitW => unitW; } }