コード例 #1
0
        /// <summary>
        /// Get the FRotator representation of this Quaternion.
        /// </summary>
        public FRotator Rotator()
        {
            DiagnosticCheckNaN();

            float singularityTest = Z * X - W * Y;
            float yawY            = 2.0f * (W * Z + X * Y);
            float yawX            = (1.0f - 2.0f * (FMath.Square(Y) + FMath.Square(Z)));

            // reference
            // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
            // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/

            // this value was found from experience, the above websites recommend different values
            // but that isn't the case for us, so I went through different testing, and finally found the case
            // where both of world lives happily.
            const float singularityThreshold = 0.4999995f;
            const float radToDeg             = (180.0f) / FMath.PI;
            FRotator    rotatorFromQuat;

            if (singularityTest < -singularityThreshold)
            {
                rotatorFromQuat.Pitch = -90.0f;
                rotatorFromQuat.Yaw   = FMath.Atan2(yawY, yawX) * radToDeg;
                rotatorFromQuat.Roll  = FRotator.NormalizeAxis(-rotatorFromQuat.Yaw - (2.0f * FMath.Atan2(X, W) * radToDeg));
            }
            else if (singularityTest > singularityThreshold)
            {
                rotatorFromQuat.Pitch = 90.0f;
                rotatorFromQuat.Yaw   = FMath.Atan2(yawY, yawX) * radToDeg;
                rotatorFromQuat.Roll  = FRotator.NormalizeAxis(rotatorFromQuat.Yaw - (2.0f * FMath.Atan2(X, W) * radToDeg));
            }
            else
            {
                rotatorFromQuat.Pitch = FMath.FastAsin(2.0f * (singularityTest)) * radToDeg;
                rotatorFromQuat.Yaw   = FMath.Atan2(yawY, yawX) * radToDeg;
                rotatorFromQuat.Roll  = FMath.Atan2(-2.0f * (W * X + Y * Z), (1.0f - 2.0f * (FMath.Square(X) + FMath.Square(Y)))) * radToDeg;
            }

            rotatorFromQuat.DiagnosticCheckNaN("FQuat::Rotator(): Rotator result " + rotatorFromQuat + " contains NaN! Quat = " + this.ToString() +
                                               ", YawY = " + yawY + ", YawX = " + yawX);

            return(rotatorFromQuat);
        }