コード例 #1
0
        //Get an average (mean) from more then two quaternions (with two, slerp would be used).
        //Note: this only works if all the quaternions are relatively close together.
        //Usage:
        //-Cumulative is an external Vector4 which holds all the added x y z and w components.
        //-newRotation is the next rotation to be added to the average pool
        //-firstRotation is the first quaternion of the array to be averaged
        //-addAmount holds the total amount of quaternions which are currently added
        //This function returns the current average quaternion
        public static Quaternion AverageQuaternion(ref Vector4 cumulative, Quaternion newRotation, Quaternion firstRotation, int addAmount)
        {
            float w = 0.0f;
            float x = 0.0f;
            float y = 0.0f;
            float z = 0.0f;

            //Before we add the new rotation to the average (mean), we have to check whether the quaternion has to be inverted. Because
            //q and -q are the same rotation, but cannot be averaged, we have to make sure they are all the same.
            if (!ExtQuaternion.IsClose(newRotation, firstRotation))
            {
                newRotation = ExtQuaternion.InverseSignQuaternion(newRotation);
            }

            //Average the values
            float addDet = 1f / (float)addAmount;

            cumulative.w += newRotation.w;
            w             = cumulative.w * addDet;
            cumulative.x += newRotation.x;
            x             = cumulative.x * addDet;
            cumulative.y += newRotation.y;
            y             = cumulative.y * addDet;
            cumulative.z += newRotation.z;
            z             = cumulative.z * addDet;

            //note: if speed is an issue, you can skip the normalization step
            return(ExtQuaternion.NormalizeQuaternion(x, y, z, w));
        }
コード例 #2
0
        public static void GetShortestAngleAxisBetween(Quaternion a, Quaternion b, out Vector3 axis, out float angle)
        {
            var dq = Quaternion.Inverse(a) * b;

            if (dq.w > 1)
            {
                dq = ExtQuaternion.Normalize(dq);
            }

            //get as doubles for precision
            var qw    = (double)dq.w;
            var qx    = (double)dq.x;
            var qy    = (double)dq.y;
            var qz    = (double)dq.z;
            var ratio = System.Math.Sqrt(1.0d - qw * qw);

            angle = (float)(2.0d * System.Math.Acos(qw)) * Mathf.Rad2Deg;
            if (ratio < 0.001d)
            {
                axis = new Vector3(1f, 0f, 0f);
            }
            else
            {
                axis = new Vector3(
                    (float)(qx / ratio),
                    (float)(qy / ratio),
                    (float)(qz / ratio));
                axis.Normalize();
            }
        }
コード例 #3
0
        public static void GetAngleAxis(this Quaternion q, out Vector3 axis, out float angle)
        {
            if (q.w > 1)
            {
                q = ExtQuaternion.Normalize(q);
            }

            //get as doubles for precision
            var qw    = (double)q.w;
            var qx    = (double)q.x;
            var qy    = (double)q.y;
            var qz    = (double)q.z;
            var ratio = System.Math.Sqrt(1.0d - qw * qw);

            angle = (float)(2.0d * System.Math.Acos(qw)) * Mathf.Rad2Deg;
            if (ratio < 0.001d)
            {
                axis = new Vector3(1f, 0f, 0f);
            }
            else
            {
                axis = new Vector3(
                    (float)(qx / ratio),
                    (float)(qy / ratio),
                    (float)(qz / ratio));
                axis.Normalize();
            }
        }
コード例 #4
0
        //Rotate a vector as if it is attached to an object with rotation "from", which is then rotated to rotation "to".
        //Similar to TransformWithParent(), but rotating a vector instead of a transform.
        public static Vector3 RotateVectorFromTo(Quaternion from, Quaternion to, Vector3 vector)
        {
            //Note: comments are in case all inputs are in World Space.
            Quaternion Q = ExtQuaternion.SubtractRotation(to, from);                  //Output is in object space.
            Vector3    A = ExtQuaternion.InverseTransformDirectionMath(from, vector); //Output is in object space.
            Vector3    B = Q * A;                                                     //Output is in local space.
            Vector3    C = ExtQuaternion.TransformDirectionMath(from, B);             //Output is in world space.

            return(C);
        }