1 /*
2  * PURPOSE:
3  *   Class representing an articulated rigid body. Stores the body's
4  *   current state, allows forces and torques to be set, handles
5  *   timestepping and implements Featherstone's algorithm.
6  *
7  * COPYRIGHT:
8  *   Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
9  *   Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
10  *   Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
11 
12  This software is provided 'as-is', without any express or implied warranty.
13  In no event will the authors be held liable for any damages arising from the use of this software.
14  Permission is granted to anyone to use this software for any purpose,
15  including commercial applications, and to alter it and redistribute it freely,
16  subject to the following restrictions:
17 
18  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.
19  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
20  3. This notice may not be removed or altered from any source distribution.
21 
22  */
23 
24 
25 #ifndef BT_MULTIBODY_H
26 #define BT_MULTIBODY_H
27 
28 #include "LinearMath/btScalar.h"
29 #include "LinearMath/btVector3.h"
30 #include "LinearMath/btQuaternion.h"
31 #include "LinearMath/btMatrix3x3.h"
32 #include "LinearMath/btAlignedObjectArray.h"
33 
34 
35 ///serialization data, don't change them if you are not familiar with the details of the serialization mechanisms
36 #ifdef BT_USE_DOUBLE_PRECISION
37 	#define btMultiBodyData	btMultiBodyDoubleData
38 	#define btMultiBodyDataName	"btMultiBodyDoubleData"
39 	#define btMultiBodyLinkData btMultiBodyLinkDoubleData
40 	#define btMultiBodyLinkDataName	"btMultiBodyLinkDoubleData"
41 #else
42 	#define btMultiBodyData	btMultiBodyFloatData
43 	#define btMultiBodyDataName	"btMultiBodyFloatData"
44 	#define btMultiBodyLinkData btMultiBodyLinkFloatData
45 	#define btMultiBodyLinkDataName	"btMultiBodyLinkFloatData"
46 #endif //BT_USE_DOUBLE_PRECISION
47 
48 #include "btMultiBodyLink.h"
49 class btMultiBodyLinkCollider;
50 
ATTRIBUTE_ALIGNED16(class)51 ATTRIBUTE_ALIGNED16(class) btMultiBody
52 {
53 public:
54 
55 
56 	BT_DECLARE_ALIGNED_ALLOCATOR();
57 
58     //
59     // initialization
60     //
61 
62 	btMultiBody(int n_links,             // NOT including the base
63 		btScalar mass,                // mass of base
64 		const btVector3 &inertia,    // inertia of base, in base frame; assumed diagonal
65 		bool fixedBase,           // whether the base is fixed (true) or can move (false)
66 		bool canSleep, bool deprecatedMultiDof=true);
67 
68 
69 	virtual ~btMultiBody();
70 
71 	//note: fixed link collision with parent is always disabled
72 	void setupFixed(int linkIndex,
73 						   btScalar mass,
74 						   const btVector3 &inertia,
75 						   int parent,
76 						   const btQuaternion &rotParentToThis,
77 						   const btVector3 &parentComToThisPivotOffset,
78                            const btVector3 &thisPivotToThisComOffset, bool deprecatedDisableParentCollision=true);
79 
80 
81 	void setupPrismatic(int i,
82                                btScalar mass,
83                                const btVector3 &inertia,
84                                int parent,
85                                const btQuaternion &rotParentToThis,
86                                const btVector3 &jointAxis,
87                                const btVector3 &parentComToThisPivotOffset,
88 							   const btVector3 &thisPivotToThisComOffset,
89 							   bool disableParentCollision);
90 
91     void setupRevolute(int linkIndex,            // 0 to num_links-1
92                        btScalar mass,
93                        const btVector3 &inertia,
94                        int parentIndex,
95                        const btQuaternion &rotParentToThis,  // rotate points in parent frame to this frame, when q = 0
96                        const btVector3 &jointAxis,    // in my frame
97                        const btVector3 &parentComToThisPivotOffset,    // vector from parent COM to joint axis, in PARENT frame
98                        const btVector3 &thisPivotToThisComOffset,       // vector from joint axis to my COM, in MY frame
99 					   bool disableParentCollision=false);
100 
101 	void setupSpherical(int linkIndex,											// 0 to num_links-1
102                        btScalar mass,
103                        const btVector3 &inertia,
104                        int parent,
105                        const btQuaternion &rotParentToThis,		// rotate points in parent frame to this frame, when q = 0
106                        const btVector3 &parentComToThisPivotOffset,			// vector from parent COM to joint axis, in PARENT frame
107                        const btVector3 &thisPivotToThisComOffset,				// vector from joint axis to my COM, in MY frame
108 					   bool disableParentCollision=false);
109 
110 	void setupPlanar(int i,											// 0 to num_links-1
111                        btScalar mass,
112                        const btVector3 &inertia,
113                        int parent,
114                        const btQuaternion &rotParentToThis,		// rotate points in parent frame to this frame, when q = 0
115 					   const btVector3 &rotationAxis,
116                        const btVector3 &parentComToThisComOffset,			// vector from parent COM to this COM, in PARENT frame
117 					   bool disableParentCollision=false);
118 
119 	const btMultibodyLink& getLink(int index) const
120 	{
121 		return m_links[index];
122 	}
123 
124 	btMultibodyLink& getLink(int index)
125 	{
126 		return m_links[index];
127 	}
128 
129 
130 	void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
131 	{
132 		m_baseCollider = collider;
133 	}
134 	const btMultiBodyLinkCollider* getBaseCollider() const
135 	{
136 		return m_baseCollider;
137 	}
138 	btMultiBodyLinkCollider* getBaseCollider()
139 	{
140 		return m_baseCollider;
141 	}
142 
143     //
144     // get parent
145     // input: link num from 0 to num_links-1
146     // output: link num from 0 to num_links-1, OR -1 to mean the base.
147     //
148     int getParent(int link_num) const;
149 
150 
151     //
152     // get number of m_links, masses, moments of inertia
153     //
154 
155     int getNumLinks() const { return m_links.size(); }
156 	int getNumDofs() const { return m_dofCount; }
157 	int getNumPosVars() const { return m_posVarCnt; }
158     btScalar getBaseMass() const { return m_baseMass; }
159     const btVector3 & getBaseInertia() const { return m_baseInertia; }
160     btScalar getLinkMass(int i) const;
161     const btVector3 & getLinkInertia(int i) const;
162 
163 
164 
165     //
166     // change mass (incomplete: can only change base mass and inertia at present)
167     //
168 
169     void setBaseMass(btScalar mass) { m_baseMass = mass; }
170     void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
171 
172 
173     //
174     // get/set pos/vel/rot/omega for the base link
175     //
176 
177     const btVector3 & getBasePos() const { return m_basePos; }    // in world frame
178     const btVector3 getBaseVel() const
179 	{
180 		return btVector3(m_realBuf[3],m_realBuf[4],m_realBuf[5]);
181 	}     // in world frame
182     const btQuaternion & getWorldToBaseRot() const
183 	{
184 		return m_baseQuat;
185 	}     // rotates world vectors into base frame
186     btVector3 getBaseOmega() const { return btVector3(m_realBuf[0],m_realBuf[1],m_realBuf[2]); }   // in world frame
187 
188     void setBasePos(const btVector3 &pos)
189 	{
190 		m_basePos = pos;
191 	}
192 
193 	void setBaseWorldTransform(const btTransform& tr)
194 	{
195 		setBasePos(tr.getOrigin());
196 		setWorldToBaseRot(tr.getRotation().inverse());
197 
198 	}
199 
200 	btTransform getBaseWorldTransform() const
201 	{
202 		btTransform tr;
203 		tr.setOrigin(getBasePos());
204 		tr.setRotation(getWorldToBaseRot().inverse());
205 		return tr;
206 	}
207 
208     void setBaseVel(const btVector3 &vel)
209 	{
210 
211 		m_realBuf[3]=vel[0]; m_realBuf[4]=vel[1]; m_realBuf[5]=vel[2];
212 	}
213     void setWorldToBaseRot(const btQuaternion &rot)
214 	{
215 		m_baseQuat = rot;					//m_baseQuat asumed to ba alias!?
216 	}
217     void setBaseOmega(const btVector3 &omega)
218 	{
219 		m_realBuf[0]=omega[0];
220 		m_realBuf[1]=omega[1];
221 		m_realBuf[2]=omega[2];
222 	}
223 
224 
225     //
226     // get/set pos/vel for child m_links (i = 0 to num_links-1)
227     //
228 
229     btScalar getJointPos(int i) const;
230     btScalar getJointVel(int i) const;
231 
232 	btScalar * getJointVelMultiDof(int i);
233 	btScalar * getJointPosMultiDof(int i);
234 
235 	const btScalar * getJointVelMultiDof(int i) const ;
236 	const btScalar * getJointPosMultiDof(int i) const ;
237 
238     void setJointPos(int i, btScalar q);
239     void setJointVel(int i, btScalar qdot);
240 	void setJointPosMultiDof(int i, btScalar *q);
241     void setJointVelMultiDof(int i, btScalar *qdot);
242 
243 
244 
245     //
246     // direct access to velocities as a vector of 6 + num_links elements.
247     // (omega first, then v, then joint velocities.)
248     //
249     const btScalar * getVelocityVector() const
250 	{
251 		return &m_realBuf[0];
252 	}
253 /*    btScalar * getVelocityVector()
254 	{
255 		return &real_buf[0];
256 	}
257   */
258 
259     //
260     // get the frames of reference (positions and orientations) of the child m_links
261     // (i = 0 to num_links-1)
262     //
263 
264     const btVector3 & getRVector(int i) const;   // vector from COM(parent(i)) to COM(i), in frame i's coords
265     const btQuaternion & getParentToLocalRot(int i) const;   // rotates vectors in frame parent(i) to vectors in frame i.
266 
267 
268     //
269     // transform vectors in local frame of link i to world frame (or vice versa)
270     //
271     btVector3 localPosToWorld(int i, const btVector3 &vec) const;
272     btVector3 localDirToWorld(int i, const btVector3 &vec) const;
273     btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
274     btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
275 
276     //
277     // transform a frame in local coordinate to a frame in world coordinate
278     //
279     btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &mat) const;
280 
281     //
282     // calculate kinetic energy and angular momentum
283     // useful for debugging.
284     //
285 
286     btScalar getKineticEnergy() const;
287     btVector3 getAngularMomentum() const;
288 
289 
290     //
291     // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
292     //
293 
294     void clearForcesAndTorques();
295    void clearConstraintForces();
296 
297 	void clearVelocities();
298 
299     void addBaseForce(const btVector3 &f)
300 	{
301 		m_baseForce += f;
302 	}
303     void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
304     void addLinkForce(int i, const btVector3 &f);
305     void addLinkTorque(int i, const btVector3 &t);
306 
307  void addBaseConstraintForce(const btVector3 &f)
308         {
309                 m_baseConstraintForce += f;
310         }
311     void addBaseConstraintTorque(const btVector3 &t) { m_baseConstraintTorque += t; }
312     void addLinkConstraintForce(int i, const btVector3 &f);
313     void addLinkConstraintTorque(int i, const btVector3 &t);
314 
315 
316 void addJointTorque(int i, btScalar Q);
317 	void addJointTorqueMultiDof(int i, int dof, btScalar Q);
318 	void addJointTorqueMultiDof(int i, const btScalar *Q);
319 
320     const btVector3 & getBaseForce() const { return m_baseForce; }
321     const btVector3 & getBaseTorque() const { return m_baseTorque; }
322     const btVector3 & getLinkForce(int i) const;
323     const btVector3 & getLinkTorque(int i) const;
324     btScalar getJointTorque(int i) const;
325 	btScalar * getJointTorqueMultiDof(int i);
326 
327 
328     //
329     // dynamics routines.
330     //
331 
332     // timestep the velocities (given the external forces/torques set using addBaseForce etc).
333     // also sets up caches for calcAccelerationDeltas.
334     //
335     // Note: the caller must provide three vectors which are used as
336     // temporary scratch space. The idea here is to reduce dynamic
337     // memory allocation: the same scratch vectors can be re-used
338     // again and again for different Multibodies, instead of each
339     // btMultiBody allocating (and then deallocating) their own
340     // individual scratch buffers. This gives a considerable speed
341     // improvement, at least on Windows (where dynamic memory
342     // allocation appears to be fairly slow).
343     //
344 
345 
346 	void computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
347                         btAlignedObjectArray<btScalar> &scratch_r,
348                         btAlignedObjectArray<btVector3> &scratch_v,
349                         btAlignedObjectArray<btMatrix3x3> &scratch_m,
350 			bool isConstraintPass=false
351 		);
352 
353 ///stepVelocitiesMultiDof is deprecated, use computeAccelerationsArticulatedBodyAlgorithmMultiDof instead
354         void stepVelocitiesMultiDof(btScalar dt,
355                         btAlignedObjectArray<btScalar> &scratch_r,
356                         btAlignedObjectArray<btVector3> &scratch_v,
357                         btAlignedObjectArray<btMatrix3x3> &scratch_m,
358                         bool isConstraintPass=false)
359 	{
360 		computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt,scratch_r,scratch_v,scratch_m,isConstraintPass);
361         }
362 
363     // calcAccelerationDeltasMultiDof
364     // input: force vector (in same format as jacobian, i.e.:
365     //                      3 torque values, 3 force values, num_links joint torque values)
366     // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
367     // (existing contents of output array are replaced)
368     // calcAccelerationDeltasMultiDof must have been called first.
369 	void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
370                                 btAlignedObjectArray<btScalar> &scratch_r,
371                                 btAlignedObjectArray<btVector3> &scratch_v) const;
372 
373 
374 	void applyDeltaVeeMultiDof2(const btScalar * delta_vee, btScalar multiplier)
375 	{
376 		for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
377                 {
378                         m_deltaV[dof] += delta_vee[dof] * multiplier;
379                 }
380 	}
381 	void processDeltaVeeMultiDof2()
382 	{
383 		applyDeltaVeeMultiDof(&m_deltaV[0],1);
384 
385 		for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
386                 {
387 			m_deltaV[dof] = 0.f;
388 		}
389 	}
390 
391 	void applyDeltaVeeMultiDof(const btScalar * delta_vee, btScalar multiplier)
392 	{
393 		//for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
394 		//	printf("%.4f ", delta_vee[dof]*multiplier);
395 		//printf("\n");
396 
397 		//btScalar sum = 0;
398 		//for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
399 		//{
400 		//	sum += delta_vee[dof]*multiplier*delta_vee[dof]*multiplier;
401 		//}
402 		//btScalar l = btSqrt(sum);
403 
404 		//if (l>m_maxAppliedImpulse)
405 		//{
406 		//	multiplier *= m_maxAppliedImpulse/l;
407 		//}
408 
409 		for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
410 		{
411 			m_realBuf[dof] += delta_vee[dof] * multiplier;
412 			btClamp(m_realBuf[dof],-m_maxCoordinateVelocity,m_maxCoordinateVelocity);
413 		}
414     }
415 
416 
417 
418     // timestep the positions (given current velocities).
419 	void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
420 
421 
422     //
423     // contacts
424     //
425 
426     // This routine fills out a contact constraint jacobian for this body.
427     // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
428     // 'normal' & 'contact_point' are both given in world coordinates.
429 
430 	void fillContactJacobianMultiDof(int link,
431                              const btVector3 &contact_point,
432                              const btVector3 &normal,
433                              btScalar *jac,
434                              btAlignedObjectArray<btScalar> &scratch_r,
435                              btAlignedObjectArray<btVector3> &scratch_v,
436 							 btAlignedObjectArray<btMatrix3x3> &scratch_m) const { fillConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
437 
438 	//a more general version of fillContactJacobianMultiDof which does not assume..
439 	//.. that the constraint in question is contact or, to be more precise, constrains linear velocity only
440 	void fillConstraintJacobianMultiDof(int link,
441                              const btVector3 &contact_point,
442 							 const btVector3 &normal_ang,
443                              const btVector3 &normal_lin,
444                              btScalar *jac,
445                              btAlignedObjectArray<btScalar> &scratch_r,
446                              btAlignedObjectArray<btVector3> &scratch_v,
447                              btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
448 
449 
450     //
451     // sleeping
452     //
453 	void	setCanSleep(bool canSleep)
454 	{
455 		m_canSleep = canSleep;
456 	}
457 
458 	bool getCanSleep()const
459 	{
460 		return m_canSleep;
461 	}
462 
463     bool isAwake() const { return m_awake; }
464     void wakeUp();
465     void goToSleep();
466     void checkMotionAndSleepIfRequired(btScalar timestep);
467 
468 	bool hasFixedBase() const
469 	{
470 		    return m_fixedBase;
471 	}
472 
473 	int getCompanionId() const
474 	{
475 		return m_companionId;
476 	}
477 	void setCompanionId(int id)
478 	{
479 		//printf("for %p setCompanionId(%d)\n",this, id);
480 		m_companionId = id;
481 	}
482 
483 	void setNumLinks(int numLinks)//careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
484 	{
485 		m_links.resize(numLinks);
486 	}
487 
488 	btScalar getLinearDamping() const
489 	{
490 			return m_linearDamping;
491 	}
492 	void setLinearDamping( btScalar damp)
493 	{
494 		m_linearDamping = damp;
495 	}
496 	btScalar getAngularDamping() const
497 	{
498 		return m_angularDamping;
499 	}
500 	void setAngularDamping( btScalar damp)
501 	{
502 		m_angularDamping = damp;
503 	}
504 
505 	bool getUseGyroTerm() const
506 	{
507 		return m_useGyroTerm;
508 	}
509 	void setUseGyroTerm(bool useGyro)
510 	{
511 		m_useGyroTerm = useGyro;
512 	}
513 	btScalar	getMaxCoordinateVelocity() const
514 	{
515 		return m_maxCoordinateVelocity ;
516 	}
517 	void	setMaxCoordinateVelocity(btScalar maxVel)
518 	{
519 		m_maxCoordinateVelocity = maxVel;
520 	}
521 
522 	btScalar	getMaxAppliedImpulse() const
523 	{
524 		return m_maxAppliedImpulse;
525 	}
526 	void	setMaxAppliedImpulse(btScalar maxImp)
527 	{
528 		m_maxAppliedImpulse = maxImp;
529 	}
530 	void	setHasSelfCollision(bool hasSelfCollision)
531 	{
532 		m_hasSelfCollision = hasSelfCollision;
533 	}
534 	bool hasSelfCollision() const
535 	{
536 		return m_hasSelfCollision;
537 	}
538 
539 
540 	void finalizeMultiDof();
541 
542 	void useRK4Integration(bool use) { m_useRK4 = use; }
543 	bool isUsingRK4Integration() const { return m_useRK4; }
544 	void useGlobalVelocities(bool use) { m_useGlobalVelocities = use; }
545 	bool isUsingGlobalVelocities() const { return m_useGlobalVelocities; }
546 
547 	bool isPosUpdated() const
548 	{
549 		return __posUpdated;
550 	}
551 	void setPosUpdated(bool updated)
552 	{
553 		__posUpdated = updated;
554 	}
555 
556 	//internalNeedsJointFeedback is for internal use only
557 	bool internalNeedsJointFeedback() const
558 	{
559 		return m_internalNeedsJointFeedback;
560 	}
561 	void	forwardKinematics(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
562 
563 	void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
564 
565 	void	updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
566 
567 	virtual	int	calculateSerializeBufferSize()	const;
568 
569 	///fills the dataBuffer and returns the struct name (and 0 on failure)
570 	virtual	const char*	serialize(void* dataBuffer,  class btSerializer* serializer) const;
571 
572 	const char*				getBaseName() const
573 	{
574 		return m_baseName;
575 	}
576 	///memory of setBaseName needs to be manager by user
577 	void	setBaseName(const char* name)
578 	{
579 		m_baseName = name;
580 	}
581 
582 	///users can point to their objects, userPointer is not used by Bullet
583 	void*	getUserPointer() const
584 	{
585 		return m_userObjectPointer;
586 	}
587 
588 	int	getUserIndex() const
589 	{
590 		return m_userIndex;
591 	}
592 
593 	int	getUserIndex2() const
594 	{
595 		return m_userIndex2;
596 	}
597 	///users can point to their objects, userPointer is not used by Bullet
598 	void	setUserPointer(void* userPointer)
599 	{
600 		m_userObjectPointer = userPointer;
601 	}
602 
603 	///users can point to their objects, userPointer is not used by Bullet
604 	void	setUserIndex(int index)
605 	{
606 		m_userIndex = index;
607 	}
608 
609 	void	setUserIndex2(int index)
610 	{
611 		m_userIndex2 = index;
612 	}
613 
614 private:
615     btMultiBody(const btMultiBody &);  // not implemented
616     void operator=(const btMultiBody &);  // not implemented
617 
618 
619 	void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const;
620 	void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const;
621 
622 	void updateLinksDofOffsets()
623 	{
624 		int dofOffset = 0, cfgOffset = 0;
625 		for(int bidx = 0; bidx < m_links.size(); ++bidx)
626 		{
627 			m_links[bidx].m_dofOffset = dofOffset; m_links[bidx].m_cfgOffset = cfgOffset;
628 			dofOffset += m_links[bidx].m_dofCount; cfgOffset += m_links[bidx].m_posVarCount;
629 		}
630 	}
631 
632 	void mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
633 
634 
635 private:
636 
637 	btMultiBodyLinkCollider* m_baseCollider;//can be NULL
638 	const char*				m_baseName;//memory needs to be manager by user!
639 
640     btVector3 m_basePos;       // position of COM of base (world frame)
641     btQuaternion m_baseQuat;   // rotates world points into base frame
642 
643     btScalar m_baseMass;         // mass of the base
644     btVector3 m_baseInertia;   // inertia of the base (in local frame; diagonal)
645 
646     btVector3 m_baseForce;     // external force applied to base. World frame.
647     btVector3 m_baseTorque;    // external torque applied to base. World frame.
648 
649     btVector3 m_baseConstraintForce;     // external force applied to base. World frame.
650     btVector3 m_baseConstraintTorque;    // external torque applied to base. World frame.
651 
652     btAlignedObjectArray<btMultibodyLink> m_links;    // array of m_links, excluding the base. index from 0 to num_links-1.
653 	btAlignedObjectArray<btMultiBodyLinkCollider*> m_colliders;
654 
655 
656     //
657     // realBuf:
658     //  offset         size            array
659     //   0              6 + num_links   v (base_omega; base_vel; joint_vels)					MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
660     //   6+num_links    num_links       D
661     //
662     // vectorBuf:
663     //  offset         size         array
664     //   0              num_links    h_top
665     //   num_links      num_links    h_bottom
666     //
667     // matrixBuf:
668     //  offset         size         array
669     //   0              num_links+1  rot_from_parent
670     //
671    btAlignedObjectArray<btScalar> m_deltaV;
672     btAlignedObjectArray<btScalar> m_realBuf;
673     btAlignedObjectArray<btVector3> m_vectorBuf;
674     btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
675 
676 
677 	btMatrix3x3 m_cachedInertiaTopLeft;
678 	btMatrix3x3 m_cachedInertiaTopRight;
679 	btMatrix3x3 m_cachedInertiaLowerLeft;
680 	btMatrix3x3 m_cachedInertiaLowerRight;
681 	bool m_cachedInertiaValid;
682 
683     bool m_fixedBase;
684 
685     // Sleep parameters.
686     bool m_awake;
687     bool m_canSleep;
688     btScalar m_sleepTimer;
689 
690 	void* m_userObjectPointer;
691 	int m_userIndex2;
692 	int m_userIndex;
693 
694 	int	m_companionId;
695 	btScalar	m_linearDamping;
696 	btScalar	m_angularDamping;
697 	bool	m_useGyroTerm;
698 	btScalar	m_maxAppliedImpulse;
699 	btScalar	m_maxCoordinateVelocity;
700 	bool		m_hasSelfCollision;
701 
702 		bool __posUpdated;
703 		int m_dofCount, m_posVarCnt;
704 	bool m_useRK4, m_useGlobalVelocities;
705 
706 	///the m_needsJointFeedback gets updated/computed during the stepVelocitiesMultiDof and it for internal usage only
707 	bool m_internalNeedsJointFeedback;
708 };
709 
710 struct btMultiBodyLinkDoubleData
711 {
712 	btQuaternionDoubleData	m_zeroRotParentToThis;
713 	btVector3DoubleData		m_parentComToThisComOffset;
714 	btVector3DoubleData		m_thisPivotToThisComOffset;
715 	btVector3DoubleData		m_jointAxisTop[6];
716 	btVector3DoubleData		m_jointAxisBottom[6];
717 
718 	btVector3DoubleData		m_linkInertia;   // inertia of the base (in local frame; diagonal)
719 	double					m_linkMass;
720 	int						m_parentIndex;
721 	int						m_jointType;
722 
723 	int						m_dofCount;
724 	int						m_posVarCount;
725 	double					m_jointPos[7];
726 	double					m_jointVel[6];
727 	double					m_jointTorque[6];
728 
729 	double					m_jointDamping;
730 	double					m_jointFriction;
731 
732 	char					*m_linkName;
733 	char					*m_jointName;
734 	btCollisionObjectDoubleData	*m_linkCollider;
735 	char					*m_paddingPtr;
736 
737 };
738 
739 struct btMultiBodyLinkFloatData
740 {
741 	btQuaternionFloatData	m_zeroRotParentToThis;
742 	btVector3FloatData		m_parentComToThisComOffset;
743 	btVector3FloatData		m_thisPivotToThisComOffset;
744 	btVector3FloatData		m_jointAxisTop[6];
745 	btVector3FloatData		m_jointAxisBottom[6];
746 	btVector3FloatData	m_linkInertia;   // inertia of the base (in local frame; diagonal)
747 	int						m_dofCount;
748 	float				m_linkMass;
749 	int					m_parentIndex;
750 	int					m_jointType;
751 
752 
753 
754 	float					m_jointPos[7];
755 	float					m_jointVel[6];
756 	float					m_jointTorque[6];
757 	int						m_posVarCount;
758 	float					m_jointDamping;
759 	float					m_jointFriction;
760 
761 	char				*m_linkName;
762 	char				*m_jointName;
763 	btCollisionObjectFloatData	*m_linkCollider;
764 	char				*m_paddingPtr;
765 
766 };
767 
768 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
769 struct	btMultiBodyDoubleData
770 {
771 	btTransformDoubleData m_baseWorldTransform;
772 	btVector3DoubleData m_baseInertia;   // inertia of the base (in local frame; diagonal)
773 	double	m_baseMass;
774 
775 	char	*m_baseName;
776 	btMultiBodyLinkDoubleData	*m_links;
777 	btCollisionObjectDoubleData	*m_baseCollider;
778 	char	*m_paddingPtr;
779 	int		m_numLinks;
780 	char	m_padding[4];
781 };
782 
783 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
784 struct	btMultiBodyFloatData
785 {
786 	char	*m_baseName;
787 	btMultiBodyLinkFloatData	*m_links;
788 	btCollisionObjectFloatData	*m_baseCollider;
789 	btTransformFloatData m_baseWorldTransform;
790 	btVector3FloatData m_baseInertia;   // inertia of the base (in local frame; diagonal)
791 
792 	float	m_baseMass;
793 	int		m_numLinks;
794 };
795 
796 
797 
798 #endif
799