Пример #1
0
        /// <summary>
        ///     Gets the shortest arc quaternion to rotate this vector
        ///     to the destination vector.
        /// </summary>   
        /// <remarks>
        ///     If you call this with a dest vector that is close to the inverse
        ///     of this vector, we will rotate 180 degrees around the 'fallbackAxis'
        ///     (if specified, or a generated axis if not) since in this case
        ///     ANY axis of rotation is valid.
        /// </remarks>
        public Quaternion GetRotationTo(Vector3 destination, Vector3 fallbackAxis)
        {
            // Based on Stan Melax's article in Game Programming Gems
            Quaternion q = new Quaternion();

            Vector3 v0 = new Vector3(this.x, this.y, this.z);
            Vector3 v1 = destination;

            // normalize both vectors
            v0.Normalize();
            v1.Normalize();

            // get the cross product of the vectors
            Vector3 c = v0.Cross(v1);

            // If the cross product approaches zero, we get unstable because ANY axis will do
            // when v0 == -v1
            float d = v0.Dot(v1);

            // If dot == 1, vectors are the same
            if (d >= 1.0f)
            {
                return Quaternion.Identity;
            }

            if (d < (1e-6f - 1.0f))
            {
                if (fallbackAxis != Vector3.Zero)
                    // rotate 180 degrees about the fallback axis
                    q = Quaternion.FromAngleAxis((float)Math.PI, fallbackAxis);
                else
                {
                    // Generate an axis
                    Vector3 axis = Vector3.UnitX.Cross(this);
                    if (axis.IsZero) // pick another if colinear
                        axis = Vector3.UnitY.Cross(this);
                    axis.Normalize();
                    q = Quaternion.FromAngleAxis((float)Math.PI, axis);
                }
            }
            else
            {
                float s = MathUtil.Sqrt( (1+d) * 2 );
                float inverse = 1 / s;

                q.x = c.x * inverse;
                q.y = c.y * inverse;
                q.z = c.z * inverse;
                q.w = s * 0.5f;
                q.Normalize();
            }
            return q;
        }
Пример #2
0
        /// <summary>
        ///		Rotates the camera about an arbitrary axis.
        /// </summary>
        /// <param name="quat"></param>
        public void Rotate(Quaternion quat)
        {
            // Note the order of the multiplication
            orientation = quat * orientation;
            orientation.Normalize();

            InvalidateView();
        }