예제 #1
0
        /**
         * Returns a new Matrix composed by the passed scale (vector3), rotation (quaternion) and translation (vector3).
         */
        public static BabylonMatrix Compose(BabylonVector3 scale, BabylonQuaternion rotation, BabylonVector3 translation)
        {
            var result = BabylonMatrix.Identity();

            BabylonMatrix.ComposeToRef(scale, rotation, translation, result);
            return(result);
        }
예제 #2
0
        public static BabylonQuaternion FromEulerAngles(float x, float y, float z)
        {
            var q = new BabylonQuaternion();

            BabylonQuaternion.RotationYawPitchRollToRef(y, x, z, q);
            return(q);
        }
예제 #3
0
        public static BabylonQuaternion Slerp(BabylonQuaternion left, BabylonQuaternion right, float amount)
        {
            float num2;
            float num3;
            float num4 = (((left.X * right.X) + (left.Y * right.Y)) + (left.Z * right.Z)) + (left.W * right.W);
            bool  flag = false;

            if (num4 < 0)
            {
                flag = true;
                num4 = -num4;
            }

            if (num4 > 0.999999)
            {
                num3 = 1 - amount;
                num2 = flag ? -amount : amount;
            }
            else
            {
                var num5 = Math.Acos((double)num4);
                var num6 = (1.0 / Math.Sin((double)num5));
                num3 = (float)((Math.Sin((1.0 - (double)amount) * (double)num5)) * (double)num6);
                num2 = (float)(flag ? ((-Math.Sin((double)amount * num5)) * num6) : ((Math.Sin((double)amount * num5)) * num6));
            }
            BabylonQuaternion result = new BabylonQuaternion()
            {
                X = (num3 * left.X) + (num2 * right.X),
                Y = (num3 * left.Y) + (num2 * right.Y),
                Z = (num3 * left.Z) + (num2 * right.Z),
                W = (num3 * left.W) + (num2 * right.W)
            };

            return(result);
        }
예제 #4
0
        // https://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors?s_tid=mwa_osa_a
        // https://github.com/mrdoob/three.js/blob/09cfc67a3f52aeb4dd0009921d82396fd5dc5172/src/math/Quaternion.js#L199-L272

        public BabylonQuaternion toQuaternion(EulerRotationOrder rotationOrder = EulerRotationOrder.XYZ)
        {
            BabylonQuaternion quaternion = new BabylonQuaternion();

            var c1 = Math.Cos(0.5 * this.X);
            var c2 = Math.Cos(0.5 * this.Y);
            var c3 = Math.Cos(0.5 * this.Z);

            var s1 = Math.Sin(0.5 * this.X);
            var s2 = Math.Sin(0.5 * this.Y);
            var s3 = Math.Sin(0.5 * this.Z);

            switch (rotationOrder)
            {
            case EulerRotationOrder.XYZ:
                quaternion.X = (float)(s1 * c2 * c3 + c1 * s2 * s3);
                quaternion.Y = (float)(c1 * s2 * c3 - s1 * c2 * s3);
                quaternion.Z = (float)(c1 * c2 * s3 + s1 * s2 * c3);
                quaternion.W = (float)(c1 * c2 * c3 - s1 * s2 * s3);
                break;

            case EulerRotationOrder.YZX:
                quaternion.X = (float)(s1 * c2 * c3 + c1 * s2 * s3);
                quaternion.Y = (float)(c1 * s2 * c3 + s1 * c2 * s3);
                quaternion.Z = (float)(c1 * c2 * s3 - s1 * s2 * c3);
                quaternion.W = (float)(c1 * c2 * c3 - s1 * s2 * s3);
                break;

            case EulerRotationOrder.ZXY:
                quaternion.X = (float)(s1 * c2 * c3 - c1 * s2 * s3);
                quaternion.Y = (float)(c1 * s2 * c3 + s1 * c2 * s3);
                quaternion.Z = (float)(c1 * c2 * s3 + s1 * s2 * c3);
                quaternion.W = (float)(c1 * c2 * c3 - s1 * s2 * s3);
                break;

            case EulerRotationOrder.XZY:
                quaternion.X = (float)(s1 * c2 * c3 - c1 * s2 * s3);
                quaternion.Y = (float)(c1 * s2 * c3 - s1 * c2 * s3);
                quaternion.Z = (float)(c1 * c2 * s3 + s1 * s2 * c3);
                quaternion.W = (float)(c1 * c2 * c3 + s1 * s2 * s3);
                break;

            case EulerRotationOrder.YXZ:
                quaternion.X = (float)(s1 * c2 * c3 + c1 * s2 * s3);
                quaternion.Y = (float)(c1 * s2 * c3 - s1 * c2 * s3);
                quaternion.Z = (float)(c1 * c2 * s3 - s1 * s2 * c3);
                quaternion.W = (float)(c1 * c2 * c3 + s1 * s2 * s3);
                break;

            case EulerRotationOrder.ZYX:
                quaternion.X = (float)(s1 * c2 * c3 - c1 * s2 * s3);
                quaternion.Y = (float)(c1 * s2 * c3 + s1 * c2 * s3);
                quaternion.Z = (float)(c1 * c2 * s3 - s1 * s2 * c3);
                quaternion.W = (float)(c1 * c2 * c3 + s1 * s2 * s3);
                break;
            }
            return(quaternion);
        }
