2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
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:
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.
16 /* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */
18 #ifndef BT_HINGECONSTRAINT_H
19 #define BT_HINGECONSTRAINT_H
21 #define _BT_USE_CENTER_LIMIT_ 1
23 #include "LinearMath/btVector3.h"
24 #include "btJacobianEntry.h"
25 #include "btTypedConstraint.h"
29 #ifdef BT_USE_DOUBLE_PRECISION
30 #define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version
31 #define btHingeConstraintDataName "btHingeConstraintDoubleData2"
33 #define btHingeConstraintData btHingeConstraintFloatData
34 #define btHingeConstraintDataName "btHingeConstraintFloatData"
35 #endif //BT_USE_DOUBLE_PRECISION
39 BT_HINGE_FLAGS_CFM_STOP = 1,
40 BT_HINGE_FLAGS_ERP_STOP = 2,
41 BT_HINGE_FLAGS_CFM_NORM = 4,
42 BT_HINGE_FLAGS_ERP_NORM = 8
45 /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
46 /// axis defines the orientation of the hinge axis
47 ATTRIBUTE_ALIGNED16(class)
48 btHingeConstraint : public btTypedConstraint
50 #ifdef IN_PARALLELL_SOLVER
53 btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
54 btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
56 btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis.
57 btTransform m_rbBFrame;
59 btScalar m_motorTargetVelocity;
60 btScalar m_maxMotorImpulse;
62 #ifdef _BT_USE_CENTER_LIMIT_
63 btAngularLimit m_limit;
65 btScalar m_lowerLimit;
66 btScalar m_upperLimit;
68 btScalar m_correction;
70 btScalar m_limitSoftness;
71 btScalar m_biasFactor;
72 btScalar m_relaxationFactor;
79 btScalar m_accLimitImpulse;
80 btScalar m_hingeAngle;
81 btScalar m_referenceSign;
84 bool m_enableAngularMotor;
85 bool m_useSolveConstraintObsolete;
86 bool m_useOffsetForConstraintFrame;
87 bool m_useReferenceFrameA;
89 btScalar m_accMotorImpulse;
98 BT_DECLARE_ALIGNED_ALLOCATOR();
100 btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false);
102 btHingeConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false);
104 btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false);
106 btHingeConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false);
108 virtual void buildJacobian();
110 virtual void getInfo1(btConstraintInfo1 * info);
112 void getInfo1NonVirtual(btConstraintInfo1 * info);
114 virtual void getInfo2(btConstraintInfo2 * info);
116 void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
118 void getInfo2Internal(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
119 void getInfo2InternalUsingFrameOffset(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
121 void updateRHS(btScalar timeStep);
123 const btRigidBody& getRigidBodyA() const
127 const btRigidBody& getRigidBodyB() const
132 btRigidBody& getRigidBodyA()
137 btRigidBody& getRigidBodyB()
142 btTransform& getFrameOffsetA()
147 btTransform& getFrameOffsetB()
152 void setFrames(const btTransform& frameA, const btTransform& frameB);
154 void setAngularOnly(bool angularOnly)
156 m_angularOnly = angularOnly;
159 void enableAngularMotor(bool enableMotor, btScalar targetVelocity, btScalar maxMotorImpulse)
161 m_enableAngularMotor = enableMotor;
162 m_motorTargetVelocity = targetVelocity;
163 m_maxMotorImpulse = maxMotorImpulse;
166 // extra motor API, including ability to set a target rotation (as opposed to angular velocity)
167 // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to
168 // maintain a given angular target.
169 void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; }
170 void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; }
171 void setMotorTargetVelocity(btScalar motorTargetVelocity) { m_motorTargetVelocity = motorTargetVelocity; }
172 void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B.
173 void setMotorTarget(btScalar targetAngle, btScalar dt);
175 void setLimit(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
177 #ifdef _BT_USE_CENTER_LIMIT_
178 m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor);
180 m_lowerLimit = btNormalizeAngle(low);
181 m_upperLimit = btNormalizeAngle(high);
182 m_limitSoftness = _softness;
183 m_biasFactor = _biasFactor;
184 m_relaxationFactor = _relaxationFactor;
188 btScalar getLimitSoftness() const
190 #ifdef _BT_USE_CENTER_LIMIT_
191 return m_limit.getSoftness();
193 return m_limitSoftness;
197 btScalar getLimitBiasFactor() const
199 #ifdef _BT_USE_CENTER_LIMIT_
200 return m_limit.getBiasFactor();
206 btScalar getLimitRelaxationFactor() const
208 #ifdef _BT_USE_CENTER_LIMIT_
209 return m_limit.getRelaxationFactor();
211 return m_relaxationFactor;
215 void setAxis(btVector3 & axisInA)
217 btVector3 rbAxisA1, rbAxisA2;
218 btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
219 btVector3 pivotInA = m_rbAFrame.getOrigin();
220 // m_rbAFrame.getOrigin() = pivotInA;
221 m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
222 rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
223 rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
225 btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA;
227 btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
228 btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
229 btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
231 m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA));
233 m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
234 rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
235 rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
236 m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis();
239 bool hasLimit() const
241 #ifdef _BT_USE_CENTER_LIMIT_
242 return m_limit.getHalfRange() > 0;
244 return m_lowerLimit <= m_upperLimit;
248 btScalar getLowerLimit() const
250 #ifdef _BT_USE_CENTER_LIMIT_
251 return m_limit.getLow();
257 btScalar getUpperLimit() const
259 #ifdef _BT_USE_CENTER_LIMIT_
260 return m_limit.getHigh();
266 ///The getHingeAngle gives the hinge angle in range [-PI,PI]
267 btScalar getHingeAngle();
269 btScalar getHingeAngle(const btTransform& transA, const btTransform& transB);
271 void testLimit(const btTransform& transA, const btTransform& transB);
273 const btTransform& getAFrame() const { return m_rbAFrame; };
274 const btTransform& getBFrame() const { return m_rbBFrame; };
276 btTransform& getAFrame() { return m_rbAFrame; };
277 btTransform& getBFrame() { return m_rbBFrame; };
279 inline int getSolveLimit()
281 #ifdef _BT_USE_CENTER_LIMIT_
282 return m_limit.isLimit();
288 inline btScalar getLimitSign()
290 #ifdef _BT_USE_CENTER_LIMIT_
291 return m_limit.getSign();
297 inline bool getAngularOnly()
299 return m_angularOnly;
301 inline bool getEnableAngularMotor()
303 return m_enableAngularMotor;
305 inline btScalar getMotorTargetVelocity()
307 return m_motorTargetVelocity;
309 inline btScalar getMaxMotorImpulse()
311 return m_maxMotorImpulse;
313 // access for UseFrameOffset
314 bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
315 void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
316 // access for UseReferenceFrameA
317 bool getUseReferenceFrameA() const { return m_useReferenceFrameA; }
318 void setUseReferenceFrameA(bool useReferenceFrameA) { m_useReferenceFrameA = useReferenceFrameA; }
320 ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
321 ///If no axis is provided, it uses the default axis for this constraint.
322 virtual void setParam(int num, btScalar value, int axis = -1);
323 ///return the local value of parameter
324 virtual btScalar getParam(int num, int axis = -1) const;
326 virtual int getFlags() const
331 virtual int calculateSerializeBufferSize() const;
333 ///fills the dataBuffer and returns the struct name (and 0 on failure)
334 virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
337 //only for backward compatibility
338 #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
339 ///this structure is not used, except for loading pre-2.82 .bullet files
340 struct btHingeConstraintDoubleData
342 btTypedConstraintData m_typeConstraintData;
343 btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
344 btTransformDoubleData m_rbBFrame;
345 int m_useReferenceFrameA;
347 int m_enableAngularMotor;
348 float m_motorTargetVelocity;
349 float m_maxMotorImpulse;
353 float m_limitSoftness;
355 float m_relaxationFactor;
357 #endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
359 ///The getAccumulatedHingeAngle returns the accumulated hinge angle, taking rotation across the -PI/PI boundary into account
360 ATTRIBUTE_ALIGNED16(class)
361 btHingeAccumulatedAngleConstraint : public btHingeConstraint
364 btScalar m_accumulatedAngle;
367 BT_DECLARE_ALIGNED_ALLOCATOR();
369 btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false)
370 : btHingeConstraint(rbA, rbB, pivotInA, pivotInB, axisInA, axisInB, useReferenceFrameA)
372 m_accumulatedAngle = getHingeAngle();
375 btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false)
376 : btHingeConstraint(rbA, pivotInA, axisInA, useReferenceFrameA)
378 m_accumulatedAngle = getHingeAngle();
381 btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false)
382 : btHingeConstraint(rbA, rbB, rbAFrame, rbBFrame, useReferenceFrameA)
384 m_accumulatedAngle = getHingeAngle();
387 btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false)
388 : btHingeConstraint(rbA, rbAFrame, useReferenceFrameA)
390 m_accumulatedAngle = getHingeAngle();
392 btScalar getAccumulatedHingeAngle();
393 void setAccumulatedHingeAngle(btScalar accAngle);
394 virtual void getInfo1(btConstraintInfo1 * info);
397 struct btHingeConstraintFloatData
399 btTypedConstraintData m_typeConstraintData;
400 btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
401 btTransformFloatData m_rbBFrame;
402 int m_useReferenceFrameA;
405 int m_enableAngularMotor;
406 float m_motorTargetVelocity;
407 float m_maxMotorImpulse;
411 float m_limitSoftness;
413 float m_relaxationFactor;
416 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
417 struct btHingeConstraintDoubleData2
419 btTypedConstraintDoubleData m_typeConstraintData;
420 btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
421 btTransformDoubleData m_rbBFrame;
422 int m_useReferenceFrameA;
424 int m_enableAngularMotor;
425 double m_motorTargetVelocity;
426 double m_maxMotorImpulse;
430 double m_limitSoftness;
432 double m_relaxationFactor;
436 SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const
438 return sizeof(btHingeConstraintData);
441 ///fills the dataBuffer and returns the struct name (and 0 on failure)
442 SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
444 btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer;
445 btTypedConstraint::serialize(&hingeData->m_typeConstraintData, serializer);
447 m_rbAFrame.serialize(hingeData->m_rbAFrame);
448 m_rbBFrame.serialize(hingeData->m_rbBFrame);
450 hingeData->m_angularOnly = m_angularOnly;
451 hingeData->m_enableAngularMotor = m_enableAngularMotor;
452 hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse);
453 hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity);
454 hingeData->m_useReferenceFrameA = m_useReferenceFrameA;
455 #ifdef _BT_USE_CENTER_LIMIT_
456 hingeData->m_lowerLimit = float(m_limit.getLow());
457 hingeData->m_upperLimit = float(m_limit.getHigh());
458 hingeData->m_limitSoftness = float(m_limit.getSoftness());
459 hingeData->m_biasFactor = float(m_limit.getBiasFactor());
460 hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor());
462 hingeData->m_lowerLimit = float(m_lowerLimit);
463 hingeData->m_upperLimit = float(m_upperLimit);
464 hingeData->m_limitSoftness = float(m_limitSoftness);
465 hingeData->m_biasFactor = float(m_biasFactor);
466 hingeData->m_relaxationFactor = float(m_relaxationFactor);
469 // Fill padding with zeros to appease msan.
470 #ifdef BT_USE_DOUBLE_PRECISION
471 hingeData->m_padding1[0] = 0;
472 hingeData->m_padding1[1] = 0;
473 hingeData->m_padding1[2] = 0;
474 hingeData->m_padding1[3] = 0;
477 return btHingeConstraintDataName;
480 #endif //BT_HINGECONSTRAINT_H