00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00087
00088
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
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
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;
00127 return 0;
00128 }
00129 if (test_value < m_loLimit)
00130 {
00131 m_currentLimit = 1;
00132 m_currentLimitError = test_value - m_loLimit;
00133 return 1;
00134 }
00135 else if (test_value> m_hiLimit)
00136 {
00137 m_currentLimit = 2;
00138 m_currentLimitError = test_value - m_hiLimit;
00139 return 2;
00140 };
00141
00142 m_currentLimit = 0;
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
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
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
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;
00188 }
00189
00190
00191
00192 btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv;
00193
00194
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
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
00221
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;
00247 m_currentLimitError[limitIndex] = btScalar(0.f);
00248 return 0;
00249 }
00250
00251 if (test_value < loLimit)
00252 {
00253 m_currentLimit[limitIndex] = 2;
00254 m_currentLimitError[limitIndex] = test_value - loLimit;
00255 return 2;
00256 }
00257 else if (test_value> hiLimit)
00258 {
00259 m_currentLimit[limitIndex] = 1;
00260 m_currentLimitError[limitIndex] = test_value - hiLimit;
00261 return 1;
00262 };
00263
00264 m_currentLimit[limitIndex] = 0;
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
00283
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
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
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
00344
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
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
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 {
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
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
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
00478 calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00479
00480
00481
00482 calcAnchorPos();
00483 btVector3 pivotAInW = m_AnchorPos;
00484 btVector3 pivotBInW = m_AnchorPos;
00485
00486
00487
00488
00489
00490 btVector3 normalWorld;
00491
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
00509 for (i=0;i<3;i++)
00510 {
00511
00512 if (testAngularLimitMotor(i))
00513 {
00514 normalWorld = this->getAxis(i);
00515
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
00535 calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00536 info->m_numConstraintRows = 0;
00537 info->nub = 6;
00538 int i;
00539
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
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
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
00584 calculateTransforms(transA,transB);
00585 if(m_useOffsetForConstraintFrame)
00586 {
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 {
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
00602
00603 btRotationalLimitMotor limot;
00604 for (int i=0;i<3 ;i++ )
00605 {
00606 if(m_linearLimits.needApplyForce(i))
00607 {
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;
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
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 {
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
00769 relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
00770
00771 btVector3 projB = ax1 * relB.dot(ax1);
00772
00773 btVector3 orthoB = relB - projB;
00774
00775 relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
00776 btVector3 projA = ax1 * relA.dot(ax1);
00777 btVector3 orthoA = relA - projA;
00778
00779 btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
00780
00781 btVector3 totalDist = projA + ax1 * desiredOffs - projB;
00782
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;
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
00812
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 {
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
00862 if (limot->m_bounce > 0)
00863 {
00864
00865 btScalar vel;
00866 if (rotational)
00867 {
00868 vel = angVelA.dot(ax1);
00869
00870
00871 vel -= angVelB.dot(ax1);
00872 }
00873 else
00874 {
00875 vel = linVelA.dot(ax1);
00876
00877
00878 vel -= linVelB.dot(ax1);
00879 }
00880
00881
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 }