public static void Concatenate(ref QuaternionWide oa, ref QuaternionWide ob, out QuaternionWide result)
        {
            var tempA = oa;
            var tempB = ob;

            ConcatenateWithoutOverlap(ref tempA, ref tempB, out result);
        }
 public static void ConcatenateWithoutOverlap(ref QuaternionWide a, ref QuaternionWide b, out QuaternionWide result)
 {
     result.X = a.W * b.X + a.X * b.W + a.Z * b.Y - a.Y * b.Z;
     result.Y = a.W * b.Y + a.Y * b.W + a.X * b.Z - a.Z * b.X;
     result.Z = a.W * b.Z + a.Z * b.W + a.Y * b.X - a.X * b.Y;
     result.W = a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z;
 }
 public static void Conjugate(ref QuaternionWide quaternion, out QuaternionWide result)
 {
     result.X = -quaternion.X;
     result.Y = -quaternion.Y;
     result.Z = -quaternion.Z;
     result.W = quaternion.W;
 }
 public static void Negate(ref QuaternionWide q, out QuaternionWide negated)
 {
     negated.X = -q.X;
     negated.Y = -q.Y;
     negated.Z = -q.Z;
     negated.W = -q.W;
 }
 public static void Add(ref QuaternionWide a, ref QuaternionWide b, out QuaternionWide result)
 {
     result.X = a.X + b.X;
     result.Y = a.Y + b.Y;
     result.Z = a.Z + b.Z;
     result.W = a.W + b.W;
 }
 public static void Scale(ref QuaternionWide q, ref Vector <float> scale, out QuaternionWide result)
 {
     result.X = q.X * scale;
     result.Y = q.Y * scale;
     result.Z = q.Z * scale;
     result.W = q.W * scale;
 }
        public static void CreateFromQuaternion(ref QuaternionWide quaternion, out Matrix3x3Wide result)
        {
            var qX2 = quaternion.X + quaternion.X;
            var qY2 = quaternion.Y + quaternion.Y;
            var qZ2 = quaternion.Z + quaternion.Z;

            var YY = qY2 * quaternion.Y;
            var ZZ = qZ2 * quaternion.Z;

            result.X.X = Vector <float> .One - YY - ZZ;
            var XY = qX2 * quaternion.Y;
            var ZW = qZ2 * quaternion.W;

            result.X.Y = XY + ZW;
            var XZ = qX2 * quaternion.Z;
            var YW = qY2 * quaternion.W;

            result.X.Z = XZ - YW;

            var XX = qX2 * quaternion.X;

            result.Y.X = XY - ZW;
            result.Y.Y = Vector <float> .One - XX - ZZ;
            var XW = qX2 * quaternion.W;
            var YZ = qY2 * quaternion.Z;

            result.Y.Z = YZ + XW;

            result.Z.X = XZ + YW;
            result.Z.Y = YZ - XW;
            result.Z.Z = Vector <float> .One - XX - YY;
        }
        public static void Normalize(ref QuaternionWide q, out QuaternionWide normalized)
        {
            var inverseNorm = Vector <float> .One / Vector.SquareRoot(q.X * q.X + q.Y * q.Y + q.Z * q.Z + q.W * q.W);

            normalized.X = q.X * inverseNorm;
            normalized.Y = q.Y * inverseNorm;
            normalized.Z = q.Z * inverseNorm;
            normalized.W = q.W * inverseNorm;
        }