예제 #5
0
        public BabylonQuaternion toQuaternionGltf()
        {
            BabylonQuaternion babylonQuaternion = RotationYawPitchRollToRefBabylon(X, -Y, -Z);
            // Doing following computation is ugly but works
            // The goal is to switch from left to right handed coordinate system
            // Swap X and Y
            var tmp = babylonQuaternion.X;

            babylonQuaternion.X = babylonQuaternion.Y;
            babylonQuaternion.Y = tmp;
            return(babylonQuaternion);
        }
예제 #6
0
        public BabylonQuaternion MultiplyWith(BabylonQuaternion quaternion)
        {
            BabylonQuaternion result = new BabylonQuaternion();

            // (a + i b + j c + k d)*(e + i f + j g + k h) = a*e - b*f - c*g- d*h + i (b*e + a*f + c*h - d*g) + j (a*g - b*h + c*e + d*f) + k (a*h + b*g - c*f + d*e)
            // W*q.W - X*q.X - Y*q.Y- Z*q.Z + i (X*q.W + W*q.X + Y*q.Z - Z*q.Y) + j (W*q.Y - X*q.Z + Y*q.W + Z*q.X) + k (W*q.Z + X*q.Y - Y*q.X + Z*q.W)
            result.W = W * quaternion.W - X * quaternion.X - Y * quaternion.Y - Z * quaternion.Z;
            result.X = X * quaternion.W + W * quaternion.X + Y * quaternion.Z - Z * quaternion.Y;
            result.Y = W * quaternion.Y - X * quaternion.Z + Y * quaternion.W + Z * quaternion.X;
            result.Z = W * quaternion.Z + X * quaternion.Y - Y * quaternion.X + Z * quaternion.W;

            return(result);
        }
예제 #7
0
        /**
         * Update a Matrix with values composed by the passed scale (vector3), rotation (quaternion) and translation (vector3).
         */
        public static void ComposeToRef(BabylonVector3 scale, BabylonQuaternion rotation, BabylonVector3 translation, BabylonMatrix result)
        {
            var matrix1 = new BabylonMatrix();

            BabylonMatrix.FromValuesToRef(scale.X, 0, 0, 0,
                                          0, scale.Y, 0, 0,
                                          0, 0, scale.Z, 0,
                                          0, 0, 0, 1, matrix1);

            var matrix0 = new BabylonMatrix();

            rotation.toRotationMatrix(matrix0);
            matrix1.multiplyToRef(matrix0, result);

            result.setTranslation(translation);
        }
