예제 #1
0
 public static Quaternion4D Squad(
     Quaternion4D q1,
     Quaternion4D a,
     Quaternion4D b,
     Quaternion4D c,
     double t)
 {
     return(Slerp(
                Slerp(q1, c, t), Slerp(a, b, t), 2 * t * (1.0 - t)));
 }
예제 #2
0
 public override bool Equals(object obj)
 {
     if (obj is Quaternion4D)
     {
         Quaternion4D q = (Quaternion4D)obj;
         return(q == this);
     }
     else
     {
         return(false);
     }
 }
예제 #3
0
        public static Vector3D QuaternionToEuler(Quaternion4D q)
        {
            double q0 = q.W;
            double q1 = q.X;
            double q2 = q.Y;
            double q3 = q.Z;

            double yaw   = Math.Atan2(2 * (q2 * q3 + q0 * q1), (q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3));
            double pitch = Math.Asin(-2 * (q1 * q3 - q0 * q2));
            double roll  = Math.Atan2(2 * (q1 * q2 + q0 * q3), (q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3));

            return(new Vector3D(yaw, pitch, roll));
        }
예제 #4
0
        /// <summary>
        /// Transforms a rotation in quaternion form to a set of Euler angles
        /// </summary>
        /// <returns>The rotation transformed to Euler angles, X=Yaw, Y=Pitch, Z=Roll (radians)</returns>
        public static Vector3D QuaternionToEuler(Quaternion4D q)
        {
            double q0 = q.W;
            double q1 = q.X;
            double q2 = q.Y;
            double q3 = q.Z;

            double x = Math.Atan2(2 * (q2 * q3 + q0 * q1), (q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3));
            double y = Math.Asin(-2 * (q1 * q3 - q0 * q2));
            double z = Math.Atan2(2 * (q1 * q2 + q0 * q3), (q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3));

            return(new Vector3D(x, y, z));
        }
예제 #5
0
        public static Quaternion4D Slerp(Quaternion4D q0, Quaternion4D q1, double t)
        {
            double cosom = q0.X * q1.X + q0.Y * q1.Y + q0.Z * q1.Z + q0.W * q1.W;
            double tmp0, tmp1, tmp2, tmp3;

            if (cosom < 0.0)
            {
                cosom = -cosom;
                tmp0  = -q1.X;
                tmp1  = -q1.Y;
                tmp2  = -q1.Z;
                tmp3  = -q1.W;
            }
            else
            {
                tmp0 = q1.X;
                tmp1 = q1.Y;
                tmp2 = q1.Z;
                tmp3 = q1.W;
            }

            /* calc coeffs */
            double scale0, scale1;

            if ((1.0 - cosom) > double.Epsilon)
            {
                // standard case (slerp)
                double omega = Math.Acos(cosom);
                double sinom = Math.Sin(omega);
                scale0 = Math.Sin((1.0 - t) * omega) / sinom;
                scale1 = Math.Sin(t * omega) / sinom;
            }
            else
            {
                /* just lerp */
                scale0 = 1.0 - t;
                scale1 = t;
            }

            Quaternion4D q = new Quaternion4D();

            q.X = scale0 * q0.X + scale1 * tmp0;
            q.Y = scale0 * q0.Y + scale1 * tmp1;
            q.Z = scale0 * q0.Z + scale1 * tmp2;
            q.W = scale0 * q0.W + scale1 * tmp3;

            return(q);
        }
예제 #6
0
        //the below functions have not been certified to work properly
        public static Quaternion4D Exp(Quaternion4D q)
        {
            double sinom;
            double om = Math.Sqrt(q.X * q.X + q.Y * q.Y + q.Z * q.Z);

            if (Math.Abs(om) < double.Epsilon)
            {
                sinom = 1.0;
            }
            else
            {
                sinom = Math.Sin(om) / om;
            }

            q.X = q.X * sinom;
            q.Y = q.Y * sinom;
            q.Z = q.Z * sinom;
            q.W = Math.Cos(om);

            return(q);
        }
예제 #7
0
        public static Quaternion4D Ln(Quaternion4D q)
        {
            double t = 0;

            double s  = Math.Sqrt(q.X * q.X + q.Y * q.Y + q.Z * q.Z);
            double om = Math.Atan2(s, q.W);

            if (Math.Abs(s) < double.Epsilon)
            {
                t = 0.0f;
            }
            else
            {
                t = om / s;
            }

            q.X = q.X * t;
            q.Y = q.Y * t;
            q.Z = q.Z * t;
            q.W = 0.0f;

            return(q);
        }
예제 #8
0
        public static void SquadSetup(
            ref Quaternion4D outA,
            ref Quaternion4D outB,
            ref Quaternion4D outC,
            Quaternion4D q0,
            Quaternion4D q1,
            Quaternion4D q2,
            Quaternion4D q3)
        {
            q0 = q0 + q1;
            q0.Normalize();

            q2 = q2 + q1;
            q2.Normalize();

            q3 = q3 + q1;
            q3.Normalize();

            q1.Normalize();

            outA = q1 * Exp(-0.25 * (Ln(Exp(q1) * q2) + Ln(Exp(q1) * q0)));
            outB = q2 * Exp(-0.25 * (Ln(Exp(q2) * q3) + Ln(Exp(q2) * q1)));
            outC = q2;
        }
예제 #9
0
 public static double Dot(Quaternion4D a, Quaternion4D b)
 {
     return(a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W);
 }
예제 #10
0
 public static double Abs(Quaternion4D q)
 {
     return(Math.Sqrt(Norm(q)));
 }
예제 #11
0
 public static double Norm(Quaternion4D q)
 {
     return(q.X * q.X + q.Y * q.Y + q.Z * q.Z + q.W * q.W);
 }