示例#9
0
        public static void TransformUnitX(ref QuaternionWide rotation, out Vector3Wide result)
        {
            var y2  = rotation.Y + rotation.Y;
            var z2  = rotation.Z + rotation.Z;
            var xy2 = rotation.X * y2;
            var xz2 = rotation.X * z2;
            var yy2 = rotation.Y * y2;
            var zz2 = rotation.Z * z2;
            var wy2 = rotation.W * y2;
            var wz2 = rotation.W * z2;

            result.X = Vector <float> .One - yy2 - zz2;
            result.Y = xy2 + wz2;
            result.Z = xz2 - wy2;
        }
        /// <summary>
        /// Constructs a quaternion from a rotation matrix.
        /// </summary>
        /// <param name="r">Rotation matrix to create the quaternion from.</param>
        /// <param name="q">Quaternion based on the rotation matrix.</param>
        public static void CreateFromRotationMatrix(ref Matrix3x3Wide r, out QuaternionWide q)
        {
            //Since we can't branch, we're going to end up calculating the possible states of all branches.
            //This requires doing more ALU work than the branching implementation, but there are a lot of common terms across the branches, and (random-ish) branches aren't free.
            //Overall, this turns out to be about 2x-2.5x more expensive per call than the scalar version, but it handles multiple lanes, so it's a net win.
            var oneAddX = Vector <float> .One + r.X.X;
            var oneSubX = Vector <float> .One - r.X.X;
            var yAddZ   = r.Y.Y + r.Z.Z;
            var ySubZ   = r.Y.Y - r.Z.Z;
            var tX      = oneAddX - yAddZ;
            var tY      = oneSubX + ySubZ;
            var tZ      = oneSubX - ySubZ;
            var tW      = oneAddX + yAddZ;

            //There are two layers of conditions- inner, and outer. We have to first select each of the two inner halves- upper, and lower-
            //and then we will select which of the two inners to use for the outer.
            var useUpper      = Vector.LessThan(r.Z.Z, Vector <float> .Zero);
            var useUpperUpper = Vector.GreaterThan(r.X.X, r.Y.Y);
            var useLowerUpper = Vector.LessThan(r.X.X, -r.Y.Y);
            var t             = Vector.ConditionalSelect(useUpper,
                                                         Vector.ConditionalSelect(useUpperUpper, tX, tY),
                                                         Vector.ConditionalSelect(useLowerUpper, tZ, tW));
            var xyAddYx = r.X.Y + r.Y.X;
            var yzSubZy = r.Y.Z - r.Z.Y;
            var zxAddXz = r.Z.X + r.X.Z;

            q.X = Vector.ConditionalSelect(useUpper,
                                           Vector.ConditionalSelect(useUpperUpper, tX, xyAddYx),
                                           Vector.ConditionalSelect(useLowerUpper, zxAddXz, yzSubZy));
            var yzAddZy = r.Y.Z + r.Z.Y;
            var zxSubXz = r.Z.X - r.X.Z;

            q.Y = Vector.ConditionalSelect(useUpper,
                                           Vector.ConditionalSelect(useUpperUpper, xyAddYx, tY),
                                           Vector.ConditionalSelect(useLowerUpper, yzAddZy, zxSubXz));
            var xySubYx = r.X.Y - r.Y.X;

            q.Z = Vector.ConditionalSelect(useUpper,
                                           Vector.ConditionalSelect(useUpperUpper, zxAddXz, yzAddZy),
                                           Vector.ConditionalSelect(useLowerUpper, tZ, xySubYx));
            q.W = Vector.ConditionalSelect(useUpper,
                                           Vector.ConditionalSelect(useUpperUpper, yzSubZy, zxSubXz),
                                           Vector.ConditionalSelect(useLowerUpper, xySubYx, tW));

            var scale = new Vector <float>(0.5f) / Vector.SquareRoot(t);

            Scale(ref q, ref scale, out q);
        }
示例#11
0
        public static void TransformUnitY(ref QuaternionWide rotation, out Vector3Wide result)
        {
            var x2  = rotation.X + rotation.X;
            var y2  = rotation.Y + rotation.Y;
            var z2  = rotation.Z + rotation.Z;
            var xx2 = rotation.X * x2;
            var xy2 = rotation.X * y2;
            var yz2 = rotation.Y * z2;
            var zz2 = rotation.Z * z2;
            var wx2 = rotation.W * x2;
            var wz2 = rotation.W * z2;

            result.X = xy2 - wz2;
            result.Y = Vector <float> .One - xx2 - zz2;
            result.Z = yz2 + wx2;
        }
示例#12
0
        public static void TransformUnitZ(ref QuaternionWide rotation, out Vector3Wide result)
        {
            var x2  = rotation.X + rotation.X;
            var y2  = rotation.Y + rotation.Y;
            var z2  = rotation.Z + rotation.Z;
            var xx2 = rotation.X * x2;
            var xz2 = rotation.X * z2;
            var yy2 = rotation.Y * y2;
            var yz2 = rotation.Y * z2;
            var wx2 = rotation.W * x2;
            var wy2 = rotation.W * y2;

            result.X = xz2 + wy2;
            result.Y = yz2 - wx2;
            result.Z = Vector <float> .One - xx2 - yy2;
        }