예제 #8
0
        /**
         * Updates the passed quaternion "result" with the passed rotation matrix values.
         */
        public static void FromRotationMatrixToRef(BabylonMatrix matrix, BabylonQuaternion result)
        {
            var   data = matrix.m;
            float m11 = data[0], m12 = data[4], m13 = data[8];
            float m21 = data[1], m22 = data[5], m23 = data[9];
            float m31 = data[2], m32 = data[6], m33 = data[10];
            var   trace = m11 + m22 + m33;
            float s;

            if (trace > 0)
            {
                s = (float)(0.5 / Math.Sqrt(trace + 1.0));

                result.W = 0.25f / s;
                result.X = (m32 - m23) * s;
                result.Y = (m13 - m31) * s;
                result.Z = (m21 - m12) * s;
            }
            else if (m11 > m22 && m11 > m33)
            {
                s = (float)(2.0 * Math.Sqrt(1.0 + m11 - m22 - m33));

                result.W = (m32 - m23) / s;
                result.X = 0.25f * s;
                result.Y = (m12 + m21) / s;
                result.Z = (m13 + m31) / s;
            }
            else if (m22 > m33)
            {
                s = (float)(2.0 * Math.Sqrt(1.0 + m22 - m11 - m33));

                result.W = (m13 - m31) / s;
                result.X = (m12 + m21) / s;
                result.Y = 0.25f * s;
                result.Z = (m23 + m32) / s;
            }
            else
            {
                s = (float)(2.0 * Math.Sqrt(1.0 + m33 - m11 - m22));

                result.W = (m21 - m12) / s;
                result.X = (m13 + m31) / s;
                result.Y = (m23 + m32) / s;
                result.Z = 0.25f * s;
            }
        }
예제 #9
0
        /**
         * Returns a new Quaternion object, computed from the Vector3 coordinates.
         */
        public BabylonQuaternion toQuaternion()
        {
            var result = new BabylonQuaternion();

            var cosxPlusz  = Math.Cos((this.X + this.Z) * 0.5);
            var sinxPlusz  = Math.Sin((this.X + this.Z) * 0.5);
            var coszMinusx = Math.Cos((this.Z - this.X) * 0.5);
            var sinzMinusx = Math.Sin((this.Z - this.X) * 0.5);
            var cosy       = Math.Cos(this.Y * 0.5);
            var siny       = Math.Sin(this.Y * 0.5);

            result.X = (float)(coszMinusx * siny);
            result.Y = (float)(-sinzMinusx * siny);
            result.Z = (float)(sinxPlusz * cosy);
            result.W = (float)(cosxPlusz * cosy);
            return(result);
        }
예제 #10
0
        /**
         * (Copy pasted from babylon)
         * Sets the passed quaternion "result" from the passed float Euler angles (y, x, z).
         */
        private BabylonQuaternion RotationYawPitchRollToRefBabylon(float yaw, float pitch, float roll)
        {
            // Produces a quaternion from Euler angles in the z-y-x orientation (Tait-Bryan angles)
            var halfRoll  = roll * 0.5;
            var halfPitch = pitch * 0.5;
            var halfYaw   = yaw * 0.5;

            var sinRoll  = Math.Sin(halfRoll);
            var cosRoll  = Math.Cos(halfRoll);
            var sinPitch = Math.Sin(halfPitch);
            var cosPitch = Math.Cos(halfPitch);
            var sinYaw   = Math.Sin(halfYaw);
            var cosYaw   = Math.Cos(halfYaw);

            var result = new BabylonQuaternion();

            result.X = (float)((cosYaw * sinPitch * cosRoll) + (sinYaw * cosPitch * sinRoll));
            result.Y = (float)((sinYaw * cosPitch * cosRoll) - (cosYaw * sinPitch * sinRoll));
            result.Z = (float)((cosYaw * cosPitch * sinRoll) - (sinYaw * sinPitch * cosRoll));
            result.W = (float)((cosYaw * cosPitch * cosRoll) + (sinYaw * sinPitch * sinRoll));
            return(result);
        }
