continue working on the slider joint

This commit is contained in:
Daniel Chappuis 2013-05-12 12:43:07 +02:00
parent f23096af50
commit 0f17bd1b0b
8 changed files with 188 additions and 10 deletions

View File

@ -78,6 +78,38 @@ void BallAndSocketJoint::initBeforeSolve(const ConstraintSolverData& constraintS
mInverseMassMatrix = massMatrix.getInverse();
}
// Warm start the constraint (apply the previous impulse at the beginning of the step)
void BallAndSocketJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
// Get the velocities
Vector3& v1 = constraintSolverData.linearVelocities[mIndexBody1];
Vector3& v2 = constraintSolverData.linearVelocities[mIndexBody2];
Vector3& w1 = constraintSolverData.angularVelocities[mIndexBody1];
Vector3& w2 = constraintSolverData.angularVelocities[mIndexBody2];
// Get the inverse mass and inverse inertia tensors of the bodies
decimal inverseMassBody1 = mBody1->getMassInverse();
decimal inverseMassBody2 = mBody2->getMassInverse();
Matrix3x3 I1 = mBody1->getInertiaTensorInverseWorld();
Matrix3x3 I2 = mBody2->getInertiaTensorInverseWorld();
// Compute the impulse P=J^T * lambda
Vector3 linearImpulseBody1 = -mImpulse;
Vector3 angularImpulseBody1 = mImpulse.cross(mU1World);
Vector3 linearImpulseBody2 = mImpulse;
Vector3 angularImpulseBody2 = -mImpulse.cross(mU2World);
// Apply the impulse to the bodies of the joint
if (mBody1->getIsMotionEnabled()) {
v1 += inverseMassBody1 * linearImpulseBody1;
w1 += I1 * angularImpulseBody1;
}
if (mBody2->getIsMotionEnabled()) {
v2 += inverseMassBody2 * linearImpulseBody2;
w2 += I2 * angularImpulseBody2;
}
}
// Solve the velocity constraint
void BallAndSocketJoint::solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) {
@ -94,8 +126,8 @@ void BallAndSocketJoint::solveVelocityConstraint(const ConstraintSolverData& con
// Get the inverse mass and inverse inertia tensors of the bodies
decimal inverseMassBody1 = mBody1->getMassInverse();
decimal inverseMassBody2 = mBody2->getMassInverse();
Matrix3x3 inverseInertiaTensorBody1 = mBody1->getInertiaTensorInverseWorld();
Matrix3x3 inverseInertiaTensorBody2 = mBody2->getInertiaTensorInverseWorld();
Matrix3x3 I1 = mBody1->getInertiaTensorInverseWorld();
Matrix3x3 I2 = mBody2->getInertiaTensorInverseWorld();
// Compute J*v
Vector3 Jv = -v1 + mU1World.cross(w1) + v2 - mU2World.cross(w2);
@ -121,11 +153,11 @@ void BallAndSocketJoint::solveVelocityConstraint(const ConstraintSolverData& con
// Apply the impulse to the bodies of the joint
if (mBody1->getIsMotionEnabled()) {
v1 += inverseMassBody1 * linearImpulseBody1;
w1 += inverseInertiaTensorBody1 * angularImpulseBody1;
w1 += I1 * angularImpulseBody1;
}
if (mBody2->getIsMotionEnabled()) {
v2 += inverseMassBody2 * linearImpulseBody2;
w2 += inverseInertiaTensorBody2 * angularImpulseBody2;
w2 += I2 * angularImpulseBody2;
}
}

View File

@ -104,6 +104,9 @@ class BallAndSocketJoint : public Constraint {
/// Initialize before solving the constraint
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
/// Solve the velocity constraint
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);

View File

@ -149,6 +149,9 @@ class Constraint {
/// Initialize before solving the constraint
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData) = 0;
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
virtual void warmstart(const ConstraintSolverData& constraintSolverData) = 0;
/// Solve the velocity constraint
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) = 0;

View File

@ -56,6 +56,11 @@ void ContactPoint::initBeforeSolve(const ConstraintSolverData& constraintSolverD
}
// Warm start the constraint (apply the previous impulse at the beginning of the step)
void ContactPoint::warmstart(const ConstraintSolverData& constraintSolverData) {
}
// Solve the velocity constraint
void ContactPoint::solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) {

View File

@ -227,6 +227,9 @@ class ContactPoint : public Constraint {
/// Initialize before solving the constraint
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
/// Solve the velocity constraint
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);

View File

@ -29,7 +29,8 @@
using namespace reactphysics3d;
// Constructor
SliderJoint::SliderJoint(const SliderJointInfo& jointInfo) : Constraint(jointInfo) {
SliderJoint::SliderJoint(const SliderJointInfo& jointInfo)
: Constraint(jointInfo), mImpulseTranslation(0, 0), mImpulseRotation(0, 0, 0) {
// Compute the local-space anchor point for each body
mLocalAnchorPointBody1 = mBody1->getTransform().getInverse() * jointInfo.anchorPointWorldSpace;
@ -64,17 +65,76 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
mN1 = mU1World.getOneUnitOrthogonalVector();
mN2 = mU1World.cross(mN1);
// Compute the cross product used in the Jacobian
// Compute the cross products used in the Jacobian
mU1WorldCrossN1 = mN2;
mU1WorldCrossN2 = mU1World.cross(mN2);
mU2WorldCrossN1 = mU2World.cross(mN1);
mU2WorldCrossN2 = mU2World.cross(mN2);
// Compute the mass matrix K=JM^-1J^t for the 2 translation constraints (2x2 matrix)
// Compute the inverse of the mass matrix K=JM^-1J^t for the 2 translation
// constraints (2x2 matrix)
const decimal n1Dotn1 = mN1.lengthSquare();
const decimal n2Dotn2 = mN2.lengthSquare();
const decimal n1Dotn2 = mN1.dot(mN2);
const decimal sumInverseMass = mBody1->getMassInverse() + mBody2->getMassInverse();
const Vector3 I1U2CrossN1 = I1 * mU2WorldCrossN1;
const Vector3 I1U2CrossN2 = I1 * mU2WorldCrossN2;
const Vector3 I2U1CrossN1 = I2 * mU1WorldCrossN1;
const Vector3 I2U1CrossN2 = I2 * mU1WorldCrossN2;
const decimal el11 = sumInverseMass * (n1Dotn1) + mU2WorldCrossN1.dot(I1U2CrossN1) +
mU1WorldCrossN1.dot(I2U1CrossN1);
const decimal el12 = sumInverseMass * (n1Dotn2) + mU2WorldCrossN1.dot(I1U2CrossN2) +
mU1WorldCrossN1.dot(I2U1CrossN2);
const decimal el21 = sumInverseMass * (n1Dotn2) + mU2WorldCrossN2.dot(I1U2CrossN1) +
mU1WorldCrossN2.dot(I2U1CrossN1);
const decimal el22 = sumInverseMass * (n2Dotn2) + mU2WorldCrossN2.dot(I1U2CrossN2) +
mU1WorldCrossN2.dot(I2U1CrossN2);
Matrix2x2 matrixKTranslation(el11, el12, el21, el22);
mInverseMassMatrixTranslationConstraint = matrixKTranslation.getInverse();
// Compute the inverse of the mass matrix K=JM^-1J^t for the 3 rotation
// contraints (3x3 matrix)
mInverseMassMatrixRotationConstraint = I1 + I2;
}
// Warm start the constraint (apply the previous impulse at the beginning of the step)
void SliderJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
// Get the velocities
Vector3& v1 = constraintSolverData.linearVelocities[mIndexBody1];
Vector3& v2 = constraintSolverData.linearVelocities[mIndexBody2];
Vector3& w1 = constraintSolverData.angularVelocities[mIndexBody1];
Vector3& w2 = constraintSolverData.angularVelocities[mIndexBody2];
// Get the inverse mass and inverse inertia tensors of the bodies
decimal inverseMassBody1 = mBody1->getMassInverse();
decimal inverseMassBody2 = mBody2->getMassInverse();
const Matrix3x3 I1 = mBody1->getInertiaTensorInverseWorld();
const Matrix3x3 I2 = mBody2->getInertiaTensorInverseWorld();
// Compute the impulse P=J^T * lambda for the 2 translation constraints
Vector3 linearImpulseBody1 = -mN1 * mImpulseTranslation.x -
mN2 * mImpulseTranslation.y;
Vector3 angularImpulseBody1 = mU2WorldCrossN1 * mImpulseTranslation.x +
mU2WorldCrossN2 * mImpulseTranslation.y;
Vector3 linearImpulseBody2 = mN1 * mImpulseTranslation.x +
mN2 * mImpulseTranslation.y;
Vector3 angularImpulseBody2 = -mU1WorldCrossN1 * mImpulseTranslation.x -
mU1WorldCrossN2 * mImpulseTranslation.y;
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
angularImpulseBody1 += -mImpulseRotation;
angularImpulseBody2 += mImpulseRotation;
// Apply the impulse to the bodies of the joint
if (mBody1->getIsMotionEnabled()) {
v1 += inverseMassBody1 * linearImpulseBody1;
w1 += I1 * angularImpulseBody1;
}
if (mBody2->getIsMotionEnabled()) {
v2 += inverseMassBody2 * linearImpulseBody2;
w2 += I2 * angularImpulseBody2;
}
}
// Solve the velocity constraint
@ -93,10 +153,65 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
// Get the inverse mass and inverse inertia tensors of the bodies
decimal inverseMassBody1 = mBody1->getMassInverse();
decimal inverseMassBody2 = mBody2->getMassInverse();
Matrix3x3 inverseInertiaTensorBody1 = mBody1->getInertiaTensorInverseWorld();
Matrix3x3 inverseInertiaTensorBody2 = mBody2->getInertiaTensorInverseWorld();
const Matrix3x3 I1 = mBody1->getInertiaTensorInverseWorld();
const Matrix3x3 I2 = mBody2->getInertiaTensorInverseWorld();
// Compute J*v
// Compute J*v for the 2 translation constraints
const decimal el1 = -mN1.dot(v1) + mU2WorldCrossN1.dot(w1) +
mN1.dot(v2) - mU1WorldCrossN1.dot(w2);
const decimal el2 = -mN2.dot(v1) + mU2WorldCrossN2.dot(w1) +
mN2.dot(v2) - mU1WorldCrossN2.dot(w2);
const Vector2 JvTranslation(el1, el2);
// Compute J*v for the 3 translation constraints
const Vector3 JvRotation = w2 - w1;
// Compute the bias "b" of the translation constraint
Vector2 bTranslation(0, 0);
decimal beta = decimal(0.2); // TODO : Use a constant here
decimal biasFactor = (beta / constraintSolverData.timeStep);
if (mPositionCorrectionTechnique == BAUMGARTE_JOINTS) {
Vector3 deltaV = x2 + mU2World - x1 - mU1World;
bTranslation.x = biasFactor * deltaV.dot(mN1);
bTranslation.y = biasFactor * deltaV.dot(mN2);
}
// Compute the bias "b" of the translation constraint
Vector3 bRotation(0, 0, 0);
if (mPositionCorrectionTechnique == BAUMGARTE_JOINTS) {
Quaternion q1 = mBody1->getTransform().getOrientation();
Quaternion q2 = mBody2->getTransform().getOrientation();
Quaternion qDiff = q1 * q2.getInverse();
bRotation = 2.0 * qDiff.getVectorV();
}
// Compute the Lagrange multiplier lambda for the 2 translation constraints
Vector2 deltaLambda = mInverseMassMatrixTranslationConstraint * (-JvTranslation - bTranslation);
mImpulseTranslation += deltaLambda;
// Compute the Lagrange multiplier lambda for the 3 rotation constraints
Vector3 deltaLambda2 = mInverseMassMatrixRotationConstraint * (-JvRotation - bRotation);
mImpulseRotation += deltaLambda2;
// Compute the impulse P=J^T * lambda for the 2 translation constraints
Vector3 linearImpulseBody1 = -mN1 * deltaLambda.x - mN2 * deltaLambda.y;
Vector3 angularImpulseBody1 = mU2WorldCrossN1 * deltaLambda.x + mU2WorldCrossN2 * deltaLambda.y;
Vector3 linearImpulseBody2 = mN1 * deltaLambda.x + mN2 * deltaLambda.y;
Vector3 angularImpulseBody2 = -mU1WorldCrossN1 * deltaLambda.x -mU1WorldCrossN2 * deltaLambda.y;
// Compute the impulse P=J^T * lambda for the 3 rotation constraints
angularImpulseBody1 += -deltaLambda2;
angularImpulseBody2 += deltaLambda2;
// Apply the impulse to the bodies of the joint
if (mBody1->getIsMotionEnabled()) {
v1 += inverseMassBody1 * linearImpulseBody1;
w1 += I1 * angularImpulseBody1;
}
if (mBody2->getIsMotionEnabled()) {
v2 += inverseMassBody2 * linearImpulseBody2;
w2 += I2 * angularImpulseBody2;
}
}
// Solve the position constraint

View File

@ -98,6 +98,18 @@ class SliderJoint : public Constraint {
/// Cross product of mU2World and mN2
Vector3 mU2WorldCrossN2;
/// Inverse of mass matrix K=JM^-1J^t for the translation constraint (2x2 matrix)
Matrix2x2 mInverseMassMatrixTranslationConstraint;
/// Inverse of mass matrix K=JM^-1J^t for the rotation constraint (3x3 matrix)
Matrix3x3 mInverseMassMatrixRotationConstraint;
/// Impulse for the 2 translation constraints
Vector2 mImpulseTranslation;
/// Impulse for the 3 rotation constraints
Vector3 mImpulseRotation;
public :
// -------------------- Methods -------------------- //
@ -114,6 +126,9 @@ class SliderJoint : public Constraint {
/// Initialize before solving the constraint
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
/// Solve the velocity constraint
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);

View File

@ -28,8 +28,10 @@
// Libraries
#include "Matrix3x3.h"
#include "Matrix2x2.h"
#include "Quaternion.h"
#include "Vector3.h"
#include "Vector2.h"
#include "Transform.h"
#include "../configuration.h"
#include "mathematics_functions.h"