コード例 #1
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        // from http://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
        private static THVector3 ToEulerRad(THQuaternion rotation)
        {
            float     sqw  = rotation.w * rotation.w;
            float     sqx  = rotation.x * rotation.x;
            float     sqy  = rotation.y * rotation.y;
            float     sqz  = rotation.z * rotation.z;
            float     unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
            float     test = rotation.x * rotation.w - rotation.y * rotation.z;
            THVector3 v;

            if (test > 0.4995f * unit)
            { // singularity at north pole
                v.y = 2f * Atan2(rotation.y, rotation.x);
                v.x = UnityEngine.Mathf.PI / 2;
                v.z = 0;
                return(NormalizeAngles(v * Rad2Deg));
            }
            if (test < -0.4995f * unit)
            { // singularity at south pole
                v.y = -2f * Atan2(rotation.y, rotation.x);
                v.x = -UnityEngine.Mathf.PI / 2;
                v.z = 0;
                return(NormalizeAngles(v * Rad2Deg));
            }
            THQuaternion q = new THQuaternion(rotation.w, rotation.z, rotation.x, rotation.y);

            v.y = (float)System.Math.Atan2(2f * q.x * q.w + 2f * q.y * q.z, 1 - 2f * (q.z * q.z + q.w * q.w)); // Yaw
            v.x = (float)System.Math.Asin(2f * (q.x * q.z - q.w * q.y));                                       // Pitch
            v.z = (float)System.Math.Atan2(2f * q.x * q.y + 2f * q.z * q.w, 1 - 2f * (q.y * q.y + q.z * q.z)); // Roll
            return(NormalizeAngles(v * Rad2Deg));
        }
コード例 #2
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        private static THQuaternion SlerpUnclamped(ref THQuaternion a, ref THQuaternion b, float t)
        {
            // if either input is zero, return the other.
            if (a.lengthSquared == 0.0f)
            {
                if (b.lengthSquared == 0.0f)
                {
                    return(identity);
                }
                return(b);
            }
            else if (b.lengthSquared == 0.0f)
            {
                return(a);
            }

            float cosHalfAngle = a.w * b.w + THVector3.Dot(a.xyz, b.xyz);

            if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
            {
                // angle = 0.0f, so just return one input.
                return(a);
            }
            else if (cosHalfAngle < 0.0f)
            {
                b.xyz        = -b.xyz;
                b.w          = -b.w;
                cosHalfAngle = -cosHalfAngle;
            }

            float blendA;
            float blendB;

            if (cosHalfAngle < 0.99f)
            {
                // do proper slerp for big angles
                float halfAngle           = (float)Math.Acos(cosHalfAngle);
                float sinHalfAngle        = (float)Math.Sin(halfAngle);
                float oneOverSinHalfAngle = 1.0f / sinHalfAngle;
                blendA = (float)Math.Sin(halfAngle * (1.0f - t)) * oneOverSinHalfAngle;
                blendB = (float)Math.Sin(halfAngle * t) * oneOverSinHalfAngle;
            }
            else
            {
                // do lerp if angle is really small.
                blendA = 1.0f - t;
                blendB = t;
            }

            THQuaternion result = new THQuaternion(a.xyz * blendA + b.xyz * blendB, blendA * a.w + blendB * b.w);

            if (result.lengthSquared > 0.0f)
            {
                return(Normalize(result));
            }
            else
            {
                return(identity);
            }
        }
コード例 #3
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        /// <summary>
        /// Set Quaternion values<para />
        /// XYZ must be in degs
        /// </summary>
        /// <param name="xyz">XYZ Angles</param>
        public static THQuaternion CreateAndSetFromVec(THVector3 xyz)
        {
            var q = new THQuaternion();

            q.Set(xyz);
            return(q);
        }
コード例 #4
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        /// <summary>
        /// Normalize a Quaternion
        /// </summary>
        /// <param name="quaternion"></param>
        /// <returns></returns>
        public static THQuaternion Normalize(THQuaternion quaternion)
        {
            var scale = 1.0f / quaternion.length;

            quaternion.xyz *= scale;
            quaternion.w   *= scale;

            return(quaternion);
        }
