00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "btHingeConstraint.h"
00018 #include "BulletDynamics/Dynamics/btRigidBody.h"
00019 #include "LinearMath/btTransformUtil.h"
00020 #include "LinearMath/btMinMax.h"
00021 #include <new>
00022 #include "btSolverBody.h"
00023
00024
00025
00026
00027 #define HINGE_USE_OBSOLETE_SOLVER false
00028
00029 #define HINGE_USE_FRAME_OFFSET true
00030
00031 #ifndef __SPU__
00032
00033
00034
00035
00036
00037 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,
00038 btVector3& axisInA,btVector3& axisInB, bool useReferenceFrameA)
00039 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),
00040 m_angularOnly(false),
00041 m_enableAngularMotor(false),
00042 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
00043 m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
00044 m_useReferenceFrameA(useReferenceFrameA),
00045 m_flags(0)
00046 {
00047 m_rbAFrame.getOrigin() = pivotInA;
00048
00049
00050 btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0);
00051
00052 btVector3 rbAxisA2;
00053 btScalar projection = axisInA.dot(rbAxisA1);
00054 if (projection >= 1.0f - SIMD_EPSILON) {
00055 rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2);
00056 rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
00057 } else if (projection <= -1.0f + SIMD_EPSILON) {
00058 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2);
00059 rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
00060 } else {
00061 rbAxisA2 = axisInA.cross(rbAxisA1);
00062 rbAxisA1 = rbAxisA2.cross(axisInA);
00063 }
00064
00065 m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
00066 rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
00067 rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
00068
00069 btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
00070 btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
00071 btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
00072
00073 m_rbBFrame.getOrigin() = pivotInB;
00074 m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
00075 rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
00076 rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
00077
00078
00079 m_lowerLimit = btScalar(1.0f);
00080 m_upperLimit = btScalar(-1.0f);
00081 m_biasFactor = 0.3f;
00082 m_relaxationFactor = 1.0f;
00083 m_limitSoftness = 0.9f;
00084 m_solveLimit = false;
00085 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
00086 }
00087
00088
00089
00090 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA, bool useReferenceFrameA)
00091 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false),
00092 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
00093 m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
00094 m_useReferenceFrameA(useReferenceFrameA),
00095 m_flags(0)
00096 {
00097
00098
00099
00100 btVector3 rbAxisA1, rbAxisA2;
00101 btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
00102
00103 m_rbAFrame.getOrigin() = pivotInA;
00104 m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
00105 rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
00106 rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
00107
00108 btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA;
00109
00110 btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
00111 btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1);
00112 btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
00113
00114
00115 m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA);
00116 m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
00117 rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
00118 rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
00119
00120
00121 m_lowerLimit = btScalar(1.0f);
00122 m_upperLimit = btScalar(-1.0f);
00123 m_biasFactor = 0.3f;
00124 m_relaxationFactor = 1.0f;
00125 m_limitSoftness = 0.9f;
00126 m_solveLimit = false;
00127 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
00128 }
00129
00130
00131
00132 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB,
00133 const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
00134 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
00135 m_angularOnly(false),
00136 m_enableAngularMotor(false),
00137 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
00138 m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
00139 m_useReferenceFrameA(useReferenceFrameA),
00140 m_flags(0)
00141 {
00142
00143 m_lowerLimit = btScalar(1.0f);
00144 m_upperLimit = btScalar(-1.0f);
00145 m_biasFactor = 0.3f;
00146 m_relaxationFactor = 1.0f;
00147 m_limitSoftness = 0.9f;
00148 m_solveLimit = false;
00149 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
00150 }
00151
00152
00153
00154 btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
00155 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame),
00156 m_angularOnly(false),
00157 m_enableAngularMotor(false),
00158 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
00159 m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
00160 m_useReferenceFrameA(useReferenceFrameA),
00161 m_flags(0)
00162 {
00164
00165 m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
00166
00167
00168 m_lowerLimit = btScalar(1.0f);
00169 m_upperLimit = btScalar(-1.0f);
00170 m_biasFactor = 0.3f;
00171 m_relaxationFactor = 1.0f;
00172 m_limitSoftness = 0.9f;
00173 m_solveLimit = false;
00174 m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
00175 }
00176
00177
00178
00179 void btHingeConstraint::buildJacobian()
00180 {
00181 if (m_useSolveConstraintObsolete)
00182 {
00183 m_appliedImpulse = btScalar(0.);
00184 m_accMotorImpulse = btScalar(0.);
00185
00186 if (!m_angularOnly)
00187 {
00188 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
00189 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
00190 btVector3 relPos = pivotBInW - pivotAInW;
00191
00192 btVector3 normal[3];
00193 if (relPos.length2() > SIMD_EPSILON)
00194 {
00195 normal[0] = relPos.normalized();
00196 }
00197 else
00198 {
00199 normal[0].setValue(btScalar(1.0),0,0);
00200 }
00201
00202 btPlaneSpace1(normal[0], normal[1], normal[2]);
00203
00204 for (int i=0;i<3;i++)
00205 {
00206 new (&m_jac[i]) btJacobianEntry(
00207 m_rbA.getCenterOfMassTransform().getBasis().transpose(),
00208 m_rbB.getCenterOfMassTransform().getBasis().transpose(),
00209 pivotAInW - m_rbA.getCenterOfMassPosition(),
00210 pivotBInW - m_rbB.getCenterOfMassPosition(),
00211 normal[i],
00212 m_rbA.getInvInertiaDiagLocal(),
00213 m_rbA.getInvMass(),
00214 m_rbB.getInvInertiaDiagLocal(),
00215 m_rbB.getInvMass());
00216 }
00217 }
00218
00219
00220
00221
00222
00223 btVector3 jointAxis0local;
00224 btVector3 jointAxis1local;
00225
00226 btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local);
00227
00228 btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
00229 btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
00230 btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
00231
00232 new (&m_jacAng[0]) btJacobianEntry(jointAxis0,
00233 m_rbA.getCenterOfMassTransform().getBasis().transpose(),
00234 m_rbB.getCenterOfMassTransform().getBasis().transpose(),
00235 m_rbA.getInvInertiaDiagLocal(),
00236 m_rbB.getInvInertiaDiagLocal());
00237
00238 new (&m_jacAng[1]) btJacobianEntry(jointAxis1,
00239 m_rbA.getCenterOfMassTransform().getBasis().transpose(),
00240 m_rbB.getCenterOfMassTransform().getBasis().transpose(),
00241 m_rbA.getInvInertiaDiagLocal(),
00242 m_rbB.getInvInertiaDiagLocal());
00243
00244 new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld,
00245 m_rbA.getCenterOfMassTransform().getBasis().transpose(),
00246 m_rbB.getCenterOfMassTransform().getBasis().transpose(),
00247 m_rbA.getInvInertiaDiagLocal(),
00248 m_rbB.getInvInertiaDiagLocal());
00249
00250
00251 m_accLimitImpulse = btScalar(0.);
00252
00253
00254 testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00255
00256
00257 btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
00258 m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
00259 getRigidBodyB().computeAngularImpulseDenominator(axisA));
00260
00261 }
00262 }
00263
00264
00265 #endif //__SPU__
00266
00267
00268 void btHingeConstraint::getInfo1(btConstraintInfo1* info)
00269 {
00270 if (m_useSolveConstraintObsolete)
00271 {
00272 info->m_numConstraintRows = 0;
00273 info->nub = 0;
00274 }
00275 else
00276 {
00277 info->m_numConstraintRows = 5;
00278 info->nub = 1;
00279
00280
00281 testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00282 if(getSolveLimit() || getEnableAngularMotor())
00283 {
00284 info->m_numConstraintRows++;
00285 info->nub--;
00286 }
00287
00288 }
00289 }
00290
00291 void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
00292 {
00293 if (m_useSolveConstraintObsolete)
00294 {
00295 info->m_numConstraintRows = 0;
00296 info->nub = 0;
00297 }
00298 else
00299 {
00300
00301 info->m_numConstraintRows = 6;
00302 info->nub = 0;
00303 }
00304 }
00305
00306 void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
00307 {
00308 if(m_useOffsetForConstraintFrame)
00309 {
00310 getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
00311 }
00312 else
00313 {
00314 getInfo2Internal(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
00315 }
00316 }
00317
00318
00319 void btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
00320 {
00322 testLimit(transA,transB);
00323
00324 getInfo2Internal(info,transA,transB,angVelA,angVelB);
00325 }
00326
00327
00328 void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
00329 {
00330
00331 btAssert(!m_useSolveConstraintObsolete);
00332 int i, skip = info->rowskip;
00333
00334 btTransform trA = transA*m_rbAFrame;
00335 btTransform trB = transB*m_rbBFrame;
00336
00337 btVector3 pivotAInW = trA.getOrigin();
00338 btVector3 pivotBInW = trB.getOrigin();
00339 #if 0
00340 if (0)
00341 {
00342 for (i=0;i<6;i++)
00343 {
00344 info->m_J1linearAxis[i*skip]=0;
00345 info->m_J1linearAxis[i*skip+1]=0;
00346 info->m_J1linearAxis[i*skip+2]=0;
00347
00348 info->m_J1angularAxis[i*skip]=0;
00349 info->m_J1angularAxis[i*skip+1]=0;
00350 info->m_J1angularAxis[i*skip+2]=0;
00351
00352 info->m_J2angularAxis[i*skip]=0;
00353 info->m_J2angularAxis[i*skip+1]=0;
00354 info->m_J2angularAxis[i*skip+2]=0;
00355
00356 info->m_constraintError[i*skip]=0.f;
00357 }
00358 }
00359 #endif //#if 0
00360
00361 info->m_J1linearAxis[0] = 1;
00362 info->m_J1linearAxis[skip + 1] = 1;
00363 info->m_J1linearAxis[2 * skip + 2] = 1;
00364
00365
00366
00367
00368
00369 btVector3 a1 = pivotAInW - transA.getOrigin();
00370 {
00371 btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
00372 btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
00373 btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
00374 btVector3 a1neg = -a1;
00375 a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
00376 }
00377 btVector3 a2 = pivotBInW - transB.getOrigin();
00378 {
00379 btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
00380 btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
00381 btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
00382 a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
00383 }
00384
00385 btScalar k = info->fps * info->erp;
00386 for(i = 0; i < 3; i++)
00387 {
00388 info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 btVector3 ax1 = trA.getBasis().getColumn(2);
00400
00401 btVector3 p = trA.getBasis().getColumn(0);
00402 btVector3 q = trA.getBasis().getColumn(1);
00403
00404 int s3 = 3 * info->rowskip;
00405 int s4 = 4 * info->rowskip;
00406
00407 info->m_J1angularAxis[s3 + 0] = p[0];
00408 info->m_J1angularAxis[s3 + 1] = p[1];
00409 info->m_J1angularAxis[s3 + 2] = p[2];
00410 info->m_J1angularAxis[s4 + 0] = q[0];
00411 info->m_J1angularAxis[s4 + 1] = q[1];
00412 info->m_J1angularAxis[s4 + 2] = q[2];
00413
00414 info->m_J2angularAxis[s3 + 0] = -p[0];
00415 info->m_J2angularAxis[s3 + 1] = -p[1];
00416 info->m_J2angularAxis[s3 + 2] = -p[2];
00417 info->m_J2angularAxis[s4 + 0] = -q[0];
00418 info->m_J2angularAxis[s4 + 1] = -q[1];
00419 info->m_J2angularAxis[s4 + 2] = -q[2];
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 btVector3 ax2 = trB.getBasis().getColumn(2);
00436 btVector3 u = ax1.cross(ax2);
00437 info->m_constraintError[s3] = k * u.dot(p);
00438 info->m_constraintError[s4] = k * u.dot(q);
00439
00440 int nrow = 4;
00441 int srow;
00442 btScalar limit_err = btScalar(0.0);
00443 int limit = 0;
00444 if(getSolveLimit())
00445 {
00446 limit_err = m_correction * m_referenceSign;
00447 limit = (limit_err > btScalar(0.0)) ? 1 : 2;
00448 }
00449
00450 int powered = 0;
00451 if(getEnableAngularMotor())
00452 {
00453 powered = 1;
00454 }
00455 if(limit || powered)
00456 {
00457 nrow++;
00458 srow = nrow * info->rowskip;
00459 info->m_J1angularAxis[srow+0] = ax1[0];
00460 info->m_J1angularAxis[srow+1] = ax1[1];
00461 info->m_J1angularAxis[srow+2] = ax1[2];
00462
00463 info->m_J2angularAxis[srow+0] = -ax1[0];
00464 info->m_J2angularAxis[srow+1] = -ax1[1];
00465 info->m_J2angularAxis[srow+2] = -ax1[2];
00466
00467 btScalar lostop = getLowerLimit();
00468 btScalar histop = getUpperLimit();
00469 if(limit && (lostop == histop))
00470 {
00471 powered = 0;
00472 }
00473 info->m_constraintError[srow] = btScalar(0.0f);
00474 btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp;
00475 if(powered)
00476 {
00477 if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
00478 {
00479 info->cfm[srow] = m_normalCFM;
00480 }
00481 btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
00482 info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
00483 info->m_lowerLimit[srow] = - m_maxMotorImpulse;
00484 info->m_upperLimit[srow] = m_maxMotorImpulse;
00485 }
00486 if(limit)
00487 {
00488 k = info->fps * currERP;
00489 info->m_constraintError[srow] += k * limit_err;
00490 if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
00491 {
00492 info->cfm[srow] = m_stopCFM;
00493 }
00494 if(lostop == histop)
00495 {
00496
00497 info->m_lowerLimit[srow] = -SIMD_INFINITY;
00498 info->m_upperLimit[srow] = SIMD_INFINITY;
00499 }
00500 else if(limit == 1)
00501 {
00502 info->m_lowerLimit[srow] = 0;
00503 info->m_upperLimit[srow] = SIMD_INFINITY;
00504 }
00505 else
00506 {
00507 info->m_lowerLimit[srow] = -SIMD_INFINITY;
00508 info->m_upperLimit[srow] = 0;
00509 }
00510
00511 btScalar bounce = m_relaxationFactor;
00512 if(bounce > btScalar(0.0))
00513 {
00514 btScalar vel = angVelA.dot(ax1);
00515 vel -= angVelB.dot(ax1);
00516
00517
00518 if(limit == 1)
00519 {
00520 if(vel < 0)
00521 {
00522 btScalar newc = -bounce * vel;
00523 if(newc > info->m_constraintError[srow])
00524 {
00525 info->m_constraintError[srow] = newc;
00526 }
00527 }
00528 }
00529 else
00530 {
00531 if(vel > 0)
00532 {
00533 btScalar newc = -bounce * vel;
00534 if(newc < info->m_constraintError[srow])
00535 {
00536 info->m_constraintError[srow] = newc;
00537 }
00538 }
00539 }
00540 }
00541 info->m_constraintError[srow] *= m_biasFactor;
00542 }
00543 }
00544 }
00545
00546
00547
00548
00549
00550
00551 void btHingeConstraint::updateRHS(btScalar timeStep)
00552 {
00553 (void)timeStep;
00554
00555 }
00556
00557
00558 btScalar btHingeConstraint::getHingeAngle()
00559 {
00560 return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00561 }
00562
00563 btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB)
00564 {
00565 const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
00566 const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
00567 const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
00568
00569 btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
00570 return m_referenceSign * angle;
00571 }
00572
00573
00574 #if 0
00575 void btHingeConstraint::testLimit()
00576 {
00577
00578 m_hingeAngle = getHingeAngle();
00579 m_correction = btScalar(0.);
00580 m_limitSign = btScalar(0.);
00581 m_solveLimit = false;
00582 if (m_lowerLimit <= m_upperLimit)
00583 {
00584 if (m_hingeAngle <= m_lowerLimit)
00585 {
00586 m_correction = (m_lowerLimit - m_hingeAngle);
00587 m_limitSign = 1.0f;
00588 m_solveLimit = true;
00589 }
00590 else if (m_hingeAngle >= m_upperLimit)
00591 {
00592 m_correction = m_upperLimit - m_hingeAngle;
00593 m_limitSign = -1.0f;
00594 m_solveLimit = true;
00595 }
00596 }
00597 return;
00598 }
00599 #else
00600
00601
00602 void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB)
00603 {
00604
00605 m_hingeAngle = getHingeAngle(transA,transB);
00606 m_correction = btScalar(0.);
00607 m_limitSign = btScalar(0.);
00608 m_solveLimit = false;
00609 if (m_lowerLimit <= m_upperLimit)
00610 {
00611 m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit);
00612 if (m_hingeAngle <= m_lowerLimit)
00613 {
00614 m_correction = (m_lowerLimit - m_hingeAngle);
00615 m_limitSign = 1.0f;
00616 m_solveLimit = true;
00617 }
00618 else if (m_hingeAngle >= m_upperLimit)
00619 {
00620 m_correction = m_upperLimit - m_hingeAngle;
00621 m_limitSign = -1.0f;
00622 m_solveLimit = true;
00623 }
00624 }
00625 return;
00626 }
00627 #endif
00628
00629 static btVector3 vHinge(0, 0, btScalar(1));
00630
00631 void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
00632 {
00633
00634 btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation();
00635 qConstraint.normalize();
00636
00637
00638 btVector3 vNoHinge = quatRotate(qConstraint, vHinge); vNoHinge.normalize();
00639 btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge);
00640 btQuaternion qHinge = qNoHinge.inverse() * qConstraint;
00641 qHinge.normalize();
00642
00643
00644 btScalar targetAngle = qHinge.getAngle();
00645 if (targetAngle > SIMD_PI)
00646 {
00647 qHinge = operator-(qHinge);
00648 targetAngle = qHinge.getAngle();
00649 }
00650 if (qHinge.getZ() < 0)
00651 targetAngle = -targetAngle;
00652
00653 setMotorTarget(targetAngle, dt);
00654 }
00655
00656 void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
00657 {
00658 if (m_lowerLimit < m_upperLimit)
00659 {
00660 if (targetAngle < m_lowerLimit)
00661 targetAngle = m_lowerLimit;
00662 else if (targetAngle > m_upperLimit)
00663 targetAngle = m_upperLimit;
00664 }
00665
00666
00667 btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
00668 btScalar dAngle = targetAngle - curAngle;
00669 m_motorTargetVelocity = dAngle / dt;
00670 }
00671
00672
00673
00674 void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
00675 {
00676 btAssert(!m_useSolveConstraintObsolete);
00677 int i, s = info->rowskip;
00678
00679 btTransform trA = transA*m_rbAFrame;
00680 btTransform trB = transB*m_rbBFrame;
00681
00682 btVector3 pivotAInW = trA.getOrigin();
00683 btVector3 pivotBInW = trB.getOrigin();
00684 #if 1
00685
00686 btVector3 ofs = trB.getOrigin() - trA.getOrigin();
00687
00688 btScalar miA = getRigidBodyA().getInvMass();
00689 btScalar miB = getRigidBodyB().getInvMass();
00690 bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
00691 btScalar miS = miA + miB;
00692 btScalar factA, factB;
00693 if(miS > btScalar(0.f))
00694 {
00695 factA = miB / miS;
00696 }
00697 else
00698 {
00699 factA = btScalar(0.5f);
00700 }
00701 factB = btScalar(1.0f) - factA;
00702
00703
00704 btVector3 ax1A = trA.getBasis().getColumn(2);
00705 btVector3 ax1B = trB.getBasis().getColumn(2);
00706 btVector3 ax1 = ax1A * factA + ax1B * factB;
00707 ax1.normalize();
00708
00709
00710 btTransform bodyA_trans = transA;
00711 btTransform bodyB_trans = transB;
00712 int s0 = 0;
00713 int s1 = s;
00714 int s2 = s * 2;
00715 int nrow = 2;
00716 btVector3 tmpA, tmpB, relA, relB, p, q;
00717
00718 relB = trB.getOrigin() - bodyB_trans.getOrigin();
00719
00720 btVector3 projB = ax1 * relB.dot(ax1);
00721
00722 btVector3 orthoB = relB - projB;
00723
00724 relA = trA.getOrigin() - bodyA_trans.getOrigin();
00725 btVector3 projA = ax1 * relA.dot(ax1);
00726 btVector3 orthoA = relA - projA;
00727 btVector3 totalDist = projA - projB;
00728
00729 relA = orthoA + totalDist * factA;
00730 relB = orthoB - totalDist * factB;
00731
00732 p = orthoB * factA + orthoA * factB;
00733 btScalar len2 = p.length2();
00734 if(len2 > SIMD_EPSILON)
00735 {
00736 p /= btSqrt(len2);
00737 }
00738 else
00739 {
00740 p = trA.getBasis().getColumn(1);
00741 }
00742
00743 q = ax1.cross(p);
00744
00745 tmpA = relA.cross(p);
00746 tmpB = relB.cross(p);
00747 for (i=0; i<3; i++) info->m_J1angularAxis[s0+i] = tmpA[i];
00748 for (i=0; i<3; i++) info->m_J2angularAxis[s0+i] = -tmpB[i];
00749 tmpA = relA.cross(q);
00750 tmpB = relB.cross(q);
00751 if(hasStaticBody && getSolveLimit())
00752 {
00753
00754 tmpB *= factB;
00755 tmpA *= factA;
00756 }
00757 for (i=0; i<3; i++) info->m_J1angularAxis[s1+i] = tmpA[i];
00758 for (i=0; i<3; i++) info->m_J2angularAxis[s1+i] = -tmpB[i];
00759 tmpA = relA.cross(ax1);
00760 tmpB = relB.cross(ax1);
00761 if(hasStaticBody)
00762 {
00763
00764 tmpB *= factB;
00765 tmpA *= factA;
00766 }
00767 for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
00768 for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
00769
00770 for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i];
00771 for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i];
00772 for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i];
00773
00774 btScalar k = info->fps * info->erp;
00775 btScalar rhs = k * p.dot(ofs);
00776 info->m_constraintError[s0] = rhs;
00777 rhs = k * q.dot(ofs);
00778 info->m_constraintError[s1] = rhs;
00779 rhs = k * ax1.dot(ofs);
00780 info->m_constraintError[s2] = rhs;
00781
00782
00783
00784
00785
00786
00787
00788 int s3 = 3 * s;
00789 int s4 = 4 * s;
00790 info->m_J1angularAxis[s3 + 0] = p[0];
00791 info->m_J1angularAxis[s3 + 1] = p[1];
00792 info->m_J1angularAxis[s3 + 2] = p[2];
00793 info->m_J1angularAxis[s4 + 0] = q[0];
00794 info->m_J1angularAxis[s4 + 1] = q[1];
00795 info->m_J1angularAxis[s4 + 2] = q[2];
00796
00797 info->m_J2angularAxis[s3 + 0] = -p[0];
00798 info->m_J2angularAxis[s3 + 1] = -p[1];
00799 info->m_J2angularAxis[s3 + 2] = -p[2];
00800 info->m_J2angularAxis[s4 + 0] = -q[0];
00801 info->m_J2angularAxis[s4 + 1] = -q[1];
00802 info->m_J2angularAxis[s4 + 2] = -q[2];
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 k = info->fps * info->erp;
00819 btVector3 u = ax1A.cross(ax1B);
00820 info->m_constraintError[s3] = k * u.dot(p);
00821 info->m_constraintError[s4] = k * u.dot(q);
00822 #endif
00823
00824 nrow = 4;
00825 int srow;
00826 btScalar limit_err = btScalar(0.0);
00827 int limit = 0;
00828 if(getSolveLimit())
00829 {
00830 limit_err = m_correction * m_referenceSign;
00831 limit = (limit_err > btScalar(0.0)) ? 1 : 2;
00832 }
00833
00834 int powered = 0;
00835 if(getEnableAngularMotor())
00836 {
00837 powered = 1;
00838 }
00839 if(limit || powered)
00840 {
00841 nrow++;
00842 srow = nrow * info->rowskip;
00843 info->m_J1angularAxis[srow+0] = ax1[0];
00844 info->m_J1angularAxis[srow+1] = ax1[1];
00845 info->m_J1angularAxis[srow+2] = ax1[2];
00846
00847 info->m_J2angularAxis[srow+0] = -ax1[0];
00848 info->m_J2angularAxis[srow+1] = -ax1[1];
00849 info->m_J2angularAxis[srow+2] = -ax1[2];
00850
00851 btScalar lostop = getLowerLimit();
00852 btScalar histop = getUpperLimit();
00853 if(limit && (lostop == histop))
00854 {
00855 powered = 0;
00856 }
00857 info->m_constraintError[srow] = btScalar(0.0f);
00858 btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp;
00859 if(powered)
00860 {
00861 if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
00862 {
00863 info->cfm[srow] = m_normalCFM;
00864 }
00865 btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
00866 info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
00867 info->m_lowerLimit[srow] = - m_maxMotorImpulse;
00868 info->m_upperLimit[srow] = m_maxMotorImpulse;
00869 }
00870 if(limit)
00871 {
00872 k = info->fps * currERP;
00873 info->m_constraintError[srow] += k * limit_err;
00874 if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
00875 {
00876 info->cfm[srow] = m_stopCFM;
00877 }
00878 if(lostop == histop)
00879 {
00880
00881 info->m_lowerLimit[srow] = -SIMD_INFINITY;
00882 info->m_upperLimit[srow] = SIMD_INFINITY;
00883 }
00884 else if(limit == 1)
00885 {
00886 info->m_lowerLimit[srow] = 0;
00887 info->m_upperLimit[srow] = SIMD_INFINITY;
00888 }
00889 else
00890 {
00891 info->m_lowerLimit[srow] = -SIMD_INFINITY;
00892 info->m_upperLimit[srow] = 0;
00893 }
00894
00895 btScalar bounce = m_relaxationFactor;
00896 if(bounce > btScalar(0.0))
00897 {
00898 btScalar vel = angVelA.dot(ax1);
00899 vel -= angVelB.dot(ax1);
00900
00901
00902 if(limit == 1)
00903 {
00904 if(vel < 0)
00905 {
00906 btScalar newc = -bounce * vel;
00907 if(newc > info->m_constraintError[srow])
00908 {
00909 info->m_constraintError[srow] = newc;
00910 }
00911 }
00912 }
00913 else
00914 {
00915 if(vel > 0)
00916 {
00917 btScalar newc = -bounce * vel;
00918 if(newc < info->m_constraintError[srow])
00919 {
00920 info->m_constraintError[srow] = newc;
00921 }
00922 }
00923 }
00924 }
00925 info->m_constraintError[srow] *= m_biasFactor;
00926 }
00927 }
00928 }
00929
00930
00933 void btHingeConstraint::setParam(int num, btScalar value, int axis)
00934 {
00935 if((axis == -1) || (axis == 5))
00936 {
00937 switch(num)
00938 {
00939 case BT_CONSTRAINT_STOP_ERP :
00940 m_stopERP = value;
00941 m_flags |= BT_HINGE_FLAGS_ERP_STOP;
00942 break;
00943 case BT_CONSTRAINT_STOP_CFM :
00944 m_stopCFM = value;
00945 m_flags |= BT_HINGE_FLAGS_CFM_STOP;
00946 break;
00947 case BT_CONSTRAINT_CFM :
00948 m_normalCFM = value;
00949 m_flags |= BT_HINGE_FLAGS_CFM_NORM;
00950 break;
00951 default :
00952 btAssertConstrParams(0);
00953 }
00954 }
00955 else
00956 {
00957 btAssertConstrParams(0);
00958 }
00959 }
00960
00962 btScalar btHingeConstraint::getParam(int num, int axis) const
00963 {
00964 btScalar retVal = 0;
00965 if((axis == -1) || (axis == 5))
00966 {
00967 switch(num)
00968 {
00969 case BT_CONSTRAINT_STOP_ERP :
00970 btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP);
00971 retVal = m_stopERP;
00972 break;
00973 case BT_CONSTRAINT_STOP_CFM :
00974 btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP);
00975 retVal = m_stopCFM;
00976 break;
00977 case BT_CONSTRAINT_CFM :
00978 btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM);
00979 retVal = m_normalCFM;
00980 break;
00981 default :
00982 btAssertConstrParams(0);
00983 }
00984 }
00985 else
00986 {
00987 btAssertConstrParams(0);
00988 }
00989 return retVal;
00990 }
00991
00992