Пример #1
0
        // for two constraints on the same rigidbody (for example vehicle friction)
        public float GetNonDiagonal(JacobianEntry jacB, float massInvA)
        {
            JacobianEntry jacA = this;
            float         lin  = massInvA * IndexedVector3.Dot(jacA.m_linearJointAxis, jacB.m_linearJointAxis);
            float         ang  = IndexedVector3.Dot(jacA.m_0MinvJt, jacB.m_aJ);

            return(lin + ang);
        }
Пример #2
0
        ///bilateral constraint between two dynamic objects
        ///positive distance = separation, negative distance = penetration
        public static void ResolveSingleBilateral(RigidBody body1, ref IndexedVector3 pos1,
                                                  RigidBody body2, ref IndexedVector3 pos2,
                                                  float distance, ref IndexedVector3 normal, ref float impulse, float timeStep)
        {
            float normalLenSqr = normal.LengthSquared();

            Debug.Assert(Math.Abs(normalLenSqr) < 1.1f);
            if (normalLenSqr > 1.1f)
            {
                impulse = 0f;
                return;
            }
            IndexedVector3 rel_pos1 = pos1 - body1.GetCenterOfMassPosition();
            IndexedVector3 rel_pos2 = pos2 - body2.GetCenterOfMassPosition();
            //this jacobian entry could be re-used for all iterations

            IndexedVector3 vel1 = body1.GetVelocityInLocalPoint(ref rel_pos1);
            IndexedVector3 vel2 = body2.GetVelocityInLocalPoint(ref rel_pos2);
            IndexedVector3 vel  = vel1 - vel2;

            IndexedBasisMatrix m1 = body1.GetCenterOfMassTransform()._basis.Transpose();
            IndexedBasisMatrix m2 = body2.GetCenterOfMassTransform()._basis.Transpose();


            JacobianEntry jac = new JacobianEntry(m1, m2, rel_pos1, rel_pos2, normal,
                                                  body1.GetInvInertiaDiagLocal(), body1.GetInvMass(),
                                                  body2.GetInvInertiaDiagLocal(), body2.GetInvMass());

            float jacDiagAB    = jac.GetDiagonal();
            float jacDiagABInv = 1f / jacDiagAB;


            float rel_vel = jac.GetRelativeVelocity(
                body1.GetLinearVelocity(),
                body1.GetCenterOfMassTransform()._basis.Transpose() * body1.GetAngularVelocity(),
                body2.GetLinearVelocity(),
                body2.GetCenterOfMassTransform()._basis.Transpose() * body2.GetAngularVelocity());
            float a = jacDiagABInv;

            rel_vel = normal.Dot(ref vel);

            //todo: move this into proper structure
            float contactDamping = 0.2f;

            if (ONLY_USE_LINEAR_MASS)
            {
                float massTerm = 1f / (body1.GetInvMass() + body2.GetInvMass());
                impulse = -contactDamping * rel_vel * massTerm;
            }
            else
            {
                float velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
                impulse = velocityImpulse;
            }
        }
Пример #3
0
        // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
        public float GetNonDiagonal(JacobianEntry jacB, float massInvA, float massInvB)
        {
            JacobianEntry  jacA = this;
            IndexedVector3 lin  = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
            IndexedVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
            IndexedVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
            IndexedVector3 lin0 = massInvA * lin;
            IndexedVector3 lin1 = massInvB * lin;
            IndexedVector3 sum  = ang0 + ang1 + lin0 + lin1;

            return(sum.X + sum.Y + sum.Z);
        }
Пример #4
0
	// for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
	public float GetNonDiagonal(JacobianEntry jacB,float massInvA,float massInvB)
	{
		JacobianEntry jacA = this;
		IndexedVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
		IndexedVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
		IndexedVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
		IndexedVector3 lin0 = massInvA * lin ;
		IndexedVector3 lin1 = massInvB * lin;
		IndexedVector3 sum = ang0+ang1+lin0+lin1;
		return sum.X+sum.Y+sum.Z;
	}
Пример #5
0
	// for two constraints on the same rigidbody (for example vehicle friction)
	public float GetNonDiagonal(JacobianEntry jacB, float massInvA)
	{
		JacobianEntry jacA = this;
		float lin = massInvA * IndexedVector3.Dot(jacA.m_linearJointAxis,jacB.m_linearJointAxis);
		float ang = IndexedVector3.Dot(jacA.m_0MinvJt,jacB.m_aJ);
		return lin + ang;
	}