示例#13
0
        public static void TransformUnitXY(ref QuaternionWide rotation, out Vector3Wide x, out Vector3Wide y)
        {
            var x2  = rotation.X + rotation.X;
            var y2  = rotation.Y + rotation.Y;
            var z2  = rotation.Z + rotation.Z;
            var xx2 = rotation.X * x2;
            var xy2 = rotation.X * y2;
            var xz2 = rotation.X * z2;
            var yy2 = rotation.Y * y2;
            var yz2 = rotation.Y * z2;
            var zz2 = rotation.Z * z2;
            var wx2 = rotation.W * x2;
            var wy2 = rotation.W * y2;
            var wz2 = rotation.W * z2;

            x.X = Vector <float> .One - yy2 - zz2;
            x.Y = xy2 + wz2;
            x.Z = xz2 - wy2;
            y.X = xy2 - wz2;
            y.Y = Vector <float> .One - xx2 - zz2;
            y.Z = yz2 + wx2;
        }
        public static void TransformWithoutOverlap(ref Vector3Wide v, ref QuaternionWide rotation, out Vector3Wide result)
        {
            //This operation is an optimized-down version of v' = q * v * q^-1.
            //The expanded form would be to treat v as an 'axis only' quaternion
            //and perform standard quaternion multiplication.  Assuming q is normalized,
            //q^-1 can be replaced by a conjugation.
            var x2  = rotation.X + rotation.X;
            var y2  = rotation.Y + rotation.Y;
            var z2  = rotation.Z + rotation.Z;
            var xx2 = rotation.X * x2;
            var xy2 = rotation.X * y2;
            var xz2 = rotation.X * z2;
            var yy2 = rotation.Y * y2;
            var yz2 = rotation.Y * z2;
            var zz2 = rotation.Z * z2;
            var wx2 = rotation.W * x2;
            var wy2 = rotation.W * y2;
            var wz2 = rotation.W * z2;

            result.X = v.X * (Vector <float> .One - yy2 - zz2) + v.Y * (xy2 - wz2) + v.Z * (xz2 + wy2);
            result.Y = v.X * (xy2 + wz2) + v.Y * (Vector <float> .One - xx2 - zz2) + v.Z * (yz2 - wx2);
            result.Z = v.X * (xz2 - wy2) + v.Y * (yz2 + wx2) + v.Z * (Vector <float> .One - xx2 - yy2);
        }
 public static void GetLength(ref QuaternionWide q, out Vector <float> length)
 {
     length = Vector.SquareRoot(q.X * q.X + q.Y * q.Y + q.Z * q.Z + q.W * q.W);
 }
 public static void GetLengthSquared(ref QuaternionWide q, out Vector <float> lengthSquared)
 {
     lengthSquared = q.X * q.X + q.Y * q.Y + q.Z * q.Z + q.W * q.W;
 }
        /// <summary>
        /// Computes the quaternion rotation between two normalized vectors.
        /// </summary>
        /// <param name="v1">First unit-length vector.</param>
        /// <param name="v2">Second unit-length vector.</param>
        /// <param name="q">Quaternion representing the rotation from v1 to v2.</param>
        public static void GetQuaternionBetweenNormalizedVectors(ref Vector3Wide v1, ref Vector3Wide v2, out QuaternionWide q)
        {
            Vector3Wide.Dot(ref v1, ref v2, out var dot);
            //For non-normal vectors, the multiplying the axes length squared would be necessary:
            //float w = dot + Sqrt(v1.LengthSquared() * v2.LengthSquared());


            //There exists an ambiguity at dot == -1. If the directions point away from each other, there are an infinite number of shortest paths.
            //One must be chosen arbitrarily. Here, we choose one by projecting onto the plane whose normal is associated with the smallest magnitude.
            //Since this is a SIMD operation, the special case is always executed and its result is conditionally selected.

            Vector3Wide.CrossWithoutOverlap(ref v1, ref v2, out var cross);
            var useNormalCase = Vector.GreaterThan(dot, new Vector <float>(-0.999999f));
            var absX          = Vector.Abs(v1.X);
            var absY          = Vector.Abs(v1.Y);
            var absZ          = Vector.Abs(v1.Z);
            var xIsSmallest   = Vector.BitwiseAnd(Vector.LessThan(absX, absY), Vector.LessThan(absX, absZ));
            var yIsSmaller    = Vector.LessThan(absY, absZ);

            q.X = Vector.ConditionalSelect(useNormalCase, cross.X, Vector.ConditionalSelect(xIsSmallest, Vector <float> .Zero, Vector.ConditionalSelect(yIsSmaller, -v1.Z, -v1.Y)));
            q.Y = Vector.ConditionalSelect(useNormalCase, cross.Y, Vector.ConditionalSelect(xIsSmallest, -v1.Z, Vector.ConditionalSelect(yIsSmaller, Vector <float> .Zero, v1.X)));
            q.Z = Vector.ConditionalSelect(useNormalCase, cross.Z, Vector.ConditionalSelect(xIsSmallest, v1.Y, Vector.ConditionalSelect(yIsSmaller, v1.X, Vector <float> .Zero)));
            q.W = Vector.ConditionalSelect(useNormalCase, dot + Vector <float> .One, Vector <float> .Zero);

            Normalize(ref q, out q);
        }
        public static void Transform(ref Vector3Wide v, ref QuaternionWide rotation, out Vector3Wide result)
        {
            var tempV = v;

            TransformWithoutOverlap(ref tempV, ref rotation, out result);
        }