2 Bullet Continuous Collision Detection and Physics Library
3 btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
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.
15 Written by: Marcus Hennix
21 btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc).
22 It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint".
23 It divides the 3 rotational DOFs into swing (movement within a cone) and twist.
24 Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape.
25 (Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.)
27 In the contraint's frame of reference:
28 twist is along the x-axis,
29 and swing 1 and 2 are along the z and y axes respectively.
32 #ifndef BT_CONETWISTCONSTRAINT_H
33 #define BT_CONETWISTCONSTRAINT_H
35 #include "LinearMath/btVector3.h"
36 #include "btJacobianEntry.h"
37 #include "btTypedConstraint.h"
39 #ifdef BT_USE_DOUBLE_PRECISION
40 #define btConeTwistConstraintData2 btConeTwistConstraintDoubleData
41 #define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData"
43 #define btConeTwistConstraintData2 btConeTwistConstraintData
44 #define btConeTwistConstraintDataName "btConeTwistConstraintData"
45 #endif //BT_USE_DOUBLE_PRECISION
51 BT_CONETWIST_FLAGS_LIN_CFM = 1,
52 BT_CONETWIST_FLAGS_LIN_ERP = 2,
53 BT_CONETWIST_FLAGS_ANG_CFM = 4
56 ///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
57 ATTRIBUTE_ALIGNED16(class)
58 btConeTwistConstraint : public btTypedConstraint
60 #ifdef IN_PARALLELL_SOLVER
63 btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
65 btTransform m_rbAFrame;
66 btTransform m_rbBFrame;
68 btScalar m_limitSoftness;
69 btScalar m_biasFactor;
70 btScalar m_relaxationFactor;
74 btScalar m_swingSpan1;
75 btScalar m_swingSpan2;
80 btVector3 m_swingAxis;
81 btVector3 m_twistAxis;
86 btScalar m_twistLimitSign;
87 btScalar m_swingCorrection;
88 btScalar m_twistCorrection;
90 btScalar m_twistAngle;
92 btScalar m_accSwingLimitImpulse;
93 btScalar m_accTwistLimitImpulse;
96 bool m_solveTwistLimit;
97 bool m_solveSwingLimit;
99 bool m_useSolveConstraintObsolete;
102 btScalar m_swingLimitRatio;
103 btScalar m_twistLimitRatio;
104 btVector3 m_twistAxisA;
107 bool m_bMotorEnabled;
108 bool m_bNormalizedMotorStrength;
109 btQuaternion m_qTarget;
110 btScalar m_maxMotorImpulse;
111 btVector3 m_accMotorImpulse;
122 void computeConeLimitInfo(const btQuaternion& qCone, // in
123 btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs
125 void computeTwistLimitInfo(const btQuaternion& qTwist, // in
126 btScalar& twistAngle, btVector3& vTwistAxis); // all outs
128 void adjustSwingAxisToUseEllipseNormal(btVector3 & vSwingAxis) const;
131 BT_DECLARE_ALIGNED_ALLOCATOR();
133 btConeTwistConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame);
135 btConeTwistConstraint(btRigidBody & rbA, const btTransform& rbAFrame);
137 virtual void buildJacobian();
139 virtual void getInfo1(btConstraintInfo1 * info);
141 void getInfo1NonVirtual(btConstraintInfo1 * info);
143 virtual void getInfo2(btConstraintInfo2 * info);
145 void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
147 virtual void solveConstraintObsolete(btSolverBody & bodyA, btSolverBody & bodyB, btScalar timeStep);
149 void updateRHS(btScalar timeStep);
151 const btRigidBody& getRigidBodyA() const
155 const btRigidBody& getRigidBodyB() const
160 void setAngularOnly(bool angularOnly)
162 m_angularOnly = angularOnly;
165 bool getAngularOnly() const
167 return m_angularOnly;
170 void setLimit(int limitIndex, btScalar limitValue)
176 m_twistSpan = limitValue;
181 m_swingSpan2 = limitValue;
186 m_swingSpan1 = limitValue;
195 btScalar getLimit(int limitIndex) const
216 btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint");
222 // setLimit(), a few notes:
224 // 0->1, recommend ~0.8->1.
225 // describes % of limits where movement is free.
226 // beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached.
228 // 0->1?, recommend 0.3 +/-0.3 or so.
229 // strength with which constraint resists zeroth order (angular, not angular velocity) limit violation.
230 // __relaxationFactor:
231 // 0->1, recommend to stay near 1.
232 // the lower the value, the less the constraint will fight velocities which violate the angular limits.
233 void setLimit(btScalar _swingSpan1, btScalar _swingSpan2, btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
235 m_swingSpan1 = _swingSpan1;
236 m_swingSpan2 = _swingSpan2;
237 m_twistSpan = _twistSpan;
239 m_limitSoftness = _softness;
240 m_biasFactor = _biasFactor;
241 m_relaxationFactor = _relaxationFactor;
244 const btTransform& getAFrame() const { return m_rbAFrame; };
245 const btTransform& getBFrame() const { return m_rbBFrame; };
247 inline int getSolveTwistLimit()
249 return m_solveTwistLimit;
252 inline int getSolveSwingLimit()
254 return m_solveSwingLimit;
257 inline btScalar getTwistLimitSign()
259 return m_twistLimitSign;
262 void calcAngleInfo();
263 void calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
265 inline btScalar getSwingSpan1() const
269 inline btScalar getSwingSpan2() const
273 inline btScalar getTwistSpan() const
277 inline btScalar getLimitSoftness() const
279 return m_limitSoftness;
281 inline btScalar getBiasFactor() const
285 inline btScalar getRelaxationFactor() const
287 return m_relaxationFactor;
289 inline btScalar getTwistAngle() const
293 bool isPastSwingLimit() { return m_solveSwingLimit; }
295 btScalar getDamping() const { return m_damping; }
296 void setDamping(btScalar damping) { m_damping = damping; }
298 void enableMotor(bool b) { m_bMotorEnabled = b; }
299 bool isMotorEnabled() const { return m_bMotorEnabled; }
300 btScalar getMaxMotorImpulse() const { return m_maxMotorImpulse; }
301 bool isMaxMotorImpulseNormalized() const { return m_bNormalizedMotorStrength; }
302 void setMaxMotorImpulse(btScalar maxMotorImpulse)
304 m_maxMotorImpulse = maxMotorImpulse;
305 m_bNormalizedMotorStrength = false;
307 void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse)
309 m_maxMotorImpulse = maxMotorImpulse;
310 m_bNormalizedMotorStrength = true;
313 btScalar getFixThresh() { return m_fixThresh; }
314 void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; }
317 // q: the desired rotation of bodyA wrt bodyB.
318 // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability)
319 // note: don't forget to enableMotor()
320 void setMotorTarget(const btQuaternion& q);
321 const btQuaternion& getMotorTarget() const { return m_qTarget; }
323 // same as above, but q is the desired rotation of frameA wrt frameB in constraint space
324 void setMotorTargetInConstraintSpace(const btQuaternion& q);
326 btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const;
328 ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
329 ///If no axis is provided, it uses the default axis for this constraint.
330 virtual void setParam(int num, btScalar value, int axis = -1);
332 virtual void setFrames(const btTransform& frameA, const btTransform& frameB);
334 const btTransform& getFrameOffsetA() const
339 const btTransform& getFrameOffsetB() const
344 ///return the local value of parameter
345 virtual btScalar getParam(int num, int axis = -1) const;
352 virtual int calculateSerializeBufferSize() const;
354 ///fills the dataBuffer and returns the struct name (and 0 on failure)
355 virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
358 struct btConeTwistConstraintDoubleData
360 btTypedConstraintDoubleData m_typeConstraintData;
361 btTransformDoubleData m_rbAFrame;
362 btTransformDoubleData m_rbBFrame;
368 double m_limitSoftness;
370 double m_relaxationFactor;
375 #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
376 ///this structure is not used, except for loading pre-2.82 .bullet files
377 struct btConeTwistConstraintData
379 btTypedConstraintData m_typeConstraintData;
380 btTransformFloatData m_rbAFrame;
381 btTransformFloatData m_rbBFrame;
387 float m_limitSoftness;
389 float m_relaxationFactor;
395 #endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
398 SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const
400 return sizeof(btConeTwistConstraintData2);
403 ///fills the dataBuffer and returns the struct name (and 0 on failure)
404 SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
406 btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*)dataBuffer;
407 btTypedConstraint::serialize(&cone->m_typeConstraintData, serializer);
409 m_rbAFrame.serialize(cone->m_rbAFrame);
410 m_rbBFrame.serialize(cone->m_rbBFrame);
412 cone->m_swingSpan1 = m_swingSpan1;
413 cone->m_swingSpan2 = m_swingSpan2;
414 cone->m_twistSpan = m_twistSpan;
415 cone->m_limitSoftness = m_limitSoftness;
416 cone->m_biasFactor = m_biasFactor;
417 cone->m_relaxationFactor = m_relaxationFactor;
418 cone->m_damping = m_damping;
420 return btConeTwistConstraintDataName;
423 #endif //BT_CONETWISTCONSTRAINT_H