protected internal override void ComputeEffectiveMass()
        {
            //For all constraints, the effective mass matrix is 1 / (J * M^-1 * JT).
            //For single bone constraints, J has 2 3x3 matrices. M^-1 (W below) is a 6x6 matrix with 2 3x3 block diagonal matrices.
            //To compute the whole denominator,
            Matrix3f linearW;

            Matrix3f.CreateScale(TargetBone.inverseMass, out linearW);
            Matrix3f linear;

            Matrix3f.Multiply(ref linearJacobian, ref linearW, out linear);            //Compute J * M^-1 for linear component
            Matrix3f.MultiplyByTransposed(ref linear, ref linearJacobian, out linear); //Compute (J * M^-1) * JT for linear component

            Matrix3f angular;

            Matrix3f.Multiply(ref angularJacobian, ref TargetBone.inertiaTensorInverse, out angular); //Compute J * M^-1 for angular component
            Matrix3f.MultiplyByTransposed(ref angular, ref angularJacobian, out angular);             //Compute (J * M^-1) * JT for angular component

            //A nice side effect of the block diagonal nature of M^-1 is that the above separated components are now combined into the complete denominator matrix by addition!
            Matrix3f.Add(ref linear, ref angular, out effectiveMass);

            //Incorporate the constraint softness into the effective mass denominator. This pushes the matrix away from singularity.
            //Softness will also be incorporated into the velocity solve iterations to complete the implementation.
            if (effectiveMass.M11 != 0)
            {
                effectiveMass.M11 += softness;
            }
            if (effectiveMass.M22 != 0)
            {
                effectiveMass.M22 += softness;
            }
            if (effectiveMass.M33 != 0)
            {
                effectiveMass.M33 += softness;
            }

            //Invert! Takes us from J * M^-1 * JT to 1 / (J * M^-1 * JT).
            Matrix3f.AdaptiveInvert(ref effectiveMass, out effectiveMass);
        }
Example #2
0
        protected internal override void ComputeEffectiveMass()
        {
            //For all constraints, the effective mass matrix is 1 / (J * M^-1 * JT).
            //For two bone constraints, J has 4 3x3 matrices. M^-1 (W below) is a 12x12 matrix with 4 3x3 block diagonal matrices.
            //To compute the whole denominator,
            Matrix3f linearW;
            Matrix3f linearA, angularA, linearB, angularB;

            if (!ConnectionA.Pinned)
            {
                Matrix3f.CreateScale(ConnectionA.inverseMass, out linearW);
                Matrix3f.Multiply(ref linearJacobianA, ref linearW, out linearA);                            //Compute J * M^-1 for linear component
                Matrix3f.MultiplyByTransposed(ref linearA, ref linearJacobianA, out linearA);                //Compute (J * M^-1) * JT for linear component

                Matrix3f.Multiply(ref angularJacobianA, ref ConnectionA.inertiaTensorInverse, out angularA); //Compute J * M^-1 for angular component
                Matrix3f.MultiplyByTransposed(ref angularA, ref angularJacobianA, out angularA);             //Compute (J * M^-1) * JT for angular component
            }
            else
            {
                //Treat pinned bones as if they have infinite inertia.
                linearA  = new Matrix3f();
                angularA = new Matrix3f();
            }

            if (!ConnectionB.Pinned)
            {
                Matrix3f.CreateScale(ConnectionB.inverseMass, out linearW);
                Matrix3f.Multiply(ref linearJacobianB, ref linearW, out linearB);                            //Compute J * M^-1 for linear component
                Matrix3f.MultiplyByTransposed(ref linearB, ref linearJacobianB, out linearB);                //Compute (J * M^-1) * JT for linear component

                Matrix3f.Multiply(ref angularJacobianB, ref ConnectionB.inertiaTensorInverse, out angularB); //Compute J * M^-1 for angular component
                Matrix3f.MultiplyByTransposed(ref angularB, ref angularJacobianB, out angularB);             //Compute (J * M^-1) * JT for angular component
            }
            else
            {
                //Treat pinned bones as if they have infinite inertia.
                linearB  = new Matrix3f();
                angularB = new Matrix3f();
            }

            //A nice side effect of the block diagonal nature of M^-1 is that the above separated components are now combined into the complete denominator matrix by addition!
            Matrix3f.Add(ref linearA, ref angularA, out effectiveMass);
            Matrix3f.Add(ref effectiveMass, ref linearB, out effectiveMass);
            Matrix3f.Add(ref effectiveMass, ref angularB, out effectiveMass);

            //Incorporate the constraint softness into the effective mass denominator. This pushes the matrix away from singularity.
            //Softness will also be incorporated into the velocity solve iterations to complete the implementation.
            if (effectiveMass.M11 != 0)
            {
                effectiveMass.M11 += softness;
            }
            if (effectiveMass.M22 != 0)
            {
                effectiveMass.M22 += softness;
            }
            if (effectiveMass.M33 != 0)
            {
                effectiveMass.M33 += softness;
            }

            //Invert! Takes us from J * M^-1 * JT to 1 / (J * M^-1 * JT).
            Matrix3f.AdaptiveInvert(ref effectiveMass, out effectiveMass);
        }