예제 #11
0
        /**
         * Decomposes the current Matrix into :
         * - a scale vector3 passed as a reference to update,
         * - a rotation quaternion passed as a reference to update,
         * - a translation vector3 passed as a reference to update.
         * Returns the boolean `true`.
         */
        public bool decompose(BabylonVector3 scale, BabylonQuaternion rotation, BabylonVector3 translation)
        {
            translation.X = this.m[12];
            translation.Y = this.m[13];
            translation.Z = this.m[14];

            scale.X = (float)Math.Sqrt(this.m[0] * this.m[0] + this.m[1] * this.m[1] + this.m[2] * this.m[2]);
            scale.Y = (float)Math.Sqrt(this.m[4] * this.m[4] + this.m[5] * this.m[5] + this.m[6] * this.m[6]);
            scale.Z = (float)Math.Sqrt(this.m[8] * this.m[8] + this.m[9] * this.m[9] + this.m[10] * this.m[10]);

            if (this.determinant() <= 0)
            {
                scale.Y *= -1;
            }

            if (scale.X == 0 || scale.Y == 0 || scale.Z == 0)
            {
                rotation.X = 0;
                rotation.Y = 0;
                rotation.Z = 0;
                rotation.W = 1;
                return(false);
            }

            var matrix = new BabylonMatrix();

            BabylonMatrix.FromValuesToRef(
                this.m[0] / scale.X, this.m[1] / scale.X, this.m[2] / scale.X, 0,
                this.m[4] / scale.Y, this.m[5] / scale.Y, this.m[6] / scale.Y, 0,
                this.m[8] / scale.Z, this.m[9] / scale.Z, this.m[10] / scale.Z, 0,
                0, 0, 0, 1, matrix);

            BabylonQuaternion.FromRotationMatrixToRef(matrix, rotation);

            return(true);
        }
예제 #12
0
        public static float[] Interpolate(BabylonAnimation animation, BabylonAnimationKey fromKey, BabylonAnimationKey toKey, float frame)
        {
            switch (animation.property)
            {
            case "_matrix":
                var fromMatrix = new BabylonMatrix();
                fromMatrix.m = new List <float>(fromKey.values).ToArray();
                var toMatrix = new BabylonMatrix();
                toMatrix.m = new List <float>(toKey.values).ToArray();
                var fromPosition = new BabylonVector3();
                var fromRotation = new BabylonQuaternion();
                var fromScaling  = new BabylonVector3();
                var toPosition   = new BabylonVector3();
                var toRotation   = new BabylonQuaternion();
                var toScaling    = new BabylonVector3();

                fromMatrix.decompose(fromScaling, fromRotation, fromPosition);
                toMatrix.decompose(toScaling, toRotation, toPosition);

                var lerpFactor = MathUtilities.GetLerpFactor(fromKey.frame, toKey.frame, frame);

                var interpolatedKeyPosition = BabylonVector3.FromArray(MathUtilities.Lerp(fromPosition.ToArray(), toPosition.ToArray(), lerpFactor));
                var interpolatedKeyRotation = BabylonQuaternion.Slerp(fromRotation, toRotation, lerpFactor);
                var interpolatedKeyScaling  = BabylonVector3.FromArray(MathUtilities.Lerp(fromScaling.ToArray(), toScaling.ToArray(), lerpFactor));

                return(BabylonMatrix.Compose(interpolatedKeyScaling, interpolatedKeyRotation, interpolatedKeyPosition).m);

            case "rotationQuaternion":
                return(BabylonQuaternion.Slerp(BabylonQuaternion.FromArray(fromKey.values), BabylonQuaternion.FromArray(toKey.values), MathUtilities.GetLerpFactor(fromKey.frame, toKey.frame, frame)).ToArray());

            case "scaling":
            case "position":
            default:
                return(MathUtilities.Lerp(fromKey.values, toKey.values, MathUtilities.GetLerpFactor(fromKey.frame, toKey.frame, frame)));
            }
        }