Пример #1
0
        internal static Vector3.Vector RotateVector3(
            QuaternionRec RotationQ,
            QuaternionRec InverseRotationQ,
            Vector3.Vector StartPoint)
        {
            // A quaternion rotation is clockwise around a vector
            // if you are looking down the vector from the origin point.
            // Like an archer with an arrow in the bow, you are sighting
            // down the arrow.
            // Compare this with representing a rotation or a moment
            // of inertia, or a torque, by using a vector cross product
            // in a right-handed coordinate system.  It goes in the
            // right direction like it should.  If the Z axis is pointing
            // straight toward you then it is the opposite
            // point of view from what an archer would see when he
            // is sighting down an arrow in his bow.  That opposite
            // point of view is a counter-clockwise rotation.


            QuaternionRec MiddlePoint = MultiplyWithLeftVector3(
                StartPoint, InverseRotationQ);

            Vector3.Vector Result = MultiplyWithResultVector3(
                RotationQ, MiddlePoint);
            return(Result);
        }
Пример #2
0
        internal static QuaternionRec Inverse(QuaternionRec In)
        {
            // QX = 1, so X is the multiplicative inverse
            // of Q.  So X = 1 / Q, or Q^(-1).

            double NSquared = NormSquared(In);

            if (NSquared < 0.0000000000001)
            {
                return(SetZero());
            }
            // throw( new Exception( "NSquared is too small in QuaternionEC.Inverse()." ));

            double InverseNS = 1.0d / NSquared;

            // The negative parts are to make it the
            // conjugate.  So the Result is the conjugate
            // divided by the norm squared.
            QuaternionRec Result;

            Result.X = -In.X * InverseNS;
            Result.Y = -In.Y * InverseNS;
            Result.Z = -In.Z * InverseNS;
            Result.W = In.W * InverseNS;
            return(Result);
        }
Пример #3
0
 internal static QuaternionRec Add(QuaternionRec Result, QuaternionRec In)
 {
     Result.X += In.X;
     Result.Y += In.Y;
     Result.Z += In.Z;
     Result.W += In.W;
     return(Result);
 }
Пример #4
0
 internal static QuaternionRec Negate(QuaternionRec Result)
 {
     Result.X = -Result.X;
     Result.Y = -Result.Y;
     Result.Z = -Result.Z;
     Result.W = -Result.W;
     return(Result);
 }
Пример #5
0
        internal static double NormSquared(QuaternionRec In)
        {
            double NS = (In.X * In.X) +
                        (In.Y * In.Y) +
                        (In.Z * In.Z) +
                        (In.W * In.W);

            return(NS);
        }
Пример #6
0
        internal static QuaternionRec Rotate(
            QuaternionRec RotationQ,
            QuaternionRec InverseRotationQ,
            QuaternionRec StartPoint)
        {
            QuaternionRec MiddlePoint = Multiply(StartPoint, InverseRotationQ);
            QuaternionRec Result      = Multiply(RotationQ, MiddlePoint);

            return(Result);
        }
Пример #7
0
        internal static QuaternionRec Conjugate(QuaternionRec In)
        {
            QuaternionRec Result;

            Result.X = -In.X;
            Result.Y = -In.Y;
            Result.Z = -In.Z;
            Result.W = In.W;
            return(Result);
        }
Пример #8
0
        internal static Vector3.Vector MultiplyWithResultVector3(
            QuaternionRec L,
            QuaternionRec R)
        {
            Vector3.Vector Result;
            Result.X = (L.X * R.W) + (L.W * R.X) + (L.Y * R.Z) + (-L.Z * R.Y);
            Result.Y = (-L.X * R.Z) + (L.Y * R.W) + (L.Z * R.X) + (L.W * R.Y);
            Result.Z = (L.X * R.Y) + (-L.Y * R.X) + (L.Z * R.W) + (L.W * R.Z);

            // It doesn't need this calculation:
            // Result.W = (-L.X * R.X) + (-L.Y * R.Y) + (-L.Z * R.Z) +  (L.W * R.W);

            return(Result);
        }
