Bullet Collision Detection & Physics Library
btSliderConstraint.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16/*
17Added by Roman Ponomarev (rponom@gmail.com)
18April 04, 2008
19*/
20
21#include "btSliderConstraint.h"
24#include <new>
25
26#define USE_OFFSET_FOR_CONSTANT_FRAME true
27
29{
58
59 m_poweredLinMotor = false;
63
64 m_poweredAngMotor = false;
68
69 m_flags = 0;
70 m_flags = 0;
71
73
75}
76
77btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
79 m_useSolveConstraintObsolete(false),
80 m_frameInA(frameInA),
81 m_frameInB(frameInB),
82 m_useLinearReferenceFrameA(useLinearReferenceFrameA)
83{
84 initParams();
85}
86
87btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
88 : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
89 m_useSolveConstraintObsolete(false),
90 m_frameInB(frameInB),
91 m_useLinearReferenceFrameA(useLinearReferenceFrameA)
92{
95 // m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
96
97 initParams();
98}
99
101{
103 {
104 info->m_numConstraintRows = 0;
105 info->nub = 0;
106 }
107 else
108 {
109 info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
110 info->nub = 2;
111 //prepare constraint
116 {
117 info->m_numConstraintRows++; // limit 3rd linear as well
118 info->nub--;
119 }
121 {
122 info->m_numConstraintRows++; // limit 3rd angular as well
123 info->nub--;
124 }
125 }
126}
127
129{
130 info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
131 info->nub = 0;
132}
133
135{
137}
138
140{
142 {
145 }
146 else
147 {
150 }
155 {
157 }
158 else
159 {
161 }
163 btVector3 normalWorld;
164 int i;
165 //linear part
166 for (i = 0; i < 3; i++)
167 {
168 normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
169 m_depth[i] = m_delta.dot(normalWorld);
170 }
171}
172
174{
175 m_solveLinLim = false;
176 m_linPos = m_depth[0];
178 {
179 if (m_depth[0] > m_upperLinLimit)
180 {
182 m_solveLinLim = true;
183 }
184 else if (m_depth[0] < m_lowerLinLimit)
185 {
187 m_solveLinLim = true;
188 }
189 else
190 {
191 m_depth[0] = btScalar(0.);
192 }
193 }
194 else
195 {
196 m_depth[0] = btScalar(0.);
197 }
198}
199
201{
202 m_angDepth = btScalar(0.);
203 m_solveAngLim = false;
205 {
209 // btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
210 btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
212 m_angPos = rot;
213 if (rot < m_lowerAngLimit)
214 {
216 m_solveAngLim = true;
217 }
218 else if (rot > m_upperAngLimit)
219 {
221 m_solveAngLim = true;
222 }
223 }
224}
225
227{
228 btVector3 ancorInA;
230 ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
231 return ancorInA;
232}
233
235{
236 btVector3 ancorInB;
237 ancorInB = m_frameInB.getOrigin();
238 return ancorInB;
239}
240
241void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass)
242{
245
247 int i, s = info->rowskip;
248
249 btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
250
251 // difference between frames in WCS
252 btVector3 ofs = trB.getOrigin() - trA.getOrigin();
253 // now get weight factors depending on masses
254 btScalar miA = rbAinvMass;
255 btScalar miB = rbBinvMass;
256 bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
257 btScalar miS = miA + miB;
258 btScalar factA, factB;
259 if (miS > btScalar(0.f))
260 {
261 factA = miB / miS;
262 }
263 else
264 {
265 factA = btScalar(0.5f);
266 }
267 factB = btScalar(1.0f) - factA;
268 btVector3 ax1, p, q;
269 btVector3 ax1A = trA.getBasis().getColumn(0);
270 btVector3 ax1B = trB.getBasis().getColumn(0);
272 {
273 // get the desired direction of slider axis
274 // as weighted sum of X-orthos of frameA and frameB in WCS
275 ax1 = ax1A * factA + ax1B * factB;
276 ax1.normalize();
277 // construct two orthos to slider axis
278 btPlaneSpace1(ax1, p, q);
279 }
280 else
281 { // old way - use frameA
282 ax1 = trA.getBasis().getColumn(0);
283 // get 2 orthos to slider axis (Y, Z)
284 p = trA.getBasis().getColumn(1);
285 q = trA.getBasis().getColumn(2);
286 }
287 // make rotations around these orthos equal
288 // the slider axis should be the only unconstrained
289 // rotational axis, the angular velocity of the two bodies perpendicular to
290 // the slider axis should be equal. thus the constraint equations are
291 // p*w1 - p*w2 = 0
292 // q*w1 - q*w2 = 0
293 // where p and q are unit vectors normal to the slider axis, and w1 and w2
294 // are the angular velocity vectors of the two bodies.
295 info->m_J1angularAxis[0] = p[0];
296 info->m_J1angularAxis[1] = p[1];
297 info->m_J1angularAxis[2] = p[2];
298 info->m_J1angularAxis[s + 0] = q[0];
299 info->m_J1angularAxis[s + 1] = q[1];
300 info->m_J1angularAxis[s + 2] = q[2];
301
302 info->m_J2angularAxis[0] = -p[0];
303 info->m_J2angularAxis[1] = -p[1];
304 info->m_J2angularAxis[2] = -p[2];
305 info->m_J2angularAxis[s + 0] = -q[0];
306 info->m_J2angularAxis[s + 1] = -q[1];
307 info->m_J2angularAxis[s + 2] = -q[2];
308 // compute the right hand side of the constraint equation. set relative
309 // body velocities along p and q to bring the slider back into alignment.
310 // if ax1A,ax1B are the unit length slider axes as computed from bodyA and
311 // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
312 // if "theta" is the angle between ax1 and ax2, we need an angular velocity
313 // along u to cover angle erp*theta in one step :
314 // |angular_velocity| = angle/time = erp*theta / stepsize
315 // = (erp*fps) * theta
316 // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
317 // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
318 // ...as ax1 and ax2 are unit length. if theta is smallish,
319 // theta ~= sin(theta), so
320 // angular_velocity = (erp*fps) * (ax1 x ax2)
321 // ax1 x ax2 is in the plane space of ax1, so we project the angular
322 // velocity to p and q to find the right hand side.
323 // btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
325 btScalar k = info->fps * currERP;
326
327 btVector3 u = ax1A.cross(ax1B);
328 info->m_constraintError[0] = k * u.dot(p);
329 info->m_constraintError[s] = k * u.dot(q);
331 {
332 info->cfm[0] = m_cfmOrthoAng;
333 info->cfm[s] = m_cfmOrthoAng;
334 }
335
336 int nrow = 1; // last filled row
337 int srow;
338 btScalar limit_err;
339 int limit;
340
341 // next two rows.
342 // we want: velA + wA x relA == velB + wB x relB ... but this would
343 // result in three equations, so we project along two orthos to the slider axis
344
345 btTransform bodyA_trans = transA;
346 btTransform bodyB_trans = transB;
347 nrow++;
348 int s2 = nrow * s;
349 nrow++;
350 int s3 = nrow * s;
351 btVector3 tmpA(0, 0, 0), tmpB(0, 0, 0), relA(0, 0, 0), relB(0, 0, 0), c(0, 0, 0);
353 {
354 // get vector from bodyB to frameB in WCS
355 relB = trB.getOrigin() - bodyB_trans.getOrigin();
356 // get its projection to slider axis
357 btVector3 projB = ax1 * relB.dot(ax1);
358 // get vector directed from bodyB to slider axis (and orthogonal to it)
359 btVector3 orthoB = relB - projB;
360 // same for bodyA
361 relA = trA.getOrigin() - bodyA_trans.getOrigin();
362 btVector3 projA = ax1 * relA.dot(ax1);
363 btVector3 orthoA = relA - projA;
364 // get desired offset between frames A and B along slider axis
365 btScalar sliderOffs = m_linPos - m_depth[0];
366 // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
367 btVector3 totalDist = projA + ax1 * sliderOffs - projB;
368 // get offset vectors relA and relB
369 relA = orthoA + totalDist * factA;
370 relB = orthoB - totalDist * factB;
371 // now choose average ortho to slider axis
372 p = orthoB * factA + orthoA * factB;
373 btScalar len2 = p.length2();
374 if (len2 > SIMD_EPSILON)
375 {
376 p /= btSqrt(len2);
377 }
378 else
379 {
380 p = trA.getBasis().getColumn(1);
381 }
382 // make one more ortho
383 q = ax1.cross(p);
384 // fill two rows
385 tmpA = relA.cross(p);
386 tmpB = relB.cross(p);
387 for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
388 for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
389 tmpA = relA.cross(q);
390 tmpB = relB.cross(q);
391 if (hasStaticBody && getSolveAngLimit())
392 { // to make constraint between static and dynamic objects more rigid
393 // remove wA (or wB) from equation if angular limit is hit
394 tmpB *= factB;
395 tmpA *= factA;
396 }
397 for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = tmpA[i];
398 for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = -tmpB[i];
399 for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
400 for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
401 for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
402 for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
403 }
404 else
405 { // old way - maybe incorrect if bodies are not on the slider axis
406 // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
407 c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
408 btVector3 tmp = c.cross(p);
409 for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = factA * tmp[i];
410 for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = factB * tmp[i];
411 tmp = c.cross(q);
412 for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = factA * tmp[i];
413 for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = factB * tmp[i];
414
415 for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
416 for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
417 for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
418 for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
419 }
420 // compute two elements of right hand side
421
422 // k = info->fps * info->erp * getSoftnessOrthoLin();
424 k = info->fps * currERP;
425
426 btScalar rhs = k * p.dot(ofs);
427 info->m_constraintError[s2] = rhs;
428 rhs = k * q.dot(ofs);
429 info->m_constraintError[s3] = rhs;
431 {
432 info->cfm[s2] = m_cfmOrthoLin;
433 info->cfm[s3] = m_cfmOrthoLin;
434 }
435
436 // check linear limits
437 limit_err = btScalar(0.0);
438 limit = 0;
439 if (getSolveLinLimit())
440 {
441 limit_err = getLinDepth() * signFact;
442 limit = (limit_err > btScalar(0.0)) ? 2 : 1;
443 }
444 bool powered = getPoweredLinMotor();
445 // if the slider has joint limits or motor, add in the extra row
446 if (limit || powered)
447 {
448 nrow++;
449 srow = nrow * info->rowskip;
450 info->m_J1linearAxis[srow + 0] = ax1[0];
451 info->m_J1linearAxis[srow + 1] = ax1[1];
452 info->m_J1linearAxis[srow + 2] = ax1[2];
453 info->m_J2linearAxis[srow + 0] = -ax1[0];
454 info->m_J2linearAxis[srow + 1] = -ax1[1];
455 info->m_J2linearAxis[srow + 2] = -ax1[2];
456 // linear torque decoupling step:
457 //
458 // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
459 // do not create a torque couple. in other words, the points that the
460 // constraint force is applied at must lie along the same ax1 axis.
461 // a torque couple will result in limited slider-jointed free
462 // bodies from gaining angular momentum.
464 {
465 // this is needed only when bodyA and bodyB are both dynamic.
466 if (!hasStaticBody)
467 {
468 tmpA = relA.cross(ax1);
469 tmpB = relB.cross(ax1);
470 info->m_J1angularAxis[srow + 0] = tmpA[0];
471 info->m_J1angularAxis[srow + 1] = tmpA[1];
472 info->m_J1angularAxis[srow + 2] = tmpA[2];
473 info->m_J2angularAxis[srow + 0] = -tmpB[0];
474 info->m_J2angularAxis[srow + 1] = -tmpB[1];
475 info->m_J2angularAxis[srow + 2] = -tmpB[2];
476 }
477 }
478 else
479 { // The old way. May be incorrect if bodies are not on the slider axis
480 btVector3 ltd; // Linear Torque Decoupling vector (a torque)
481 ltd = c.cross(ax1);
482 info->m_J1angularAxis[srow + 0] = factA * ltd[0];
483 info->m_J1angularAxis[srow + 1] = factA * ltd[1];
484 info->m_J1angularAxis[srow + 2] = factA * ltd[2];
485 info->m_J2angularAxis[srow + 0] = factB * ltd[0];
486 info->m_J2angularAxis[srow + 1] = factB * ltd[1];
487 info->m_J2angularAxis[srow + 2] = factB * ltd[2];
488 }
489 // right-hand part
490 btScalar lostop = getLowerLinLimit();
491 btScalar histop = getUpperLinLimit();
492 if (limit && (lostop == histop))
493 { // the joint motor is ineffective
494 powered = false;
495 }
496 info->m_constraintError[srow] = 0.;
497 info->m_lowerLimit[srow] = 0.;
498 info->m_upperLimit[srow] = 0.;
500 if (powered)
501 {
503 {
504 info->cfm[srow] = m_cfmDirLin;
505 }
507 btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
508 info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
509 info->m_lowerLimit[srow] += -getMaxLinMotorForce() / info->fps;
510 info->m_upperLimit[srow] += getMaxLinMotorForce() / info->fps;
511 }
512 if (limit)
513 {
514 k = info->fps * currERP;
515 info->m_constraintError[srow] += k * limit_err;
517 {
518 info->cfm[srow] = m_cfmLimLin;
519 }
520 if (lostop == histop)
521 { // limited low and high simultaneously
522 info->m_lowerLimit[srow] = -SIMD_INFINITY;
523 info->m_upperLimit[srow] = SIMD_INFINITY;
524 }
525 else if (limit == 1)
526 { // low limit
527 info->m_lowerLimit[srow] = -SIMD_INFINITY;
528 info->m_upperLimit[srow] = 0;
529 }
530 else
531 { // high limit
532 info->m_lowerLimit[srow] = 0;
533 info->m_upperLimit[srow] = SIMD_INFINITY;
534 }
535 // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
536 btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
537 if (bounce > btScalar(0.0))
538 {
539 btScalar vel = linVelA.dot(ax1);
540 vel -= linVelB.dot(ax1);
541 vel *= signFact;
542 // only apply bounce if the velocity is incoming, and if the
543 // resulting c[] exceeds what we already have.
544 if (limit == 1)
545 { // low limit
546 if (vel < 0)
547 {
548 btScalar newc = -bounce * vel;
549 if (newc > info->m_constraintError[srow])
550 {
551 info->m_constraintError[srow] = newc;
552 }
553 }
554 }
555 else
556 { // high limit - all those computations are reversed
557 if (vel > 0)
558 {
559 btScalar newc = -bounce * vel;
560 if (newc < info->m_constraintError[srow])
561 {
562 info->m_constraintError[srow] = newc;
563 }
564 }
565 }
566 }
567 info->m_constraintError[srow] *= getSoftnessLimLin();
568 } // if(limit)
569 } // if linear limit
570 // check angular limits
571 limit_err = btScalar(0.0);
572 limit = 0;
573 if (getSolveAngLimit())
574 {
575 limit_err = getAngDepth();
576 limit = (limit_err > btScalar(0.0)) ? 1 : 2;
577 }
578 // if the slider has joint limits, add in the extra row
579 powered = getPoweredAngMotor();
580 if (limit || powered)
581 {
582 nrow++;
583 srow = nrow * info->rowskip;
584 info->m_J1angularAxis[srow + 0] = ax1[0];
585 info->m_J1angularAxis[srow + 1] = ax1[1];
586 info->m_J1angularAxis[srow + 2] = ax1[2];
587
588 info->m_J2angularAxis[srow + 0] = -ax1[0];
589 info->m_J2angularAxis[srow + 1] = -ax1[1];
590 info->m_J2angularAxis[srow + 2] = -ax1[2];
591
592 btScalar lostop = getLowerAngLimit();
593 btScalar histop = getUpperAngLimit();
594 if (limit && (lostop == histop))
595 { // the joint motor is ineffective
596 powered = false;
597 }
599 if (powered)
600 {
602 {
603 info->cfm[srow] = m_cfmDirAng;
604 }
606 info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
607 info->m_lowerLimit[srow] = -getMaxAngMotorForce() / info->fps;
608 info->m_upperLimit[srow] = getMaxAngMotorForce() / info->fps;
609 }
610 if (limit)
611 {
612 k = info->fps * currERP;
613 info->m_constraintError[srow] += k * limit_err;
615 {
616 info->cfm[srow] = m_cfmLimAng;
617 }
618 if (lostop == histop)
619 {
620 // limited low and high simultaneously
621 info->m_lowerLimit[srow] = -SIMD_INFINITY;
622 info->m_upperLimit[srow] = SIMD_INFINITY;
623 }
624 else if (limit == 1)
625 { // low limit
626 info->m_lowerLimit[srow] = 0;
627 info->m_upperLimit[srow] = SIMD_INFINITY;
628 }
629 else
630 { // high limit
631 info->m_lowerLimit[srow] = -SIMD_INFINITY;
632 info->m_upperLimit[srow] = 0;
633 }
634 // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
635 btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
636 if (bounce > btScalar(0.0))
637 {
639 vel -= m_rbB.getAngularVelocity().dot(ax1);
640 // only apply bounce if the velocity is incoming, and if the
641 // resulting c[] exceeds what we already have.
642 if (limit == 1)
643 { // low limit
644 if (vel < 0)
645 {
646 btScalar newc = -bounce * vel;
647 if (newc > info->m_constraintError[srow])
648 {
649 info->m_constraintError[srow] = newc;
650 }
651 }
652 }
653 else
654 { // high limit - all those computations are reversed
655 if (vel > 0)
656 {
657 btScalar newc = -bounce * vel;
658 if (newc < info->m_constraintError[srow])
659 {
660 info->m_constraintError[srow] = newc;
661 }
662 }
663 }
664 }
665 info->m_constraintError[srow] *= getSoftnessLimAng();
666 } // if(limit)
667 } // if angular limit or powered
668}
669
672void btSliderConstraint::setParam(int num, btScalar value, int axis)
673{
674 switch (num)
675 {
677 if (axis < 1)
678 {
679 m_softnessLimLin = value;
681 }
682 else if (axis < 3)
683 {
684 m_softnessOrthoLin = value;
686 }
687 else if (axis == 3)
688 {
689 m_softnessLimAng = value;
691 }
692 else if (axis < 6)
693 {
694 m_softnessOrthoAng = value;
696 }
697 else
698 {
700 }
701 break;
703 if (axis < 1)
704 {
705 m_cfmDirLin = value;
707 }
708 else if (axis == 3)
709 {
710 m_cfmDirAng = value;
712 }
713 else
714 {
716 }
717 break;
719 if (axis < 1)
720 {
721 m_cfmLimLin = value;
723 }
724 else if (axis < 3)
725 {
726 m_cfmOrthoLin = value;
728 }
729 else if (axis == 3)
730 {
731 m_cfmLimAng = value;
733 }
734 else if (axis < 6)
735 {
736 m_cfmOrthoAng = value;
738 }
739 else
740 {
742 }
743 break;
744 }
745}
746
749{
750 btScalar retVal(SIMD_INFINITY);
751 switch (num)
752 {
754 if (axis < 1)
755 {
757 retVal = m_softnessLimLin;
758 }
759 else if (axis < 3)
760 {
762 retVal = m_softnessOrthoLin;
763 }
764 else if (axis == 3)
765 {
767 retVal = m_softnessLimAng;
768 }
769 else if (axis < 6)
770 {
772 retVal = m_softnessOrthoAng;
773 }
774 else
775 {
777 }
778 break;
780 if (axis < 1)
781 {
783 retVal = m_cfmDirLin;
784 }
785 else if (axis == 3)
786 {
788 retVal = m_cfmDirAng;
789 }
790 else
791 {
793 }
794 break;
796 if (axis < 1)
797 {
799 retVal = m_cfmLimLin;
800 }
801 else if (axis < 3)
802 {
804 retVal = m_cfmOrthoLin;
805 }
806 else if (axis == 3)
807 {
809 retVal = m_cfmLimAng;
810 }
811 else if (axis < 6)
812 {
814 retVal = m_cfmOrthoAng;
815 }
816 else
817 {
819 }
820 break;
821 }
822 return retVal;
823}
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:314
btScalar btSqrt(btScalar y)
Definition: btScalar.h:466
btScalar btAtan2(btScalar x, btScalar y)
Definition: btScalar.h:518
btScalar btFabs(btScalar x)
Definition: btScalar.h:497
#define SIMD_INFINITY
Definition: btScalar.h:544
#define SIMD_EPSILON
Definition: btScalar.h:543
#define btAssert(x)
Definition: btScalar.h:153
#define USE_OFFSET_FOR_CONSTANT_FRAME
@ BT_SLIDER_FLAGS_CFM_DIRANG
@ BT_SLIDER_FLAGS_ERP_LIMLIN
@ BT_SLIDER_FLAGS_CFM_DIRLIN
@ BT_SLIDER_FLAGS_CFM_ORTANG
@ BT_SLIDER_FLAGS_CFM_ORTLIN
@ BT_SLIDER_FLAGS_ERP_ORTANG
@ BT_SLIDER_FLAGS_CFM_LIMANG
@ BT_SLIDER_FLAGS_ERP_ORTLIN
@ BT_SLIDER_FLAGS_CFM_LIMLIN
@ BT_SLIDER_FLAGS_ERP_LIMANG
#define SLIDER_CONSTRAINT_DEF_DAMPING
#define SLIDER_CONSTRAINT_DEF_SOFTNESS
#define SLIDER_CONSTRAINT_DEF_RESTITUTION
#define SLIDER_CONSTRAINT_DEF_CFM
#define btAssertConstrParams(_par)
btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
@ BT_CONSTRAINT_CFM
@ BT_CONSTRAINT_STOP_CFM
@ BT_CONSTRAINT_STOP_ERP
@ SLIDER_CONSTRAINT_TYPE
void btPlaneSpace1(const T &n, T &p, T &q)
Definition: btVector3.h:1251
btVector3 getColumn(int i) const
Get a column of the matrix as a vector.
Definition: btMatrix3x3.h:142
The btRigidBody is the main class for rigid body objects.
Definition: btRigidBody.h:60
btScalar getInvMass() const
Definition: btRigidBody.h:263
const btTransform & getCenterOfMassTransform() const
Definition: btRigidBody.h:429
const btVector3 & getAngularVelocity() const
Definition: btRigidBody.h:437
const btVector3 & getLinearVelocity() const
Definition: btRigidBody.h:433
btScalar getTargetLinMotorVelocity()
btSliderConstraint(btRigidBody &rbA, btRigidBody &rbB, const btTransform &frameInA, const btTransform &frameInB, bool useLinearReferenceFrameA)
btTransform m_calculatedTransformB
const btTransform & getCalculatedTransformB() const
btTransform m_calculatedTransformA
virtual btScalar getParam(int num, int axis=-1) const
return the local value of parameter
const btTransform & getCalculatedTransformA() const
virtual void getInfo2(btConstraintInfo2 *info)
internal method used by the constraint solver, don't use them directly
btScalar m_accumulatedLinMotorImpulse
btScalar getTargetAngMotorVelocity()
void calculateTransforms(const btTransform &transA, const btTransform &transB)
btScalar m_accumulatedAngMotorImpulse
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...
virtual void getInfo1(btConstraintInfo1 *info)
internal method used by the constraint solver, don't use them directly
btScalar getMaxAngMotorForce()
btScalar getMaxLinMotorForce()
void getInfo2NonVirtual(btConstraintInfo2 *info, const btTransform &transA, const btTransform &transB, const btVector3 &linVelA, const btVector3 &linVelB, btScalar rbAinvMass, btScalar rbBinvMass)
bool m_useSolveConstraintObsolete
for backwards compatibility during the transition to 'getInfo/getInfo2'
void getInfo1NonVirtual(btConstraintInfo1 *info)
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:30
btTransform inverse() const
Return the inverse of this transform.
Definition: btTransform.h:183
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:109
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:114
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
btRigidBody & m_rbA
btRigidBody & m_rbB
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:82
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:380
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:229
btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:251
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:303