Bullet Collision Detection & Physics Library
btSliderConstraint.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 /*
17 Added by Roman Ponomarev (rponom@gmail.com)
18 April 04, 2008
19 */
20 
21 
22 
23 #include "btSliderConstraint.h"
26 #include <new>
27 
28 #define USE_OFFSET_FOR_CONSTANT_FRAME true
29 
31 {
33  m_upperLinLimit = btScalar(-1.0);
60 
61  m_poweredLinMotor = false;
65 
66  m_poweredAngMotor = false;
70 
71  m_flags = 0;
72  m_flags = 0;
73 
75 
77 }
78 
79 
80 
81 
82 
83 btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
85  m_useSolveConstraintObsolete(false),
86  m_frameInA(frameInA),
87  m_frameInB(frameInB),
88  m_useLinearReferenceFrameA(useLinearReferenceFrameA)
89 {
90  initParams();
91 }
92 
93 
94 
95 btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
96  : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
97  m_useSolveConstraintObsolete(false),
98  m_frameInB(frameInB),
99  m_useLinearReferenceFrameA(useLinearReferenceFrameA)
100 {
103 // m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
104 
105  initParams();
106 }
107 
108 
109 
110 
111 
112 
114 {
116  {
117  info->m_numConstraintRows = 0;
118  info->nub = 0;
119  }
120  else
121  {
122  info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
123  info->nub = 2;
124  //prepare constraint
126  testAngLimits();
127  testLinLimits();
129  {
130  info->m_numConstraintRows++; // limit 3rd linear as well
131  info->nub--;
132  }
134  {
135  info->m_numConstraintRows++; // limit 3rd angular as well
136  info->nub--;
137  }
138  }
139 }
140 
142 {
143 
144  info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
145  info->nub = 0;
146 }
147 
149 {
151 }
152 
153 
154 
155 
156 
157 
158 
160 {
162  {
165  }
166  else
167  {
170  }
175  {
177  }
178  else
179  {
181  }
183  btVector3 normalWorld;
184  int i;
185  //linear part
186  for(i = 0; i < 3; i++)
187  {
188  normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
189  m_depth[i] = m_delta.dot(normalWorld);
190  }
191 }
192 
193 
194 
196 {
197  m_solveLinLim = false;
198  m_linPos = m_depth[0];
200  {
201  if(m_depth[0] > m_upperLinLimit)
202  {
203  m_depth[0] -= m_upperLinLimit;
204  m_solveLinLim = true;
205  }
206  else if(m_depth[0] < m_lowerLinLimit)
207  {
208  m_depth[0] -= m_lowerLinLimit;
209  m_solveLinLim = true;
210  }
211  else
212  {
213  m_depth[0] = btScalar(0.);
214  }
215  }
216  else
217  {
218  m_depth[0] = btScalar(0.);
219  }
220 }
221 
222 
223 
225 {
226  m_angDepth = btScalar(0.);
227  m_solveAngLim = false;
229  {
233 // btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
234  btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
236  m_angPos = rot;
237  if(rot < m_lowerAngLimit)
238  {
239  m_angDepth = rot - m_lowerAngLimit;
240  m_solveAngLim = true;
241  }
242  else if(rot > m_upperAngLimit)
243  {
244  m_angDepth = rot - m_upperAngLimit;
245  m_solveAngLim = true;
246  }
247  }
248 }
249 
251 {
252  btVector3 ancorInA;
254  ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
255  return ancorInA;
256 }
257 
258 
259 
261 {
262  btVector3 ancorInB;
263  ancorInB = m_frameInB.getOrigin();
264  return ancorInB;
265 }
266 
267 
268 void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass )
269 {
270  const btTransform& trA = getCalculatedTransformA();
271  const btTransform& trB = getCalculatedTransformB();
272 
274  int i, s = info->rowskip;
275 
276  btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
277 
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))
287  {
288  factA = miB / miS;
289  }
290  else
291  {
292  factA = btScalar(0.5f);
293  }
294  factB = btScalar(1.0f) - factA;
295  btVector3 ax1, p, q;
296  btVector3 ax1A = trA.getBasis().getColumn(0);
297  btVector3 ax1B = trB.getBasis().getColumn(0);
299  {
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;
303  ax1.normalize();
304  // construct two orthos to slider axis
305  btPlaneSpace1 (ax1, p, q);
306  }
307  else
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);
313  }
314  // make rotations around these orthos equal
315  // the slider axis should be the only unconstrained
316  // rotational axis, the angular velocity of the two bodies perpendicular to
317  // the slider axis should be equal. thus the constraint equations are
318  // p*w1 - p*w2 = 0
319  // q*w1 - q*w2 = 0
320  // where p and q are unit vectors normal to the slider axis, and w1 and w2
321  // are the angular velocity vectors of the two bodies.
322  info->m_J1angularAxis[0] = p[0];
323  info->m_J1angularAxis[1] = p[1];
324  info->m_J1angularAxis[2] = p[2];
325  info->m_J1angularAxis[s+0] = q[0];
326  info->m_J1angularAxis[s+1] = q[1];
327  info->m_J1angularAxis[s+2] = q[2];
328 
329  info->m_J2angularAxis[0] = -p[0];
330  info->m_J2angularAxis[1] = -p[1];
331  info->m_J2angularAxis[2] = -p[2];
332  info->m_J2angularAxis[s+0] = -q[0];
333  info->m_J2angularAxis[s+1] = -q[1];
334  info->m_J2angularAxis[s+2] = -q[2];
335  // compute the right hand side of the constraint equation. set relative
336  // body velocities along p and q to bring the slider back into alignment.
337  // if ax1A,ax1B are the unit length slider axes as computed from bodyA and
338  // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
339  // if "theta" is the angle between ax1 and ax2, we need an angular velocity
340  // along u to cover angle erp*theta in one step :
341  // |angular_velocity| = angle/time = erp*theta / stepsize
342  // = (erp*fps) * theta
343  // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
344  // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
345  // ...as ax1 and ax2 are unit length. if theta is smallish,
346  // theta ~= sin(theta), so
347  // angular_velocity = (erp*fps) * (ax1 x ax2)
348  // ax1 x ax2 is in the plane space of ax1, so we project the angular
349  // velocity to p and q to find the right hand side.
350 // btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
352  btScalar k = info->fps * currERP;
353 
354  btVector3 u = ax1A.cross(ax1B);
355  info->m_constraintError[0] = k * u.dot(p);
356  info->m_constraintError[s] = k * u.dot(q);
358  {
359  info->cfm[0] = m_cfmOrthoAng;
360  info->cfm[s] = m_cfmOrthoAng;
361  }
362 
363  int nrow = 1; // last filled row
364  int srow;
365  btScalar limit_err;
366  int limit;
367  int powered;
368 
369  // next two rows.
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
372 
373  btTransform bodyA_trans = transA;
374  btTransform bodyB_trans = transB;
375  nrow++;
376  int s2 = nrow * s;
377  nrow++;
378  int s3 = nrow * s;
379  btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0);
381  {
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;
388  // same for bodyA
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)
403  {
404  p /= btSqrt(len2);
405  }
406  else
407  {
408  p = trA.getBasis().getColumn(1);
409  }
410  // make one more ortho
411  q = ax1.cross(p);
412  // fill two rows
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
422  tmpB *= factB;
423  tmpA *= factA;
424  }
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];
429  for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
430  for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
431  }
432  else
433  { // old way - maybe incorrect if bodies are not on the slider axis
434  // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
435  c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
436  btVector3 tmp = c.cross(p);
437  for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
438  for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
439  tmp = c.cross(q);
440  for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
441  for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
442 
443  for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
444  for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
445  for (i=0; i<3; i++) info->m_J2linearAxis[s2+i] = -p[i];
446  for (i=0; i<3; i++) info->m_J2linearAxis[s3+i] = -q[i];
447  }
448  // compute two elements of right hand side
449 
450  // k = info->fps * info->erp * getSoftnessOrthoLin();
452  k = info->fps * currERP;
453 
454  btScalar rhs = k * p.dot(ofs);
455  info->m_constraintError[s2] = rhs;
456  rhs = k * q.dot(ofs);
457  info->m_constraintError[s3] = rhs;
459  {
460  info->cfm[s2] = m_cfmOrthoLin;
461  info->cfm[s3] = m_cfmOrthoLin;
462  }
463 
464 
465  // check linear limits
466  limit_err = btScalar(0.0);
467  limit = 0;
468  if(getSolveLinLimit())
469  {
470  limit_err = getLinDepth() * signFact;
471  limit = (limit_err > btScalar(0.0)) ? 2 : 1;
472  }
473  powered = 0;
474  if(getPoweredLinMotor())
475  {
476  powered = 1;
477  }
478  // if the slider has joint limits or motor, add in the extra row
479  if (limit || powered)
480  {
481  nrow++;
482  srow = nrow * info->rowskip;
483  info->m_J1linearAxis[srow+0] = ax1[0];
484  info->m_J1linearAxis[srow+1] = ax1[1];
485  info->m_J1linearAxis[srow+2] = ax1[2];
486  info->m_J2linearAxis[srow+0] = -ax1[0];
487  info->m_J2linearAxis[srow+1] = -ax1[1];
488  info->m_J2linearAxis[srow+2] = -ax1[2];
489  // linear torque decoupling step:
490  //
491  // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
492  // do not create a torque couple. in other words, the points that the
493  // constraint force is applied at must lie along the same ax1 axis.
494  // a torque couple will result in limited slider-jointed free
495  // bodies from gaining angular momentum.
497  {
498  // this is needed only when bodyA and bodyB are both dynamic.
499  if(!hasStaticBody)
500  {
501  tmpA = relA.cross(ax1);
502  tmpB = relB.cross(ax1);
503  info->m_J1angularAxis[srow+0] = tmpA[0];
504  info->m_J1angularAxis[srow+1] = tmpA[1];
505  info->m_J1angularAxis[srow+2] = tmpA[2];
506  info->m_J2angularAxis[srow+0] = -tmpB[0];
507  info->m_J2angularAxis[srow+1] = -tmpB[1];
508  info->m_J2angularAxis[srow+2] = -tmpB[2];
509  }
510  }
511  else
512  { // The old way. May be incorrect if bodies are not on the slider axis
513  btVector3 ltd; // Linear Torque Decoupling vector (a torque)
514  ltd = c.cross(ax1);
515  info->m_J1angularAxis[srow+0] = factA*ltd[0];
516  info->m_J1angularAxis[srow+1] = factA*ltd[1];
517  info->m_J1angularAxis[srow+2] = factA*ltd[2];
518  info->m_J2angularAxis[srow+0] = factB*ltd[0];
519  info->m_J2angularAxis[srow+1] = factB*ltd[1];
520  info->m_J2angularAxis[srow+2] = factB*ltd[2];
521  }
522  // right-hand part
523  btScalar lostop = getLowerLinLimit();
524  btScalar histop = getUpperLinLimit();
525  if(limit && (lostop == histop))
526  { // the joint motor is ineffective
527  powered = 0;
528  }
529  info->m_constraintError[srow] = 0.;
530  info->m_lowerLimit[srow] = 0.;
531  info->m_upperLimit[srow] = 0.;
532  currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
533  if(powered)
534  {
536  {
537  info->cfm[srow] = m_cfmDirLin;
538  }
539  btScalar tag_vel = getTargetLinMotorVelocity();
540  btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
541  info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
542  info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps;
543  info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps;
544  }
545  if(limit)
546  {
547  k = info->fps * currERP;
548  info->m_constraintError[srow] += k * limit_err;
550  {
551  info->cfm[srow] = m_cfmLimLin;
552  }
553  if(lostop == histop)
554  { // limited low and high simultaneously
555  info->m_lowerLimit[srow] = -SIMD_INFINITY;
556  info->m_upperLimit[srow] = SIMD_INFINITY;
557  }
558  else if(limit == 1)
559  { // low limit
560  info->m_lowerLimit[srow] = -SIMD_INFINITY;
561  info->m_upperLimit[srow] = 0;
562  }
563  else
564  { // high limit
565  info->m_lowerLimit[srow] = 0;
566  info->m_upperLimit[srow] = SIMD_INFINITY;
567  }
568  // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
569  btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
570  if(bounce > btScalar(0.0))
571  {
572  btScalar vel = linVelA.dot(ax1);
573  vel -= linVelB.dot(ax1);
574  vel *= signFact;
575  // only apply bounce if the velocity is incoming, and if the
576  // resulting c[] exceeds what we already have.
577  if(limit == 1)
578  { // low limit
579  if(vel < 0)
580  {
581  btScalar newc = -bounce * vel;
582  if (newc > info->m_constraintError[srow])
583  {
584  info->m_constraintError[srow] = newc;
585  }
586  }
587  }
588  else
589  { // high limit - all those computations are reversed
590  if(vel > 0)
591  {
592  btScalar newc = -bounce * vel;
593  if(newc < info->m_constraintError[srow])
594  {
595  info->m_constraintError[srow] = newc;
596  }
597  }
598  }
599  }
600  info->m_constraintError[srow] *= getSoftnessLimLin();
601  } // if(limit)
602  } // if linear limit
603  // check angular limits
604  limit_err = btScalar(0.0);
605  limit = 0;
606  if(getSolveAngLimit())
607  {
608  limit_err = getAngDepth();
609  limit = (limit_err > btScalar(0.0)) ? 1 : 2;
610  }
611  // if the slider has joint limits, add in the extra row
612  powered = 0;
613  if(getPoweredAngMotor())
614  {
615  powered = 1;
616  }
617  if(limit || powered)
618  {
619  nrow++;
620  srow = nrow * info->rowskip;
621  info->m_J1angularAxis[srow+0] = ax1[0];
622  info->m_J1angularAxis[srow+1] = ax1[1];
623  info->m_J1angularAxis[srow+2] = ax1[2];
624 
625  info->m_J2angularAxis[srow+0] = -ax1[0];
626  info->m_J2angularAxis[srow+1] = -ax1[1];
627  info->m_J2angularAxis[srow+2] = -ax1[2];
628 
629  btScalar lostop = getLowerAngLimit();
630  btScalar histop = getUpperAngLimit();
631  if(limit && (lostop == histop))
632  { // the joint motor is ineffective
633  powered = 0;
634  }
635  currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
636  if(powered)
637  {
639  {
640  info->cfm[srow] = m_cfmDirAng;
641  }
642  btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP);
643  info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
644  info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps;
645  info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps;
646  }
647  if(limit)
648  {
649  k = info->fps * currERP;
650  info->m_constraintError[srow] += k * limit_err;
652  {
653  info->cfm[srow] = m_cfmLimAng;
654  }
655  if(lostop == histop)
656  {
657  // limited low and high simultaneously
658  info->m_lowerLimit[srow] = -SIMD_INFINITY;
659  info->m_upperLimit[srow] = SIMD_INFINITY;
660  }
661  else if(limit == 1)
662  { // low limit
663  info->m_lowerLimit[srow] = 0;
664  info->m_upperLimit[srow] = SIMD_INFINITY;
665  }
666  else
667  { // high limit
668  info->m_lowerLimit[srow] = -SIMD_INFINITY;
669  info->m_upperLimit[srow] = 0;
670  }
671  // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
672  btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
673  if(bounce > btScalar(0.0))
674  {
675  btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
676  vel -= m_rbB.getAngularVelocity().dot(ax1);
677  // only apply bounce if the velocity is incoming, and if the
678  // resulting c[] exceeds what we already have.
679  if(limit == 1)
680  { // low limit
681  if(vel < 0)
682  {
683  btScalar newc = -bounce * vel;
684  if(newc > info->m_constraintError[srow])
685  {
686  info->m_constraintError[srow] = newc;
687  }
688  }
689  }
690  else
691  { // high limit - all those computations are reversed
692  if(vel > 0)
693  {
694  btScalar newc = -bounce * vel;
695  if(newc < info->m_constraintError[srow])
696  {
697  info->m_constraintError[srow] = newc;
698  }
699  }
700  }
701  }
702  info->m_constraintError[srow] *= getSoftnessLimAng();
703  } // if(limit)
704  } // if angular limit or powered
705 }
706 
707 
710 void btSliderConstraint::setParam(int num, btScalar value, int axis)
711 {
712  switch(num)
713  {
715  if(axis < 1)
716  {
717  m_softnessLimLin = value;
719  }
720  else if(axis < 3)
721  {
722  m_softnessOrthoLin = value;
724  }
725  else if(axis == 3)
726  {
727  m_softnessLimAng = value;
729  }
730  else if(axis < 6)
731  {
732  m_softnessOrthoAng = value;
734  }
735  else
736  {
738  }
739  break;
740  case BT_CONSTRAINT_CFM :
741  if(axis < 1)
742  {
743  m_cfmDirLin = value;
745  }
746  else if(axis == 3)
747  {
748  m_cfmDirAng = value;
750  }
751  else
752  {
754  }
755  break;
757  if(axis < 1)
758  {
759  m_cfmLimLin = value;
761  }
762  else if(axis < 3)
763  {
764  m_cfmOrthoLin = value;
766  }
767  else if(axis == 3)
768  {
769  m_cfmLimAng = value;
771  }
772  else if(axis < 6)
773  {
774  m_cfmOrthoAng = value;
776  }
777  else
778  {
780  }
781  break;
782  }
783 }
784 
786 btScalar btSliderConstraint::getParam(int num, int axis) const
787 {
788  btScalar retVal(SIMD_INFINITY);
789  switch(num)
790  {
792  if(axis < 1)
793  {
795  retVal = m_softnessLimLin;
796  }
797  else if(axis < 3)
798  {
800  retVal = m_softnessOrthoLin;
801  }
802  else if(axis == 3)
803  {
805  retVal = m_softnessLimAng;
806  }
807  else if(axis < 6)
808  {
810  retVal = m_softnessOrthoAng;
811  }
812  else
813  {
815  }
816  break;
817  case BT_CONSTRAINT_CFM :
818  if(axis < 1)
819  {
821  retVal = m_cfmDirLin;
822  }
823  else if(axis == 3)
824  {
826  retVal = m_cfmDirAng;
827  }
828  else
829  {
831  }
832  break;
834  if(axis < 1)
835  {
837  retVal = m_cfmLimLin;
838  }
839  else if(axis < 3)
840  {
842  retVal = m_cfmOrthoLin;
843  }
844  else if(axis == 3)
845  {
847  retVal = m_cfmLimAng;
848  }
849  else if(axis < 6)
850  {
852  retVal = m_cfmOrthoAng;
853  }
854  else
855  {
857  }
858  break;
859  }
860  return retVal;
861 }
862 
863 
864 
btScalar getInvMass() const
Definition: btRigidBody.h:267
void calculateTransforms(const btTransform &transA, const btTransform &transB)
#define SLIDER_CONSTRAINT_DEF_RESTITUTION
#define SIMD_EPSILON
Definition: btScalar.h:448
btScalar getMaxAngMotorForce()
const btTransform & getCalculatedTransformA() const
const btTransform & getCalculatedTransformB() const
#define USE_OFFSET_FOR_CONSTANT_FRAME
void getInfo2NonVirtual(btConstraintInfo2 *info, const btTransform &transA, const btTransform &transB, const btVector3 &linVelA, const btVector3 &linVelB, btScalar rbAinvMass, btScalar rbBinvMass)
virtual void getInfo2(btConstraintInfo2 *info)
internal method used by the constraint solver, don't use them directly
btScalar m_accumulatedAngMotorImpulse
void btPlaneSpace1(const T &n, T &p, T &q)
Definition: btVector3.h:1271
btScalar btSqrt(btScalar y)
Definition: btScalar.h:387
#define btAssert(x)
Definition: btScalar.h:101
btScalar m_accumulatedLinMotorImpulse
btTransform m_calculatedTransformB
btVector3 getColumn(int i) const
Get a column of the matrix as a vector.
Definition: btMatrix3x3.h:134
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:297
btSliderConstraint(btRigidBody &rbA, btRigidBody &rbB, const btTransform &frameInA, const btTransform &frameInB, bool useLinearReferenceFrameA)
btScalar getMaxLinMotorForce()
#define SIMD_INFINITY
Definition: btScalar.h:449
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
const btTransform & getCenterOfMassTransform() const
Definition: btRigidBody.h:353
btScalar btAtan2(btScalar x, btScalar y)
Definition: btScalar.h:426
#define SLIDER_CONSTRAINT_DEF_CFM
const btVector3 & getAngularVelocity() const
Definition: btRigidBody.h:359
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:377
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:59
virtual btScalar getParam(int num, int axis=-1) const
return the local value of parameter
btTransform inverse() const
Return the inverse of this transform.
Definition: btTransform.h:188
virtual void getInfo1(btConstraintInfo1 *info)
internal method used by the constraint solver, don't use them directly
btScalar getTargetLinMotorVelocity()
#define SLIDER_CONSTRAINT_DEF_SOFTNESS
void getInfo1NonVirtual(btConstraintInfo1 *info)
btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:257
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
btScalar getTargetAngMotorVelocity()
btTransform m_calculatedTransformA
TypedConstraint is the baseclass for Bullet constraints and vehicles.
btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact)
internal method used by the constraint solver, don't use them directly
bool m_useSolveConstraintObsolete
for backwards compatibility during the transition to 'getInfo/getInfo2'
const btVector3 & getLinearVelocity() const
Definition: btRigidBody.h:356
#define btAssertConstrParams(_par)
#define SLIDER_CONSTRAINT_DEF_DAMPING
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:266
virtual void setParam(int num, btScalar value, int axis=-1)
override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0...
btScalar btFabs(btScalar x)
Definition: btScalar.h:407