1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2006 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 /* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ 17 18 #ifndef BT_HINGECONSTRAINT_H 19 #define BT_HINGECONSTRAINT_H 20 21 #define _BT_USE_CENTER_LIMIT_ 1 22 23 24 #include "LinearMath/btVector3.h" 25 #include "btJacobianEntry.h" 26 #include "btTypedConstraint.h" 27 28 class btRigidBody; 29 30 #ifdef BT_USE_DOUBLE_PRECISION 31 #define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version 32 #define btHingeConstraintDataName "btHingeConstraintDoubleData2" 33 #else 34 #define btHingeConstraintData btHingeConstraintFloatData 35 #define btHingeConstraintDataName "btHingeConstraintFloatData" 36 #endif //BT_USE_DOUBLE_PRECISION 37 38 39 40 enum btHingeFlags 41 { 42 BT_HINGE_FLAGS_CFM_STOP = 1, 43 BT_HINGE_FLAGS_ERP_STOP = 2, 44 BT_HINGE_FLAGS_CFM_NORM = 4, 45 BT_HINGE_FLAGS_ERP_NORM = 8 46 }; 47 48 49 /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space 50 /// axis defines the orientation of the hinge axis 51 ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint 52 { 53 #ifdef IN_PARALLELL_SOLVER 54 public: 55 #endif 56 btJacobianEntry m_jac[3]; //3 orthogonal linear constraints 57 btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor 58 59 btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. 60 btTransform m_rbBFrame; 61 62 btScalar m_motorTargetVelocity; 63 btScalar m_maxMotorImpulse; 64 65 66 #ifdef _BT_USE_CENTER_LIMIT_ 67 btAngularLimit m_limit; 68 #else 69 btScalar m_lowerLimit; 70 btScalar m_upperLimit; 71 btScalar m_limitSign; 72 btScalar m_correction; 73 74 btScalar m_limitSoftness; 75 btScalar m_biasFactor; 76 btScalar m_relaxationFactor; 77 78 bool m_solveLimit; 79 #endif 80 81 btScalar m_kHinge; 82 83 84 btScalar m_accLimitImpulse; 85 btScalar m_hingeAngle; 86 btScalar m_referenceSign; 87 88 bool m_angularOnly; 89 bool m_enableAngularMotor; 90 bool m_useSolveConstraintObsolete; 91 bool m_useOffsetForConstraintFrame; 92 bool m_useReferenceFrameA; 93 94 btScalar m_accMotorImpulse; 95 96 int m_flags; 97 btScalar m_normalCFM; 98 btScalar m_normalERP; 99 btScalar m_stopCFM; 100 btScalar m_stopERP; 101 102 103 public: 104 105 BT_DECLARE_ALIGNED_ALLOCATOR(); 106 107 btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false); 108 109 btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false); 110 111 btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); 112 113 btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false); 114 115 116 virtual void buildJacobian(); 117 118 virtual void getInfo1 (btConstraintInfo1* info); 119 120 void getInfo1NonVirtual(btConstraintInfo1* info); 121 122 virtual void getInfo2 (btConstraintInfo2* info); 123 124 void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); 125 126 void getInfo2Internal(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); 127 void getInfo2InternalUsingFrameOffset(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB); 128 129 130 void updateRHS(btScalar timeStep); 131 132 const btRigidBody& getRigidBodyA() const 133 { 134 return m_rbA; 135 } 136 const btRigidBody& getRigidBodyB() const 137 { 138 return m_rbB; 139 } 140 141 btRigidBody& getRigidBodyA() 142 { 143 return m_rbA; 144 } 145 146 btRigidBody& getRigidBodyB() 147 { 148 return m_rbB; 149 } 150 151 btTransform& getFrameOffsetA() 152 { 153 return m_rbAFrame; 154 } 155 156 btTransform& getFrameOffsetB() 157 { 158 return m_rbBFrame; 159 } 160 161 void setFrames(const btTransform& frameA, const btTransform& frameB); 162 163 void setAngularOnly(bool angularOnly) 164 { 165 m_angularOnly = angularOnly; 166 } 167 168 void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse) 169 { 170 m_enableAngularMotor = enableMotor; 171 m_motorTargetVelocity = targetVelocity; 172 m_maxMotorImpulse = maxMotorImpulse; 173 } 174 175 // extra motor API, including ability to set a target rotation (as opposed to angular velocity) 176 // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to 177 // maintain a given angular target. 178 void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; } 179 void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; } 180 void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B. 181 void setMotorTarget(btScalar targetAngle, btScalar dt); 182 183 184 void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) 185 { 186 #ifdef _BT_USE_CENTER_LIMIT_ 187 m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor); 188 #else 189 m_lowerLimit = btNormalizeAngle(low); 190 m_upperLimit = btNormalizeAngle(high); 191 m_limitSoftness = _softness; 192 m_biasFactor = _biasFactor; 193 m_relaxationFactor = _relaxationFactor; 194 #endif 195 } 196 197 void setAxis(btVector3& axisInA) 198 { 199 btVector3 rbAxisA1, rbAxisA2; 200 btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2); 201 btVector3 pivotInA = m_rbAFrame.getOrigin(); 202 // m_rbAFrame.getOrigin() = pivotInA; 203 m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), 204 rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), 205 rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); 206 207 btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA; 208 209 btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); 210 btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); 211 btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); 212 213 m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA)); 214 215 m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), 216 rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), 217 rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); 218 m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis(); 219 220 } 221 222 bool hasLimit() const { 223 #ifdef _BT_USE_CENTER_LIMIT_ 224 return m_limit.getHalfRange() > 0; 225 #else 226 return m_lowerLimit <= m_upperLimit; 227 #endif 228 } 229 230 btScalar getLowerLimit() const 231 { 232 #ifdef _BT_USE_CENTER_LIMIT_ 233 return m_limit.getLow(); 234 #else 235 return m_lowerLimit; 236 #endif 237 } 238 239 btScalar getUpperLimit() const 240 { 241 #ifdef _BT_USE_CENTER_LIMIT_ 242 return m_limit.getHigh(); 243 #else 244 return m_upperLimit; 245 #endif 246 } 247 248 249 ///The getHingeAngle gives the hinge angle in range [-PI,PI] 250 btScalar getHingeAngle(); 251 252 btScalar getHingeAngle(const btTransform& transA,const btTransform& transB); 253 254 void testLimit(const btTransform& transA,const btTransform& transB); 255 256 257 const btTransform& getAFrame() const { return m_rbAFrame; }; 258 const btTransform& getBFrame() const { return m_rbBFrame; }; 259 260 btTransform& getAFrame() { return m_rbAFrame; }; 261 btTransform& getBFrame() { return m_rbBFrame; }; 262 263 inline int getSolveLimit() 264 { 265 #ifdef _BT_USE_CENTER_LIMIT_ 266 return m_limit.isLimit(); 267 #else 268 return m_solveLimit; 269 #endif 270 } 271 272 inline btScalar getLimitSign() 273 { 274 #ifdef _BT_USE_CENTER_LIMIT_ 275 return m_limit.getSign(); 276 #else 277 return m_limitSign; 278 #endif 279 } 280 281 inline bool getAngularOnly() 282 { 283 return m_angularOnly; 284 } 285 inline bool getEnableAngularMotor() 286 { 287 return m_enableAngularMotor; 288 } 289 inline btScalar getMotorTargetVelosity() 290 { 291 return m_motorTargetVelocity; 292 } 293 inline btScalar getMaxMotorImpulse() 294 { 295 return m_maxMotorImpulse; 296 } 297 // access for UseFrameOffset 298 bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; } 299 void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; } 300 301 302 ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 303 ///If no axis is provided, it uses the default axis for this constraint. 304 virtual void setParam(int num, btScalar value, int axis = -1); 305 ///return the local value of parameter 306 virtual btScalar getParam(int num, int axis = -1) const; 307 308 virtual int calculateSerializeBufferSize() const; 309 310 ///fills the dataBuffer and returns the struct name (and 0 on failure) 311 virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; 312 313 314 }; 315 316 317 //only for backward compatibility 318 #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION 319 ///this structure is not used, except for loading pre-2.82 .bullet files 320 struct btHingeConstraintDoubleData 321 { 322 btTypedConstraintData m_typeConstraintData; 323 btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. 324 btTransformDoubleData m_rbBFrame; 325 int m_useReferenceFrameA; 326 int m_angularOnly; 327 int m_enableAngularMotor; 328 float m_motorTargetVelocity; 329 float m_maxMotorImpulse; 330 331 float m_lowerLimit; 332 float m_upperLimit; 333 float m_limitSoftness; 334 float m_biasFactor; 335 float m_relaxationFactor; 336 337 }; 338 #endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION 339 340 ///The getAccumulatedHingeAngle returns the accumulated hinge angle, taking rotation across the -PI/PI boundary into account 341 ATTRIBUTE_ALIGNED16(class) btHingeAccumulatedAngleConstraint : public btHingeConstraint 342 { 343 protected: 344 btScalar m_accumulatedAngle; 345 public: 346 347 BT_DECLARE_ALIGNED_ALLOCATOR(); 348 349 btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false) 350 :btHingeConstraint(rbA,rbB,pivotInA,pivotInB, axisInA,axisInB, useReferenceFrameA ) 351 { 352 m_accumulatedAngle=getHingeAngle(); 353 } 354 355 btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false) 356 :btHingeConstraint(rbA,pivotInA,axisInA, useReferenceFrameA) 357 { 358 m_accumulatedAngle=getHingeAngle(); 359 } 360 361 btHingeAccumulatedAngleConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false) 362 :btHingeConstraint(rbA,rbB, rbAFrame, rbBFrame, useReferenceFrameA ) 363 { 364 m_accumulatedAngle=getHingeAngle(); 365 } 366 367 btHingeAccumulatedAngleConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false) 368 :btHingeConstraint(rbA,rbAFrame, useReferenceFrameA ) 369 { 370 m_accumulatedAngle=getHingeAngle(); 371 } 372 btScalar getAccumulatedHingeAngle(); 373 void setAccumulatedHingeAngle(btScalar accAngle); 374 virtual void getInfo1 (btConstraintInfo1* info); 375 376 }; 377 378 struct btHingeConstraintFloatData 379 { 380 btTypedConstraintData m_typeConstraintData; 381 btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis. 382 btTransformFloatData m_rbBFrame; 383 int m_useReferenceFrameA; 384 int m_angularOnly; 385 386 int m_enableAngularMotor; 387 float m_motorTargetVelocity; 388 float m_maxMotorImpulse; 389 390 float m_lowerLimit; 391 float m_upperLimit; 392 float m_limitSoftness; 393 float m_biasFactor; 394 float m_relaxationFactor; 395 396 }; 397 398 399 400 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 401 struct btHingeConstraintDoubleData2 402 { 403 btTypedConstraintDoubleData m_typeConstraintData; 404 btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis. 405 btTransformDoubleData m_rbBFrame; 406 int m_useReferenceFrameA; 407 int m_angularOnly; 408 int m_enableAngularMotor; 409 double m_motorTargetVelocity; 410 double m_maxMotorImpulse; 411 412 double m_lowerLimit; 413 double m_upperLimit; 414 double m_limitSoftness; 415 double m_biasFactor; 416 double m_relaxationFactor; 417 char m_padding1[4]; 418 419 }; 420 421 422 423 424 SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const 425 { 426 return sizeof(btHingeConstraintData); 427 } 428 429 ///fills the dataBuffer and returns the struct name (and 0 on failure) 430 SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const 431 { 432 btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer; 433 btTypedConstraint::serialize(&hingeData->m_typeConstraintData,serializer); 434 435 m_rbAFrame.serialize(hingeData->m_rbAFrame); 436 m_rbBFrame.serialize(hingeData->m_rbBFrame); 437 438 hingeData->m_angularOnly = m_angularOnly; 439 hingeData->m_enableAngularMotor = m_enableAngularMotor; 440 hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse); 441 hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity); 442 hingeData->m_useReferenceFrameA = m_useReferenceFrameA; 443 #ifdef _BT_USE_CENTER_LIMIT_ 444 hingeData->m_lowerLimit = float(m_limit.getLow()); 445 hingeData->m_upperLimit = float(m_limit.getHigh()); 446 hingeData->m_limitSoftness = float(m_limit.getSoftness()); 447 hingeData->m_biasFactor = float(m_limit.getBiasFactor()); 448 hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor()); 449 #else 450 hingeData->m_lowerLimit = float(m_lowerLimit); 451 hingeData->m_upperLimit = float(m_upperLimit); 452 hingeData->m_limitSoftness = float(m_limitSoftness); 453 hingeData->m_biasFactor = float(m_biasFactor); 454 hingeData->m_relaxationFactor = float(m_relaxationFactor); 455 #endif 456 457 return btHingeConstraintDataName; 458 } 459 460 #endif //BT_HINGECONSTRAINT_H 461