1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/ 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 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. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 */ 15 16 #ifndef BT_TYPED_CONSTRAINT_H 17 #define BT_TYPED_CONSTRAINT_H 18 19 20 #include "LinearMath/btScalar.h" 21 #include "btSolverConstraint.h" 22 #include "BulletDynamics/Dynamics/btRigidBody.h" 23 24 #ifdef BT_USE_DOUBLE_PRECISION 25 #define btTypedConstraintData2 btTypedConstraintDoubleData 26 #define btTypedConstraintDataName "btTypedConstraintDoubleData" 27 #else 28 #define btTypedConstraintData2 btTypedConstraintFloatData 29 #define btTypedConstraintDataName "btTypedConstraintFloatData" 30 #endif //BT_USE_DOUBLE_PRECISION 31 32 33 class btSerializer; 34 35 //Don't change any of the existing enum values, so add enum types at the end for serialization compatibility 36 enum btTypedConstraintType 37 { 38 POINT2POINT_CONSTRAINT_TYPE=3, 39 HINGE_CONSTRAINT_TYPE, 40 CONETWIST_CONSTRAINT_TYPE, 41 D6_CONSTRAINT_TYPE, 42 SLIDER_CONSTRAINT_TYPE, 43 CONTACT_CONSTRAINT_TYPE, 44 D6_SPRING_CONSTRAINT_TYPE, 45 GEAR_CONSTRAINT_TYPE, 46 FIXED_CONSTRAINT_TYPE, 47 D6_SPRING_2_CONSTRAINT_TYPE, 48 MAX_CONSTRAINT_TYPE 49 }; 50 51 52 enum btConstraintParams 53 { 54 BT_CONSTRAINT_ERP=1, 55 BT_CONSTRAINT_STOP_ERP, 56 BT_CONSTRAINT_CFM, 57 BT_CONSTRAINT_STOP_CFM 58 }; 59 60 #if 1 61 #define btAssertConstrParams(_par) btAssert(_par) 62 #else 63 #define btAssertConstrParams(_par) 64 #endif 65 66 67 ATTRIBUTE_ALIGNED16(struct) btJointFeedback 68 { 69 btVector3 m_appliedForceBodyA; 70 btVector3 m_appliedTorqueBodyA; 71 btVector3 m_appliedForceBodyB; 72 btVector3 m_appliedTorqueBodyB; 73 }; 74 75 76 ///TypedConstraint is the baseclass for Bullet constraints and vehicles 77 ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject 78 { 79 int m_userConstraintType; 80 81 union 82 { 83 int m_userConstraintId; 84 void* m_userConstraintPtr; 85 }; 86 87 btScalar m_breakingImpulseThreshold; 88 bool m_isEnabled; 89 bool m_needsFeedback; 90 int m_overrideNumSolverIterations; 91 92 93 btTypedConstraint& operator=(btTypedConstraint& other) 94 { 95 btAssert(0); 96 (void) other; 97 return *this; 98 } 99 100 protected: 101 btRigidBody& m_rbA; 102 btRigidBody& m_rbB; 103 btScalar m_appliedImpulse; 104 btScalar m_dbgDrawSize; 105 btJointFeedback* m_jointFeedback; 106 107 ///internal method used by the constraint solver, don't use them directly 108 btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact); 109 110 111 public: 112 113 BT_DECLARE_ALIGNED_ALLOCATOR(); 114 115 virtual ~btTypedConstraint() {}; 116 btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); 117 btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); 118 119 struct btConstraintInfo1 { 120 int m_numConstraintRows,nub; 121 }; 122 123 static btRigidBody& getFixedBody(); 124 125 struct btConstraintInfo2 { 126 // integrator parameters: frames per second (1/stepsize), default error 127 // reduction parameter (0..1). 128 btScalar fps,erp; 129 130 // for the first and second body, pointers to two (linear and angular) 131 // n*3 jacobian sub matrices, stored by rows. these matrices will have 132 // been initialized to 0 on entry. if the second body is zero then the 133 // J2xx pointers may be 0. 134 btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis; 135 136 // elements to jump from one row to the next in J's 137 int rowskip; 138 139 // right hand sides of the equation J*v = c + cfm * lambda. cfm is the 140 // "constraint force mixing" vector. c is set to zero on entry, cfm is 141 // set to a constant value (typically very small or zero) value on entry. 142 btScalar *m_constraintError,*cfm; 143 144 // lo and hi limits for variables (set to -/+ infinity on entry). 145 btScalar *m_lowerLimit,*m_upperLimit; 146 147 // findex vector for variables. see the LCP solver interface for a 148 // description of what this does. this is set to -1 on entry. 149 // note that the returned indexes are relative to the first index of 150 // the constraint. 151 int *findex; 152 // number of solver iterations 153 int m_numIterations; 154 155 //damping of the velocity 156 btScalar m_damping; 157 }; 158 159 int getOverrideNumSolverIterations() const 160 { 161 return m_overrideNumSolverIterations; 162 } 163 164 ///override the number of constraint solver iterations used to solve this constraint 165 ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations 166 void setOverrideNumSolverIterations(int overideNumIterations) 167 { 168 m_overrideNumSolverIterations = overideNumIterations; 169 } 170 171 ///internal method used by the constraint solver, don't use them directly 172 virtual void buildJacobian() {}; 173 174 ///internal method used by the constraint solver, don't use them directly 175 virtual void setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep) 176 { 177 (void)ca; 178 (void)solverBodyA; 179 (void)solverBodyB; 180 (void)timeStep; 181 } 182 183 ///internal method used by the constraint solver, don't use them directly 184 virtual void getInfo1 (btConstraintInfo1* info)=0; 185 186 ///internal method used by the constraint solver, don't use them directly 187 virtual void getInfo2 (btConstraintInfo2* info)=0; 188 189 ///internal method used by the constraint solver, don't use them directly 190 void internalSetAppliedImpulse(btScalar appliedImpulse) 191 { 192 m_appliedImpulse = appliedImpulse; 193 } 194 ///internal method used by the constraint solver, don't use them directly 195 btScalar internalGetAppliedImpulse() 196 { 197 return m_appliedImpulse; 198 } 199 200 201 btScalar getBreakingImpulseThreshold() const 202 { 203 return m_breakingImpulseThreshold; 204 } 205 206 void setBreakingImpulseThreshold(btScalar threshold) 207 { 208 m_breakingImpulseThreshold = threshold; 209 } 210 211 bool isEnabled() const 212 { 213 return m_isEnabled; 214 } 215 216 void setEnabled(bool enabled) 217 { 218 m_isEnabled=enabled; 219 } 220 221 222 ///internal method used by the constraint solver, don't use them directly 223 virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/,btSolverBody& /*bodyB*/,btScalar /*timeStep*/) {}; 224 225 226 const btRigidBody& getRigidBodyA() const 227 { 228 return m_rbA; 229 } 230 const btRigidBody& getRigidBodyB() const 231 { 232 return m_rbB; 233 } 234 235 btRigidBody& getRigidBodyA() 236 { 237 return m_rbA; 238 } 239 btRigidBody& getRigidBodyB() 240 { 241 return m_rbB; 242 } 243 244 int getUserConstraintType() const 245 { 246 return m_userConstraintType ; 247 } 248 249 void setUserConstraintType(int userConstraintType) 250 { 251 m_userConstraintType = userConstraintType; 252 }; 253 254 void setUserConstraintId(int uid) 255 { 256 m_userConstraintId = uid; 257 } 258 259 int getUserConstraintId() const 260 { 261 return m_userConstraintId; 262 } 263 264 void setUserConstraintPtr(void* ptr) 265 { 266 m_userConstraintPtr = ptr; 267 } 268 269 void* getUserConstraintPtr() 270 { 271 return m_userConstraintPtr; 272 } 273 274 void setJointFeedback(btJointFeedback* jointFeedback) 275 { 276 m_jointFeedback = jointFeedback; 277 } 278 279 const btJointFeedback* getJointFeedback() const 280 { 281 return m_jointFeedback; 282 } 283 284 btJointFeedback* getJointFeedback() 285 { 286 return m_jointFeedback; 287 } 288 289 290 int getUid() const 291 { 292 return m_userConstraintId; 293 } 294 295 bool needsFeedback() const 296 { 297 return m_needsFeedback; 298 } 299 300 ///enableFeedback will allow to read the applied linear and angular impulse 301 ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information 302 void enableFeedback(bool needsFeedback) 303 { 304 m_needsFeedback = needsFeedback; 305 } 306 307 ///getAppliedImpulse is an estimated total applied impulse. 308 ///This feedback could be used to determine breaking constraints or playing sounds. 309 btScalar getAppliedImpulse() const 310 { 311 btAssert(m_needsFeedback); 312 return m_appliedImpulse; 313 } 314 315 btTypedConstraintType getConstraintType () const 316 { 317 return btTypedConstraintType(m_objectType); 318 } 319 320 void setDbgDrawSize(btScalar dbgDrawSize) 321 { 322 m_dbgDrawSize = dbgDrawSize; 323 } 324 btScalar getDbgDrawSize() 325 { 326 return m_dbgDrawSize; 327 } 328 329 ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 330 ///If no axis is provided, it uses the default axis for this constraint. 331 virtual void setParam(int num, btScalar value, int axis = -1) = 0; 332 333 ///return the local value of parameter 334 virtual btScalar getParam(int num, int axis = -1) const = 0; 335 336 virtual int calculateSerializeBufferSize() const; 337 338 ///fills the dataBuffer and returns the struct name (and 0 on failure) 339 virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; 340 341 }; 342 343 // returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits 344 // all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI]) 345 SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians) 346 { 347 if(angleLowerLimitInRadians >= angleUpperLimitInRadians) 348 { 349 return angleInRadians; 350 } 351 else if(angleInRadians < angleLowerLimitInRadians) 352 { 353 btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians)); 354 btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians)); 355 return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI); 356 } 357 else if(angleInRadians > angleUpperLimitInRadians) 358 { 359 btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians)); 360 btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians)); 361 return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians; 362 } 363 else 364 { 365 return angleInRadians; 366 } 367 } 368 369 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 370 struct btTypedConstraintFloatData 371 { 372 btRigidBodyFloatData *m_rbA; 373 btRigidBodyFloatData *m_rbB; 374 char *m_name; 375 376 int m_objectType; 377 int m_userConstraintType; 378 int m_userConstraintId; 379 int m_needsFeedback; 380 381 float m_appliedImpulse; 382 float m_dbgDrawSize; 383 384 int m_disableCollisionsBetweenLinkedBodies; 385 int m_overrideNumSolverIterations; 386 387 float m_breakingImpulseThreshold; 388 int m_isEnabled; 389 390 }; 391 392 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 393 394 #define BT_BACKWARDS_COMPATIBLE_SERIALIZATION 395 #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION 396 ///this structure is not used, except for loading pre-2.82 .bullet files 397 struct btTypedConstraintData 398 { 399 btRigidBodyData *m_rbA; 400 btRigidBodyData *m_rbB; 401 char *m_name; 402 403 int m_objectType; 404 int m_userConstraintType; 405 int m_userConstraintId; 406 int m_needsFeedback; 407 408 float m_appliedImpulse; 409 float m_dbgDrawSize; 410 411 int m_disableCollisionsBetweenLinkedBodies; 412 int m_overrideNumSolverIterations; 413 414 float m_breakingImpulseThreshold; 415 int m_isEnabled; 416 417 }; 418 #endif //BACKWARDS_COMPATIBLE 419 420 struct btTypedConstraintDoubleData 421 { 422 btRigidBodyDoubleData *m_rbA; 423 btRigidBodyDoubleData *m_rbB; 424 char *m_name; 425 426 int m_objectType; 427 int m_userConstraintType; 428 int m_userConstraintId; 429 int m_needsFeedback; 430 431 double m_appliedImpulse; 432 double m_dbgDrawSize; 433 434 int m_disableCollisionsBetweenLinkedBodies; 435 int m_overrideNumSolverIterations; 436 437 double m_breakingImpulseThreshold; 438 int m_isEnabled; 439 char padding[4]; 440 441 }; 442 443 444 SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const 445 { 446 return sizeof(btTypedConstraintData2); 447 } 448 449 450 451 class btAngularLimit 452 { 453 private: 454 btScalar 455 m_center, 456 m_halfRange, 457 m_softness, 458 m_biasFactor, 459 m_relaxationFactor, 460 m_correction, 461 m_sign; 462 463 bool 464 m_solveLimit; 465 466 public: 467 /// Default constructor initializes limit as inactive, allowing free constraint movement 468 btAngularLimit() 469 :m_center(0.0f), 470 m_halfRange(-1.0f), 471 m_softness(0.9f), 472 m_biasFactor(0.3f), 473 m_relaxationFactor(1.0f), 474 m_correction(0.0f), 475 m_sign(0.0f), 476 m_solveLimit(false) 477 {} 478 479 /// Sets all limit's parameters. 480 /// When low > high limit becomes inactive. 481 /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit 482 void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f); 483 484 /// Checks conastaint angle against limit. If limit is active and the angle violates the limit 485 /// correction is calculated. 486 void test(const btScalar angle); 487 488 /// Returns limit's softness 489 inline btScalar getSoftness() const 490 { 491 return m_softness; 492 } 493 494 /// Returns limit's bias factor 495 inline btScalar getBiasFactor() const 496 { 497 return m_biasFactor; 498 } 499 500 /// Returns limit's relaxation factor 501 inline btScalar getRelaxationFactor() const 502 { 503 return m_relaxationFactor; 504 } 505 506 /// Returns correction value evaluated when test() was invoked 507 inline btScalar getCorrection() const 508 { 509 return m_correction; 510 } 511 512 /// Returns sign value evaluated when test() was invoked 513 inline btScalar getSign() const 514 { 515 return m_sign; 516 } 517 518 /// Gives half of the distance between min and max limit angle 519 inline btScalar getHalfRange() const 520 { 521 return m_halfRange; 522 } 523 524 /// Returns true when the last test() invocation recognized limit violation 525 inline bool isLimit() const 526 { 527 return m_solveLimit; 528 } 529 530 /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle 531 /// returned is modified so it equals to the limit closest to given angle. 532 void fit(btScalar& angle) const; 533 534 /// Returns correction value multiplied by sign value 535 btScalar getError() const; 536 537 btScalar getLow() const; 538 539 btScalar getHigh() const; 540 541 }; 542 543 544 545 #endif //BT_TYPED_CONSTRAINT_H 546