/// <summary> /// copy constructor /// </summary> public qfloat(qfloat q) { this.x = q.x; this.y = q.y; this.z = q.z; this.w = q.w; }
/// <summary> /// Create a quaternion from two normalized axis (http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors) /// </summary> public qfloat(float3 u, float3 v) { var localW = float3.Cross(u, v); var dot = float3.Dot(u, v); var q = new qfloat(localW.x, localW.y, localW.z, 1f + dot).Normalized; this.x = q.x; this.y = q.y; this.z = q.z; this.w = q.w; }
/// <summary> /// Calculates a proper spherical interpolation between two quaternions (only works for normalized quaternions). /// </summary> public static qfloat Mix(qfloat x, qfloat y, float a) { var cosTheta = (double)Dot(x, y); if (cosTheta > 1 - float.Epsilon) { return(Lerp(x, y, a)); } else { var angle = System.Math.Acos((double)cosTheta); return((qfloat)((System.Math.Sin((1 - (double)a) * angle) * (qdouble)x + System.Math.Sin((double)a * angle) * (qdouble)y) / System.Math.Sin(angle))); } }
/// <summary> /// Calculates a proper spherical interpolation between two quaternions (only works for normalized quaternions). /// </summary> public static qfloat SLerp(qfloat x, qfloat y, float a) { var z = y; var cosTheta = (double)Dot(x, y); if (cosTheta < 0) { z = -y; cosTheta = -cosTheta; } if (cosTheta > 1 - float.Epsilon) { return(Lerp(x, z, a)); } else { var angle = System.Math.Acos((double)cosTheta); return((qfloat)((System.Math.Sin((1 - (double)a) * angle) * (qdouble)x + System.Math.Sin((double)a * angle) * (qdouble)z) / System.Math.Sin(angle))); } }
/// <summary> /// Tries to convert the string representation of the quaternion into a quaternion representation (using a designated separator), returns false if string was invalid. /// </summary> public static bool TryParse(string s, string sep, out qfloat result) { result = Zero; if (string.IsNullOrEmpty(s)) { return(false); } var kvp = s.Split(new[] { sep }, StringSplitOptions.None); if (kvp.Length != 4) { return(false); } float x = 0f, y = 0f, z = 0f, w = 0f; var ok = ((float.TryParse(kvp[0].Trim(), out x) && float.TryParse(kvp[1].Trim(), out y)) && (float.TryParse(kvp[2].Trim(), out z) && float.TryParse(kvp[3].Trim(), out w))); result = ok ? new qfloat(x, y, z, w) : Zero; return(ok); }
/// <summary> /// Returns a bool4 from component-wise application of Equal (lhs == rhs). /// </summary> public static bool4 Equal(qfloat lhs, float rhs) => new bool4(lhs.x == rhs, lhs.y == rhs, lhs.z == rhs, lhs.w == rhs);
/// <summary> /// Returns a bool4 from component-wise application of IsPositiveInfinity (float.IsPositiveInfinity(v)). /// </summary> public static bool4 IsPositiveInfinity(qfloat v) => new bool4(float.IsPositiveInfinity(v.x), float.IsPositiveInfinity(v.y), float.IsPositiveInfinity(v.z), float.IsPositiveInfinity(v.w));
/// <summary> /// Returns a bool4 from component-wise application of IsNaN (float.IsNaN(v)). /// </summary> public static bool4 IsNaN(qfloat v) => new bool4(float.IsNaN(v.x), float.IsNaN(v.y), float.IsNaN(v.z), float.IsNaN(v.w));
/// <summary> /// Returns a bool4 from component-wise application of IsFinite (!float.IsNaN(v) && !float.IsInfinity(v)). /// </summary> public static bool4 IsFinite(qfloat v) => new bool4(!float.IsNaN(v.x) && !float.IsInfinity(v.x), !float.IsNaN(v.y) && !float.IsInfinity(v.y), !float.IsNaN(v.z) && !float.IsInfinity(v.z), !float.IsNaN(v.w) && !float.IsInfinity(v.w));
/// <summary> /// Returns a bool4 from component-wise application of IsPositiveInfinity (float.IsPositiveInfinity(v)). /// </summary> public static bool4 IsPositiveInfinity(qfloat v) => qfloat.IsPositiveInfinity(v);
/// <summary> /// Returns a bool4 from component-wise application of GreaterThanEqual (lhs >= rhs). /// </summary> public static bool4 GreaterThanEqual(float lhs, qfloat rhs) => new bool4(lhs >= rhs.x, lhs >= rhs.y, lhs >= rhs.z, lhs >= rhs.w);
/// <summary> /// Returns a bool4 from component-wise application of GreaterThan (lhs > rhs). /// </summary> public static bool4 GreaterThan(qfloat lhs, float rhs) => new bool4(lhs.x > rhs, lhs.y > rhs, lhs.z > rhs, lhs.w > rhs);
/// <summary> /// Returns a bool4 from component-wise application of IsNaN (float.IsNaN(v)). /// </summary> public static bool4 IsNaN(qfloat v) => qfloat.IsNaN(v);
/// <summary> /// Returns the cross product between two quaternions. /// </summary> public static qfloat Cross(qfloat q1, qfloat q2) => new qfloat(q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x, q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z);
/// <summary> /// Returns the inner product (dot product, scalar product) of the two quaternions. /// </summary> public static float Dot(qfloat lhs, qfloat rhs) => ((lhs.x * rhs.x + lhs.y * rhs.y) + (lhs.z * rhs.z + lhs.w * rhs.w));
/// <summary> /// Tries to convert the string representation of the quaternion into a quaternion representation (using ', ' as a separator), returns false if string was invalid. /// </summary> public static bool TryParse(string s, out qfloat result) => TryParse(s, ", ", out result);
/// <summary> /// Returns true iff this equals rhs component-wise. /// </summary> public bool Equals(qfloat rhs) => ((x.Equals(rhs.x) && y.Equals(rhs.y)) && (z.Equals(rhs.z) && w.Equals(rhs.w)));
/// <summary> /// Returns a qfloat from component-wise application of Lerp (min * (1-a) + max * a). /// </summary> public static qfloat Lerp(float min, float max, qfloat a) => new qfloat(min * (1 - a.x) + max * a.x, min * (1 - a.y) + max * a.y, min * (1 - a.z) + max * a.z, min * (1 - a.w) + max * a.w);
/// <summary> /// Returns a bool4 from component-wise application of NotEqual (lhs != rhs). /// </summary> public static bool4 NotEqual(qfloat lhs, float rhs) => new bool4(lhs.x != rhs, lhs.y != rhs, lhs.z != rhs, lhs.w != rhs);
/// <summary> /// Returns a bool4 from component-wise application of LesserThanEqual (lhs <= rhs). /// </summary> public static bool4 LesserThanEqual(qfloat lhs, float rhs) => new bool4(lhs.x <= rhs, lhs.y <= rhs, lhs.z <= rhs, lhs.w <= rhs);
/// <summary> /// Returns a bool4 from component-wise application of NotEqual (lhs != rhs). /// </summary> public static bool4 NotEqual(float lhs, qfloat rhs) => new bool4(lhs != rhs.x, lhs != rhs.y, lhs != rhs.z, lhs != rhs.w);
/// <summary> /// Returns a qfloat from component-wise application of Lerp (min * (1-a) + max * a). /// </summary> public static qfloat Lerp(qfloat min, qfloat max, qfloat a) => new qfloat(min.x * (1 - a.x) + max.x * a.x, min.y * (1 - a.y) + max.y * a.y, min.z * (1 - a.z) + max.z * a.z, min.w * (1 - a.w) + max.w * a.w);
/// <summary> /// Returns a bool4 from component-wise application of GreaterThanEqual (lhs >= rhs). /// </summary> public static bool4 GreaterThanEqual(qfloat lhs, float rhs) => new bool4(lhs.x >= rhs, lhs.y >= rhs, lhs.z >= rhs, lhs.w >= rhs);
/// <summary> /// Returns a bool4 from component-wise application of IsFinite (!float.IsNaN(v) && !float.IsInfinity(v)). /// </summary> public static bool4 IsFinite(qfloat v) => qfloat.IsFinite(v);
/// <summary> /// Returns a bool4 from component-wise application of LesserThan (lhs < rhs). /// </summary> public static bool4 LesserThan(qfloat lhs, float rhs) => new bool4(lhs.x < rhs, lhs.y < rhs, lhs.z < rhs, lhs.w < rhs);
/// <summary> /// Creates a rotation matrix from a qfloat. /// </summary> public float3x3(qfloat q) : this(q.ToMat3) { }
/// <summary> /// Returns a bool4 from component-wise application of LesserThanEqual (lhs <= rhs). /// </summary> public static bool4 LesserThanEqual(float lhs, qfloat rhs) => new bool4(lhs <= rhs.x, lhs <= rhs.y, lhs <= rhs.z, lhs <= rhs.w);
/// <summary> /// Applies squad interpolation of these quaternions /// </summary> public static qfloat Squad(qfloat q1, qfloat q2, qfloat s1, qfloat s2, float h) => Mix(Mix(q1, q2, h), Mix(s1, s2, h), 2 * (1 - h) * h);
/// <summary> /// Returns a qfloat from component-wise application of Lerp (min * (1-a) + max * a). /// </summary> public static qfloat Lerp(qfloat min, qfloat max, float a) => new qfloat(min.x * (1 - a) + max.x * a, min.y * (1 - a) + max.y * a, min.z * (1 - a) + max.z * a, min.w * (1 - a) + max.w * a);
/// <summary> /// Returns a bool4 from component-wise application of IsInfinity (float.IsInfinity(v)). /// </summary> public static bool4 IsInfinity(qfloat v) => qfloat.IsInfinity(v);