62
68
m_maxAngMotorForce = btScalar(0.);
63
69
m_accumulatedAngMotorImpulse = btScalar(0.0);
69
btSliderConstraint::btSliderConstraint()
70
:btTypedConstraint(SLIDER_CONSTRAINT_TYPE),
71
m_useLinearReferenceFrameA(true),
72
m_useSolveConstraintObsolete(false)
73
// m_useSolveConstraintObsolete(true)
74
m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME;
76
calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
80
83
btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
81
: btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB)
82
, m_frameInA(frameInA)
83
, m_frameInB(frameInB),
84
m_useLinearReferenceFrameA(useLinearReferenceFrameA),
85
m_useSolveConstraintObsolete(false)
86
// m_useSolveConstraintObsolete(true)
92
static btRigidBody s_fixed(0, 0, 0);
93
btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
94
: btTypedConstraint(SLIDER_CONSTRAINT_TYPE, s_fixed, rbB)
84
: btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
85
m_useSolveConstraintObsolete(false),
96
87
m_frameInB(frameInB),
97
m_useLinearReferenceFrameA(useLinearReferenceFrameB),
98
m_useSolveConstraintObsolete(false)
99
// m_useSolveConstraintObsolete(true)
101
///not providing rigidbody B means implicitly using worldspace for body B
88
m_useLinearReferenceFrameA(useLinearReferenceFrameA)
95
btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
96
: btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
97
m_useSolveConstraintObsolete(false),
99
m_useLinearReferenceFrameA(useLinearReferenceFrameA)
101
///not providing rigidbody A means implicitly using worldspace for body A
102
m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
102
103
// m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
109
void btSliderConstraint::buildJacobian()
111
if (!m_useSolveConstraintObsolete)
115
if(m_useLinearReferenceFrameA)
117
buildJacobianInt(m_rbA, m_rbB, m_frameInA, m_frameInB);
121
buildJacobianInt(m_rbB, m_rbA, m_frameInB, m_frameInA);
127
void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
129
//calculate transforms
130
m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA;
131
m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB;
132
m_realPivotAInW = m_calculatedTransformA.getOrigin();
133
m_realPivotBInW = m_calculatedTransformB.getOrigin();
134
m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
135
m_delta = m_realPivotBInW - m_realPivotAInW;
136
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
137
m_relPosA = m_projPivotInW - rbA.getCenterOfMassPosition();
138
m_relPosB = m_realPivotBInW - rbB.getCenterOfMassPosition();
139
btVector3 normalWorld;
142
for(i = 0; i < 3; i++)
144
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
145
new (&m_jacLin[i]) btJacobianEntry(
146
rbA.getCenterOfMassTransform().getBasis().transpose(),
147
rbB.getCenterOfMassTransform().getBasis().transpose(),
151
rbA.getInvInertiaDiagLocal(),
153
rbB.getInvInertiaDiagLocal(),
156
m_jacLinDiagABInv[i] = btScalar(1.) / m_jacLin[i].getDiagonal();
157
m_depth[i] = m_delta.dot(normalWorld);
161
for(i = 0; i < 3; i++)
163
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
164
new (&m_jacAng[i]) btJacobianEntry(
166
rbA.getCenterOfMassTransform().getBasis().transpose(),
167
rbB.getCenterOfMassTransform().getBasis().transpose(),
168
rbA.getInvInertiaDiagLocal(),
169
rbB.getInvInertiaDiagLocal()
173
btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0);
174
m_kAngle = btScalar(1.0 )/ (rbA.computeAngularImpulseDenominator(axisA) + rbB.computeAngularImpulseDenominator(axisA));
175
// clear accumulator for motors
176
m_accumulatedLinMotorImpulse = btScalar(0.0);
177
m_accumulatedAngMotorImpulse = btScalar(0.0);
141
void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
144
info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
212
148
void btSliderConstraint::getInfo2(btConstraintInfo2* info)
150
getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass());
159
void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
161
if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
163
m_calculatedTransformA = transA * m_frameInA;
164
m_calculatedTransformB = transB * m_frameInB;
168
m_calculatedTransformA = transB * m_frameInB;
169
m_calculatedTransformB = transA * m_frameInA;
171
m_realPivotAInW = m_calculatedTransformA.getOrigin();
172
m_realPivotBInW = m_calculatedTransformB.getOrigin();
173
m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
174
if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
176
m_delta = m_realPivotBInW - m_realPivotAInW;
180
m_delta = m_realPivotAInW - m_realPivotBInW;
182
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
183
btVector3 normalWorld;
186
for(i = 0; i < 3; i++)
188
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
189
m_depth[i] = m_delta.dot(normalWorld);
195
void btSliderConstraint::testLinLimits(void)
197
m_solveLinLim = false;
198
m_linPos = m_depth[0];
199
if(m_lowerLinLimit <= m_upperLinLimit)
201
if(m_depth[0] > m_upperLinLimit)
203
m_depth[0] -= m_upperLinLimit;
204
m_solveLinLim = true;
206
else if(m_depth[0] < m_lowerLinLimit)
208
m_depth[0] -= m_lowerLinLimit;
209
m_solveLinLim = true;
213
m_depth[0] = btScalar(0.);
218
m_depth[0] = btScalar(0.);
224
void btSliderConstraint::testAngLimits(void)
226
m_angDepth = btScalar(0.);
227
m_solveAngLim = false;
228
if(m_lowerAngLimit <= m_upperAngLimit)
230
const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
231
const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
232
const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
233
// btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
234
btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
235
rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit);
237
if(rot < m_lowerAngLimit)
239
m_angDepth = rot - m_lowerAngLimit;
240
m_solveAngLim = true;
242
else if(rot > m_upperAngLimit)
244
m_angDepth = rot - m_upperAngLimit;
245
m_solveAngLim = true;
250
btVector3 btSliderConstraint::getAncorInA(void)
253
ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
254
ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
260
btVector3 btSliderConstraint::getAncorInB(void)
263
ancorInB = m_frameInB.getOrigin();
268
void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass )
270
const btTransform& trA = getCalculatedTransformA();
271
const btTransform& trB = getCalculatedTransformB();
214
273
btAssert(!m_useSolveConstraintObsolete);
215
274
int i, s = info->rowskip;
216
const btTransform& trA = getCalculatedTransformA();
217
const btTransform& trB = getCalculatedTransformB();
218
276
btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
219
// make rotations around Y and Z equal
278
// difference between frames in WCS
279
btVector3 ofs = trB.getOrigin() - trA.getOrigin();
280
// now get weight factors depending on masses
281
btScalar miA = rbAinvMass;
282
btScalar miB = rbBinvMass;
283
bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
284
btScalar miS = miA + miB;
285
btScalar factA, factB;
286
if(miS > btScalar(0.f))
292
factA = btScalar(0.5f);
294
factB = btScalar(1.0f) - factA;
296
btVector3 ax1A = trA.getBasis().getColumn(0);
297
btVector3 ax1B = trB.getBasis().getColumn(0);
298
if(m_useOffsetForConstraintFrame)
300
// get the desired direction of slider axis
301
// as weighted sum of X-orthos of frameA and frameB in WCS
302
ax1 = ax1A * factA + ax1B * factB;
304
// construct two orthos to slider axis
305
btPlaneSpace1 (ax1, p, q);
308
{ // old way - use frameA
309
ax1 = trA.getBasis().getColumn(0);
310
// get 2 orthos to slider axis (Y, Z)
311
p = trA.getBasis().getColumn(1);
312
q = trA.getBasis().getColumn(2);
314
// make rotations around these orthos equal
220
315
// the slider axis should be the only unconstrained
221
316
// rotational axis, the angular velocity of the two bodies perpendicular to
222
317
// the slider axis should be equal. thus the constraint equations are
258
347
// angular_velocity = (erp*fps) * (ax1 x ax2)
259
348
// ax1 x ax2 is in the plane space of ax1, so we project the angular
260
349
// velocity to p and q to find the right hand side.
261
btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
262
btVector3 ax2 = trB.getBasis().getColumn(0);
263
btVector3 u = ax1.cross(ax2);
350
// btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
351
btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp;
352
btScalar k = info->fps * currERP;
354
btVector3 u = ax1A.cross(ax1B);
264
355
info->m_constraintError[0] = k * u.dot(p);
265
356
info->m_constraintError[s] = k * u.dot(q);
266
// pull out pos and R for both bodies. also get the connection
267
// vector c = pos2-pos1.
268
// next two rows. we want: vel2 = vel1 + w1 x c ... but this would
269
// result in three equations, so we project along the planespace vectors
270
// so that sliding along the slider axis is disregarded. for symmetry we
271
// also consider rotation around center of mass of two bodies (factA and factB).
272
btTransform bodyA_trans = m_rbA.getCenterOfMassTransform();
273
btTransform bodyB_trans = m_rbB.getCenterOfMassTransform();
274
int s2 = 2 * s, s3 = 3 * s;
276
btScalar miA = m_rbA.getInvMass();
277
btScalar miB = m_rbB.getInvMass();
278
btScalar miS = miA + miB;
279
btScalar factA, factB;
280
if(miS > btScalar(0.f))
286
factA = btScalar(0.5f);
288
if(factA > 0.99f) factA = 0.99f;
289
if(factA < 0.01f) factA = 0.01f;
290
factB = btScalar(1.0f) - factA;
291
c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
292
btVector3 tmp = c.cross(p);
293
for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
294
for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
296
for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
297
for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
357
if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
359
info->cfm[0] = m_cfmOrthoAng;
360
info->cfm[s] = m_cfmOrthoAng;
299
for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
300
for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
301
// compute two elements of right hand side. we want to align the offset
302
// point (in body 2's frame) with the center of body 1.
303
btVector3 ofs; // offset point in global coordinates
304
ofs = trB.getOrigin() - trA.getOrigin();
305
k = info->fps * info->erp * getSoftnessOrthoLin();
306
info->m_constraintError[s2] = k * p.dot(ofs);
307
info->m_constraintError[s3] = k * q.dot(ofs);
308
int nrow = 3; // last filled row
363
int nrow = 1; // last filled row
310
// check linear limits linear
311
btScalar limit_err = btScalar(0.0);
370
// we want: velA + wA x relA == velB + wB x relB ... but this would
371
// result in three equations, so we project along two orthos to the slider axis
373
btTransform bodyA_trans = transA;
374
btTransform bodyB_trans = transB;
379
btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0);
380
if(m_useOffsetForConstraintFrame)
382
// get vector from bodyB to frameB in WCS
383
relB = trB.getOrigin() - bodyB_trans.getOrigin();
384
// get its projection to slider axis
385
btVector3 projB = ax1 * relB.dot(ax1);
386
// get vector directed from bodyB to slider axis (and orthogonal to it)
387
btVector3 orthoB = relB - projB;
389
relA = trA.getOrigin() - bodyA_trans.getOrigin();
390
btVector3 projA = ax1 * relA.dot(ax1);
391
btVector3 orthoA = relA - projA;
392
// get desired offset between frames A and B along slider axis
393
btScalar sliderOffs = m_linPos - m_depth[0];
394
// desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
395
btVector3 totalDist = projA + ax1 * sliderOffs - projB;
396
// get offset vectors relA and relB
397
relA = orthoA + totalDist * factA;
398
relB = orthoB - totalDist * factB;
399
// now choose average ortho to slider axis
400
p = orthoB * factA + orthoA * factB;
401
btScalar len2 = p.length2();
402
if(len2 > SIMD_EPSILON)
408
p = trA.getBasis().getColumn(1);
410
// make one more ortho
413
tmpA = relA.cross(p);
414
tmpB = relB.cross(p);
415
for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
416
for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
417
tmpA = relA.cross(q);
418
tmpB = relB.cross(q);
419
if(hasStaticBody && getSolveAngLimit())
420
{ // to make constraint between static and dynamic objects more rigid
421
// remove wA (or wB) from equation if angular limit is hit
425
for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i];
426
for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i];
427
for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
428
for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
431
{ // old way - maybe incorrect if bodies are not on the slider axis
432
// see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
433
c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
434
btVector3 tmp = c.cross(p);
435
for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
436
for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
438
for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
439
for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
441
for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
442
for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
444
// compute two elements of right hand side
446
// k = info->fps * info->erp * getSoftnessOrthoLin();
447
currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp;
448
k = info->fps * currERP;
450
btScalar rhs = k * p.dot(ofs);
451
info->m_constraintError[s2] = rhs;
452
rhs = k * q.dot(ofs);
453
info->m_constraintError[s3] = rhs;
454
if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
456
info->cfm[s2] = m_cfmOrthoLin;
457
info->cfm[s3] = m_cfmOrthoLin;
461
// check linear limits
462
limit_err = btScalar(0.0);
313
464
if(getSolveLinLimit())
315
466
limit_err = getLinDepth() * signFact;
316
467
limit = (limit_err > btScalar(0.0)) ? 2 : 1;
319
470
if(getPoweredLinMotor())
522
void btSliderConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep)
524
if (m_useSolveConstraintObsolete)
526
m_timeStep = timeStep;
527
if(m_useLinearReferenceFrameA)
529
solveConstraintInt(m_rbA,bodyA, m_rbB,bodyB);
533
solveConstraintInt(m_rbB,bodyB, m_rbA,bodyA);
540
void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btSolverBody& bodyA,btRigidBody& rbB, btSolverBody& bodyB)
545
bodyA.getVelocityInLocalPointObsolete(m_relPosA,velA);
547
bodyB.getVelocityInLocalPointObsolete(m_relPosB,velB);
548
btVector3 vel = velA - velB;
549
for(i = 0; i < 3; i++)
551
const btVector3& normal = m_jacLin[i].m_linearJointAxis;
552
btScalar rel_vel = normal.dot(vel);
553
// calculate positional error
554
btScalar depth = m_depth[i];
556
btScalar softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin);
557
btScalar restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin);
558
btScalar damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin);
559
// calcutate and apply impulse
560
btScalar normalImpulse = softness * (restitution * depth / m_timeStep - damping * rel_vel) * m_jacLinDiagABInv[i];
561
btVector3 impulse_vector = normal * normalImpulse;
563
//rbA.applyImpulse( impulse_vector, m_relPosA);
564
//rbB.applyImpulse(-impulse_vector, m_relPosB);
566
btVector3 ftorqueAxis1 = m_relPosA.cross(normal);
567
btVector3 ftorqueAxis2 = m_relPosB.cross(normal);
568
bodyA.applyImpulse(normal*rbA.getInvMass(), rbA.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse);
569
bodyB.applyImpulse(normal*rbB.getInvMass(), rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse);
574
if(m_poweredLinMotor && (!i))
575
{ // apply linear motor
576
if(m_accumulatedLinMotorImpulse < m_maxLinMotorForce)
578
btScalar desiredMotorVel = m_targetLinMotorVelocity;
579
btScalar motor_relvel = desiredMotorVel + rel_vel;
580
normalImpulse = -motor_relvel * m_jacLinDiagABInv[i];
581
// clamp accumulated impulse
582
btScalar new_acc = m_accumulatedLinMotorImpulse + btFabs(normalImpulse);
583
if(new_acc > m_maxLinMotorForce)
585
new_acc = m_maxLinMotorForce;
587
btScalar del = new_acc - m_accumulatedLinMotorImpulse;
588
if(normalImpulse < btScalar(0.0))
590
normalImpulse = -del;
596
m_accumulatedLinMotorImpulse = new_acc;
597
// apply clamped impulse
598
impulse_vector = normal * normalImpulse;
599
//rbA.applyImpulse( impulse_vector, m_relPosA);
600
//rbB.applyImpulse(-impulse_vector, m_relPosB);
603
btVector3 ftorqueAxis1 = m_relPosA.cross(normal);
604
btVector3 ftorqueAxis2 = m_relPosB.cross(normal);
605
bodyA.applyImpulse(normal*rbA.getInvMass(), rbA.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse);
606
bodyB.applyImpulse(normal*rbB.getInvMass(), rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse);
615
// get axes in world space
616
btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0);
617
btVector3 axisB = m_calculatedTransformB.getBasis().getColumn(0);
620
bodyA.getAngularVelocity(angVelA);
622
bodyB.getAngularVelocity(angVelB);
624
btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA);
625
btVector3 angVelAroundAxisB = axisB * axisB.dot(angVelB);
627
btVector3 angAorthog = angVelA - angVelAroundAxisA;
628
btVector3 angBorthog = angVelB - angVelAroundAxisB;
629
btVector3 velrelOrthog = angAorthog-angBorthog;
630
//solve orthogonal angular velocity correction
631
btScalar len = velrelOrthog.length();
632
btScalar orthorImpulseMag = 0.f;
634
if (len > btScalar(0.00001))
636
btVector3 normal = velrelOrthog.normalized();
637
btScalar denom = rbA.computeAngularImpulseDenominator(normal) + rbB.computeAngularImpulseDenominator(normal);
638
//velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng;
639
orthorImpulseMag = (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng;
641
//solve angular positional correction
642
btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep);
643
btVector3 angularAxis = angularError;
644
btScalar angularImpulseMag = 0;
646
btScalar len2 = angularError.length();
647
if (len2>btScalar(0.00001))
649
btVector3 normal2 = angularError.normalized();
650
btScalar denom2 = rbA.computeAngularImpulseDenominator(normal2) + rbB.computeAngularImpulseDenominator(normal2);
651
angularImpulseMag = (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng;
652
angularError *= angularImpulseMag;
655
//rbA.applyTorqueImpulse(-velrelOrthog+angularError);
656
//rbB.applyTorqueImpulse(velrelOrthog-angularError);
658
bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*velrelOrthog,-orthorImpulseMag);
659
bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*velrelOrthog,orthorImpulseMag);
660
bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*angularAxis,angularImpulseMag);
661
bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*angularAxis,-angularImpulseMag);
665
//solve angular limits
668
impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / m_timeStep;
669
impulseMag *= m_kAngle * m_softnessLimAng;
673
impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / m_timeStep;
674
impulseMag *= m_kAngle * m_softnessDirAng;
676
btVector3 impulse = axisA * impulseMag;
677
//rbA.applyTorqueImpulse(impulse);
678
//rbB.applyTorqueImpulse(-impulse);
680
bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*axisA,impulseMag);
681
bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-impulseMag);
685
//apply angular motor
686
if(m_poweredAngMotor)
688
if(m_accumulatedAngMotorImpulse < m_maxAngMotorForce)
690
btVector3 velrel = angVelAroundAxisA - angVelAroundAxisB;
691
btScalar projRelVel = velrel.dot(axisA);
693
btScalar desiredMotorVel = m_targetAngMotorVelocity;
694
btScalar motor_relvel = desiredMotorVel - projRelVel;
696
btScalar angImpulse = m_kAngle * motor_relvel;
697
// clamp accumulated impulse
698
btScalar new_acc = m_accumulatedAngMotorImpulse + btFabs(angImpulse);
699
if(new_acc > m_maxAngMotorForce)
701
new_acc = m_maxAngMotorForce;
703
btScalar del = new_acc - m_accumulatedAngMotorImpulse;
704
if(angImpulse < btScalar(0.0))
712
m_accumulatedAngMotorImpulse = new_acc;
713
// apply clamped impulse
714
btVector3 motorImp = angImpulse * axisA;
715
//rbA.applyTorqueImpulse(motorImp);
716
//rbB.applyTorqueImpulse(-motorImp);
718
bodyA.applyImpulse(btVector3(0,0,0), rbA.getInvInertiaTensorWorld()*axisA,angImpulse);
719
bodyB.applyImpulse(btVector3(0,0,0), rbB.getInvInertiaTensorWorld()*axisA,-angImpulse);
728
void btSliderConstraint::calculateTransforms(void){
729
if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
731
m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA;
732
m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB;
736
m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB;
737
m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA;
739
m_realPivotAInW = m_calculatedTransformA.getOrigin();
740
m_realPivotBInW = m_calculatedTransformB.getOrigin();
741
m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
742
if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
744
m_delta = m_realPivotBInW - m_realPivotAInW;
748
m_delta = m_realPivotAInW - m_realPivotBInW;
750
m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
751
btVector3 normalWorld;
754
for(i = 0; i < 3; i++)
756
normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
757
m_depth[i] = m_delta.dot(normalWorld);
763
void btSliderConstraint::testLinLimits(void)
765
m_solveLinLim = false;
766
m_linPos = m_depth[0];
767
if(m_lowerLinLimit <= m_upperLinLimit)
769
if(m_depth[0] > m_upperLinLimit)
771
m_depth[0] -= m_upperLinLimit;
772
m_solveLinLim = true;
774
else if(m_depth[0] < m_lowerLinLimit)
776
m_depth[0] -= m_lowerLinLimit;
777
m_solveLinLim = true;
781
m_depth[0] = btScalar(0.);
786
m_depth[0] = btScalar(0.);
792
void btSliderConstraint::testAngLimits(void)
794
m_angDepth = btScalar(0.);
795
m_solveAngLim = false;
796
if(m_lowerAngLimit <= m_upperAngLimit)
798
const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
799
const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
800
const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
801
btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
803
if(rot < m_lowerAngLimit)
805
m_angDepth = rot - m_lowerAngLimit;
806
m_solveAngLim = true;
808
else if(rot > m_upperAngLimit)
810
m_angDepth = rot - m_upperAngLimit;
811
m_solveAngLim = true;
818
btVector3 btSliderConstraint::getAncorInA(void)
821
ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
822
ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
828
btVector3 btSliderConstraint::getAncorInB(void)
831
ancorInB = m_frameInB.getOrigin();
701
///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
702
///If no axis is provided, it uses the default axis for this constraint.
703
void btSliderConstraint::setParam(int num, btScalar value, int axis)
707
case BT_CONSTRAINT_STOP_ERP :
710
m_softnessLimLin = value;
711
m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
715
m_softnessOrthoLin = value;
716
m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
720
m_softnessLimAng = value;
721
m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
725
m_softnessOrthoAng = value;
726
m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
730
btAssertConstrParams(0);
733
case BT_CONSTRAINT_CFM :
737
m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
742
m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
746
btAssertConstrParams(0);
749
case BT_CONSTRAINT_STOP_CFM :
753
m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
757
m_cfmOrthoLin = value;
758
m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
763
m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
767
m_cfmOrthoAng = value;
768
m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
772
btAssertConstrParams(0);
778
///return the local value of parameter
779
btScalar btSliderConstraint::getParam(int num, int axis) const
781
btScalar retVal(SIMD_INFINITY);
784
case BT_CONSTRAINT_STOP_ERP :
787
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
788
retVal = m_softnessLimLin;
792
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
793
retVal = m_softnessOrthoLin;
797
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
798
retVal = m_softnessLimAng;
802
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
803
retVal = m_softnessOrthoAng;
807
btAssertConstrParams(0);
810
case BT_CONSTRAINT_CFM :
813
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
814
retVal = m_cfmDirLin;
818
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
819
retVal = m_cfmDirAng;
823
btAssertConstrParams(0);
826
case BT_CONSTRAINT_STOP_CFM :
829
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
830
retVal = m_cfmLimLin;
834
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
835
retVal = m_cfmOrthoLin;
839
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
840
retVal = m_cfmLimAng;
844
btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
845
retVal = m_cfmOrthoAng;
849
btAssertConstrParams(0);