예제 #1
0
        /// <summary>
        /// Converts the quaternion rotation into axis/angle rotation.
        /// </summary>
        /// <param name="axis">Axis around which the rotation is performed.</param>
        /// <param name="angle">Amount of rotation.</param>
        public void ToAxisAngle(out Vector3 axis, out Degree angle)
        {
            float fSqrLength = x * x + y * y + z * z;

            if (fSqrLength > 0.0f)
            {
                angle = 2.0f * MathEx.Acos(w);
                float fInvLength = MathEx.InvSqrt(fSqrLength);
                axis.x = x * fInvLength;
                axis.y = y * fInvLength;
                axis.z = z * fInvLength;
            }
            else
            {
                // Angle is 0, so any axis will do
                angle  = (Degree)0.0f;
                axis.x = 1.0f;
                axis.y = 0.0f;
                axis.z = 0.0f;
            }
        }
예제 #2
0
        /// <summary>
        /// Decomposes the matrix into a set of values.
        /// </summary>
        /// <param name="matQ">Columns form orthonormal bases. If your matrix is affine and doesn't use non-uniform scaling
        /// this matrix will be the rotation part of the matrix.
        /// </param>
        /// <param name="vecD">If the matrix is affine these will be scaling factors of the matrix.</param>
        /// <param name="vecU">If the matrix is affine these will be shear factors of the matrix.</param>
        public void QDUDecomposition(out Matrix3 matQ, out Vector3 vecD, out Vector3 vecU)
        {
            matQ = new Matrix3();
            vecD = new Vector3();
            vecU = new Vector3();

            // Build orthogonal matrix Q
            float invLength = MathEx.InvSqrt(m00 * m00 + m10 * m10 + m20 * m20);

            matQ.m00 = m00 * invLength;
            matQ.m10 = m10 * invLength;
            matQ.m20 = m20 * invLength;

            float dot = matQ.m00 * m01 + matQ.m10 * m11 + matQ.m20 * m21;

            matQ.m01 = m01 - dot * matQ.m00;
            matQ.m11 = m11 - dot * matQ.m10;
            matQ.m21 = m21 - dot * matQ.m20;

            invLength = MathEx.InvSqrt(matQ.m01 * matQ.m01 + matQ.m11 * matQ.m11 + matQ.m21 * matQ.m21);
            matQ.m01 *= invLength;
            matQ.m11 *= invLength;
            matQ.m21 *= invLength;

            dot      = matQ.m00 * m02 + matQ.m10 * m12 + matQ.m20 * m22;
            matQ.m02 = m02 - dot * matQ.m00;
            matQ.m12 = m12 - dot * matQ.m10;
            matQ.m22 = m22 - dot * matQ.m20;

            dot       = matQ.m01 * m02 + matQ.m11 * m12 + matQ.m21 * m22;
            matQ.m02 -= dot * matQ.m01;
            matQ.m12 -= dot * matQ.m11;
            matQ.m22 -= dot * matQ.m21;

            invLength = MathEx.InvSqrt(matQ.m02 * matQ.m02 + matQ.m12 * matQ.m12 + matQ.m22 * matQ.m22);
            matQ.m02 *= invLength;
            matQ.m12 *= invLength;
            matQ.m22 *= invLength;

            // Guarantee that orthogonal matrix has determinant 1 (no reflections)
            float fDet = matQ.m00 * matQ.m11 * matQ.m22 + matQ.m01 * matQ.m12 * matQ.m20 +
                         matQ.m02 * matQ.m10 * matQ.m21 - matQ.m02 * matQ.m11 * matQ.m20 -
                         matQ.m01 * matQ.m10 * matQ.m22 - matQ.m00 * matQ.m12 * matQ.m21;

            if (fDet < 0.0f)
            {
                matQ.m00 = -matQ.m00;
                matQ.m01 = -matQ.m01;
                matQ.m02 = -matQ.m02;
                matQ.m10 = -matQ.m10;
                matQ.m11 = -matQ.m11;
                matQ.m12 = -matQ.m12;
                matQ.m20 = -matQ.m20;
                matQ.m21 = -matQ.m21;
                matQ.m21 = -matQ.m22;
            }

            // Build "right" matrix R
            Matrix3 matRight = new Matrix3();

            matRight.m00 = matQ.m00 * m00 + matQ.m10 * m10 + matQ.m20 * m20;
            matRight.m01 = matQ.m00 * m01 + matQ.m10 * m11 + matQ.m20 * m21;
            matRight.m11 = matQ.m01 * m01 + matQ.m11 * m11 + matQ.m21 * m21;
            matRight.m02 = matQ.m00 * m02 + matQ.m10 * m12 + matQ.m20 * m22;
            matRight.m12 = matQ.m01 * m02 + matQ.m11 * m12 + matQ.m21 * m22;
            matRight.m22 = matQ.m02 * m02 + matQ.m12 * m12 + matQ.m22 * m22;

            // The scaling component
            vecD[0] = matRight.m00;
            vecD[1] = matRight.m11;
            vecD[2] = matRight.m22;

            // The shear component
            float invD0 = 1.0f / vecD[0];

            vecU[0] = matRight.m01 * invD0;
            vecU[1] = matRight.m02 * invD0;
            vecU[2] = matRight.m12 / vecD[1];
        }