public static Quaternion EulerToQuaternion(Vector3 eulerAngle)
        {
            //角度转弧度
            eulerAngle = MoMath.Deg2Rad(eulerAngle);

            float cX = MathF.Cos(eulerAngle.X / 2.0f);
            float sX = MathF.Sin(eulerAngle.X / 2.0f);

            float cY = MathF.Cos(eulerAngle.Y / 2.0f);
            float sY = MathF.Sin(eulerAngle.Y / 2.0f);

            float cZ = MathF.Cos(eulerAngle.Z / 2.0f);
            float sZ = MathF.Sin(eulerAngle.Z / 2.0f);

            Quaternion qX = new Quaternion(sX, 0, 0, cX);
            Quaternion qY = new Quaternion(0, sY, 0, cY);
            Quaternion qZ = new Quaternion(0, 0, sZ, cZ);

            Quaternion q = (qY * qX) * qZ;

#if DEBUG
            if (!MoMath.CompareApproximate(q.LengthSquared(), 1f))
            {
                string msg = string.Format($"EulerToQuaternion failed, {q.X} {q.Y} {q.Z} {q.W} sqrLength={q.LengthSquared()}");
                MoLog.Log(ELogType.Assert, msg);
            }
#endif

            return(q);
        }
Example #2
0
        // Right handed
        public static bool LookRotationToMatrix(Vector3 viewVec, Vector3 upVec, out Matrix3x3 m)
        {
            m = Matrix3x3.Identity;

            Vector3 z = viewVec;
            // compute u0
            float mag = z.Length();

            if (mag < Vector3Helper.Epsilon)
            {
                return(false);
            }
            z /= mag;

            Vector3 x = Vector3.Cross(upVec, z);

            mag = x.Length();
            if (mag < Vector3Helper.Epsilon)
            {
                return(false);
            }
            x /= mag;

            Vector3 y = Vector3.Cross(z, x);

            if (!MoMath.CompareApproximate(y.Length(), 1.0F))
            {
                return(false);
            }

            m.SetOrthoNormalBasis(x, y, z);
            return(true);
        }
        private static Matrix3x3 QuaternionToMatrix(Quaternion q)
        {
#if DEBUG
            // If q is guaranteed to be a unit quaternion, s will always be 1.
            // In that case, this calculation can be optimized out.
            if (!MoMath.CompareApproximate(q.LengthSquared(), 1.0F))
            {
                string msg = string.Format($"QuaternionToMatrix conversion failed, because input Quaternion is invalid {q.X} {q.Y} {q.Z} {q.W} sqrLength={q.LengthSquared()}");
                MoLog.Log(ELogType.Assert, msg);
            }
#endif

            // Precalculate coordinate products
            float x  = q.X * 2.0F;
            float y  = q.Y * 2.0F;
            float z  = q.Z * 2.0F;
            float xx = q.X * x;
            float yy = q.Y * y;
            float zz = q.Z * z;
            float xy = q.X * y;
            float xz = q.X * z;
            float yz = q.Y * z;
            float wx = q.W * x;
            float wy = q.W * y;
            float wz = q.W * z;

            // Calculate 3x3 matrix from orthonormal basis
            Matrix3x3 m = Matrix3x3.Identity;

            m.Data[0] = 1.0f - (yy + zz);
            m.Data[1] = xy + wz;
            m.Data[2] = xz - wy;

            m.Data[3] = xy - wz;
            m.Data[4] = 1.0f - (xx + zz);
            m.Data[5] = yz + wx;

            m.Data[6] = xz + wy;
            m.Data[7] = yz - wx;
            m.Data[8] = 1.0f - (xx + yy);

            return(m);
        }
        private static Quaternion MatrixToQuaternion(Matrix3x3 kRot)
        {
            Quaternion q = new Quaternion();

            // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
            // article "Quaternionf Calculus and Fast Animation".

#if DEBUG
            float det = kRot.GetDeterminant();
            if (!MoMath.CompareApproximate(det, 1.0F, .005f))
            {
                MoLog.Log(ELogType.Assert, "MatrixToQuaternion det assert.");
            }
#endif

            float fTrace = kRot.Get(0, 0) + kRot.Get(1, 1) + kRot.Get(2, 2);
            float fRoot;

            if (fTrace > 0.0f)
            {
                // |w| > 1/2, may as well choose w > 1/2
                fRoot = MathF.Sqrt(fTrace + 1.0f);     // 2w
                q.W   = 0.5f * fRoot;
                fRoot = 0.5f / fRoot;                  // 1/(4w)
                q.X   = (kRot.Get(2, 1) - kRot.Get(1, 2)) * fRoot;
                q.Y   = (kRot.Get(0, 2) - kRot.Get(2, 0)) * fRoot;
                q.Z   = (kRot.Get(1, 0) - kRot.Get(0, 1)) * fRoot;
            }
            else
            {
                // |w| <= 1/2
                int[] s_iNext = new int[3] {
                    1, 2, 0
                };
                int i = 0;
                if (kRot.Get(1, 1) > kRot.Get(0, 0))
                {
                    i = 1;
                }
                if (kRot.Get(2, 2) > kRot.Get(i, i))
                {
                    i = 2;
                }
                int j = s_iNext[i];
                int k = s_iNext[j];

                fRoot = MathF.Sqrt(kRot.Get(i, i) - kRot.Get(j, j) - kRot.Get(k, k) + 1.0f);
                float[] apkQuat = new float[3] {
                    q.X, q.Y, q.Z
                };

#if DEBUG
                if (fRoot < Vector3Helper.Epsilon)
                {
                    MoLog.Log(ELogType.Assert, "MatrixToQuaternion fRoot assert.");
                }
#endif

                apkQuat[i] = 0.5f * fRoot;
                fRoot      = 0.5f / fRoot;
                q.W        = (kRot.Get(k, j) - kRot.Get(j, k)) * fRoot;
                apkQuat[j] = (kRot.Get(j, i) + kRot.Get(i, j)) * fRoot;
                apkQuat[k] = (kRot.Get(k, i) + kRot.Get(i, k)) * fRoot;

                q.X = apkQuat[0];
                q.Y = apkQuat[1];
                q.Z = apkQuat[2];
            }
            q = Quaternion.Normalize(q);

            return(q);
        }