Blender V2.61 - r43446
|
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 /* 00017 Added by Roman Ponomarev (rponom@gmail.com) 00018 April 04, 2008 00019 */ 00020 00021 00022 00023 #include "btSliderConstraint.h" 00024 #include "BulletDynamics/Dynamics/btRigidBody.h" 00025 #include "LinearMath/btTransformUtil.h" 00026 #include <new> 00027 00028 #define USE_OFFSET_FOR_CONSTANT_FRAME true 00029 00030 void btSliderConstraint::initParams() 00031 { 00032 m_lowerLinLimit = btScalar(1.0); 00033 m_upperLinLimit = btScalar(-1.0); 00034 m_lowerAngLimit = btScalar(0.); 00035 m_upperAngLimit = btScalar(0.); 00036 m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; 00037 m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; 00038 m_dampingDirLin = btScalar(0.); 00039 m_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM; 00040 m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; 00041 m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; 00042 m_dampingDirAng = btScalar(0.); 00043 m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM; 00044 m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; 00045 m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; 00046 m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; 00047 m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM; 00048 m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; 00049 m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; 00050 m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; 00051 m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM; 00052 m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; 00053 m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; 00054 m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; 00055 m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM; 00056 m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; 00057 m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; 00058 m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; 00059 m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM; 00060 00061 m_poweredLinMotor = false; 00062 m_targetLinMotorVelocity = btScalar(0.); 00063 m_maxLinMotorForce = btScalar(0.); 00064 m_accumulatedLinMotorImpulse = btScalar(0.0); 00065 00066 m_poweredAngMotor = false; 00067 m_targetAngMotorVelocity = btScalar(0.); 00068 m_maxAngMotorForce = btScalar(0.); 00069 m_accumulatedAngMotorImpulse = btScalar(0.0); 00070 00071 m_flags = 0; 00072 m_flags = 0; 00073 00074 m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME; 00075 00076 calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); 00077 } 00078 00079 00080 00081 00082 00083 btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) 00084 : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB), 00085 m_useSolveConstraintObsolete(false), 00086 m_frameInA(frameInA), 00087 m_frameInB(frameInB), 00088 m_useLinearReferenceFrameA(useLinearReferenceFrameA) 00089 { 00090 initParams(); 00091 } 00092 00093 00094 00095 btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA) 00096 : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB), 00097 m_useSolveConstraintObsolete(false), 00098 m_frameInB(frameInB), 00099 m_useLinearReferenceFrameA(useLinearReferenceFrameA) 00100 { 00102 m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB; 00103 // m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin()); 00104 00105 initParams(); 00106 } 00107 00108 00109 00110 00111 00112 00113 void btSliderConstraint::getInfo1(btConstraintInfo1* info) 00114 { 00115 if (m_useSolveConstraintObsolete) 00116 { 00117 info->m_numConstraintRows = 0; 00118 info->nub = 0; 00119 } 00120 else 00121 { 00122 info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular 00123 info->nub = 2; 00124 //prepare constraint 00125 calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform()); 00126 testAngLimits(); 00127 testLinLimits(); 00128 if(getSolveLinLimit() || getPoweredLinMotor()) 00129 { 00130 info->m_numConstraintRows++; // limit 3rd linear as well 00131 info->nub--; 00132 } 00133 if(getSolveAngLimit() || getPoweredAngMotor()) 00134 { 00135 info->m_numConstraintRows++; // limit 3rd angular as well 00136 info->nub--; 00137 } 00138 } 00139 } 00140 00141 void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info) 00142 { 00143 00144 info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used) 00145 info->nub = 0; 00146 } 00147 00148 void btSliderConstraint::getInfo2(btConstraintInfo2* info) 00149 { 00150 getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass()); 00151 } 00152 00153 00154 00155 00156 00157 00158 00159 void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB) 00160 { 00161 if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete)) 00162 { 00163 m_calculatedTransformA = transA * m_frameInA; 00164 m_calculatedTransformB = transB * m_frameInB; 00165 } 00166 else 00167 { 00168 m_calculatedTransformA = transB * m_frameInB; 00169 m_calculatedTransformB = transA * m_frameInA; 00170 } 00171 m_realPivotAInW = m_calculatedTransformA.getOrigin(); 00172 m_realPivotBInW = m_calculatedTransformB.getOrigin(); 00173 m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X 00174 if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete) 00175 { 00176 m_delta = m_realPivotBInW - m_realPivotAInW; 00177 } 00178 else 00179 { 00180 m_delta = m_realPivotAInW - m_realPivotBInW; 00181 } 00182 m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; 00183 btVector3 normalWorld; 00184 int i; 00185 //linear part 00186 for(i = 0; i < 3; i++) 00187 { 00188 normalWorld = m_calculatedTransformA.getBasis().getColumn(i); 00189 m_depth[i] = m_delta.dot(normalWorld); 00190 } 00191 } 00192 00193 00194 00195 void btSliderConstraint::testLinLimits(void) 00196 { 00197 m_solveLinLim = false; 00198 m_linPos = m_depth[0]; 00199 if(m_lowerLinLimit <= m_upperLinLimit) 00200 { 00201 if(m_depth[0] > m_upperLinLimit) 00202 { 00203 m_depth[0] -= m_upperLinLimit; 00204 m_solveLinLim = true; 00205 } 00206 else if(m_depth[0] < m_lowerLinLimit) 00207 { 00208 m_depth[0] -= m_lowerLinLimit; 00209 m_solveLinLim = true; 00210 } 00211 else 00212 { 00213 m_depth[0] = btScalar(0.); 00214 } 00215 } 00216 else 00217 { 00218 m_depth[0] = btScalar(0.); 00219 } 00220 } 00221 00222 00223 00224 void btSliderConstraint::testAngLimits(void) 00225 { 00226 m_angDepth = btScalar(0.); 00227 m_solveAngLim = false; 00228 if(m_lowerAngLimit <= m_upperAngLimit) 00229 { 00230 const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1); 00231 const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2); 00232 const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); 00233 // btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); 00234 btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0)); 00235 rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit); 00236 m_angPos = rot; 00237 if(rot < m_lowerAngLimit) 00238 { 00239 m_angDepth = rot - m_lowerAngLimit; 00240 m_solveAngLim = true; 00241 } 00242 else if(rot > m_upperAngLimit) 00243 { 00244 m_angDepth = rot - m_upperAngLimit; 00245 m_solveAngLim = true; 00246 } 00247 } 00248 } 00249 00250 btVector3 btSliderConstraint::getAncorInA(void) 00251 { 00252 btVector3 ancorInA; 00253 ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis; 00254 ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA; 00255 return ancorInA; 00256 } 00257 00258 00259 00260 btVector3 btSliderConstraint::getAncorInB(void) 00261 { 00262 btVector3 ancorInB; 00263 ancorInB = m_frameInB.getOrigin(); 00264 return ancorInB; 00265 } 00266 00267 00268 void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass ) 00269 { 00270 const btTransform& trA = getCalculatedTransformA(); 00271 const btTransform& trB = getCalculatedTransformB(); 00272 00273 btAssert(!m_useSolveConstraintObsolete); 00274 int i, s = info->rowskip; 00275 00276 btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f); 00277 00278 // difference between frames in WCS 00279 btVector3 ofs = trB.getOrigin() - trA.getOrigin(); 00280 // now get weight factors depending on masses 00281 btScalar miA = rbAinvMass; 00282 btScalar miB = rbBinvMass; 00283 bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON); 00284 btScalar miS = miA + miB; 00285 btScalar factA, factB; 00286 if(miS > btScalar(0.f)) 00287 { 00288 factA = miB / miS; 00289 } 00290 else 00291 { 00292 factA = btScalar(0.5f); 00293 } 00294 factB = btScalar(1.0f) - factA; 00295 btVector3 ax1, p, q; 00296 btVector3 ax1A = trA.getBasis().getColumn(0); 00297 btVector3 ax1B = trB.getBasis().getColumn(0); 00298 if(m_useOffsetForConstraintFrame) 00299 { 00300 // get the desired direction of slider axis 00301 // as weighted sum of X-orthos of frameA and frameB in WCS 00302 ax1 = ax1A * factA + ax1B * factB; 00303 ax1.normalize(); 00304 // construct two orthos to slider axis 00305 btPlaneSpace1 (ax1, p, q); 00306 } 00307 else 00308 { // old way - use frameA 00309 ax1 = trA.getBasis().getColumn(0); 00310 // get 2 orthos to slider axis (Y, Z) 00311 p = trA.getBasis().getColumn(1); 00312 q = trA.getBasis().getColumn(2); 00313 } 00314 // make rotations around these orthos equal 00315 // the slider axis should be the only unconstrained 00316 // rotational axis, the angular velocity of the two bodies perpendicular to 00317 // the slider axis should be equal. thus the constraint equations are 00318 // p*w1 - p*w2 = 0 00319 // q*w1 - q*w2 = 0 00320 // where p and q are unit vectors normal to the slider axis, and w1 and w2 00321 // are the angular velocity vectors of the two bodies. 00322 info->m_J1angularAxis[0] = p[0]; 00323 info->m_J1angularAxis[1] = p[1]; 00324 info->m_J1angularAxis[2] = p[2]; 00325 info->m_J1angularAxis[s+0] = q[0]; 00326 info->m_J1angularAxis[s+1] = q[1]; 00327 info->m_J1angularAxis[s+2] = q[2]; 00328 00329 info->m_J2angularAxis[0] = -p[0]; 00330 info->m_J2angularAxis[1] = -p[1]; 00331 info->m_J2angularAxis[2] = -p[2]; 00332 info->m_J2angularAxis[s+0] = -q[0]; 00333 info->m_J2angularAxis[s+1] = -q[1]; 00334 info->m_J2angularAxis[s+2] = -q[2]; 00335 // compute the right hand side of the constraint equation. set relative 00336 // body velocities along p and q to bring the slider back into alignment. 00337 // if ax1A,ax1B are the unit length slider axes as computed from bodyA and 00338 // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2). 00339 // if "theta" is the angle between ax1 and ax2, we need an angular velocity 00340 // along u to cover angle erp*theta in one step : 00341 // |angular_velocity| = angle/time = erp*theta / stepsize 00342 // = (erp*fps) * theta 00343 // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| 00344 // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) 00345 // ...as ax1 and ax2 are unit length. if theta is smallish, 00346 // theta ~= sin(theta), so 00347 // angular_velocity = (erp*fps) * (ax1 x ax2) 00348 // ax1 x ax2 is in the plane space of ax1, so we project the angular 00349 // velocity to p and q to find the right hand side. 00350 // btScalar k = info->fps * info->erp * getSoftnessOrthoAng(); 00351 btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp; 00352 btScalar k = info->fps * currERP; 00353 00354 btVector3 u = ax1A.cross(ax1B); 00355 info->m_constraintError[0] = k * u.dot(p); 00356 info->m_constraintError[s] = k * u.dot(q); 00357 if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG) 00358 { 00359 info->cfm[0] = m_cfmOrthoAng; 00360 info->cfm[s] = m_cfmOrthoAng; 00361 } 00362 00363 int nrow = 1; // last filled row 00364 int srow; 00365 btScalar limit_err; 00366 int limit; 00367 int powered; 00368 00369 // next two rows. 00370 // we want: velA + wA x relA == velB + wB x relB ... but this would 00371 // result in three equations, so we project along two orthos to the slider axis 00372 00373 btTransform bodyA_trans = transA; 00374 btTransform bodyB_trans = transB; 00375 nrow++; 00376 int s2 = nrow * s; 00377 nrow++; 00378 int s3 = nrow * s; 00379 btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0); 00380 if(m_useOffsetForConstraintFrame) 00381 { 00382 // get vector from bodyB to frameB in WCS 00383 relB = trB.getOrigin() - bodyB_trans.getOrigin(); 00384 // get its projection to slider axis 00385 btVector3 projB = ax1 * relB.dot(ax1); 00386 // get vector directed from bodyB to slider axis (and orthogonal to it) 00387 btVector3 orthoB = relB - projB; 00388 // same for bodyA 00389 relA = trA.getOrigin() - bodyA_trans.getOrigin(); 00390 btVector3 projA = ax1 * relA.dot(ax1); 00391 btVector3 orthoA = relA - projA; 00392 // get desired offset between frames A and B along slider axis 00393 btScalar sliderOffs = m_linPos - m_depth[0]; 00394 // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis 00395 btVector3 totalDist = projA + ax1 * sliderOffs - projB; 00396 // get offset vectors relA and relB 00397 relA = orthoA + totalDist * factA; 00398 relB = orthoB - totalDist * factB; 00399 // now choose average ortho to slider axis 00400 p = orthoB * factA + orthoA * factB; 00401 btScalar len2 = p.length2(); 00402 if(len2 > SIMD_EPSILON) 00403 { 00404 p /= btSqrt(len2); 00405 } 00406 else 00407 { 00408 p = trA.getBasis().getColumn(1); 00409 } 00410 // make one more ortho 00411 q = ax1.cross(p); 00412 // fill two rows 00413 tmpA = relA.cross(p); 00414 tmpB = relB.cross(p); 00415 for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i]; 00416 for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i]; 00417 tmpA = relA.cross(q); 00418 tmpB = relB.cross(q); 00419 if(hasStaticBody && getSolveAngLimit()) 00420 { // to make constraint between static and dynamic objects more rigid 00421 // remove wA (or wB) from equation if angular limit is hit 00422 tmpB *= factB; 00423 tmpA *= factA; 00424 } 00425 for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i]; 00426 for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i]; 00427 for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; 00428 for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; 00429 } 00430 else 00431 { // old way - maybe incorrect if bodies are not on the slider axis 00432 // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0 00433 c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin(); 00434 btVector3 tmp = c.cross(p); 00435 for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i]; 00436 for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i]; 00437 tmp = c.cross(q); 00438 for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i]; 00439 for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i]; 00440 00441 for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i]; 00442 for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i]; 00443 } 00444 // compute two elements of right hand side 00445 00446 // k = info->fps * info->erp * getSoftnessOrthoLin(); 00447 currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp; 00448 k = info->fps * currERP; 00449 00450 btScalar rhs = k * p.dot(ofs); 00451 info->m_constraintError[s2] = rhs; 00452 rhs = k * q.dot(ofs); 00453 info->m_constraintError[s3] = rhs; 00454 if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN) 00455 { 00456 info->cfm[s2] = m_cfmOrthoLin; 00457 info->cfm[s3] = m_cfmOrthoLin; 00458 } 00459 00460 00461 // check linear limits 00462 limit_err = btScalar(0.0); 00463 limit = 0; 00464 if(getSolveLinLimit()) 00465 { 00466 limit_err = getLinDepth() * signFact; 00467 limit = (limit_err > btScalar(0.0)) ? 2 : 1; 00468 } 00469 powered = 0; 00470 if(getPoweredLinMotor()) 00471 { 00472 powered = 1; 00473 } 00474 // if the slider has joint limits or motor, add in the extra row 00475 if (limit || powered) 00476 { 00477 nrow++; 00478 srow = nrow * info->rowskip; 00479 info->m_J1linearAxis[srow+0] = ax1[0]; 00480 info->m_J1linearAxis[srow+1] = ax1[1]; 00481 info->m_J1linearAxis[srow+2] = ax1[2]; 00482 // linear torque decoupling step: 00483 // 00484 // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies 00485 // do not create a torque couple. in other words, the points that the 00486 // constraint force is applied at must lie along the same ax1 axis. 00487 // a torque couple will result in limited slider-jointed free 00488 // bodies from gaining angular momentum. 00489 if(m_useOffsetForConstraintFrame) 00490 { 00491 // this is needed only when bodyA and bodyB are both dynamic. 00492 if(!hasStaticBody) 00493 { 00494 tmpA = relA.cross(ax1); 00495 tmpB = relB.cross(ax1); 00496 info->m_J1angularAxis[srow+0] = tmpA[0]; 00497 info->m_J1angularAxis[srow+1] = tmpA[1]; 00498 info->m_J1angularAxis[srow+2] = tmpA[2]; 00499 info->m_J2angularAxis[srow+0] = -tmpB[0]; 00500 info->m_J2angularAxis[srow+1] = -tmpB[1]; 00501 info->m_J2angularAxis[srow+2] = -tmpB[2]; 00502 } 00503 } 00504 else 00505 { // The old way. May be incorrect if bodies are not on the slider axis 00506 btVector3 ltd; // Linear Torque Decoupling vector (a torque) 00507 ltd = c.cross(ax1); 00508 info->m_J1angularAxis[srow+0] = factA*ltd[0]; 00509 info->m_J1angularAxis[srow+1] = factA*ltd[1]; 00510 info->m_J1angularAxis[srow+2] = factA*ltd[2]; 00511 info->m_J2angularAxis[srow+0] = factB*ltd[0]; 00512 info->m_J2angularAxis[srow+1] = factB*ltd[1]; 00513 info->m_J2angularAxis[srow+2] = factB*ltd[2]; 00514 } 00515 // right-hand part 00516 btScalar lostop = getLowerLinLimit(); 00517 btScalar histop = getUpperLinLimit(); 00518 if(limit && (lostop == histop)) 00519 { // the joint motor is ineffective 00520 powered = 0; 00521 } 00522 info->m_constraintError[srow] = 0.; 00523 info->m_lowerLimit[srow] = 0.; 00524 info->m_upperLimit[srow] = 0.; 00525 currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp; 00526 if(powered) 00527 { 00528 if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN) 00529 { 00530 info->cfm[srow] = m_cfmDirLin; 00531 } 00532 btScalar tag_vel = getTargetLinMotorVelocity(); 00533 btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP); 00534 info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity(); 00535 info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps; 00536 info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps; 00537 } 00538 if(limit) 00539 { 00540 k = info->fps * currERP; 00541 info->m_constraintError[srow] += k * limit_err; 00542 if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN) 00543 { 00544 info->cfm[srow] = m_cfmLimLin; 00545 } 00546 if(lostop == histop) 00547 { // limited low and high simultaneously 00548 info->m_lowerLimit[srow] = -SIMD_INFINITY; 00549 info->m_upperLimit[srow] = SIMD_INFINITY; 00550 } 00551 else if(limit == 1) 00552 { // low limit 00553 info->m_lowerLimit[srow] = -SIMD_INFINITY; 00554 info->m_upperLimit[srow] = 0; 00555 } 00556 else 00557 { // high limit 00558 info->m_lowerLimit[srow] = 0; 00559 info->m_upperLimit[srow] = SIMD_INFINITY; 00560 } 00561 // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that) 00562 btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin()); 00563 if(bounce > btScalar(0.0)) 00564 { 00565 btScalar vel = linVelA.dot(ax1); 00566 vel -= linVelB.dot(ax1); 00567 vel *= signFact; 00568 // only apply bounce if the velocity is incoming, and if the 00569 // resulting c[] exceeds what we already have. 00570 if(limit == 1) 00571 { // low limit 00572 if(vel < 0) 00573 { 00574 btScalar newc = -bounce * vel; 00575 if (newc > info->m_constraintError[srow]) 00576 { 00577 info->m_constraintError[srow] = newc; 00578 } 00579 } 00580 } 00581 else 00582 { // high limit - all those computations are reversed 00583 if(vel > 0) 00584 { 00585 btScalar newc = -bounce * vel; 00586 if(newc < info->m_constraintError[srow]) 00587 { 00588 info->m_constraintError[srow] = newc; 00589 } 00590 } 00591 } 00592 } 00593 info->m_constraintError[srow] *= getSoftnessLimLin(); 00594 } // if(limit) 00595 } // if linear limit 00596 // check angular limits 00597 limit_err = btScalar(0.0); 00598 limit = 0; 00599 if(getSolveAngLimit()) 00600 { 00601 limit_err = getAngDepth(); 00602 limit = (limit_err > btScalar(0.0)) ? 1 : 2; 00603 } 00604 // if the slider has joint limits, add in the extra row 00605 powered = 0; 00606 if(getPoweredAngMotor()) 00607 { 00608 powered = 1; 00609 } 00610 if(limit || powered) 00611 { 00612 nrow++; 00613 srow = nrow * info->rowskip; 00614 info->m_J1angularAxis[srow+0] = ax1[0]; 00615 info->m_J1angularAxis[srow+1] = ax1[1]; 00616 info->m_J1angularAxis[srow+2] = ax1[2]; 00617 00618 info->m_J2angularAxis[srow+0] = -ax1[0]; 00619 info->m_J2angularAxis[srow+1] = -ax1[1]; 00620 info->m_J2angularAxis[srow+2] = -ax1[2]; 00621 00622 btScalar lostop = getLowerAngLimit(); 00623 btScalar histop = getUpperAngLimit(); 00624 if(limit && (lostop == histop)) 00625 { // the joint motor is ineffective 00626 powered = 0; 00627 } 00628 currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp; 00629 if(powered) 00630 { 00631 if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG) 00632 { 00633 info->cfm[srow] = m_cfmDirAng; 00634 } 00635 btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP); 00636 info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity(); 00637 info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps; 00638 info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps; 00639 } 00640 if(limit) 00641 { 00642 k = info->fps * currERP; 00643 info->m_constraintError[srow] += k * limit_err; 00644 if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG) 00645 { 00646 info->cfm[srow] = m_cfmLimAng; 00647 } 00648 if(lostop == histop) 00649 { 00650 // limited low and high simultaneously 00651 info->m_lowerLimit[srow] = -SIMD_INFINITY; 00652 info->m_upperLimit[srow] = SIMD_INFINITY; 00653 } 00654 else if(limit == 1) 00655 { // low limit 00656 info->m_lowerLimit[srow] = 0; 00657 info->m_upperLimit[srow] = SIMD_INFINITY; 00658 } 00659 else 00660 { // high limit 00661 info->m_lowerLimit[srow] = -SIMD_INFINITY; 00662 info->m_upperLimit[srow] = 0; 00663 } 00664 // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) 00665 btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng()); 00666 if(bounce > btScalar(0.0)) 00667 { 00668 btScalar vel = m_rbA.getAngularVelocity().dot(ax1); 00669 vel -= m_rbB.getAngularVelocity().dot(ax1); 00670 // only apply bounce if the velocity is incoming, and if the 00671 // resulting c[] exceeds what we already have. 00672 if(limit == 1) 00673 { // low limit 00674 if(vel < 0) 00675 { 00676 btScalar newc = -bounce * vel; 00677 if(newc > info->m_constraintError[srow]) 00678 { 00679 info->m_constraintError[srow] = newc; 00680 } 00681 } 00682 } 00683 else 00684 { // high limit - all those computations are reversed 00685 if(vel > 0) 00686 { 00687 btScalar newc = -bounce * vel; 00688 if(newc < info->m_constraintError[srow]) 00689 { 00690 info->m_constraintError[srow] = newc; 00691 } 00692 } 00693 } 00694 } 00695 info->m_constraintError[srow] *= getSoftnessLimAng(); 00696 } // if(limit) 00697 } // if angular limit or powered 00698 } 00699 00700 00703 void btSliderConstraint::setParam(int num, btScalar value, int axis) 00704 { 00705 switch(num) 00706 { 00707 case BT_CONSTRAINT_STOP_ERP : 00708 if(axis < 1) 00709 { 00710 m_softnessLimLin = value; 00711 m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN; 00712 } 00713 else if(axis < 3) 00714 { 00715 m_softnessOrthoLin = value; 00716 m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN; 00717 } 00718 else if(axis == 3) 00719 { 00720 m_softnessLimAng = value; 00721 m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG; 00722 } 00723 else if(axis < 6) 00724 { 00725 m_softnessOrthoAng = value; 00726 m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG; 00727 } 00728 else 00729 { 00730 btAssertConstrParams(0); 00731 } 00732 break; 00733 case BT_CONSTRAINT_CFM : 00734 if(axis < 1) 00735 { 00736 m_cfmDirLin = value; 00737 m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN; 00738 } 00739 else if(axis == 3) 00740 { 00741 m_cfmDirAng = value; 00742 m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG; 00743 } 00744 else 00745 { 00746 btAssertConstrParams(0); 00747 } 00748 break; 00749 case BT_CONSTRAINT_STOP_CFM : 00750 if(axis < 1) 00751 { 00752 m_cfmLimLin = value; 00753 m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN; 00754 } 00755 else if(axis < 3) 00756 { 00757 m_cfmOrthoLin = value; 00758 m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN; 00759 } 00760 else if(axis == 3) 00761 { 00762 m_cfmLimAng = value; 00763 m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG; 00764 } 00765 else if(axis < 6) 00766 { 00767 m_cfmOrthoAng = value; 00768 m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG; 00769 } 00770 else 00771 { 00772 btAssertConstrParams(0); 00773 } 00774 break; 00775 } 00776 } 00777 00779 btScalar btSliderConstraint::getParam(int num, int axis) const 00780 { 00781 btScalar retVal(SIMD_INFINITY); 00782 switch(num) 00783 { 00784 case BT_CONSTRAINT_STOP_ERP : 00785 if(axis < 1) 00786 { 00787 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN); 00788 retVal = m_softnessLimLin; 00789 } 00790 else if(axis < 3) 00791 { 00792 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN); 00793 retVal = m_softnessOrthoLin; 00794 } 00795 else if(axis == 3) 00796 { 00797 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG); 00798 retVal = m_softnessLimAng; 00799 } 00800 else if(axis < 6) 00801 { 00802 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG); 00803 retVal = m_softnessOrthoAng; 00804 } 00805 else 00806 { 00807 btAssertConstrParams(0); 00808 } 00809 break; 00810 case BT_CONSTRAINT_CFM : 00811 if(axis < 1) 00812 { 00813 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN); 00814 retVal = m_cfmDirLin; 00815 } 00816 else if(axis == 3) 00817 { 00818 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG); 00819 retVal = m_cfmDirAng; 00820 } 00821 else 00822 { 00823 btAssertConstrParams(0); 00824 } 00825 break; 00826 case BT_CONSTRAINT_STOP_CFM : 00827 if(axis < 1) 00828 { 00829 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN); 00830 retVal = m_cfmLimLin; 00831 } 00832 else if(axis < 3) 00833 { 00834 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN); 00835 retVal = m_cfmOrthoLin; 00836 } 00837 else if(axis == 3) 00838 { 00839 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG); 00840 retVal = m_cfmLimAng; 00841 } 00842 else if(axis < 6) 00843 { 00844 btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG); 00845 retVal = m_cfmOrthoAng; 00846 } 00847 else 00848 { 00849 btAssertConstrParams(0); 00850 } 00851 break; 00852 } 00853 return retVal; 00854 } 00855 00856 00857