Пример #9
0
        internal static Vector3.Vector RotationWithSetupDegrees(
            double AngleDegrees,
            QuaternionRec Axis,
            Vector3.Vector InVector)
        {
            double Angle = NumbersEC.DegreesToRadians(AngleDegrees);

            QuaternionRec RotationQ        = SetAsRotation(Axis, Angle);
            QuaternionRec InverseRotationQ = Inverse(RotationQ);

            Vector3.Vector ResultPoint = RotateVector3(
                RotationQ,
                InverseRotationQ,
                InVector);

            return(ResultPoint);
        }
Пример #10
0
        internal static QuaternionRec MultiplyWithLeftVector3(
            Vector3.Vector L,
            QuaternionRec R)
        {
            QuaternionRec Result;

            // Result.X =  (L.X * R.W) +  (0 * R.X) +  (L.Y * R.Z) + (-L.Z * R.Y);
            // Result.Y = (-L.X * R.Z) +  (L.Y * R.W) +  (L.Z * R.X) +  (0 * R.Y);
            // Result.Z =  (L.X * R.Y) + (-L.Y * R.X) +  (L.Z * R.W) +  (0 * R.Z);
            // Result.W = (-L.X * R.X) + (-L.Y * R.Y) + (-L.Z * R.Z) +  (0 * R.W);

            Result.X = (L.X * R.W) + (L.Y * R.Z) + (-L.Z * R.Y);
            Result.Y = (-L.X * R.Z) + (L.Y * R.W) + (L.Z * R.X);
            Result.Z = (L.X * R.Y) + (-L.Y * R.X) + (L.Z * R.W);
            Result.W = (-L.X * R.X) + (-L.Y * R.Y) + (-L.Z * R.Z);
            return(Result);
        }
Пример #11
0
        internal static QuaternionRec Normalize(QuaternionRec In)
        {
            double Length = Norm(In);

            if (Length < 0.000000000000000001d)
            {
                return(SetZero());
            }
            // throw( new Exception( "Length is too small in QuaternionEC.Normalize()." ));

            double Inverse = 1.0d / Length;

            QuaternionRec Result;

            Result.X = In.X * Inverse;
            Result.Y = In.Y * Inverse;
            Result.Z = In.Z * Inverse;
            Result.W = In.W * Inverse;
            return(Result);
        }
Пример #12
0
        ///////////////////////////
        // Notes on Multiplication:

        // It is a right-handed coordinate system.  Positive
        // Z values go toward the viewer.  X goes to the
        // right, Y goes up.

        // ij = k    ji = -k
        // jk = i    kj = -i
        // ki = j    ik = -j

        // xy = z    yx = -z
        // yz = x    zy = -x
        // zx = y    xz = -y

        //   i^2 = j^2 = k^2 = ijk = -1

        // With two regular complex numbers you do:
        //      (a + bi)(c + di) =
        //      ac + adi + bic + bidi

        // a1 is like a with subscript 1.

        // Multiply two quaternions:
        // Left times Right.
        // (a1x + b1y + c1z + w1)(a2x + b2y + c2z + w2)

        // Distributive Property:
        // a1x(a2x + b2y + c2z + w2) +
        // b1y(a2x + b2y + c2z + w2) +
        // c1z(a2x + b2y + c2z + w2) +
        // w1(a2x + b2y + c2z + w2)

        // Distributive Property again:
        // a1xa2x + a1xb2y + a1xc2z + a1xw2 +
        // b1ya2x + b1yb2y + b1yc2z + b1yw2 +
        // c1za2x + c1zb2y + c1zc2z + c1zw2 +
        // w1a2x + w1b2y + w1c2z + w1w2

        // a1a2xx + a1b2xy + a1c2xz + a1w2x +
        // b1a2yx + b1b2yy + b1c2yz + b1w2y +
        // c1a2zx + c1b2zy + c1c2zz + c1w2z +
        // w1a2x + w1b2y + w1c2z + w1w2

        // xy = z    yx = -z
        // yz = x    zy = -x
        // zx = y    xz = -y
        // a1a2-1 + a1b2z + a1c2-y + a1w2x +
        // b1a2-z + b1b2-1 + b1c2x + b1w2y +
        // c1a2y + c1b2-x + c1c2-1 + c1w2z +
        // w1a2x + w1b2y + w1c2z + w1w2

        // Rearrange it so the components are together:
        // a1w2x + w1a2x + b1c2x + c1b2-x +
        // a1c2-y + b1w2y + c1a2y + w1b2y +
        // a1b2z + b1a2-z + c1w2z + w1c2z +
        // -a1a2 + -b1b2 + -c1c2 + w1w2

        // a1w2x + w1a2x + b1c2x + -c1b2x +
        // -a1c2y + b1w2y + c1a2y + w1b2y +
        // a1b2z + -b1a2z + c1w2z + w1c2z +
        // -a1a2 + -b1b2 + -c1c2 + w1w2

        // x(a1w2 + w1a2 + b1c2 + -c1b2) +
        // y(-a1c2 + b1w2 + c1a2 + w1b2) +
        // z(a1b2 + -b1a2 + c1w2 + w1c2) +
        // The W parts:
        // -a1a2 + -b1b2 + -c1c2 + w1w2
        ///////////////////////////



        internal static QuaternionRec Multiply(
            QuaternionRec L,
            QuaternionRec R)
        {
            // Result.X = a1w2 + w1a2 + b1c2 + -c1b2;
            // Result.Y = -a1c2 + b1w2 + c1a2 + w1b2;
            // Result.Z = a1b2 + -b1a2 + c1w2 + w1c2;
            // Result.W = -a1a2 + -b1b2 + -c1c2 + w1w2;

            QuaternionRec Result;

            // The vector Cross Product part:
            Result.X = (L.X * R.W) + (L.W * R.X) + (L.Y * R.Z) + (-L.Z * R.Y);
            Result.Y = (-L.X * R.Z) + (L.Y * R.W) + (L.Z * R.X) + (L.W * R.Y);
            Result.Z = (L.X * R.Y) + (-L.Y * R.X) + (L.Z * R.W) + (L.W * R.Z);

            // Almost the same as the vector Dot Product.
            Result.W = (-L.X * R.X) + (-L.Y * R.Y) + (-L.Z * R.Z) + (L.W * R.W);
            return(Result);
        }