コード例 #5
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        public override bool Equals(object other)
        {
            if (!(other is THQuaternion))
            {
                return(false);
            }
            THQuaternion quaternion = (THQuaternion)other;

            return(this.x.Equals(quaternion.x) && this.y.Equals(quaternion.y) && this.z.Equals(quaternion.z) && this.w.Equals(quaternion.w));
        }
コード例 #6
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        /// <summary>
        /// Retuens the invenrse of a <paramref name="rotation"/>
        /// </summary>
        /// <param name="rotation">Rotation</param>
        /// <returns>Inverted rotation</returns>
        public static THQuaternion Inverse(THQuaternion rotation)
        {
            float lengthSq = rotation.lengthSquared;

            if (lengthSq != 0.0)
            {
                float i = 1.0f / lengthSq;
                return(new THQuaternion(rotation.xyz * -i, rotation.w * i));
            }
            return(rotation);
        }
コード例 #7
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
 /// <summary>
 /// Interpolates between <paramref name="a"/> and <paramref name="b"/> by <paramref name="t"/> then Normalizes the result. <paramref name="t"/> is clampled from 0-1
 /// </summary>
 /// <param name="a">First Quaternion</param>
 /// <param name="b">Second Quaternion</param>
 /// <param name="t">Interpolation steps</param>
 /// <returns>Lerped Quaternion</returns>
 public static THQuaternion Lerp(THQuaternion a, THQuaternion b, float t)
 {
     if (t > 1)
     {
         t = 1;
     }
     if (t < 0)
     {
         t = 0;
     }
     return(Slerp(ref a, ref b, t)); // TODO: use lerp not slerp, "Because quaternion works in 4D. Rotation in 4D are linear" ???
 }
コード例 #8
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        /// <summary>
        /// Rotates from <paramref name="a"/> towards <paramref name="b"/> by a maximum angle <paramref name="maxDegreesDelta"/>
        /// </summary>
        /// <param name="a">First Quaternion</param>
        /// <param name="b">Second Quaternion</param>
        /// <param name="maxDegreesDelta">Max change in angle</param>
        public static THQuaternion RotateTowards(THQuaternion a, THQuaternion b, float maxDegreesDelta)
        {
            float num = THQuaternion.Angle(a, b);

            if (num == 0f)
            {
                return(b);
            }
            float t = Math.Min(1f, maxDegreesDelta / num);

            return(THQuaternion.SlerpUnclamped(a, b, t));
        }
コード例 #9
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        private static void ToAxisAngleRad(THQuaternion q, out THVector3 axis, out float angle)
        {
            if (Math.Abs(q.w) > 1.0f)
            {
                q.Normalize();
            }
            angle = 2.0f * (float)Math.Acos(q.w); // angle
            float den = (float)Sqrt(1.0 - q.w * q.w);

            if (den > 0.0001f)
            {
                axis = q.xyz / den;
            }
            else
            {
                // This occurs when the angle is zero.
                // Not a problem: just set an arbitrary normalized axis.
                axis = new THVector3(1, 0, 0);
            }
        }
コード例 #10
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
 public bool Equals(THQuaternion other)
 {
     return(this.x.Equals(other.x) && this.y.Equals(other.y) && this.z.Equals(other.z) && this.w.Equals(other.w));
 }
コード例 #11
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        /// <summary>
        /// Produce a normalized version of an input Quaternion
        /// </summary>
        /// <param name="q">Input Quaternion</param>
        /// <param name="result">Output Quaternion</param>
        public static void Normalize(ref THQuaternion q, out THQuaternion result)
        {
            var scale = 1f / q.length;

            result = new THQuaternion(q.xyz * scale, q.w * scale);
        }
コード例 #12
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
 /// <summary>
 /// Produce a Dot procude of the Quaternion
 /// </summary>
 /// <param name="a">First Quaternion</param>
 /// <param name="b">Second Quaternion</param>
 /// <returns></returns>
 public static float Dot(THQuaternion a, THQuaternion b)
 {
     return(a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w);
 }
コード例 #13
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        /// <summary>
        /// Returns the angle in degrees between two rotations <paramref name="a"/> and <paramref name="b"/>
        /// </summary>
        /// <param name="a">First Quaternion</param>
        /// <param name="b">First Quaternion</param>
        public static float Angle(THQuaternion a, THQuaternion b)
        {
            float f = THQuaternion.Dot(a, b);

            return(Acos(UnityEngine.Mathf.Min(UnityEngine.Mathf.Abs(f), 1f)) * 2f * radToDeg);
        }