Пример #6
0
        //
        // solve unilateral raint (equality, direct method)
        //
        public void ResolveUnilateralPairConstraint(RigidBody body0, RigidBody body1, ref IndexedBasisMatrix world2A,
                                                    ref IndexedBasisMatrix world2B,
                                                    ref IndexedVector3 invInertiaADiag,
                                                    float invMassA,
                                                    ref IndexedVector3 linvelA, ref IndexedVector3 angvelA,
                                                    ref IndexedVector3 rel_posA1,
                                                    ref IndexedVector3 invInertiaBDiag,
                                                    float invMassB,
                                                    ref IndexedVector3 linvelB, ref IndexedVector3 angvelB,
                                                    ref IndexedVector3 rel_posA2,
                                                    float depthA, ref IndexedVector3 normalA,
                                                    ref IndexedVector3 rel_posB1, ref IndexedVector3 rel_posB2,
                                                    float depthB, ref IndexedVector3 normalB,
                                                    out float imp0, out float imp1)
        {
            //(void)linvelA;
            //(void)linvelB;
            //(void)angvelB;
            //(void)angvelA;

            imp0 = 0f;
            imp1 = 0f;

            float len = Math.Abs(normalA.Length()) - 1f;

            if (Math.Abs(len) >= MathUtil.SIMD_EPSILON)
            {
                return;
            }

            Debug.Assert(len < MathUtil.SIMD_EPSILON);

            //this jacobian entry could be re-used for all iterations
            JacobianEntry jacA = new JacobianEntry(ref world2A, ref world2B, ref rel_posA1, ref rel_posA2, ref normalA, ref invInertiaADiag, invMassA,
                                                   ref invInertiaBDiag, invMassB);
            JacobianEntry jacB = new JacobianEntry(ref world2A, ref world2B, ref rel_posB1, ref rel_posB2, ref normalB, ref invInertiaADiag, invMassA,
                                                   ref invInertiaBDiag, invMassB);

            // float vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
            // float vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);

            float vel0 = IndexedVector3.Dot(normalA, (body0.GetVelocityInLocalPoint(ref rel_posA1) - body1.GetVelocityInLocalPoint(ref rel_posA1)));
            float vel1 = IndexedVector3.Dot(normalB, (body0.GetVelocityInLocalPoint(ref rel_posB1) - body1.GetVelocityInLocalPoint(ref rel_posB1)));

            //	float penetrationImpulse = (depth*contactTau*timeCorrection)  * massTerm;//jacDiagABInv
            float massTerm = 1f / (invMassA + invMassB);


            // calculate rhs (or error) terms
            float dv0 = depthA * m_tau * massTerm - vel0 * m_damping;
            float dv1 = depthB * m_tau * massTerm - vel1 * m_damping;


            // dC/dv * dv = -C

            // jacobian * impulse = -error
            //

            //impulse = jacobianInverse * -error

            // inverting 2x2 symmetric system (offdiagonal are equal!)
            //


            float nonDiag = jacA.GetNonDiagonal(jacB, invMassA, invMassB);
            float invDet  = 1f / (jacA.GetDiagonal() * jacB.GetDiagonal() - nonDiag * nonDiag);

            //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
            //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;

            imp0 = dv0 * jacA.GetDiagonal() * invDet + dv1 * -nonDiag * invDet;
            imp1 = dv1 * jacB.GetDiagonal() * invDet + dv0 * -nonDiag * invDet;

            //[a b]								  [d -c]
            //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)

            //[jA nD] * [imp0] = [dv0]
            //[nD jB]   [imp1]   [dv1]
        }
Пример #7
0
		protected virtual void BuildAngularJacobian(out JacobianEntry jacAngular, ref IndexedVector3 jointAxisW)
		{
			jacAngular = new JacobianEntry(jointAxisW,
									  m_rbA.GetCenterOfMassTransform()._basis.Transpose(),
									  m_rbB.GetCenterOfMassTransform()._basis.Transpose(),
									  m_rbA.GetInvInertiaDiagLocal(),
									  m_rbB.GetInvInertiaDiagLocal());

		}