Пример #13
0
        internal static QuaternionRec SetAsRotation(
            QuaternionRec Axis,
            double Angle)
        {
            // Make sure it's a unit quaternion.
            Axis.W = 0;
            Axis   = Normalize(Axis);

            // If Angle was Pi / 2 then this would be
            // Pi / 4.
            double HalfAngle       = Angle * 0.5d;
            double SineHalfAngle   = Math.Sin(HalfAngle);
            double CosineHalfAngle = Math.Cos(HalfAngle);

            QuaternionRec Result;

            Result.X = Axis.X * SineHalfAngle;
            Result.Y = Axis.Y * SineHalfAngle;
            Result.Z = Axis.Z * SineHalfAngle;
            Result.W = CosineHalfAngle;
            return(Result);
        }
Пример #14
0
        internal static QuaternionRec CrossProduct(
            QuaternionRec Left,
            QuaternionRec Right)
        {
            // i x j = k
            // j x k = i
            // k x i = j

            QuaternionRec Result;

            // W is not used.
            Result.W = 0;

            Result.X = (Left.Y * Right.Z) -
                       (Left.Z * Right.Y);

            Result.Y = (Left.Z * Right.X) -
                       (Left.X * Right.Z);

            Result.Z = (Left.X * Right.Y) -
                       (Left.Y * Right.X);

            return(Result);
        }
Пример #15
0
        internal static bool IsAlmostEqual(QuaternionRec Left, QuaternionRec Right, double SmallNumber)
        {
            if (!DoubleIsAlmostEqual(Left.X, Right.X, SmallNumber))
            {
                return(false);
            }

            if (!DoubleIsAlmostEqual(Left.Y, Right.Y, SmallNumber))
            {
                return(false);
            }

            if (!DoubleIsAlmostEqual(Left.Z, Right.Z, SmallNumber))
            {
                return(false);
            }

            if (!DoubleIsAlmostEqual(Left.W, Right.W, SmallNumber))
            {
                return(false);
            }

            return(true);
        }
Пример #16
0
        internal static double Norm(QuaternionRec In)
        {
            double NSquared = NormSquared(In);

            return(Math.Sqrt(NSquared));
        }