コード例 #14
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
        // from http://answers.unity3d.com/questions/467614/what-is-the-source-code-of-quaternionlookrotation.html
        /// <summary>
        /// Creates a rotation with the specified <paramref name="forward"/> and <paramref name="up"/> directions
        /// </summary>
        /// <param name="forward">Forward direction</param>
        /// <param name="up">Upward direction</param>
        /// <returns></returns>
        private static THQuaternion LookRotation(ref THVector3 forward, ref THVector3 up)
        {
            // Magic

            forward = THVector3.Normalize(forward);
            THVector3 right = THVector3.Normalize(THVector3.Cross(up, forward));

            up = THVector3.Cross(forward, right);
            var m00 = right.x;
            var m01 = right.y;
            var m02 = right.z;
            var m10 = up.x;
            var m11 = up.y;
            var m12 = up.z;
            var m20 = forward.x;
            var m21 = forward.y;
            var m22 = forward.z;


            float num8       = (m00 + m11) + m22;
            var   quaternion = new THQuaternion();

            if (num8 > 0f)
            {
                var num = (float)System.Math.Sqrt(num8 + 1f);
                quaternion.w = num * 0.5f;
                num          = 0.5f / num;
                quaternion.x = (m12 - m21) * num;
                quaternion.y = (m20 - m02) * num;
                quaternion.z = (m01 - m10) * num;
                return(quaternion);
            }
            if ((m00 >= m11) && (m00 >= m22))
            {
                var num7 = (float)System.Math.Sqrt(((1f + m00) - m11) - m22);
                var num4 = 0.5f / num7;
                quaternion.x = 0.5f * num7;
                quaternion.y = (m01 + m10) * num4;
                quaternion.z = (m02 + m20) * num4;
                quaternion.w = (m12 - m21) * num4;
                return(quaternion);
            }
            if (m11 > m22)
            {
                var num6 = (float)System.Math.Sqrt(((1f + m11) - m00) - m22);
                var num3 = 0.5f / num6;
                quaternion.x = (m10 + m01) * num3;
                quaternion.y = 0.5f * num6;
                quaternion.z = (m21 + m12) * num3;
                quaternion.w = (m20 - m02) * num3;
                return(quaternion);
            }
            var num5 = (float)System.Math.Sqrt(((1f + m22) - m00) - m11);
            var num2 = 0.5f / num5;

            quaternion.x = (m20 + m02) * num2;
            quaternion.y = (m21 + m12) * num2;
            quaternion.z = 0.5f * num5;
            quaternion.w = (m01 - m10) * num2;
            return(quaternion);
        }
コード例 #15
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
 /// <summary>
 /// Interpolates between <paramref name="a"/> and <paramref name="b"/> by <paramref name="t"/> and normalizes the result afterwards. The parameter <paramref name="t"/> is not clamped
 /// </summary>
 /// <param name="a">First Quaternion</param>
 /// <param name="b">Second Quaternion</param>
 /// <param name="t">Interpolation steps</param>
 /// <remarks>Lerped Quaternion</remarks>
 public static THQuaternion LerpUnclamped(THQuaternion a, THQuaternion b, float t)
 {
     return(Slerp(ref a, ref b, t));
 }
コード例 #16
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
 /// <summary>
 /// Spherically interpolates between <paramref name="a"/> and <paramref name="b"/> by <paramref name="t"/>. The parameter <paramref name="t"/> is clamped to the range [0, 1].</para>
 /// </summary>
 /// <param name="a">First Quaternion</param>
 /// <param name="b">Second Quaternion</param>
 /// <param name="t">Steps</param>
 /// <returns>Slerped Quaternion</returns>
 public static THQuaternion Slerp(THQuaternion a, THQuaternion b, float t)
 {
     return(Slerp(ref a, ref b, t));
 }
コード例 #17
0
ファイル: Quaternion.cs プロジェクト: maxs-rose/UnityUtils
 private static THQuaternion Slerp(ref THQuaternion a, ref THQuaternion b, float t)
 {
     return(SlerpUnclamped(ref a, ref b, Clamp01(t)));
 }