Пример #8
0
		protected virtual void BuildLinearJacobian(
			out JacobianEntry jacLinear, ref IndexedVector3 normalWorld,
			ref IndexedVector3 pivotAInW, ref IndexedVector3 pivotBInW)
		{
			jacLinear = new JacobianEntry(
				m_rbA.GetCenterOfMassTransform()._basis.Transpose(),
				m_rbB.GetCenterOfMassTransform()._basis.Transpose(),
				pivotAInW - m_rbA.GetCenterOfMassPosition(),
				pivotBInW - m_rbB.GetCenterOfMassPosition(),
				normalWorld,
				m_rbA.GetInvInertiaDiagLocal(),
				m_rbA.GetInvMass(),
				m_rbB.GetInvInertiaDiagLocal(),
				m_rbB.GetInvMass());
		}
Пример #9
0
	    //
	    // solve unilateral raint (equality, direct method)
	    //
        public void ResolveUnilateralPairConstraint(RigidBody body0, RigidBody body1, ref IndexedBasisMatrix world2A,
                            ref IndexedBasisMatrix world2B,
                            ref IndexedVector3 invInertiaADiag,
                            float invMassA,
                            ref IndexedVector3 linvelA, ref IndexedVector3 angvelA,
                            ref IndexedVector3 rel_posA1,
                            ref IndexedVector3 invInertiaBDiag,
                            float invMassB,
                            ref IndexedVector3 linvelB, ref IndexedVector3 angvelB,
                            ref IndexedVector3 rel_posA2,
                            float depthA, ref IndexedVector3 normalA,
                            ref IndexedVector3 rel_posB1, ref IndexedVector3 rel_posB2,
                            float depthB, ref IndexedVector3 normalB,
                            out float imp0, out float imp1)
        {
            //(void)linvelA;
            //(void)linvelB;
            //(void)angvelB;
            //(void)angvelA;

	        imp0 = 0f;
	        imp1 = 0f;

	        float len = Math.Abs(normalA.Length()) - 1f;
	        if (Math.Abs(len) >= MathUtil.SIMD_EPSILON)
		        return;

	        Debug.Assert(len < MathUtil.SIMD_EPSILON);

	        //this jacobian entry could be re-used for all iterations
	        JacobianEntry jacA = new JacobianEntry(ref world2A,ref world2B,ref rel_posA1,ref rel_posA2,ref normalA,ref invInertiaADiag,invMassA,
		        ref invInertiaBDiag,invMassB);
	        JacobianEntry jacB = new JacobianEntry(ref world2A,ref world2B,ref rel_posB1,ref rel_posB2,ref normalB,ref invInertiaADiag,invMassA,
		        ref invInertiaBDiag,invMassB);
        	
	        // float vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
	        // float vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);

	        float vel0 = IndexedVector3.Dot(normalA,(body0.GetVelocityInLocalPoint(ref rel_posA1)-body1.GetVelocityInLocalPoint(ref rel_posA1)));
	        float vel1 = IndexedVector3.Dot(normalB,(body0.GetVelocityInLocalPoint(ref rel_posB1)-body1.GetVelocityInLocalPoint(ref rel_posB1)));

        //	float penetrationImpulse = (depth*contactTau*timeCorrection)  * massTerm;//jacDiagABInv
	        float massTerm = 1f / (invMassA + invMassB);


	        // calculate rhs (or error) terms
	        float dv0 = depthA  * m_tau * massTerm - vel0 * m_damping;
	        float dv1 = depthB  * m_tau * massTerm - vel1 * m_damping;


	        // dC/dv * dv = -C
        	
	        // jacobian * impulse = -error
	        //

	        //impulse = jacobianInverse * -error

	        // inverting 2x2 symmetric system (offdiagonal are equal!)
	        // 


	        float nonDiag = jacA.GetNonDiagonal(jacB,invMassA,invMassB);
	        float invDet = 1f / (jacA.GetDiagonal() * jacB.GetDiagonal() - nonDiag * nonDiag );
        	
	        //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
	        //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;

	        imp0 = dv0 * jacA.GetDiagonal() * invDet + dv1 * -nonDiag * invDet;
	        imp1 = dv1 * jacB.GetDiagonal() * invDet + dv0 * - nonDiag * invDet;

	        //[a b]								  [d -c]
	        //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)

	        //[jA nD] * [imp0] = [dv0]
	        //[nD jB]   [imp1]   [dv1]
        }
        public override void BuildJacobian()
        {
            if (m_useSolveConstraintObsolete)
            {
                m_appliedImpulse = 0.0f;
                m_accTwistLimitImpulse = 0.0f;
                m_accSwingLimitImpulse = 0.0f;
                m_accMotorImpulse = IndexedVector3.Zero;

                if (!m_angularOnly)
                {
                    IndexedVector3 pivotAInW = m_rbA.GetCenterOfMassTransform() * m_rbAFrame._origin;
                    IndexedVector3 pivotBInW = m_rbB.GetCenterOfMassTransform() * m_rbBFrame._origin;
                    IndexedVector3 relPos = pivotBInW - pivotAInW;

                    IndexedVector3[] normal = new IndexedVector3[3];
                    if (relPos.LengthSquared() > MathUtil.SIMD_EPSILON)
                    {
                        normal[0] = relPos.Normalized();
                    }
                    else
                    {
                        normal[0] = new IndexedVector3(1.0f, 0, 0);
                    }

                    TransformUtil.PlaneSpace1(ref normal[0], out normal[1], out normal[2]);

                    for (int i = 0; i < 3; i++)
                    {
                        m_jac[i] = new JacobianEntry(
                        m_rbA.GetCenterOfMassTransform()._basis.Transpose(),
                        m_rbB.GetCenterOfMassTransform()._basis.Transpose(),
                        pivotAInW - m_rbA.GetCenterOfMassPosition(),
                        pivotBInW - m_rbB.GetCenterOfMassPosition(),
                        normal[i],
                        m_rbA.GetInvInertiaDiagLocal(),
                        m_rbA.GetInvMass(),
                        m_rbB.GetInvInertiaDiagLocal(),
                        m_rbB.GetInvMass());
                    }
                }

                CalcAngleInfo2(m_rbA.GetCenterOfMassTransform(), m_rbB.GetCenterOfMassTransform(), m_rbA.GetInvInertiaTensorWorld(), m_rbB.GetInvInertiaTensorWorld());
            }
        }
		///bilateral constraint between two dynamic objects
		///positive distance = separation, negative distance = penetration
		public static void ResolveSingleBilateral(RigidBody body1, ref IndexedVector3 pos1,
							  RigidBody body2, ref IndexedVector3 pos2,
							  float distance, ref IndexedVector3 normal, ref float impulse, float timeStep)
		{
			float normalLenSqr = normal.LengthSquared();
			Debug.Assert(Math.Abs(normalLenSqr) < 1.1f);
			if (normalLenSqr > 1.1f)
			{
				impulse = 0f;
				return;
			}
			IndexedVector3 rel_pos1 = pos1 - body1.GetCenterOfMassPosition();
			IndexedVector3 rel_pos2 = pos2 - body2.GetCenterOfMassPosition();
			//this jacobian entry could be re-used for all iterations

			IndexedVector3 vel1 = body1.GetVelocityInLocalPoint(ref rel_pos1);
			IndexedVector3 vel2 = body2.GetVelocityInLocalPoint(ref rel_pos2);
			IndexedVector3 vel = vel1 - vel2;

            IndexedBasisMatrix m1 = body1.GetCenterOfMassTransform()._basis.Transpose();
            IndexedBasisMatrix m2 = body2.GetCenterOfMassTransform()._basis.Transpose();


			JacobianEntry jac = new JacobianEntry(m1, m2, rel_pos1, rel_pos2, normal,
				body1.GetInvInertiaDiagLocal(), body1.GetInvMass(),
				body2.GetInvInertiaDiagLocal(), body2.GetInvMass());

			float jacDiagAB = jac.GetDiagonal();
			float jacDiagABInv = 1f / jacDiagAB;


			float rel_vel = jac.GetRelativeVelocity(
				body1.GetLinearVelocity(),
                body1.GetCenterOfMassTransform()._basis.Transpose() * body1.GetAngularVelocity(),
                body2.GetLinearVelocity(),
                body2.GetCenterOfMassTransform()._basis.Transpose() * body2.GetAngularVelocity());
            float a = jacDiagABInv;

			rel_vel = normal.Dot(ref vel);

			//todo: move this into proper structure
			float contactDamping = 0.2f;

			if (ONLY_USE_LINEAR_MASS)
			{
				float massTerm = 1f / (body1.GetInvMass() + body2.GetInvMass());
				impulse = -contactDamping * rel_vel * massTerm;
			}
			else
			{
				float velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
				impulse = velocityImpulse;
			}
		}