using System; using System.Runtime.InteropServices; namespace AssetStudio { [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct Quaternion : IEquatable, IYAMLExportable { public float X; public float Y; public float Z; public float W; public Quaternion(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; } public float this[int index] { get { switch (index) { case 0: return X; case 1: return Y; case 2: return Z; case 3: return W; default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!"); } } set { switch (index) { case 0: X = value; break; case 1: Y = value; break; case 2: Z = value; break; case 3: W = value; break; default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!"); } } } public override int GetHashCode() { return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1); } public override bool Equals(object other) { if (!(other is Quaternion)) return false; return Equals((Quaternion)other); } public bool Equals(Quaternion other) { return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W); } public static float Dot(Quaternion a, Quaternion b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W; } private static bool IsEqualUsingDot(float dot) { return dot > 1.0f - kEpsilon; } public static bool operator ==(Quaternion lhs, Quaternion rhs) { return IsEqualUsingDot(Dot(lhs, rhs)); } public static bool operator !=(Quaternion lhs, Quaternion rhs) { return !(lhs == rhs); } public YAMLNode ExportYAML() { var node = new YAMLMappingNode(); node.Style = MappingStyle.Flow; node.Add("x", X); node.Add("y", Y); node.Add("z", Z); node.Add("w", W); return node; } private const float kEpsilon = 0.000001F; } }