Bullet Collision Detection & Physics Library
btConeTwistConstraint.h
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
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 Written by: Marcus Hennix
16 */
17 
18 
19 
20 /*
21 Overview:
22 
23 btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc).
24 It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint".
25 It divides the 3 rotational DOFs into swing (movement within a cone) and twist.
26 Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape.
27 (Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.)
28 
29 In the contraint's frame of reference:
30 twist is along the x-axis,
31 and swing 1 and 2 are along the z and y axes respectively.
32 */
33 
34 
35 
36 #ifndef BT_CONETWISTCONSTRAINT_H
37 #define BT_CONETWISTCONSTRAINT_H
38 
39 #include "LinearMath/btVector3.h"
40 #include "btJacobianEntry.h"
41 #include "btTypedConstraint.h"
42 
43 class btRigidBody;
44 
46 {
50 };
51 
54 {
55 #ifdef IN_PARALLELL_SOLVER
56 public:
57 #endif
58  btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
59 
62 
66 
68 
72 
74 
77 
80 
84 
86 
89 
93 
95 
96  // not yet used...
100 
101  // motor
107 
108  // parameters
109  int m_flags;
113 
114 protected:
115 
116  void init();
117 
118  void computeConeLimitInfo(const btQuaternion& qCone, // in
119  btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs
120 
121  void computeTwistLimitInfo(const btQuaternion& qTwist, // in
122  btScalar& twistAngle, btVector3& vTwistAxis); // all outs
123 
124  void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const;
125 
126 
127 public:
128 
130 
131  btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame);
132 
133  btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame);
134 
135  virtual void buildJacobian();
136 
137  virtual void getInfo1 (btConstraintInfo1* info);
138 
139  void getInfo1NonVirtual(btConstraintInfo1* info);
140 
141  virtual void getInfo2 (btConstraintInfo2* info);
142 
143  void getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
144 
145  virtual void solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar timeStep);
146 
147 
148  void updateRHS(btScalar timeStep);
149 
150 
151  const btRigidBody& getRigidBodyA() const
152  {
153  return m_rbA;
154  }
155  const btRigidBody& getRigidBodyB() const
156  {
157  return m_rbB;
158  }
159 
160  void setAngularOnly(bool angularOnly)
161  {
162  m_angularOnly = angularOnly;
163  }
164 
165  void setLimit(int limitIndex,btScalar limitValue)
166  {
167  switch (limitIndex)
168  {
169  case 3:
170  {
171  m_twistSpan = limitValue;
172  break;
173  }
174  case 4:
175  {
176  m_swingSpan2 = limitValue;
177  break;
178  }
179  case 5:
180  {
181  m_swingSpan1 = limitValue;
182  break;
183  }
184  default:
185  {
186  }
187  };
188  }
189 
190  // setLimit(), a few notes:
191  // _softness:
192  // 0->1, recommend ~0.8->1.
193  // describes % of limits where movement is free.
194  // beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached.
195  // _biasFactor:
196  // 0->1?, recommend 0.3 +/-0.3 or so.
197  // strength with which constraint resists zeroth order (angular, not angular velocity) limit violation.
198  // __relaxationFactor:
199  // 0->1, recommend to stay near 1.
200  // the lower the value, the less the constraint will fight velocities which violate the angular limits.
201  void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
202  {
203  m_swingSpan1 = _swingSpan1;
204  m_swingSpan2 = _swingSpan2;
205  m_twistSpan = _twistSpan;
206 
207  m_limitSoftness = _softness;
208  m_biasFactor = _biasFactor;
209  m_relaxationFactor = _relaxationFactor;
210  }
211 
212  const btTransform& getAFrame() { return m_rbAFrame; };
213  const btTransform& getBFrame() { return m_rbBFrame; };
214 
215  inline int getSolveTwistLimit()
216  {
217  return m_solveTwistLimit;
218  }
219 
220  inline int getSolveSwingLimit()
221  {
222  return m_solveTwistLimit;
223  }
224 
226  {
227  return m_twistLimitSign;
228  }
229 
230  void calcAngleInfo();
231  void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
232 
234  {
235  return m_swingSpan1;
236  }
238  {
239  return m_swingSpan2;
240  }
242  {
243  return m_twistSpan;
244  }
246  {
247  return m_twistAngle;
248  }
249  bool isPastSwingLimit() { return m_solveSwingLimit; }
250 
251  void setDamping(btScalar damping) { m_damping = damping; }
252 
253  void enableMotor(bool b) { m_bMotorEnabled = b; }
254  void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; }
255  void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; }
256 
257  btScalar getFixThresh() { return m_fixThresh; }
258  void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; }
259 
260  // setMotorTarget:
261  // q: the desired rotation of bodyA wrt bodyB.
262  // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability)
263  // note: don't forget to enableMotor()
264  void setMotorTarget(const btQuaternion &q);
265 
266  // same as above, but q is the desired rotation of frameA wrt frameB in constraint space
267  void setMotorTargetInConstraintSpace(const btQuaternion &q);
268 
269  btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const;
270 
273  virtual void setParam(int num, btScalar value, int axis = -1);
274 
275  virtual void setFrames(const btTransform& frameA, const btTransform& frameB);
276 
278  {
279  return m_rbAFrame;
280  }
281 
283  {
284  return m_rbBFrame;
285  }
286 
287 
289  virtual btScalar getParam(int num, int axis = -1) const;
290 
291  virtual int calculateSerializeBufferSize() const;
292 
294  virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
295 
296 };
297 
300 {
304 
305  //limits
308  float m_twistSpan;
312 
313  float m_damping;
314 
315  char m_pad[4];
316 
317 };
318 
319 
320 
322 {
323  return sizeof(btConeTwistConstraintData);
324 
325 }
326 
327 
329 SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
330 {
333 
336 
337  cone->m_swingSpan1 = float(m_swingSpan1);
338  cone->m_swingSpan2 = float(m_swingSpan2);
339  cone->m_twistSpan = float(m_twistSpan);
340  cone->m_limitSoftness = float(m_limitSoftness);
341  cone->m_biasFactor = float(m_biasFactor);
342  cone->m_relaxationFactor = float(m_relaxationFactor);
343  cone->m_damping = float(m_damping);
344 
345  return "btConeTwistConstraintData";
346 }
347 
348 
349 #endif //BT_CONETWISTCONSTRAINT_H