btGeneric6DofConstraint.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose,
00008 including commercial applications, and to alter it and redistribute it freely,
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 /*
00016 2007-09-09
00017 Refactored by Francisco Le?n
00018 email: projectileman@yahoo.com
00019 http://gimpact.sf.net
00020 */
00021 
00022 #include "btGeneric6DofConstraint.h"
00023 #include "BulletDynamics/Dynamics/btRigidBody.h"
00024 #include "LinearMath/btTransformUtil.h"
00025 #include "LinearMath/btTransformUtil.h"
00026 #include <new>
00027 
00028 
00029 
00030 #define D6_USE_OBSOLETE_METHOD false
00031 #define D6_USE_FRAME_OFFSET true
00032 
00033 
00034 
00035 
00036 
00037 
00038 btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
00039 : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB)
00040 , m_frameInA(frameInA)
00041 , m_frameInB(frameInB),
00042 m_useLinearReferenceFrameA(useLinearReferenceFrameA),
00043 m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
00044 m_flags(0),
00045 m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD)
00046 {
00047         calculateTransforms();
00048 }
00049 
00050 
00051 
00052 btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
00053         : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB),
00054                 m_frameInB(frameInB),
00055                 m_useLinearReferenceFrameA(useLinearReferenceFrameB),
00056                 m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
00057                 m_flags(0),
00058                 m_useSolveConstraintObsolete(false)
00059 {
00061         m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
00062         calculateTransforms();
00063 }
00064 
00065 
00066 
00067 
00068 #define GENERIC_D6_DISABLE_WARMSTARTING 1
00069 
00070 
00071 
00072 btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
00073 btScalar btGetMatrixElem(const btMatrix3x3& mat, int index)
00074 {
00075         int i = index%3;
00076         int j = index/3;
00077         return mat[i][j];
00078 }
00079 
00080 
00081 
00083 bool    matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz);
00084 bool    matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
00085 {
00086         //      // rot =  cy*cz          -cy*sz           sy
00087         //      //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
00088         //      //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
00089         //
00090 
00091         btScalar fi = btGetMatrixElem(mat,2);
00092         if (fi < btScalar(1.0f))
00093         {
00094                 if (fi > btScalar(-1.0f))
00095                 {
00096                         xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
00097                         xyz[1] = btAsin(btGetMatrixElem(mat,2));
00098                         xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
00099                         return true;
00100                 }
00101                 else
00102                 {
00103                         // WARNING.  Not unique.  XA - ZA = -atan2(r10,r11)
00104                         xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
00105                         xyz[1] = -SIMD_HALF_PI;
00106                         xyz[2] = btScalar(0.0);
00107                         return false;
00108                 }
00109         }
00110         else
00111         {
00112                 // WARNING.  Not unique.  XAngle + ZAngle = atan2(r10,r11)
00113                 xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
00114                 xyz[1] = SIMD_HALF_PI;
00115                 xyz[2] = 0.0;
00116         }
00117         return false;
00118 }
00119 
00121 
00122 int btRotationalLimitMotor::testLimitValue(btScalar test_value)
00123 {
00124         if(m_loLimit>m_hiLimit)
00125         {
00126                 m_currentLimit = 0;//Free from violation
00127                 return 0;
00128         }
00129         if (test_value < m_loLimit)
00130         {
00131                 m_currentLimit = 1;//low limit violation
00132                 m_currentLimitError =  test_value - m_loLimit;
00133                 return 1;
00134         }
00135         else if (test_value> m_hiLimit)
00136         {
00137                 m_currentLimit = 2;//High limit violation
00138                 m_currentLimitError = test_value - m_hiLimit;
00139                 return 2;
00140         };
00141 
00142         m_currentLimit = 0;//Free from violation
00143         return 0;
00144 
00145 }
00146 
00147 
00148 
00149 btScalar btRotationalLimitMotor::solveAngularLimits(
00150         btScalar timeStep,btVector3& axis,btScalar jacDiagABInv,
00151         btRigidBody * body0, btRigidBody * body1 )
00152 {
00153         if (needApplyTorques()==false) return 0.0f;
00154 
00155         btScalar target_velocity = m_targetVelocity;
00156         btScalar maxMotorForce = m_maxMotorForce;
00157 
00158         //current error correction
00159         if (m_currentLimit!=0)
00160         {
00161                 target_velocity = -m_stopERP*m_currentLimitError/(timeStep);
00162                 maxMotorForce = m_maxLimitForce;
00163         }
00164 
00165         maxMotorForce *= timeStep;
00166 
00167         // current velocity difference
00168 
00169         btVector3 angVelA;
00170         body0->internalGetAngularVelocity(angVelA);
00171         btVector3 angVelB;
00172         body1->internalGetAngularVelocity(angVelB);
00173 
00174         btVector3 vel_diff;
00175         vel_diff = angVelA-angVelB;
00176 
00177 
00178 
00179         btScalar rel_vel = axis.dot(vel_diff);
00180 
00181         // correction velocity
00182         btScalar motor_relvel = m_limitSoftness*(target_velocity  - m_damping*rel_vel);
00183 
00184 
00185         if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON  )
00186         {
00187                 return 0.0f;//no need for applying force
00188         }
00189 
00190 
00191         // correction impulse
00192         btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv;
00193 
00194         // clip correction impulse
00195         btScalar clippedMotorImpulse;
00196 
00198         if (unclippedMotorImpulse>0.0f)
00199         {
00200                 clippedMotorImpulse =  unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse;
00201         }
00202         else
00203         {
00204                 clippedMotorImpulse =  unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse;
00205         }
00206 
00207 
00208         // sort with accumulated impulses
00209         btScalar        lo = btScalar(-BT_LARGE_FLOAT);
00210         btScalar        hi = btScalar(BT_LARGE_FLOAT);
00211 
00212         btScalar oldaccumImpulse = m_accumulatedImpulse;
00213         btScalar sum = oldaccumImpulse + clippedMotorImpulse;
00214         m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
00215 
00216         clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse;
00217 
00218         btVector3 motorImp = clippedMotorImpulse * axis;
00219 
00220         //body0->applyTorqueImpulse(motorImp);
00221         //body1->applyTorqueImpulse(-motorImp);
00222 
00223         body0->internalApplyImpulse(btVector3(0,0,0), body0->getInvInertiaTensorWorld()*axis,clippedMotorImpulse);
00224         body1->internalApplyImpulse(btVector3(0,0,0), body1->getInvInertiaTensorWorld()*axis,-clippedMotorImpulse);
00225 
00226 
00227         return clippedMotorImpulse;
00228 
00229 
00230 }
00231 
00233 
00234 
00235 
00236 
00238 
00239 
00240 int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value)
00241 {
00242         btScalar loLimit = m_lowerLimit[limitIndex];
00243         btScalar hiLimit = m_upperLimit[limitIndex];
00244         if(loLimit > hiLimit)
00245         {
00246                 m_currentLimit[limitIndex] = 0;//Free from violation
00247                 m_currentLimitError[limitIndex] = btScalar(0.f);
00248                 return 0;
00249         }
00250 
00251         if (test_value < loLimit)
00252         {
00253                 m_currentLimit[limitIndex] = 2;//low limit violation
00254                 m_currentLimitError[limitIndex] =  test_value - loLimit;
00255                 return 2;
00256         }
00257         else if (test_value> hiLimit)
00258         {
00259                 m_currentLimit[limitIndex] = 1;//High limit violation
00260                 m_currentLimitError[limitIndex] = test_value - hiLimit;
00261                 return 1;
00262         };
00263 
00264         m_currentLimit[limitIndex] = 0;//Free from violation
00265         m_currentLimitError[limitIndex] = btScalar(0.f);
00266         return 0;
00267 }
00268 
00269 
00270 
00271 btScalar btTranslationalLimitMotor::solveLinearAxis(
00272         btScalar timeStep,
00273         btScalar jacDiagABInv,
00274         btRigidBody& body1,const btVector3 &pointInA,
00275         btRigidBody& body2,const btVector3 &pointInB,
00276         int limit_index,
00277         const btVector3 & axis_normal_on_a,
00278         const btVector3 & anchorPos)
00279 {
00280 
00282         //    btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition();
00283         //    btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition();
00284         btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition();
00285         btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition();
00286 
00287         btVector3 vel1;
00288         body1.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1);
00289         btVector3 vel2;
00290         body2.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2);
00291         btVector3 vel = vel1 - vel2;
00292 
00293         btScalar rel_vel = axis_normal_on_a.dot(vel);
00294 
00295 
00296 
00298 
00299         //positional error (zeroth order error)
00300         btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a);
00301         btScalar        lo = btScalar(-BT_LARGE_FLOAT);
00302         btScalar        hi = btScalar(BT_LARGE_FLOAT);
00303 
00304         btScalar minLimit = m_lowerLimit[limit_index];
00305         btScalar maxLimit = m_upperLimit[limit_index];
00306 
00307         //handle the limits
00308         if (minLimit < maxLimit)
00309         {
00310                 {
00311                         if (depth > maxLimit)
00312                         {
00313                                 depth -= maxLimit;
00314                                 lo = btScalar(0.);
00315 
00316                         }
00317                         else
00318                         {
00319                                 if (depth < minLimit)
00320                                 {
00321                                         depth -= minLimit;
00322                                         hi = btScalar(0.);
00323                                 }
00324                                 else
00325                                 {
00326                                         return 0.0f;
00327                                 }
00328                         }
00329                 }
00330         }
00331 
00332         btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv;
00333 
00334 
00335 
00336 
00337         btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index];
00338         btScalar sum = oldNormalImpulse + normalImpulse;
00339         m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
00340         normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse;
00341 
00342         btVector3 impulse_vector = axis_normal_on_a * normalImpulse;
00343         //body1.applyImpulse( impulse_vector, rel_pos1);
00344         //body2.applyImpulse(-impulse_vector, rel_pos2);
00345 
00346         btVector3 ftorqueAxis1 = rel_pos1.cross(axis_normal_on_a);
00347         btVector3 ftorqueAxis2 = rel_pos2.cross(axis_normal_on_a);
00348         body1.internalApplyImpulse(axis_normal_on_a*body1.getInvMass(), body1.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse);
00349         body2.internalApplyImpulse(axis_normal_on_a*body2.getInvMass(), body2.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse);
00350 
00351 
00352 
00353 
00354         return normalImpulse;
00355 }
00356 
00358 
00359 void btGeneric6DofConstraint::calculateAngleInfo()
00360 {
00361         btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
00362         matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
00363         // in euler angle mode we do not actually constrain the angular velocity
00364         // along the axes axis[0] and axis[2] (although we do use axis[1]) :
00365         //
00366         //    to get                    constrain w2-w1 along           ...not
00367         //    ------                    ---------------------           ------
00368         //    d(angle[0])/dt = 0        ax[1] x ax[2]                   ax[0]
00369         //    d(angle[1])/dt = 0        ax[1]
00370         //    d(angle[2])/dt = 0        ax[0] x ax[1]                   ax[2]
00371         //
00372         // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
00373         // to prove the result for angle[0], write the expression for angle[0] from
00374         // GetInfo1 then take the derivative. to prove this for angle[2] it is
00375         // easier to take the euler rate expression for d(angle[2])/dt with respect
00376         // to the components of w and set that to 0.
00377         btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
00378         btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
00379 
00380         m_calculatedAxis[1] = axis2.cross(axis0);
00381         m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
00382         m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
00383 
00384         m_calculatedAxis[0].normalize();
00385         m_calculatedAxis[1].normalize();
00386         m_calculatedAxis[2].normalize();
00387 
00388 }
00389 
00390 void btGeneric6DofConstraint::calculateTransforms()
00391 {
00392         calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00393 }
00394 
00395 void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
00396 {
00397         m_calculatedTransformA = transA * m_frameInA;
00398         m_calculatedTransformB = transB * m_frameInB;
00399         calculateLinearInfo();
00400         calculateAngleInfo();
00401         if(m_useOffsetForConstraintFrame)
00402         {       //  get weight factors depending on masses
00403                 btScalar miA = getRigidBodyA().getInvMass();
00404                 btScalar miB = getRigidBodyB().getInvMass();
00405                 m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
00406                 btScalar miS = miA + miB;
00407                 if(miS > btScalar(0.f))
00408                 {
00409                         m_factA = miB / miS;
00410                 }
00411                 else 
00412                 {
00413                         m_factA = btScalar(0.5f);
00414                 }
00415                 m_factB = btScalar(1.0f) - m_factA;
00416         }
00417 }
00418 
00419 
00420 
00421 void btGeneric6DofConstraint::buildLinearJacobian(
00422         btJacobianEntry & jacLinear,const btVector3 & normalWorld,
00423         const btVector3 & pivotAInW,const btVector3 & pivotBInW)
00424 {
00425         new (&jacLinear) btJacobianEntry(
00426         m_rbA.getCenterOfMassTransform().getBasis().transpose(),
00427         m_rbB.getCenterOfMassTransform().getBasis().transpose(),
00428         pivotAInW - m_rbA.getCenterOfMassPosition(),
00429         pivotBInW - m_rbB.getCenterOfMassPosition(),
00430         normalWorld,
00431         m_rbA.getInvInertiaDiagLocal(),
00432         m_rbA.getInvMass(),
00433         m_rbB.getInvInertiaDiagLocal(),
00434         m_rbB.getInvMass());
00435 }
00436 
00437 
00438 
00439 void btGeneric6DofConstraint::buildAngularJacobian(
00440         btJacobianEntry & jacAngular,const btVector3 & jointAxisW)
00441 {
00442          new (&jacAngular)      btJacobianEntry(jointAxisW,
00443                                       m_rbA.getCenterOfMassTransform().getBasis().transpose(),
00444                                       m_rbB.getCenterOfMassTransform().getBasis().transpose(),
00445                                       m_rbA.getInvInertiaDiagLocal(),
00446                                       m_rbB.getInvInertiaDiagLocal());
00447 
00448 }
00449 
00450 
00451 
00452 bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
00453 {
00454         btScalar angle = m_calculatedAxisAngleDiff[axis_index];
00455         angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
00456         m_angularLimits[axis_index].m_currentPosition = angle;
00457         //test limits
00458         m_angularLimits[axis_index].testLimitValue(angle);
00459         return m_angularLimits[axis_index].needApplyTorques();
00460 }
00461 
00462 
00463 
00464 void btGeneric6DofConstraint::buildJacobian()
00465 {
00466 #ifndef __SPU__
00467         if (m_useSolveConstraintObsolete)
00468         {
00469 
00470                 // Clear accumulated impulses for the next simulation step
00471                 m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
00472                 int i;
00473                 for(i = 0; i < 3; i++)
00474                 {
00475                         m_angularLimits[i].m_accumulatedImpulse = btScalar(0.);
00476                 }
00477                 //calculates transform
00478                 calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00479 
00480                 //  const btVector3& pivotAInW = m_calculatedTransformA.getOrigin();
00481                 //  const btVector3& pivotBInW = m_calculatedTransformB.getOrigin();
00482                 calcAnchorPos();
00483                 btVector3 pivotAInW = m_AnchorPos;
00484                 btVector3 pivotBInW = m_AnchorPos;
00485 
00486                 // not used here
00487                 //    btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
00488                 //    btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
00489 
00490                 btVector3 normalWorld;
00491                 //linear part
00492                 for (i=0;i<3;i++)
00493                 {
00494                         if (m_linearLimits.isLimited(i))
00495                         {
00496                                 if (m_useLinearReferenceFrameA)
00497                                         normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
00498                                 else
00499                                         normalWorld = m_calculatedTransformB.getBasis().getColumn(i);
00500 
00501                                 buildLinearJacobian(
00502                                         m_jacLinear[i],normalWorld ,
00503                                         pivotAInW,pivotBInW);
00504 
00505                         }
00506                 }
00507 
00508                 // angular part
00509                 for (i=0;i<3;i++)
00510                 {
00511                         //calculates error angle
00512                         if (testAngularLimitMotor(i))
00513                         {
00514                                 normalWorld = this->getAxis(i);
00515                                 // Create angular atom
00516                                 buildAngularJacobian(m_jacAng[i],normalWorld);
00517                         }
00518                 }
00519 
00520         }
00521 #endif //__SPU__
00522 
00523 }
00524 
00525 
00526 void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info)
00527 {
00528         if (m_useSolveConstraintObsolete)
00529         {
00530                 info->m_numConstraintRows = 0;
00531                 info->nub = 0;
00532         } else
00533         {
00534                 //prepare constraint
00535                 calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00536                 info->m_numConstraintRows = 0;
00537                 info->nub = 6;
00538                 int i;
00539                 //test linear limits
00540                 for(i = 0; i < 3; i++)
00541                 {
00542                         if(m_linearLimits.needApplyForce(i))
00543                         {
00544                                 info->m_numConstraintRows++;
00545                                 info->nub--;
00546                         }
00547                 }
00548                 //test angular limits
00549                 for (i=0;i<3 ;i++ )
00550                 {
00551                         if(testAngularLimitMotor(i))
00552                         {
00553                                 info->m_numConstraintRows++;
00554                                 info->nub--;
00555                         }
00556                 }
00557         }
00558 }
00559 
00560 void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
00561 {
00562         if (m_useSolveConstraintObsolete)
00563         {
00564                 info->m_numConstraintRows = 0;
00565                 info->nub = 0;
00566         } else
00567         {
00568                 //pre-allocate all 6
00569                 info->m_numConstraintRows = 6;
00570                 info->nub = 0;
00571         }
00572 }
00573 
00574 
00575 void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info)
00576 {
00577         getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(),m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
00578 }
00579 
00580 void btGeneric6DofConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
00581 {
00582         btAssert(!m_useSolveConstraintObsolete);
00583         //prepare constraint
00584         calculateTransforms(transA,transB);
00585         if(m_useOffsetForConstraintFrame)
00586         { // for stability better to solve angular limits first
00587                 int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
00588                 setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
00589         }
00590         else
00591         { // leave old version for compatibility
00592                 int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
00593                 setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
00594         }
00595 }
00596 
00597 
00598 
00599 int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
00600 {
00601 //      int row = 0;
00602         //solve linear limits
00603         btRotationalLimitMotor limot;
00604         for (int i=0;i<3 ;i++ )
00605         {
00606                 if(m_linearLimits.needApplyForce(i))
00607                 { // re-use rotational motor code
00608                         limot.m_bounce = btScalar(0.f);
00609                         limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
00610                         limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
00611                         limot.m_currentLimitError  = m_linearLimits.m_currentLimitError[i];
00612                         limot.m_damping  = m_linearLimits.m_damping;
00613                         limot.m_enableMotor  = m_linearLimits.m_enableMotor[i];
00614                         limot.m_hiLimit  = m_linearLimits.m_upperLimit[i];
00615                         limot.m_limitSoftness  = m_linearLimits.m_limitSoftness;
00616                         limot.m_loLimit  = m_linearLimits.m_lowerLimit[i];
00617                         limot.m_maxLimitForce  = btScalar(0.f);
00618                         limot.m_maxMotorForce  = m_linearLimits.m_maxMotorForce[i];
00619                         limot.m_targetVelocity  = m_linearLimits.m_targetVelocity[i];
00620                         btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
00621                         int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT);
00622                         limot.m_normalCFM       = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
00623                         limot.m_stopCFM         = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
00624                         limot.m_stopERP         = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
00625                         if(m_useOffsetForConstraintFrame)
00626                         {
00627                                 int indx1 = (i + 1) % 3;
00628                                 int indx2 = (i + 2) % 3;
00629                                 int rotAllowed = 1; // rotations around orthos to current axis
00630                                 if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
00631                                 {
00632                                         rotAllowed = 0;
00633                                 }
00634                                 row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
00635                         }
00636                         else
00637                         {
00638                                 row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0);
00639                         }
00640                 }
00641         }
00642         return row;
00643 }
00644 
00645 
00646 
00647 int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
00648 {
00649         btGeneric6DofConstraint * d6constraint = this;
00650         int row = row_offset;
00651         //solve angular limits
00652         for (int i=0;i<3 ;i++ )
00653         {
00654                 if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
00655                 {
00656                         btVector3 axis = d6constraint->getAxis(i);
00657                         int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT);
00658                         if(!(flags & BT_6DOF_FLAGS_CFM_NORM))
00659                         {
00660                                 m_angularLimits[i].m_normalCFM = info->cfm[0];
00661                         }
00662                         if(!(flags & BT_6DOF_FLAGS_CFM_STOP))
00663                         {
00664                                 m_angularLimits[i].m_stopCFM = info->cfm[0];
00665                         }
00666                         if(!(flags & BT_6DOF_FLAGS_ERP_STOP))
00667                         {
00668                                 m_angularLimits[i].m_stopERP = info->erp;
00669                         }
00670                         row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
00671                                                                                                 transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
00672                 }
00673         }
00674 
00675         return row;
00676 }
00677 
00678 
00679 
00680 
00681 void    btGeneric6DofConstraint::updateRHS(btScalar     timeStep)
00682 {
00683         (void)timeStep;
00684 
00685 }
00686 
00687 
00688 
00689 btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const
00690 {
00691         return m_calculatedAxis[axis_index];
00692 }
00693 
00694 
00695 btScalar        btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const
00696 {
00697         return m_calculatedLinearDiff[axisIndex];
00698 }
00699 
00700 
00701 btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const
00702 {
00703         return m_calculatedAxisAngleDiff[axisIndex];
00704 }
00705 
00706 
00707 
00708 void btGeneric6DofConstraint::calcAnchorPos(void)
00709 {
00710         btScalar imA = m_rbA.getInvMass();
00711         btScalar imB = m_rbB.getInvMass();
00712         btScalar weight;
00713         if(imB == btScalar(0.0))
00714         {
00715                 weight = btScalar(1.0);
00716         }
00717         else
00718         {
00719                 weight = imA / (imA + imB);
00720         }
00721         const btVector3& pA = m_calculatedTransformA.getOrigin();
00722         const btVector3& pB = m_calculatedTransformB.getOrigin();
00723         m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight);
00724         return;
00725 }
00726 
00727 
00728 
00729 void btGeneric6DofConstraint::calculateLinearInfo()
00730 {
00731         m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
00732         m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
00733         for(int i = 0; i < 3; i++)
00734         {
00735                 m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
00736                 m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
00737         }
00738 }
00739 
00740 
00741 
00742 int btGeneric6DofConstraint::get_limit_motor_info2(
00743         btRotationalLimitMotor * limot,
00744         const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
00745         btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed)
00746 {
00747     int srow = row * info->rowskip;
00748     int powered = limot->m_enableMotor;
00749     int limit = limot->m_currentLimit;
00750     if (powered || limit)
00751     {   // if the joint is powered, or has joint limits, add in the extra row
00752         btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
00753         btScalar *J2 = rotational ? info->m_J2angularAxis : 0;
00754         J1[srow+0] = ax1[0];
00755         J1[srow+1] = ax1[1];
00756         J1[srow+2] = ax1[2];
00757         if(rotational)
00758         {
00759             J2[srow+0] = -ax1[0];
00760             J2[srow+1] = -ax1[1];
00761             J2[srow+2] = -ax1[2];
00762         }
00763         if((!rotational))
00764         {
00765                         if (m_useOffsetForConstraintFrame)
00766                         {
00767                                 btVector3 tmpA, tmpB, relA, relB;
00768                                 // get vector from bodyB to frameB in WCS
00769                                 relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
00770                                 // get its projection to constraint axis
00771                                 btVector3 projB = ax1 * relB.dot(ax1);
00772                                 // get vector directed from bodyB to constraint axis (and orthogonal to it)
00773                                 btVector3 orthoB = relB - projB;
00774                                 // same for bodyA
00775                                 relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
00776                                 btVector3 projA = ax1 * relA.dot(ax1);
00777                                 btVector3 orthoA = relA - projA;
00778                                 // get desired offset between frames A and B along constraint axis
00779                                 btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
00780                                 // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
00781                                 btVector3 totalDist = projA + ax1 * desiredOffs - projB;
00782                                 // get offset vectors relA and relB
00783                                 relA = orthoA + totalDist * m_factA;
00784                                 relB = orthoB - totalDist * m_factB;
00785                                 tmpA = relA.cross(ax1);
00786                                 tmpB = relB.cross(ax1);
00787                                 if(m_hasStaticBody && (!rotAllowed))
00788                                 {
00789                                         tmpA *= m_factA;
00790                                         tmpB *= m_factB;
00791                                 }
00792                                 int i;
00793                                 for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
00794                                 for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
00795                         } else
00796                         {
00797                                 btVector3 ltd;  // Linear Torque Decoupling vector
00798                                 btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
00799                                 ltd = c.cross(ax1);
00800                                 info->m_J1angularAxis[srow+0] = ltd[0];
00801                                 info->m_J1angularAxis[srow+1] = ltd[1];
00802                                 info->m_J1angularAxis[srow+2] = ltd[2];
00803 
00804                                 c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
00805                                 ltd = -c.cross(ax1);
00806                                 info->m_J2angularAxis[srow+0] = ltd[0];
00807                                 info->m_J2angularAxis[srow+1] = ltd[1];
00808                                 info->m_J2angularAxis[srow+2] = ltd[2];
00809                         }
00810         }
00811         // if we're limited low and high simultaneously, the joint motor is
00812         // ineffective
00813         if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0;
00814         info->m_constraintError[srow] = btScalar(0.f);
00815         if (powered)
00816         {
00817                         info->cfm[srow] = limot->m_normalCFM;
00818             if(!limit)
00819             {
00820                                 btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
00821 
00822                                 btScalar mot_fact = getMotorFactor(     limot->m_currentPosition, 
00823                                                                                                         limot->m_loLimit,
00824                                                                                                         limot->m_hiLimit, 
00825                                                                                                         tag_vel, 
00826                                                                                                         info->fps * limot->m_stopERP);
00827                                 info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
00828                 info->m_lowerLimit[srow] = -limot->m_maxMotorForce;
00829                 info->m_upperLimit[srow] = limot->m_maxMotorForce;
00830             }
00831         }
00832         if(limit)
00833         {
00834             btScalar k = info->fps * limot->m_stopERP;
00835                         if(!rotational)
00836                         {
00837                                 info->m_constraintError[srow] += k * limot->m_currentLimitError;
00838                         }
00839                         else
00840                         {
00841                                 info->m_constraintError[srow] += -k * limot->m_currentLimitError;
00842                         }
00843                         info->cfm[srow] = limot->m_stopCFM;
00844             if (limot->m_loLimit == limot->m_hiLimit)
00845             {   // limited low and high simultaneously
00846                 info->m_lowerLimit[srow] = -SIMD_INFINITY;
00847                 info->m_upperLimit[srow] = SIMD_INFINITY;
00848             }
00849             else
00850             {
00851                 if (limit == 1)
00852                 {
00853                     info->m_lowerLimit[srow] = 0;
00854                     info->m_upperLimit[srow] = SIMD_INFINITY;
00855                 }
00856                 else
00857                 {
00858                     info->m_lowerLimit[srow] = -SIMD_INFINITY;
00859                     info->m_upperLimit[srow] = 0;
00860                 }
00861                 // deal with bounce
00862                 if (limot->m_bounce > 0)
00863                 {
00864                     // calculate joint velocity
00865                     btScalar vel;
00866                     if (rotational)
00867                     {
00868                         vel = angVelA.dot(ax1);
00869 //make sure that if no body -> angVelB == zero vec
00870 //                        if (body1)
00871                             vel -= angVelB.dot(ax1);
00872                     }
00873                     else
00874                     {
00875                         vel = linVelA.dot(ax1);
00876 //make sure that if no body -> angVelB == zero vec
00877 //                        if (body1)
00878                             vel -= linVelB.dot(ax1);
00879                     }
00880                     // only apply bounce if the velocity is incoming, and if the
00881                     // resulting c[] exceeds what we already have.
00882                     if (limit == 1)
00883                     {
00884                         if (vel < 0)
00885                         {
00886                             btScalar newc = -limot->m_bounce* vel;
00887                             if (newc > info->m_constraintError[srow]) 
00888                                                                 info->m_constraintError[srow] = newc;
00889                         }
00890                     }
00891                     else
00892                     {
00893                         if (vel > 0)
00894                         {
00895                             btScalar newc = -limot->m_bounce * vel;
00896                             if (newc < info->m_constraintError[srow]) 
00897                                                                 info->m_constraintError[srow] = newc;
00898                         }
00899                     }
00900                 }
00901             }
00902         }
00903         return 1;
00904     }
00905     else return 0;
00906 }
00907 
00908 
00909 
00910 
00911 
00912 
00915 void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis)
00916 {
00917         if((axis >= 0) && (axis < 3))
00918         {
00919                 switch(num)
00920                 {
00921                         case BT_CONSTRAINT_STOP_ERP : 
00922                                 m_linearLimits.m_stopERP[axis] = value;
00923                                 m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
00924                                 break;
00925                         case BT_CONSTRAINT_STOP_CFM : 
00926                                 m_linearLimits.m_stopCFM[axis] = value;
00927                                 m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
00928                                 break;
00929                         case BT_CONSTRAINT_CFM : 
00930                                 m_linearLimits.m_normalCFM[axis] = value;
00931                                 m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
00932                                 break;
00933                         default : 
00934                                 btAssertConstrParams(0);
00935                 }
00936         }
00937         else if((axis >=3) && (axis < 6))
00938         {
00939                 switch(num)
00940                 {
00941                         case BT_CONSTRAINT_STOP_ERP : 
00942                                 m_angularLimits[axis - 3].m_stopERP = value;
00943                                 m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
00944                                 break;
00945                         case BT_CONSTRAINT_STOP_CFM : 
00946                                 m_angularLimits[axis - 3].m_stopCFM = value;
00947                                 m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
00948                                 break;
00949                         case BT_CONSTRAINT_CFM : 
00950                                 m_angularLimits[axis - 3].m_normalCFM = value;
00951                                 m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
00952                                 break;
00953                         default : 
00954                                 btAssertConstrParams(0);
00955                 }
00956         }
00957         else
00958         {
00959                 btAssertConstrParams(0);
00960         }
00961 }
00962 
00964 btScalar btGeneric6DofConstraint::getParam(int num, int axis) const 
00965 {
00966         btScalar retVal = 0;
00967         if((axis >= 0) && (axis < 3))
00968         {
00969                 switch(num)
00970                 {
00971                         case BT_CONSTRAINT_STOP_ERP : 
00972                                 btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
00973                                 retVal = m_linearLimits.m_stopERP[axis];
00974                                 break;
00975                         case BT_CONSTRAINT_STOP_CFM : 
00976                                 btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
00977                                 retVal = m_linearLimits.m_stopCFM[axis];
00978                                 break;
00979                         case BT_CONSTRAINT_CFM : 
00980                                 btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
00981                                 retVal = m_linearLimits.m_normalCFM[axis];
00982                                 break;
00983                         default : 
00984                                 btAssertConstrParams(0);
00985                 }
00986         }
00987         else if((axis >=3) && (axis < 6))
00988         {
00989                 switch(num)
00990                 {
00991                         case BT_CONSTRAINT_STOP_ERP : 
00992                                 btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
00993                                 retVal = m_angularLimits[axis - 3].m_stopERP;
00994                                 break;
00995                         case BT_CONSTRAINT_STOP_CFM : 
00996                                 btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
00997                                 retVal = m_angularLimits[axis - 3].m_stopCFM;
00998                                 break;
00999                         case BT_CONSTRAINT_CFM : 
01000                                 btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
01001                                 retVal = m_angularLimits[axis - 3].m_normalCFM;
01002                                 break;
01003                         default : 
01004                                 btAssertConstrParams(0);
01005                 }
01006         }
01007         else
01008         {
01009                 btAssertConstrParams(0);
01010         }
01011         return retVal;
01012 }

Generated on Mon Feb 15 22:17:04 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1