forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			2041 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			2041 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * PURPOSE:
							 | 
						||
| 
								 | 
							
								 *   Class representing an articulated rigid body. Stores the body's
							 | 
						||
| 
								 | 
							
								 *   current state, allows forces and torques to be set, handles
							 | 
						||
| 
								 | 
							
								 *   timestepping and implements Featherstone's algorithm.
							 | 
						||
| 
								 | 
							
								 *   
							 | 
						||
| 
								 | 
							
								 * COPYRIGHT:
							 | 
						||
| 
								 | 
							
								 *   Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
							 | 
						||
| 
								 | 
							
								 *   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)
							 | 
						||
| 
								 | 
							
								 *   Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 This software is provided 'as-is', without any express or implied warranty.
							 | 
						||
| 
								 | 
							
								 In no event will the authors be held liable for any damages arising from the use of this software.
							 | 
						||
| 
								 | 
							
								 Permission is granted to anyone to use this software for any purpose,
							 | 
						||
| 
								 | 
							
								 including commercial applications, and to alter it and redistribute it freely,
							 | 
						||
| 
								 | 
							
								 subject to the following restrictions:
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								 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.
							 | 
						||
| 
								 | 
							
								 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
							 | 
						||
| 
								 | 
							
								 3. This notice may not be removed or altered from any source distribution.
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "btMultiBody.h"
							 | 
						||
| 
								 | 
							
								#include "btMultiBodyLink.h"
							 | 
						||
| 
								 | 
							
								#include "btMultiBodyLinkCollider.h"
							 | 
						||
| 
								 | 
							
								#include "btMultiBodyJointFeedback.h"
							 | 
						||
| 
								 | 
							
								#include "LinearMath/btTransformUtil.h"
							 | 
						||
| 
								 | 
							
								#include "LinearMath/btSerializer.h"
							 | 
						||
| 
								 | 
							
								//#include "Bullet3Common/b3Logging.h"
							 | 
						||
| 
								 | 
							
								// #define INCLUDE_GYRO_TERM 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								///todo: determine if we need these options. If so, make a proper API, otherwise delete those globals
							 | 
						||
| 
								 | 
							
								bool gJointFeedbackInWorldSpace = false;
							 | 
						||
| 
								 | 
							
								bool gJointFeedbackInJointFrame = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace {
							 | 
						||
| 
								 | 
							
								    const btScalar SLEEP_EPSILON = btScalar(0.05);  // this is a squared velocity (m^2 s^-2)
							 | 
						||
| 
								 | 
							
								    const btScalar SLEEP_TIMEOUT = btScalar(2);     // in seconds
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace {
							 | 
						||
| 
								 | 
							
								    void SpatialTransform(const btMatrix3x3 &rotation_matrix,  // rotates vectors in 'from' frame to vectors in 'to' frame
							 | 
						||
| 
								 | 
							
								                          const btVector3 &displacement,     // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
							 | 
						||
| 
								 | 
							
								                          const btVector3 &top_in,       // top part of input vector
							 | 
						||
| 
								 | 
							
								                          const btVector3 &bottom_in,    // bottom part of input vector
							 | 
						||
| 
								 | 
							
								                          btVector3 &top_out,         // top part of output vector
							 | 
						||
| 
								 | 
							
								                          btVector3 &bottom_out)      // bottom part of output vector
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        top_out = rotation_matrix * top_in;
							 | 
						||
| 
								 | 
							
								        bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
								    void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix,
							 | 
						||
| 
								 | 
							
								                                 const btVector3 &displacement,
							 | 
						||
| 
								 | 
							
								                                 const btVector3 &top_in,
							 | 
						||
| 
								 | 
							
								                                 const btVector3 &bottom_in,
							 | 
						||
| 
								 | 
							
								                                 btVector3 &top_out,
							 | 
						||
| 
								 | 
							
								                                 btVector3 &bottom_out)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        top_out = rotation_matrix.transpose() * top_in;
							 | 
						||
| 
								 | 
							
								        bottom_out = rotation_matrix.transpose() * (bottom_in + displacement.cross(top_in));		
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btScalar SpatialDotProduct(const btVector3 &a_top,
							 | 
						||
| 
								 | 
							
								                            const btVector3 &a_bottom,
							 | 
						||
| 
								 | 
							
								                            const btVector3 &b_top,
							 | 
						||
| 
								 | 
							
								                            const btVector3 &b_bottom)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return a_bottom.dot(b_top) + a_top.dot(b_bottom);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void SpatialCrossProduct(const btVector3 &a_top,
							 | 
						||
| 
								 | 
							
								                            const btVector3 &a_bottom,
							 | 
						||
| 
								 | 
							
								                            const btVector3 &b_top,
							 | 
						||
| 
								 | 
							
								                            const btVector3 &b_bottom,
							 | 
						||
| 
								 | 
							
															btVector3 &top_out,
							 | 
						||
| 
								 | 
							
															btVector3 &bottom_out)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										top_out = a_top.cross(b_top);
							 | 
						||
| 
								 | 
							
										bottom_out = a_bottom.cross(b_top) + a_top.cross(b_bottom);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Implementation of class btMultiBody
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btMultiBody::btMultiBody(int n_links,
							 | 
						||
| 
								 | 
							
								                     btScalar mass,
							 | 
						||
| 
								 | 
							
								                     const btVector3 &inertia,
							 | 
						||
| 
								 | 
							
								                     bool fixedBase,
							 | 
						||
| 
								 | 
							
								                     bool canSleep,
							 | 
						||
| 
								 | 
							
										     bool /*deprecatedUseMultiDof*/)
							 | 
						||
| 
								 | 
							
								    : 
							 | 
						||
| 
								 | 
							
								    	m_baseCollider(0),
							 | 
						||
| 
								 | 
							
										m_baseName(0),
							 | 
						||
| 
								 | 
							
								    	m_basePos(0,0,0),
							 | 
						||
| 
								 | 
							
								    	m_baseQuat(0, 0, 0, 1),
							 | 
						||
| 
								 | 
							
								      m_baseMass(mass),
							 | 
						||
| 
								 | 
							
								      m_baseInertia(inertia),
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
										m_fixedBase(fixedBase),
							 | 
						||
| 
								 | 
							
										m_awake(true),
							 | 
						||
| 
								 | 
							
										m_canSleep(canSleep),
							 | 
						||
| 
								 | 
							
										m_sleepTimer(0),
							 | 
						||
| 
								 | 
							
										m_userObjectPointer(0),
							 | 
						||
| 
								 | 
							
										m_userIndex2(-1),
							 | 
						||
| 
								 | 
							
										m_userIndex(-1),
							 | 
						||
| 
								 | 
							
										m_linearDamping(0.04f),
							 | 
						||
| 
								 | 
							
										m_angularDamping(0.04f),
							 | 
						||
| 
								 | 
							
										m_useGyroTerm(true),
							 | 
						||
| 
								 | 
							
											m_maxAppliedImpulse(1000.f),
							 | 
						||
| 
								 | 
							
										m_maxCoordinateVelocity(100.f),
							 | 
						||
| 
								 | 
							
											m_hasSelfCollision(true),		
							 | 
						||
| 
								 | 
							
										__posUpdated(false),
							 | 
						||
| 
								 | 
							
											m_dofCount(0),
							 | 
						||
| 
								 | 
							
										m_posVarCnt(0),
							 | 
						||
| 
								 | 
							
										m_useRK4(false), 	
							 | 
						||
| 
								 | 
							
										m_useGlobalVelocities(false),
							 | 
						||
| 
								 | 
							
										m_internalNeedsJointFeedback(false)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									m_cachedInertiaTopLeft.setValue(0,0,0,0,0,0,0,0,0);
							 | 
						||
| 
								 | 
							
									m_cachedInertiaTopRight.setValue(0,0,0,0,0,0,0,0,0);
							 | 
						||
| 
								 | 
							
									m_cachedInertiaLowerLeft.setValue(0,0,0,0,0,0,0,0,0);
							 | 
						||
| 
								 | 
							
									m_cachedInertiaLowerRight.setValue(0,0,0,0,0,0,0,0,0);
							 | 
						||
| 
								 | 
							
									m_cachedInertiaValid=false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links.resize(n_links);
							 | 
						||
| 
								 | 
							
									m_matrixBuf.resize(n_links + 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_baseForce.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								    m_baseTorque.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btMultiBody::~btMultiBody()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setupFixed(int i,
							 | 
						||
| 
								 | 
							
														   btScalar mass,
							 | 
						||
| 
								 | 
							
														   const btVector3 &inertia,
							 | 
						||
| 
								 | 
							
														   int parent,
							 | 
						||
| 
								 | 
							
														   const btQuaternion &rotParentToThis,
							 | 
						||
| 
								 | 
							
														   const btVector3 &parentComToThisPivotOffset,
							 | 
						||
| 
								 | 
							
								                           const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									m_links[i].m_mass = mass;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_inertiaLocal = inertia;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_parent = parent;
							 | 
						||
| 
								 | 
							
									 m_links[i].setAxisTop(0, 0., 0., 0.);
							 | 
						||
| 
								 | 
							
								    m_links[i].setAxisBottom(0, btVector3(0,0,0));
							 | 
						||
| 
								 | 
							
								    m_links[i].m_zeroRotParentToThis = rotParentToThis;
							 | 
						||
| 
								 | 
							
									m_links[i].m_dVector = thisPivotToThisComOffset;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_eVector = parentComToThisPivotOffset;    
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointType = btMultibodyLink::eFixed;
							 | 
						||
| 
								 | 
							
									m_links[i].m_dofCount = 0;
							 | 
						||
| 
								 | 
							
									m_links[i].m_posVarCount = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;    
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									m_links[i].updateCacheMultiDof();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									updateLinksDofOffsets();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setupPrismatic(int i,
							 | 
						||
| 
								 | 
							
								                               btScalar mass,
							 | 
						||
| 
								 | 
							
								                               const btVector3 &inertia,
							 | 
						||
| 
								 | 
							
								                               int parent,
							 | 
						||
| 
								 | 
							
								                               const btQuaternion &rotParentToThis,
							 | 
						||
| 
								 | 
							
								                               const btVector3 &jointAxis,
							 | 
						||
| 
								 | 
							
								                               const btVector3 &parentComToThisPivotOffset,
							 | 
						||
| 
								 | 
							
															   const btVector3 &thisPivotToThisComOffset,
							 | 
						||
| 
								 | 
							
															   bool disableParentCollision)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									m_dofCount += 1;
							 | 
						||
| 
								 | 
							
									m_posVarCnt += 1;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								    m_links[i].m_mass = mass;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_inertiaLocal = inertia;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_parent = parent;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_zeroRotParentToThis = rotParentToThis;
							 | 
						||
| 
								 | 
							
								    m_links[i].setAxisTop(0, 0., 0., 0.);
							 | 
						||
| 
								 | 
							
								    m_links[i].setAxisBottom(0, jointAxis);
							 | 
						||
| 
								 | 
							
								    m_links[i].m_eVector = parentComToThisPivotOffset;
							 | 
						||
| 
								 | 
							
									m_links[i].m_dVector = thisPivotToThisComOffset;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_cachedRotParentToThis = rotParentToThis;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointType = btMultibodyLink::ePrismatic;
							 | 
						||
| 
								 | 
							
									m_links[i].m_dofCount = 1;
							 | 
						||
| 
								 | 
							
									m_links[i].m_posVarCount = 1;	
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointPos[0] = 0.f;
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointTorque[0] = 0.f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (disableParentCollision)
							 | 
						||
| 
								 | 
							
										m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									m_links[i].updateCacheMultiDof();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									updateLinksDofOffsets();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setupRevolute(int i,
							 | 
						||
| 
								 | 
							
								                              btScalar mass,
							 | 
						||
| 
								 | 
							
								                              const btVector3 &inertia,
							 | 
						||
| 
								 | 
							
								                              int parent,
							 | 
						||
| 
								 | 
							
								                              const btQuaternion &rotParentToThis,
							 | 
						||
| 
								 | 
							
								                              const btVector3 &jointAxis,
							 | 
						||
| 
								 | 
							
								                              const btVector3 &parentComToThisPivotOffset,
							 | 
						||
| 
								 | 
							
								                              const btVector3 &thisPivotToThisComOffset,
							 | 
						||
| 
								 | 
							
															  bool disableParentCollision)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									m_dofCount += 1;
							 | 
						||
| 
								 | 
							
									m_posVarCnt += 1;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								    m_links[i].m_mass = mass;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_inertiaLocal = inertia;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_parent = parent;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_zeroRotParentToThis = rotParentToThis;
							 | 
						||
| 
								 | 
							
								    m_links[i].setAxisTop(0, jointAxis);
							 | 
						||
| 
								 | 
							
								    m_links[i].setAxisBottom(0, jointAxis.cross(thisPivotToThisComOffset));
							 | 
						||
| 
								 | 
							
								    m_links[i].m_dVector = thisPivotToThisComOffset;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_eVector = parentComToThisPivotOffset;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointType = btMultibodyLink::eRevolute;
							 | 
						||
| 
								 | 
							
									m_links[i].m_dofCount = 1;
							 | 
						||
| 
								 | 
							
									m_links[i].m_posVarCount = 1;	
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointPos[0] = 0.f;
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointTorque[0] = 0.f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (disableParentCollision)
							 | 
						||
| 
								 | 
							
										m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
									m_links[i].updateCacheMultiDof();
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									updateLinksDofOffsets();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setupSpherical(int i,
							 | 
						||
| 
								 | 
							
														   btScalar mass,
							 | 
						||
| 
								 | 
							
														   const btVector3 &inertia,
							 | 
						||
| 
								 | 
							
														   int parent,
							 | 
						||
| 
								 | 
							
														   const btQuaternion &rotParentToThis,
							 | 
						||
| 
								 | 
							
														   const btVector3 &parentComToThisPivotOffset,
							 | 
						||
| 
								 | 
							
														   const btVector3 &thisPivotToThisComOffset,
							 | 
						||
| 
								 | 
							
														   bool disableParentCollision)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									m_dofCount += 3;
							 | 
						||
| 
								 | 
							
									m_posVarCnt += 4;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_mass = mass;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_inertiaLocal = inertia;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_parent = parent;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_zeroRotParentToThis = rotParentToThis;    
							 | 
						||
| 
								 | 
							
								    m_links[i].m_dVector = thisPivotToThisComOffset;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_eVector = parentComToThisPivotOffset;    
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointType = btMultibodyLink::eSpherical;
							 | 
						||
| 
								 | 
							
									m_links[i].m_dofCount = 3;
							 | 
						||
| 
								 | 
							
									m_links[i].m_posVarCount = 4;
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisTop(0, 1.f, 0.f, 0.f);
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisTop(1, 0.f, 1.f, 0.f);
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisTop(2, 0.f, 0.f, 1.f);
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisBottom(0, m_links[i].getAxisTop(0).cross(thisPivotToThisComOffset));
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisBottom(1, m_links[i].getAxisTop(1).cross(thisPivotToThisComOffset));
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisBottom(2, m_links[i].getAxisTop(2).cross(thisPivotToThisComOffset));
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f; m_links[i].m_jointPos[3] = 1.f;
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (disableParentCollision)
							 | 
						||
| 
								 | 
							
										m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;    
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									m_links[i].updateCacheMultiDof();	
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									updateLinksDofOffsets();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setupPlanar(int i,
							 | 
						||
| 
								 | 
							
														   btScalar mass,
							 | 
						||
| 
								 | 
							
														   const btVector3 &inertia,
							 | 
						||
| 
								 | 
							
														   int parent,
							 | 
						||
| 
								 | 
							
														   const btQuaternion &rotParentToThis,
							 | 
						||
| 
								 | 
							
														   const btVector3 &rotationAxis,
							 | 
						||
| 
								 | 
							
														   const btVector3 &parentComToThisComOffset,						   
							 | 
						||
| 
								 | 
							
														   bool disableParentCollision)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									m_dofCount += 3;
							 | 
						||
| 
								 | 
							
									m_posVarCnt += 3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_mass = mass;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_inertiaLocal = inertia;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_parent = parent;
							 | 
						||
| 
								 | 
							
								    m_links[i].m_zeroRotParentToThis = rotParentToThis;    
							 | 
						||
| 
								 | 
							
									m_links[i].m_dVector.setZero();
							 | 
						||
| 
								 | 
							
								    m_links[i].m_eVector = parentComToThisComOffset;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									btVector3 vecNonParallelToRotAxis(1, 0, 0);
							 | 
						||
| 
								 | 
							
									if(rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999)
							 | 
						||
| 
								 | 
							
										vecNonParallelToRotAxis.setValue(0, 1, 0);
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointType = btMultibodyLink::ePlanar;
							 | 
						||
| 
								 | 
							
									m_links[i].m_dofCount = 3;
							 | 
						||
| 
								 | 
							
									m_links[i].m_posVarCount = 3;
							 | 
						||
| 
								 | 
							
									btVector3 n=rotationAxis.normalized();
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisTop(0, n[0],n[1],n[2]);
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisTop(1,0,0,0);
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisTop(2,0,0,0);
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisBottom(0,0,0,0);
							 | 
						||
| 
								 | 
							
									btVector3 cr = m_links[i].getAxisTop(0).cross(vecNonParallelToRotAxis);
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisBottom(1,cr[0],cr[1],cr[2]);
							 | 
						||
| 
								 | 
							
									cr = m_links[i].getAxisBottom(1).cross(m_links[i].getAxisTop(0));
							 | 
						||
| 
								 | 
							
									m_links[i].setAxisBottom(2,cr[0],cr[1],cr[2]);
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (disableParentCollision)
							 | 
						||
| 
								 | 
							
										m_links[i].m_flags |=BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
									m_links[i].updateCacheMultiDof();
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									updateLinksDofOffsets();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::finalizeMultiDof()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									m_deltaV.resize(0);
							 | 
						||
| 
								 | 
							
									m_deltaV.resize(6 + m_dofCount);
							 | 
						||
| 
								 | 
							
									m_realBuf.resize(6 + m_dofCount + m_dofCount*m_dofCount + 6 + m_dofCount);			//m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels")
							 | 
						||
| 
								 | 
							
									m_vectorBuf.resize(2 * m_dofCount);													//two 3-vectors (i.e. one six-vector) for each system dof	("h" matrices)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									updateLinksDofOffsets();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								int btMultiBody::getParent(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar btMultiBody::getLinkMass(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_mass;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const btVector3 & btMultiBody::getLinkInertia(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_inertiaLocal;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar btMultiBody::getJointPos(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_jointPos[0];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar btMultiBody::getJointVel(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_realBuf[6 + m_links[i].m_dofOffset];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar * btMultiBody::getJointPosMultiDof(int i)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return &m_links[i].m_jointPos[0];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar * btMultiBody::getJointVelMultiDof(int i)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return &m_realBuf[6 + m_links[i].m_dofOffset];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const btScalar * btMultiBody::getJointPosMultiDof(int i) const 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return &m_links[i].m_jointPos[0];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const btScalar * btMultiBody::getJointVelMultiDof(int i) const 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return &m_realBuf[6 + m_links[i].m_dofOffset];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setJointPos(int i, btScalar q)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_links[i].m_jointPos[0] = q;
							 | 
						||
| 
								 | 
							
								    m_links[i].updateCacheMultiDof();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setJointPosMultiDof(int i, btScalar *q)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for(int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
							 | 
						||
| 
								 | 
							
										m_links[i].m_jointPos[pos] = q[pos];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    m_links[i].updateCacheMultiDof();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setJointVel(int i, btScalar qdot)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_realBuf[6 + m_links[i].m_dofOffset] = qdot;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::setJointVelMultiDof(int i, btScalar *qdot)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										m_realBuf[6 + m_links[i].m_dofOffset + dof] = qdot[dof];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const btVector3 & btMultiBody::getRVector(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const btQuaternion & btMultiBody::getParentToLocalRot(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_cachedRotParentToThis;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btAssert(i>=-1);
							 | 
						||
| 
								 | 
							
									btAssert(i<m_links.size());
							 | 
						||
| 
								 | 
							
									if ((i<-1) || (i>=m_links.size()))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btVector3 result = local_pos;
							 | 
						||
| 
								 | 
							
								    while (i != -1) {
							 | 
						||
| 
								 | 
							
								        // 'result' is in frame i. transform it to frame parent(i)
							 | 
						||
| 
								 | 
							
								        result += getRVector(i);
							 | 
						||
| 
								 | 
							
								        result = quatRotate(getParentToLocalRot(i).inverse(),result);
							 | 
						||
| 
								 | 
							
								        i = getParent(i);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // 'result' is now in the base frame. transform it to world frame
							 | 
						||
| 
								 | 
							
								    result = quatRotate(getWorldToBaseRot().inverse() ,result);
							 | 
						||
| 
								 | 
							
								    result += getBasePos();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btAssert(i>=-1);
							 | 
						||
| 
								 | 
							
									btAssert(i<m_links.size());
							 | 
						||
| 
								 | 
							
									if ((i<-1) || (i>=m_links.size()))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i == -1) {
							 | 
						||
| 
								 | 
							
								        // world to base
							 | 
						||
| 
								 | 
							
								        return quatRotate(getWorldToBaseRot(),(world_pos - getBasePos()));
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        // find position in parent frame, then transform to current frame
							 | 
						||
| 
								 | 
							
								        return quatRotate(getParentToLocalRot(i),worldPosToLocal(getParent(i), world_pos)) - getRVector(i);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btAssert(i>=-1);
							 | 
						||
| 
								 | 
							
									btAssert(i<m_links.size());
							 | 
						||
| 
								 | 
							
									if ((i<-1) || (i>=m_links.size()))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btVector3 result = local_dir;
							 | 
						||
| 
								 | 
							
								    while (i != -1) {
							 | 
						||
| 
								 | 
							
								        result = quatRotate(getParentToLocalRot(i).inverse() , result);
							 | 
						||
| 
								 | 
							
								        i = getParent(i);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    result = quatRotate(getWorldToBaseRot().inverse() , result);
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btAssert(i>=-1);
							 | 
						||
| 
								 | 
							
									btAssert(i<m_links.size());
							 | 
						||
| 
								 | 
							
									if ((i<-1) || (i>=m_links.size()))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i == -1) {
							 | 
						||
| 
								 | 
							
								        return quatRotate(getWorldToBaseRot(), world_dir);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        return quatRotate(getParentToLocalRot(i) ,worldDirToLocal(getParent(i), world_dir));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btMatrix3x3 btMultiBody::localFrameToWorld(int i, const btMatrix3x3 &local_frame) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    btMatrix3x3 result = local_frame;
							 | 
						||
| 
								 | 
							
								    btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0));
							 | 
						||
| 
								 | 
							
								    btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1));
							 | 
						||
| 
								 | 
							
								    btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2));
							 | 
						||
| 
								 | 
							
								    result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]);
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
								    // Calculates the velocities of each link (and the base) in its local frame
							 | 
						||
| 
								 | 
							
								    omega[0] = quatRotate(m_baseQuat ,getBaseOmega());
							 | 
						||
| 
								 | 
							
								    vel[0] = quatRotate(m_baseQuat ,getBaseVel());
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // transform parent vel into this frame, store in omega[i+1], vel[i+1]
							 | 
						||
| 
								 | 
							
								        SpatialTransform(btMatrix3x3(m_links[i].m_cachedRotParentToThis), m_links[i].m_cachedRVector,
							 | 
						||
| 
								 | 
							
								                         omega[parent+1], vel[parent+1],
							 | 
						||
| 
								 | 
							
								                         omega[i+1], vel[i+1]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // now add qidot * shat_i
							 | 
						||
| 
								 | 
							
										//only supported for revolute/prismatic joints, todo: spherical and planar joints
							 | 
						||
| 
								 | 
							
										switch(m_links[i].m_jointType)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::ePrismatic:
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::eRevolute:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btVector3 axisTop = m_links[i].getAxisTop(0);
							 | 
						||
| 
								 | 
							
												btVector3 axisBottom = m_links[i].getAxisBottom(0);
							 | 
						||
| 
								 | 
							
												btScalar jointVel = getJointVel(i);
							 | 
						||
| 
								 | 
							
												omega[i+1] += jointVel * axisTop;
							 | 
						||
| 
								 | 
							
												vel[i+1] += jointVel * axisBottom;
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar btMultiBody::getKineticEnergy() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
								    // TODO: would be better not to allocate memory here
							 | 
						||
| 
								 | 
							
								    btAlignedObjectArray<btVector3> omega;omega.resize(num_links+1);
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<btVector3> vel;vel.resize(num_links+1);
							 | 
						||
| 
								 | 
							
								    compTreeLinkVelocities(&omega[0], &vel[0]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // we will do the factor of 0.5 at the end
							 | 
						||
| 
								 | 
							
								    btScalar result = m_baseMass * vel[0].dot(vel[0]);
							 | 
						||
| 
								 | 
							
								    result += omega[0].dot(m_baseInertia * omega[0]);
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i) {
							 | 
						||
| 
								 | 
							
								        result += m_links[i].m_mass * vel[i+1].dot(vel[i+1]);
							 | 
						||
| 
								 | 
							
								        result += omega[i+1].dot(m_links[i].m_inertiaLocal * omega[i+1]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0.5f * result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 btMultiBody::getAngularMomentum() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
								    // TODO: would be better not to allocate memory here
							 | 
						||
| 
								 | 
							
								    btAlignedObjectArray<btVector3> omega;omega.resize(num_links+1);
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<btVector3> vel;vel.resize(num_links+1);
							 | 
						||
| 
								 | 
							
								    btAlignedObjectArray<btQuaternion> rot_from_world;rot_from_world.resize(num_links+1);
							 | 
						||
| 
								 | 
							
								    compTreeLinkVelocities(&omega[0], &vel[0]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rot_from_world[0] = m_baseQuat;
							 | 
						||
| 
								 | 
							
								    btVector3 result = quatRotate(rot_from_world[0].inverse() , (m_baseInertia * omega[0]));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i) {
							 | 
						||
| 
								 | 
							
								        rot_from_world[i+1] = m_links[i].m_cachedRotParentToThis * rot_from_world[m_links[i].m_parent+1];
							 | 
						||
| 
								 | 
							
								        result += (quatRotate(rot_from_world[i+1].inverse() , (m_links[i].m_inertiaLocal * omega[i+1])));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::clearConstraintForces()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									m_baseConstraintForce.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
									m_baseConstraintTorque.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < getNumLinks(); ++i) {
							 | 
						||
| 
								 | 
							
								        m_links[i].m_appliedConstraintForce.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								        m_links[i].m_appliedConstraintTorque.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								void btMultiBody::clearForcesAndTorques()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_baseForce.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								    m_baseTorque.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < getNumLinks(); ++i) {
							 | 
						||
| 
								 | 
							
								        m_links[i].m_appliedForce.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
								        m_links[i].m_appliedTorque.setValue(0, 0, 0);
							 | 
						||
| 
								 | 
							
										m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = m_links[i].m_jointTorque[3] = m_links[i].m_jointTorque[4] = m_links[i].m_jointTorque[5] = 0.f;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::clearVelocities()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < 6 + getNumDofs(); ++i) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										m_realBuf[i] = 0.f;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								void btMultiBody::addLinkForce(int i, const btVector3 &f)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_links[i].m_appliedForce += f;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::addLinkTorque(int i, const btVector3 &t)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_links[i].m_appliedTorque += t;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::addLinkConstraintForce(int i, const btVector3 &f)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_links[i].m_appliedConstraintForce += f;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::addLinkConstraintTorque(int i, const btVector3 &t)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_links[i].m_appliedConstraintTorque += t;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::addJointTorque(int i, btScalar Q)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_links[i].m_jointTorque[0] += Q;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::addJointTorqueMultiDof(int i, int dof, btScalar Q)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									m_links[i].m_jointTorque[dof] += Q;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::addJointTorqueMultiDof(int i, const btScalar *Q)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										m_links[i].m_jointTorque[dof] = Q[dof];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const btVector3 & btMultiBody::getLinkForce(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_appliedForce;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const btVector3 & btMultiBody::getLinkTorque(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_appliedTorque;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar btMultiBody::getJointTorque(int i) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return m_links[i].m_jointTorque[0];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar * btMultiBody::getJointTorqueMultiDof(int i)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return &m_links[i].m_jointTorque[0];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline btMatrix3x3 outerProduct(const btVector3& v0, const btVector3& v1)				//renamed it from vecMulVecTranspose (http://en.wikipedia.org/wiki/Outer_product); maybe it should be moved to btVector3 like dot and cross?
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
										btVector3 row0 = btVector3( 
							 | 
						||
| 
								 | 
							
											v0.x() * v1.x(),
							 | 
						||
| 
								 | 
							
											v0.x() * v1.y(),
							 | 
						||
| 
								 | 
							
											v0.x() * v1.z());
							 | 
						||
| 
								 | 
							
										btVector3 row1 = btVector3( 
							 | 
						||
| 
								 | 
							
											v0.y() * v1.x(),
							 | 
						||
| 
								 | 
							
											v0.y() * v1.y(),
							 | 
						||
| 
								 | 
							
											v0.y() * v1.z());
							 | 
						||
| 
								 | 
							
										btVector3 row2 = btVector3( 
							 | 
						||
| 
								 | 
							
											v0.z() * v1.x(),
							 | 
						||
| 
								 | 
							
											v0.z() * v1.y(),
							 | 
						||
| 
								 | 
							
											v0.z() * v1.z());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        btMatrix3x3 m(row0[0],row0[1],row0[2],
							 | 
						||
| 
								 | 
							
														row1[0],row1[1],row1[2],
							 | 
						||
| 
								 | 
							
														row2[0],row2[1],row2[2]);
							 | 
						||
| 
								 | 
							
										return m;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define vecMulVecTranspose(v0, v1Transposed) outerProduct(v0, v1Transposed)
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
							 | 
						||
| 
								 | 
							
								                               btAlignedObjectArray<btScalar> &scratch_r,
							 | 
						||
| 
								 | 
							
								                               btAlignedObjectArray<btVector3> &scratch_v,
							 | 
						||
| 
								 | 
							
								                               btAlignedObjectArray<btMatrix3x3> &scratch_m,
							 | 
						||
| 
								 | 
							
												bool isConstraintPass)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot)
							 | 
						||
| 
								 | 
							
								    // and the base linear & angular accelerations.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // We apply damping forces in this routine as well as any external forces specified by the 
							 | 
						||
| 
								 | 
							
								    // caller (via addBaseForce etc).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // output should point to an array of 6 + num_links reals.
							 | 
						||
| 
								 | 
							
								    // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame),
							 | 
						||
| 
								 | 
							
								    // num_links joint acceleration values.
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
									// We added support for multi degree of freedom (multi dof) joints.
							 | 
						||
| 
								 | 
							
									// In addition we also can compute the joint reaction forces. This is performed in a second pass,
							 | 
						||
| 
								 | 
							
									// so that we can include the effect of the constraint solver forces (computed in the PGS LCP solver)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_internalNeedsJointFeedback = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const btScalar DAMPING_K1_LINEAR = m_linearDamping;
							 | 
						||
| 
								 | 
							
									const btScalar DAMPING_K2_LINEAR = m_linearDamping;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const btScalar DAMPING_K1_ANGULAR = m_angularDamping;
							 | 
						||
| 
								 | 
							
									const btScalar DAMPING_K2_ANGULAR= m_angularDamping;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btVector3 base_vel = getBaseVel();
							 | 
						||
| 
								 | 
							
								    btVector3 base_omega = getBaseOmega();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Temporary matrices/vectors -- use scratch space from caller
							 | 
						||
| 
								 | 
							
								    // so that we don't have to keep reallocating every frame
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    scratch_r.resize(2*m_dofCount + 6);				//multidof? ("Y"s use it and it is used to store qdd) => 2 x m_dofCount
							 | 
						||
| 
								 | 
							
								    scratch_v.resize(8*num_links + 6);
							 | 
						||
| 
								 | 
							
								    scratch_m.resize(4*num_links + 4);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//btScalar * r_ptr = &scratch_r[0];
							 | 
						||
| 
								 | 
							
								    btScalar * output = &scratch_r[m_dofCount];  // "output" holds the q_double_dot results
							 | 
						||
| 
								 | 
							
								    btVector3 * v_ptr = &scratch_v[0];
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    // vhat_i  (top = angular, bottom = linear part)	
							 | 
						||
| 
								 | 
							
									btSpatialMotionVector *spatVel = (btSpatialMotionVector *)v_ptr;
							 | 
						||
| 
								 | 
							
									v_ptr += num_links * 2 + 2;
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
								    // zhat_i^A    
							 | 
						||
| 
								 | 
							
									btSpatialForceVector * zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
							 | 
						||
| 
								 | 
							
									v_ptr += num_links * 2 + 2;
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
								    // chat_i  (note NOT defined for the base)    
							 | 
						||
| 
								 | 
							
									btSpatialMotionVector * spatCoriolisAcc = (btSpatialMotionVector *)v_ptr;
							 | 
						||
| 
								 | 
							
									v_ptr += num_links * 2;
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
								    // Ihat_i^A.    
							 | 
						||
| 
								 | 
							
									btSymmetricSpatialDyad * spatInertia = (btSymmetricSpatialDyad *)&scratch_m[num_links + 1];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Cached 3x3 rotation matrices from parent frame to this frame.
							 | 
						||
| 
								 | 
							
								    btMatrix3x3 * rot_from_parent = &m_matrixBuf[0];
							 | 
						||
| 
								 | 
							
								    btMatrix3x3 * rot_from_world = &scratch_m[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // hhat_i, ahat_i
							 | 
						||
| 
								 | 
							
								    // hhat is NOT stored for the base (but ahat is)    
							 | 
						||
| 
								 | 
							
									btSpatialForceVector * h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
							 | 
						||
| 
								 | 
							
									btSpatialMotionVector * spatAcc = (btSpatialMotionVector *)v_ptr;
							 | 
						||
| 
								 | 
							
									v_ptr += num_links * 2 + 2;
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
								    // Y_i, invD_i
							 | 
						||
| 
								 | 
							
								    btScalar * invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
							 | 
						||
| 
								 | 
							
									btScalar * Y = &scratch_r[0];
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									//aux variables	
							 | 
						||
| 
								 | 
							
									btSpatialMotionVector spatJointVel;					//spatial velocity due to the joint motion (i.e. without predecessors' influence)
							 | 
						||
| 
								 | 
							
									btScalar D[36];										//"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do	
							 | 
						||
| 
								 | 
							
									btScalar invD_times_Y[6];							//D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies	
							 | 
						||
| 
								 | 
							
									btSpatialMotionVector result;							//holds results of the SolveImatrix op; it is a spatial motion vector (accel)
							 | 
						||
| 
								 | 
							
									btScalar Y_minus_hT_a[6];							//Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough	
							 | 
						||
| 
								 | 
							
									btSpatialForceVector spatForceVecTemps[6];				//6 temporary spatial force vectors
							 | 
						||
| 
								 | 
							
									btSpatialTransformationMatrix fromParent;				//spatial transform from parent to child
							 | 
						||
| 
								 | 
							
									btSymmetricSpatialDyad dyadTemp;						//inertia matrix temp
							 | 
						||
| 
								 | 
							
									btSpatialTransformationMatrix fromWorld;
							 | 
						||
| 
								 | 
							
									fromWorld.m_trnVec.setZero();
							 | 
						||
| 
								 | 
							
									/////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // ptr to the joint accel part of the output
							 | 
						||
| 
								 | 
							
								    btScalar * joint_accel = output + 6;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Start of the algorithm proper.
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    // First 'upward' loop.
							 | 
						||
| 
								 | 
							
								    // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rot_from_parent[0] = btMatrix3x3(m_baseQuat);				//m_baseQuat assumed to be alias!?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//create the vector of spatial velocity of the base by transforming global-coor linear and angular velocities into base-local coordinates
							 | 
						||
| 
								 | 
							
									spatVel[0].setVector(rot_from_parent[0] * base_omega, rot_from_parent[0] * base_vel);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (m_fixedBase) 
							 | 
						||
| 
								 | 
							
									{        
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[0].setZero();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
									else 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btVector3 baseForce = isConstraintPass? m_baseConstraintForce : m_baseForce;
							 | 
						||
| 
								 | 
							
										btVector3 baseTorque = isConstraintPass? m_baseConstraintTorque : m_baseTorque;
							 | 
						||
| 
								 | 
							
										//external forces		
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[0].setVector(-(rot_from_parent[0] * baseTorque), -(rot_from_parent[0] * baseForce));	
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//adding damping terms (only)
							 | 
						||
| 
								 | 
							
										btScalar linDampMult = 1., angDampMult = 1.;
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().safeNorm()),
							 | 
						||
| 
								 | 
							
																   linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm()));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										//p += vhat x Ihat vhat - done in a simpler way
							 | 
						||
| 
								 | 
							
										if (m_useGyroTerm)
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[0].addAngular(spatVel[0].getAngular().cross(m_baseInertia * spatVel[0].getAngular()));
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[0].addLinear(m_baseMass * spatVel[0].getAngular().cross(spatVel[0].getLinear()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
							 | 
						||
| 
								 | 
							
									spatInertia[0].setMatrix(	btMatrix3x3(0,0,0,0,0,0,0,0,0),
							 | 
						||
| 
								 | 
							
																//
							 | 
						||
| 
								 | 
							
																btMatrix3x3(m_baseMass, 0, 0,
							 | 
						||
| 
								 | 
							
																			0, m_baseMass, 0,
							 | 
						||
| 
								 | 
							
																			0, 0, m_baseMass),
							 | 
						||
| 
								 | 
							
																//
							 | 
						||
| 
								 | 
							
																btMatrix3x3(m_baseInertia[0], 0, 0,
							 | 
						||
| 
								 | 
							
																			0, m_baseInertia[1], 0,
							 | 
						||
| 
								 | 
							
																			0, 0, m_baseInertia[2])
							 | 
						||
| 
								 | 
							
															);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rot_from_world[0] = rot_from_parent[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i) {		
							 | 
						||
| 
								 | 
							
								        const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
								        rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
							 | 
						||
| 
								 | 
							
								        rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
										fromWorld.m_rotMat = rot_from_world[i+1];
							 | 
						||
| 
								 | 
							
										fromParent.transform(spatVel[parent+1], spatVel[i+1]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// now set vhat_i to its true value by doing
							 | 
						||
| 
								 | 
							
								        // vhat_i += qidot * shat_i			
							 | 
						||
| 
								 | 
							
										if(!m_useGlobalVelocities)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											spatJointVel.setZero();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)		
							 | 
						||
| 
								 | 
							
												spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// remember vhat_i is really vhat_p(i) (but in current frame) at this point	=> we need to add velocity across the inboard joint
							 | 
						||
| 
								 | 
							
											spatVel[i+1] += spatJointVel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											// vhat_i is vhat_p(i) transformed to local coors + the velocity across the i-th inboard joint
							 | 
						||
| 
								 | 
							
											//spatVel[i+1] = fromParent * spatVel[parent+1] + spatJointVel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											fromWorld.transformRotationOnly(m_links[i].m_absFrameTotVelocity, spatVel[i+1]);
							 | 
						||
| 
								 | 
							
											fromWorld.transformRotationOnly(m_links[i].m_absFrameLocVelocity, spatJointVel);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// we can now calculate chat_i 		
							 | 
						||
| 
								 | 
							
										spatVel[i+1].cross(spatJointVel, spatCoriolisAcc[i]);		
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // calculate zhat_i^A
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										//external forces		
							 | 
						||
| 
								 | 
							
										btVector3 linkAppliedForce = isConstraintPass? m_links[i].m_appliedConstraintForce : m_links[i].m_appliedForce;
							 | 
						||
| 
								 | 
							
										btVector3 linkAppliedTorque =isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque;
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[i+1].setVector(-(rot_from_world[i+1] * linkAppliedTorque), -(rot_from_world[i+1] * linkAppliedForce ));
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								#if 0	
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											b3Printf("stepVelocitiesMultiDof zeroAccSpatFrc[%d] linear:%f,%f,%f, angular:%f,%f,%f",
							 | 
						||
| 
								 | 
							
											i+1,
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[i+1].m_topVec[0],
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[i+1].m_topVec[1],
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[i+1].m_topVec[2],
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[i+1].m_bottomVec[0],
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[i+1].m_bottomVec[1],
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[i+1].m_bottomVec[2]);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										//adding damping terms (only)
							 | 
						||
| 
								 | 
							
										btScalar linDampMult = 1., angDampMult = 1.;
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[i+1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i+1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i+1].getAngular().safeNorm()),
							 | 
						||
| 
								 | 
							
																	 linDampMult * m_links[i].m_mass * spatVel[i+1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i+1].getLinear().safeNorm()));
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
								        // calculate Ihat_i^A
							 | 
						||
| 
								 | 
							
										//init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
							 | 
						||
| 
								 | 
							
										spatInertia[i+1].setMatrix(	btMatrix3x3(0,0,0,0,0,0,0,0,0),
							 | 
						||
| 
								 | 
							
																	//
							 | 
						||
| 
								 | 
							
																	btMatrix3x3(m_links[i].m_mass, 0, 0,
							 | 
						||
| 
								 | 
							
																				0, m_links[i].m_mass, 0,
							 | 
						||
| 
								 | 
							
																				0, 0, m_links[i].m_mass),
							 | 
						||
| 
								 | 
							
																	//
							 | 
						||
| 
								 | 
							
																	btMatrix3x3(m_links[i].m_inertiaLocal[0], 0, 0,
							 | 
						||
| 
								 | 
							
																				0, m_links[i].m_inertiaLocal[1], 0,
							 | 
						||
| 
								 | 
							
																				0, 0, m_links[i].m_inertiaLocal[2])
							 | 
						||
| 
								 | 
							
																);
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										//p += vhat x Ihat vhat - done in a simpler way
							 | 
						||
| 
								 | 
							
										if(m_useGyroTerm)
							 | 
						||
| 
								 | 
							
											zeroAccSpatFrc[i+1].addAngular(spatVel[i+1].getAngular().cross(m_links[i].m_inertiaLocal * spatVel[i+1].getAngular()));			
							 | 
						||
| 
								 | 
							
										//		
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[i+1].addLinear(m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear()));
							 | 
						||
| 
								 | 
							
										//btVector3 temp = m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear());
							 | 
						||
| 
								 | 
							
										////clamp parent's omega
							 | 
						||
| 
								 | 
							
										//btScalar parOmegaMod = temp.length();
							 | 
						||
| 
								 | 
							
										//btScalar parOmegaModMax = 1000;
							 | 
						||
| 
								 | 
							
										//if(parOmegaMod > parOmegaModMax)
							 | 
						||
| 
								 | 
							
										//	temp *= parOmegaModMax / parOmegaMod;
							 | 
						||
| 
								 | 
							
										//zeroAccSpatFrc[i+1].addLinear(temp);
							 | 
						||
| 
								 | 
							
										//printf("|zeroAccSpatFrc[%d]| = %.4f\n", i+1, temp.length());
							 | 
						||
| 
								 | 
							
										//temp = spatCoriolisAcc[i].getLinear();
							 | 
						||
| 
								 | 
							
										//printf("|spatCoriolisAcc[%d]| = %.4f\n", i+1, temp.length());
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//printf("w[%d] = [%.4f %.4f %.4f]\n", i, vel_top_angular[i+1].x(), vel_top_angular[i+1].y(), vel_top_angular[i+1].z());
							 | 
						||
| 
								 | 
							
										//printf("v[%d] = [%.4f %.4f %.4f]\n", i, vel_bottom_linear[i+1].x(), vel_bottom_linear[i+1].y(), vel_bottom_linear[i+1].z());		
							 | 
						||
| 
								 | 
							
										//printf("c[%d] = [%.4f %.4f %.4f]\n", i, coriolis_bottom_linear[i].x(), coriolis_bottom_linear[i].y(), coriolis_bottom_linear[i].z());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								    // 'Downward' loop.
							 | 
						||
| 
								 | 
							
								    // (part of TreeForwardDynamics in Mirtich.)
							 | 
						||
| 
								 | 
							
								    for (int i = num_links - 1; i >= 0; --i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
										fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											hDof = spatInertia[i+1] * m_links[i].m_axes[dof];
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											Y[m_links[i].m_dofOffset + dof] = m_links[i].m_jointTorque[dof]
							 | 
						||
| 
								 | 
							
											- m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i+1])
							 | 
						||
| 
								 | 
							
											- spatCoriolisAcc[i].dot(hDof)
							 | 
						||
| 
								 | 
							
											;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btScalar *D_row = &D[dof * m_links[i].m_dofCount];			
							 | 
						||
| 
								 | 
							
											for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
							 | 
						||
| 
								 | 
							
												D_row[dof2] = m_links[i].m_axes[dof].dot(hDof2);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
							 | 
						||
| 
								 | 
							
										switch(m_links[i].m_jointType)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::ePrismatic:
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::eRevolute:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												invDi[0] = 1.0f / D[0];
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::eSpherical:
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::ePlanar:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btMatrix3x3 D3x3; D3x3.setValue(D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8]);
							 | 
						||
| 
								 | 
							
												btMatrix3x3 invD3x3; invD3x3 = D3x3.inverse();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												//unroll the loop?
							 | 
						||
| 
								 | 
							
												for(int row = 0; row < 3; ++row)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													for(int col = 0; col < 3; ++col)
							 | 
						||
| 
								 | 
							
													{						
							 | 
						||
| 
								 | 
							
														invDi[row * 3 + col] = invD3x3[row][col];
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//determine h*D^{-1}
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											spatForceVecTemps[dof].setZero();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
							 | 
						||
| 
								 | 
							
											{				
							 | 
						||
| 
								 | 
							
												btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
							 | 
						||
| 
								 | 
							
												//				
							 | 
						||
| 
								 | 
							
												spatForceVecTemps[dof] += hDof2 * invDi[dof2 * m_links[i].m_dofCount + dof];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										dyadTemp = spatInertia[i+1];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//determine (h*D^{-1}) * h^{T}
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{			
							 | 
						||
| 
								 | 
							
											btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											dyadTemp -= symmetricSpatialOuterProduct(hDof, spatForceVecTemps[dof]);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										fromParent.transformInverse(dyadTemp, spatInertia[parent+1], btSpatialTransformationMatrix::Add);
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											invD_times_Y[dof] = 0.f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];				
							 | 
						||
| 
								 | 
							
											}	
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										spatForceVecTemps[0] = zeroAccSpatFrc[i+1] + spatInertia[i+1] * spatCoriolisAcc[i];		
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{				
							 | 
						||
| 
								 | 
							
											btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											spatForceVecTemps[0] += hDof * invD_times_Y[dof];			
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[parent+1] += spatForceVecTemps[1];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Second 'upward' loop
							 | 
						||
| 
								 | 
							
								    // (part of TreeForwardDynamics in Mirtich)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (m_fixedBase) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        spatAcc[0].setZero();
							 | 
						||
| 
								 | 
							
								    } 
							 | 
						||
| 
								 | 
							
									else 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        if (num_links > 0) 
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											m_cachedInertiaValid = true;
							 | 
						||
| 
								 | 
							
											m_cachedInertiaTopLeft = spatInertia[0].m_topLeftMat;
							 | 
						||
| 
								 | 
							
											m_cachedInertiaTopRight = spatInertia[0].m_topRightMat;
							 | 
						||
| 
								 | 
							
											m_cachedInertiaLowerLeft = spatInertia[0].m_bottomLeftMat;
							 | 
						||
| 
								 | 
							
											m_cachedInertiaLowerRight= spatInertia[0].m_topLeftMat.transpose();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        }		
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										solveImatrix(zeroAccSpatFrc[0], result);
							 | 
						||
| 
								 | 
							
										spatAcc[0] = -result;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								    // now do the loop over the m_links
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										//	qdd = D^{-1} * (Y - h^{T}*apar) = (S^{T}*I*S)^{-1} * (tau - S^{T}*I*cor - S^{T}*zeroAccFrc - S^{T}*I*apar)
							 | 
						||
| 
								 | 
							
										//	a = apar + cor + Sqdd
							 | 
						||
| 
								 | 
							
										//or
							 | 
						||
| 
								 | 
							
										//	qdd = D^{-1} * (Y - h^{T}*(apar+cor))
							 | 
						||
| 
								 | 
							
										//	a = apar + Sqdd
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
										fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										fromParent.transform(spatAcc[parent+1], spatAcc[i+1]);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
											//			
							 | 
						||
| 
								 | 
							
											Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i+1].dot(hDof);			
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
							 | 
						||
| 
								 | 
							
										//D^{-1} * (Y - h^{T}*apar)
							 | 
						||
| 
								 | 
							
										mulMatrix(invDi, Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										spatAcc[i+1] += spatCoriolisAcc[i];		
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)		
							 | 
						||
| 
								 | 
							
											spatAcc[i+1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (m_links[i].m_jointFeedback)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											m_internalNeedsJointFeedback = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											btVector3 angularBotVec = (spatInertia[i+1]*spatAcc[i+1]+zeroAccSpatFrc[i+1]).m_bottomVec;
							 | 
						||
| 
								 | 
							
											btVector3 linearTopVec = (spatInertia[i+1]*spatAcc[i+1]+zeroAccSpatFrc[i+1]).m_topVec;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (gJointFeedbackInJointFrame)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												//shift the reaction forces to the joint frame
							 | 
						||
| 
								 | 
							
												//linear (force) component is the same
							 | 
						||
| 
								 | 
							
												//shift the angular (torque, moment) component using the relative position,  m_links[i].m_dVector
							 | 
						||
| 
								 | 
							
												 angularBotVec = angularBotVec - linearTopVec.cross(m_links[i].m_dVector);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (gJointFeedbackInWorldSpace)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (isConstraintPass)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
								 m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += m_links[i].m_cachedWorldTransform.getBasis()*angularBotVec;
							 | 
						||
| 
								 | 
							
								                                        m_links[i].m_jointFeedback->m_reactionForces.m_topVec += m_links[i].m_cachedWorldTransform.getBasis()*linearTopVec;
							 | 
						||
| 
								 | 
							
												} else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = m_links[i].m_cachedWorldTransform.getBasis()*angularBotVec;
							 | 
						||
| 
								 | 
							
													m_links[i].m_jointFeedback->m_reactionForces.m_topVec = m_links[i].m_cachedWorldTransform.getBasis()*linearTopVec;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											} else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (isConstraintPass)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													  m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += angularBotVec;                        
							 | 
						||
| 
								 | 
							
								                                m_links[i].m_jointFeedback->m_reactionForces.m_topVec += linearTopVec;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
												m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = angularBotVec;
							 | 
						||
| 
								 | 
							
												m_links[i].m_jointFeedback->m_reactionForces.m_topVec = linearTopVec;
							 | 
						||
| 
								 | 
							
												}		
							 | 
						||
| 
								 | 
							
											}	
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // transform base accelerations back to the world frame.
							 | 
						||
| 
								 | 
							
								    btVector3 omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
							 | 
						||
| 
								 | 
							
									output[0] = omegadot_out[0];
							 | 
						||
| 
								 | 
							
									output[1] = omegadot_out[1];
							 | 
						||
| 
								 | 
							
									output[2] = omegadot_out[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btVector3 vdot_out = rot_from_parent[0].transpose() * (spatAcc[0].getLinear() + spatVel[0].getAngular().cross(spatVel[0].getLinear()));
							 | 
						||
| 
								 | 
							
									output[3] = vdot_out[0];
							 | 
						||
| 
								 | 
							
									output[4] = vdot_out[1];
							 | 
						||
| 
								 | 
							
									output[5] = vdot_out[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/////////////////
							 | 
						||
| 
								 | 
							
									//printf("q = [");
							 | 
						||
| 
								 | 
							
									//printf("%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f ", m_baseQuat.x(), m_baseQuat.y(), m_baseQuat.z(), m_baseQuat.w(), m_basePos.x(), m_basePos.y(), m_basePos.z());
							 | 
						||
| 
								 | 
							
									//for(int link = 0; link < getNumLinks(); ++link)
							 | 
						||
| 
								 | 
							
									//	for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
									//		printf("%.6f ", m_links[link].m_jointPos[dof]);
							 | 
						||
| 
								 | 
							
									//printf("]\n");
							 | 
						||
| 
								 | 
							
									////
							 | 
						||
| 
								 | 
							
									//printf("qd = [");
							 | 
						||
| 
								 | 
							
									//for(int dof = 0; dof < getNumDofs() + 6; ++dof)
							 | 
						||
| 
								 | 
							
									//	printf("%.6f ", m_realBuf[dof]);
							 | 
						||
| 
								 | 
							
									//printf("]\n");
							 | 
						||
| 
								 | 
							
									//printf("qdd = [");
							 | 
						||
| 
								 | 
							
									//for(int dof = 0; dof < getNumDofs() + 6; ++dof)
							 | 
						||
| 
								 | 
							
									//	printf("%.6f ", output[dof]);
							 | 
						||
| 
								 | 
							
									//printf("]\n");
							 | 
						||
| 
								 | 
							
									/////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Final step: add the accelerations (times dt) to the velocities.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!isConstraintPass)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									if(dt > 0.)
							 | 
						||
| 
								 | 
							
										applyDeltaVeeMultiDof(output, dt);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									/////
							 | 
						||
| 
								 | 
							
									//btScalar angularThres = 1;
							 | 
						||
| 
								 | 
							
									//btScalar maxAngVel = 0.;		
							 | 
						||
| 
								 | 
							
									//bool scaleDown = 1.;
							 | 
						||
| 
								 | 
							
									//for(int link = 0; link < m_links.size(); ++link)
							 | 
						||
| 
								 | 
							
									//{		
							 | 
						||
| 
								 | 
							
									//	if(spatVel[link+1].getAngular().length() > maxAngVel)
							 | 
						||
| 
								 | 
							
									//	{
							 | 
						||
| 
								 | 
							
									//		maxAngVel = spatVel[link+1].getAngular().length();
							 | 
						||
| 
								 | 
							
									//		scaleDown = angularThres / spatVel[link+1].getAngular().length();
							 | 
						||
| 
								 | 
							
									//		break;
							 | 
						||
| 
								 | 
							
									//	}		
							 | 
						||
| 
								 | 
							
									//}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//if(scaleDown != 1.)
							 | 
						||
| 
								 | 
							
									//{
							 | 
						||
| 
								 | 
							
									//	for(int link = 0; link < m_links.size(); ++link)
							 | 
						||
| 
								 | 
							
									//	{
							 | 
						||
| 
								 | 
							
									//		if(m_links[link].m_jointType == btMultibodyLink::eRevolute || m_links[link].m_jointType == btMultibodyLink::eSpherical)
							 | 
						||
| 
								 | 
							
									//		{
							 | 
						||
| 
								 | 
							
									//			for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
									//				getJointVelMultiDof(link)[dof] *= scaleDown;
							 | 
						||
| 
								 | 
							
									//		}
							 | 
						||
| 
								 | 
							
									//	}
							 | 
						||
| 
								 | 
							
									//}
							 | 
						||
| 
								 | 
							
									/////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/////////////////////
							 | 
						||
| 
								 | 
							
									if(m_useGlobalVelocities)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < num_links; ++i) 
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
											//rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);    /// <- done
							 | 
						||
| 
								 | 
							
											//rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1];		/// <- done
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
											fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
											fromWorld.m_rotMat = rot_from_world[i+1];			
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
											// vhat_i = i_xhat_p(i) * vhat_p(i)		
							 | 
						||
| 
								 | 
							
											fromParent.transform(spatVel[parent+1], spatVel[i+1]);
							 | 
						||
| 
								 | 
							
											//nice alternative below (using operator *) but it generates temps
							 | 
						||
| 
								 | 
							
											/////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// now set vhat_i to its true value by doing
							 | 
						||
| 
								 | 
							
											// vhat_i += qidot * shat_i			
							 | 
						||
| 
								 | 
							
											spatJointVel.setZero();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)		
							 | 
						||
| 
								 | 
							
												spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
											// remember vhat_i is really vhat_p(i) (but in current frame) at this point	=> we need to add velocity across the inboard joint
							 | 
						||
| 
								 | 
							
											spatVel[i+1] += spatJointVel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											fromWorld.transformInverseRotationOnly(spatVel[i+1], m_links[i].m_absFrameTotVelocity);
							 | 
						||
| 
								 | 
							
											fromWorld.transformInverseRotationOnly(spatJointVel, m_links[i].m_absFrameLocVelocity);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, btScalar result[6]) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
									///solve I * x = rhs, so the result = invI * rhs
							 | 
						||
| 
								 | 
							
								    if (num_links == 0) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										// in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
							 | 
						||
| 
								 | 
							
								        result[0] = rhs_bot[0] / m_baseInertia[0];
							 | 
						||
| 
								 | 
							
								        result[1] = rhs_bot[1] / m_baseInertia[1];
							 | 
						||
| 
								 | 
							
								        result[2] = rhs_bot[2] / m_baseInertia[2];
							 | 
						||
| 
								 | 
							
								        result[3] = rhs_top[0] / m_baseMass;
							 | 
						||
| 
								 | 
							
								        result[4] = rhs_top[1] / m_baseMass;
							 | 
						||
| 
								 | 
							
								        result[5] = rhs_top[2] / m_baseMass;
							 | 
						||
| 
								 | 
							
								    } else 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (!m_cachedInertiaValid)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for (int i=0;i<6;i++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												result[i] = 0.f;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										/// Special routine for calculating the inverse of a spatial inertia matrix
							 | 
						||
| 
								 | 
							
										///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
							 | 
						||
| 
								 | 
							
										btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
							 | 
						||
| 
								 | 
							
										tmp = invIupper_right * m_cachedInertiaLowerRight;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invI_upper_left = (tmp * Binv);
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
							 | 
						||
| 
								 | 
							
										tmp = m_cachedInertiaTopLeft  * invI_upper_left;
							 | 
						||
| 
								 | 
							
										tmp[0][0]-= 1.0;
							 | 
						||
| 
								 | 
							
										tmp[1][1]-= 1.0;
							 | 
						||
| 
								 | 
							
										tmp[2][2]-= 1.0;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invI_lower_left = (Binv * tmp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//multiply result = invI * rhs
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										  btVector3 vtop = invI_upper_left*rhs_top;
							 | 
						||
| 
								 | 
							
										  btVector3 tmp;
							 | 
						||
| 
								 | 
							
										  tmp = invIupper_right * rhs_bot;
							 | 
						||
| 
								 | 
							
										  vtop += tmp;
							 | 
						||
| 
								 | 
							
										  btVector3 vbot = invI_lower_left*rhs_top;
							 | 
						||
| 
								 | 
							
										  tmp = invI_lower_right * rhs_bot;
							 | 
						||
| 
								 | 
							
										  vbot += tmp;
							 | 
						||
| 
								 | 
							
										  result[0] = vtop[0];
							 | 
						||
| 
								 | 
							
										  result[1] = vtop[1];
							 | 
						||
| 
								 | 
							
										  result[2] = vtop[2];
							 | 
						||
| 
								 | 
							
										  result[3] = vbot[0];
							 | 
						||
| 
								 | 
							
										  result[4] = vbot[1];
							 | 
						||
| 
								 | 
							
										  result[5] = vbot[2];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								void btMultiBody::solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
									///solve I * x = rhs, so the result = invI * rhs
							 | 
						||
| 
								 | 
							
								    if (num_links == 0) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										// in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
							 | 
						||
| 
								 | 
							
										result.setAngular(rhs.getAngular() / m_baseInertia);
							 | 
						||
| 
								 | 
							
										result.setLinear(rhs.getLinear() / m_baseMass);		
							 | 
						||
| 
								 | 
							
								    } else 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/// Special routine for calculating the inverse of a spatial inertia matrix
							 | 
						||
| 
								 | 
							
										///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
							 | 
						||
| 
								 | 
							
										if (!m_cachedInertiaValid)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											result.setLinear(btVector3(0,0,0));
							 | 
						||
| 
								 | 
							
											result.setAngular(btVector3(0,0,0));
							 | 
						||
| 
								 | 
							
											result.setVector(btVector3(0,0,0),btVector3(0,0,0));
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse()*-1.f;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
							 | 
						||
| 
								 | 
							
										tmp = invIupper_right * m_cachedInertiaLowerRight;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invI_upper_left = (tmp * Binv);
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
							 | 
						||
| 
								 | 
							
										tmp = m_cachedInertiaTopLeft  * invI_upper_left;
							 | 
						||
| 
								 | 
							
										tmp[0][0]-= 1.0;
							 | 
						||
| 
								 | 
							
										tmp[1][1]-= 1.0;
							 | 
						||
| 
								 | 
							
										tmp[2][2]-= 1.0;
							 | 
						||
| 
								 | 
							
										btMatrix3x3 invI_lower_left = (Binv * tmp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//multiply result = invI * rhs
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										  btVector3 vtop = invI_upper_left*rhs.getLinear();
							 | 
						||
| 
								 | 
							
										  btVector3 tmp;
							 | 
						||
| 
								 | 
							
										  tmp = invIupper_right * rhs.getAngular();
							 | 
						||
| 
								 | 
							
										  vtop += tmp;
							 | 
						||
| 
								 | 
							
										  btVector3 vbot = invI_lower_left*rhs.getLinear();
							 | 
						||
| 
								 | 
							
										  tmp = invI_lower_right * rhs.getAngular();
							 | 
						||
| 
								 | 
							
										  vbot += tmp;
							 | 
						||
| 
								 | 
							
										  result.setVector(vtop, vbot);		  
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for (int row = 0; row < rowsA; row++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (int col = 0; col < colsB; col++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											pC[row * colsB + col] = 0.f;
							 | 
						||
| 
								 | 
							
											for (int inner = 0; inner < rowsB; inner++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												pC[row * colsB + col] += pA[row * colsA + inner] * pB[col + inner * colsB];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
							 | 
						||
| 
								 | 
							
								                                       btAlignedObjectArray<btScalar> &scratch_r, btAlignedObjectArray<btVector3> &scratch_v) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // Temporary matrices/vectors -- use scratch space from caller
							 | 
						||
| 
								 | 
							
								    // so that we don't have to keep reallocating every frame
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();	
							 | 
						||
| 
								 | 
							
								    scratch_r.resize(m_dofCount);
							 | 
						||
| 
								 | 
							
								    scratch_v.resize(4*num_links + 4);	    
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btScalar * r_ptr = m_dofCount ? &scratch_r[0] : 0;
							 | 
						||
| 
								 | 
							
								    btVector3 * v_ptr = &scratch_v[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // zhat_i^A (scratch space)
							 | 
						||
| 
								 | 
							
								    btSpatialForceVector * zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
							 | 
						||
| 
								 | 
							
									v_ptr += num_links * 2 + 2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // rot_from_parent (cached from calcAccelerations)
							 | 
						||
| 
								 | 
							
								    const btMatrix3x3 * rot_from_parent = &m_matrixBuf[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // hhat (cached), accel (scratch)
							 | 
						||
| 
								 | 
							
								    // hhat is NOT stored for the base (but ahat is) 
							 | 
						||
| 
								 | 
							
									const btSpatialForceVector * h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
							 | 
						||
| 
								 | 
							
									btSpatialMotionVector * spatAcc = (btSpatialMotionVector *)v_ptr;
							 | 
						||
| 
								 | 
							
									v_ptr += num_links * 2 + 2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Y_i (scratch), invD_i (cached)
							 | 
						||
| 
								 | 
							
								    const btScalar * invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
							 | 
						||
| 
								 | 
							
									btScalar * Y = r_ptr; 
							 | 
						||
| 
								 | 
							
									////////////////
							 | 
						||
| 
								 | 
							
									//aux variables
							 | 
						||
| 
								 | 
							
									btScalar invD_times_Y[6];							//D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
							 | 
						||
| 
								 | 
							
									btSpatialMotionVector result;							//holds results of the SolveImatrix op; it is a spatial motion vector (accel)
							 | 
						||
| 
								 | 
							
									btScalar Y_minus_hT_a[6];							//Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough	
							 | 
						||
| 
								 | 
							
									btSpatialForceVector spatForceVecTemps[6];				//6 temporary spatial force vectors
							 | 
						||
| 
								 | 
							
									btSpatialTransformationMatrix fromParent;	
							 | 
						||
| 
								 | 
							
									/////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // First 'upward' loop.
							 | 
						||
| 
								 | 
							
								    // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Fill in zero_acc
							 | 
						||
| 
								 | 
							
								    // -- set to force/torque on the base, zero otherwise
							 | 
						||
| 
								 | 
							
								    if (m_fixedBase) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        zeroAccSpatFrc[0].setZero();
							 | 
						||
| 
								 | 
							
								    } else 
							 | 
						||
| 
								 | 
							
									{	
							 | 
						||
| 
								 | 
							
										//test forces
							 | 
						||
| 
								 | 
							
										fromParent.m_rotMat = rot_from_parent[0];
							 | 
						||
| 
								 | 
							
										fromParent.transformRotationOnly(btSpatialForceVector(-force[0],-force[1],-force[2], -force[3],-force[4],-force[5]), zeroAccSpatFrc[0]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[i+1].setZero();
							 | 
						||
| 
								 | 
							
								    }    
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// 'Downward' loop.
							 | 
						||
| 
								 | 
							
								    // (part of TreeForwardDynamics in Mirtich.)
							 | 
						||
| 
								 | 
							
								    for (int i = num_links - 1; i >= 0; --i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
										fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											Y[m_links[i].m_dofOffset + dof] = force[6 + m_links[i].m_dofOffset + dof]
							 | 
						||
| 
								 | 
							
																			- m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i+1])
							 | 
						||
| 
								 | 
							
																			;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btVector3 in_top, in_bottom, out_top, out_bottom;
							 | 
						||
| 
								 | 
							
										const btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											invD_times_Y[dof] = 0.f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for(int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];				
							 | 
						||
| 
								 | 
							
											}	
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										 // Zp += pXi * (Zi + hi*Yi/Di)
							 | 
						||
| 
								 | 
							
										spatForceVecTemps[0] = zeroAccSpatFrc[i+1];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
											spatForceVecTemps[0] += hDof * invD_times_Y[dof];		
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
										zeroAccSpatFrc[parent+1] += spatForceVecTemps[1];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// ptr to the joint accel part of the output
							 | 
						||
| 
								 | 
							
								    btScalar * joint_accel = output + 6;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Second 'upward' loop
							 | 
						||
| 
								 | 
							
								    // (part of TreeForwardDynamics in Mirtich)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (m_fixedBase) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        spatAcc[0].setZero();
							 | 
						||
| 
								 | 
							
								    } 
							 | 
						||
| 
								 | 
							
									else 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										solveImatrix(zeroAccSpatFrc[0], result);
							 | 
						||
| 
								 | 
							
										spatAcc[0] = -result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								    // now do the loop over the m_links
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
										fromParent.m_rotMat = rot_from_parent[i+1]; fromParent.m_trnVec = m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										fromParent.transform(spatAcc[parent+1], spatAcc[i+1]);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
											//			
							 | 
						||
| 
								 | 
							
											Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i+1].dot(hDof);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const btScalar *invDi = &invD[m_links[i].m_dofOffset*m_links[i].m_dofOffset];
							 | 
						||
| 
								 | 
							
										mulMatrix(const_cast<btScalar*>(invDi), Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for(int dof = 0; dof < m_links[i].m_dofCount; ++dof)		
							 | 
						||
| 
								 | 
							
											spatAcc[i+1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];      
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // transform base accelerations back to the world frame.
							 | 
						||
| 
								 | 
							
								    btVector3 omegadot_out;
							 | 
						||
| 
								 | 
							
								    omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
							 | 
						||
| 
								 | 
							
									output[0] = omegadot_out[0];
							 | 
						||
| 
								 | 
							
									output[1] = omegadot_out[1];
							 | 
						||
| 
								 | 
							
									output[2] = omegadot_out[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btVector3 vdot_out;
							 | 
						||
| 
								 | 
							
								    vdot_out = rot_from_parent[0].transpose() * spatAcc[0].getLinear();
							 | 
						||
| 
								 | 
							
									output[3] = vdot_out[0];
							 | 
						||
| 
								 | 
							
									output[4] = vdot_out[1];
							 | 
						||
| 
								 | 
							
									output[5] = vdot_out[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/////////////////
							 | 
						||
| 
								 | 
							
									//printf("delta = [");
							 | 
						||
| 
								 | 
							
									//for(int dof = 0; dof < getNumDofs() + 6; ++dof)
							 | 
						||
| 
								 | 
							
									//	printf("%.2f ", output[dof]);
							 | 
						||
| 
								 | 
							
									//printf("]\n");
							 | 
						||
| 
								 | 
							
									/////////////////
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
							 | 
						||
| 
								 | 
							
								{	
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
								    // step position by adding dt * velocity
							 | 
						||
| 
								 | 
							
									//btVector3 v = getBaseVel();	
							 | 
						||
| 
								 | 
							
								    //m_basePos += dt * v;
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
							 | 
						||
| 
								 | 
							
									btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]);			//note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
							 | 
						||
| 
								 | 
							
									//	
							 | 
						||
| 
								 | 
							
									pBasePos[0] += dt * pBaseVel[0];
							 | 
						||
| 
								 | 
							
									pBasePos[1] += dt * pBaseVel[1];
							 | 
						||
| 
								 | 
							
									pBasePos[2] += dt * pBaseVel[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									///////////////////////////////
							 | 
						||
| 
								 | 
							
									//local functor for quaternion integration (to avoid error prone redundancy)
							 | 
						||
| 
								 | 
							
									struct
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										//"exponential map" based on btTransformUtil::integrateTransform(..)
							 | 
						||
| 
								 | 
							
										void operator() (const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											//baseBody	=>	quat is alias and omega is global coor
							 | 
						||
| 
								 | 
							
											//!baseBody	=>	quat is alibi and omega is local coor	
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											btVector3 axis;
							 | 
						||
| 
								 | 
							
											btVector3 angvel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if(!baseBody)			
							 | 
						||
| 
								 | 
							
												angvel = quatRotate(quat, omega);				//if quat is not m_baseQuat, it is alibi => ok			
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												angvel = omega;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
											btScalar fAngle = angvel.length(); 		
							 | 
						||
| 
								 | 
							
											//limit the angular motion
							 | 
						||
| 
								 | 
							
											if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												fAngle = btScalar(0.5)*SIMD_HALF_PI / dt;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( fAngle < btScalar(0.001) )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												// use Taylor's expansions of sync function
							 | 
						||
| 
								 | 
							
												axis   = angvel*( btScalar(0.5)*dt-(dt*dt*dt)*(btScalar(0.020833333333))*fAngle*fAngle );
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												// sync(fAngle) = sin(c*fAngle)/t
							 | 
						||
| 
								 | 
							
												axis   = angvel*( btSin(btScalar(0.5)*fAngle*dt)/fAngle );
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											if(!baseBody)				
							 | 
						||
| 
								 | 
							
												quat = btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat;			
							 | 
						||
| 
								 | 
							
											else			
							 | 
						||
| 
								 | 
							
												quat = quat * btQuaternion(-axis.x(),-axis.y(),-axis.z(),btCos( fAngle*dt*btScalar(0.5) ));
							 | 
						||
| 
								 | 
							
												//equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();			
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
											quat.normalize();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									} pQuatUpdateFun;
							 | 
						||
| 
								 | 
							
									///////////////////////////////
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
							 | 
						||
| 
								 | 
							
									//	
							 | 
						||
| 
								 | 
							
									btScalar *pBaseQuat = pq ? pq : m_baseQuat;	
							 | 
						||
| 
								 | 
							
									btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0];		//note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									btQuaternion baseQuat; baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
							 | 
						||
| 
								 | 
							
									btVector3 baseOmega; baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
							 | 
						||
| 
								 | 
							
									pQuatUpdateFun(baseOmega, baseQuat, true, dt);
							 | 
						||
| 
								 | 
							
									pBaseQuat[0] = baseQuat.x();
							 | 
						||
| 
								 | 
							
									pBaseQuat[1] = baseQuat.y();
							 | 
						||
| 
								 | 
							
									pBaseQuat[2] = baseQuat.z();
							 | 
						||
| 
								 | 
							
									pBaseQuat[3] = baseQuat.w();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//printf("pBaseOmega = %.4f %.4f %.4f\n", pBaseOmega->x(), pBaseOmega->y(), pBaseOmega->z());
							 | 
						||
| 
								 | 
							
									//printf("pBaseVel = %.4f %.4f %.4f\n", pBaseVel->x(), pBaseVel->y(), pBaseVel->z());
							 | 
						||
| 
								 | 
							
									//printf("baseQuat = %.4f %.4f %.4f %.4f\n", pBaseQuat->x(), pBaseQuat->y(), pBaseQuat->z(), pBaseQuat->w());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(pq)		
							 | 
						||
| 
								 | 
							
										pq += 7;
							 | 
						||
| 
								 | 
							
									if(pqd)
							 | 
						||
| 
								 | 
							
										pqd += 6;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Finally we can update m_jointPos for each of the m_links
							 | 
						||
| 
								 | 
							
								    for (int i = 0; i < num_links; ++i) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btScalar *pJointPos = (pq ? pq : &m_links[i].m_jointPos[0]);		
							 | 
						||
| 
								 | 
							
										btScalar *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										switch(m_links[i].m_jointType)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::ePrismatic:
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::eRevolute:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btScalar jointVel = pJointVel[0];	
							 | 
						||
| 
								 | 
							
												pJointPos[0] += dt * jointVel;
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::eSpherical:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btVector3 jointVel; jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
							 | 
						||
| 
								 | 
							
												btQuaternion jointOri; jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
							 | 
						||
| 
								 | 
							
												pQuatUpdateFun(jointVel, jointOri, false, dt);
							 | 
						||
| 
								 | 
							
												pJointPos[0] = jointOri.x(); pJointPos[1] = jointOri.y(); pJointPos[2] = jointOri.z(); pJointPos[3] = jointOri.w();
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											case btMultibodyLink::ePlanar:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												pJointPos[0] += dt * getJointVelMultiDof(i)[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
							 | 
						||
| 
								 | 
							
												btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
							 | 
						||
| 
								 | 
							
												pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
							 | 
						||
| 
								 | 
							
												pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										m_links[i].updateCacheMultiDof(pq);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if(pq)		
							 | 
						||
| 
								 | 
							
											pq += m_links[i].m_posVarCount;
							 | 
						||
| 
								 | 
							
										if(pqd)
							 | 
						||
| 
								 | 
							
											pqd += m_links[i].m_dofCount;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::fillConstraintJacobianMultiDof(int link,
							 | 
						||
| 
								 | 
							
								                                    const btVector3 &contact_point,
							 | 
						||
| 
								 | 
							
																	const btVector3 &normal_ang,
							 | 
						||
| 
								 | 
							
								                                    const btVector3 &normal_lin,
							 | 
						||
| 
								 | 
							
								                                    btScalar *jac,
							 | 
						||
| 
								 | 
							
								                                    btAlignedObjectArray<btScalar> &scratch_r,
							 | 
						||
| 
								 | 
							
								                                    btAlignedObjectArray<btVector3> &scratch_v,
							 | 
						||
| 
								 | 
							
								                                    btAlignedObjectArray<btMatrix3x3> &scratch_m) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // temporary space
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
									int m_dofCount = getNumDofs();
							 | 
						||
| 
								 | 
							
								    scratch_v.resize(3*num_links + 3);			//(num_links + base) offsets + (num_links + base) normals_lin + (num_links + base) normals_ang
							 | 
						||
| 
								 | 
							
								    scratch_m.resize(num_links + 1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btVector3 * v_ptr = &scratch_v[0];
							 | 
						||
| 
								 | 
							
								    btVector3 * p_minus_com_local = v_ptr; v_ptr += num_links + 1;
							 | 
						||
| 
								 | 
							
								    btVector3 * n_local_lin = v_ptr; v_ptr += num_links + 1;
							 | 
						||
| 
								 | 
							
									btVector3 * n_local_ang = v_ptr; v_ptr += num_links + 1;
							 | 
						||
| 
								 | 
							
								    btAssert(v_ptr - &scratch_v[0] == scratch_v.size());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    scratch_r.resize(m_dofCount);
							 | 
						||
| 
								 | 
							
								    btScalar * results = m_dofCount > 0 ? &scratch_r[0] : 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    btMatrix3x3 * rot_from_world = &scratch_m[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const btVector3 p_minus_com_world = contact_point - m_basePos;
							 | 
						||
| 
								 | 
							
									const btVector3 &normal_lin_world = normal_lin;							//convenience
							 | 
						||
| 
								 | 
							
									const btVector3 &normal_ang_world = normal_ang;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rot_from_world[0] = btMatrix3x3(m_baseQuat);    
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    // omega coeffients first.
							 | 
						||
| 
								 | 
							
								    btVector3 omega_coeffs_world;
							 | 
						||
| 
								 | 
							
								    omega_coeffs_world = p_minus_com_world.cross(normal_lin_world);
							 | 
						||
| 
								 | 
							
									jac[0] = omega_coeffs_world[0] + normal_ang_world[0];
							 | 
						||
| 
								 | 
							
									jac[1] = omega_coeffs_world[1] + normal_ang_world[1];
							 | 
						||
| 
								 | 
							
									jac[2] = omega_coeffs_world[2] + normal_ang_world[2];
							 | 
						||
| 
								 | 
							
								    // then v coefficients
							 | 
						||
| 
								 | 
							
								    jac[3] = normal_lin_world[0];
							 | 
						||
| 
								 | 
							
								    jac[4] = normal_lin_world[1];
							 | 
						||
| 
								 | 
							
								    jac[5] = normal_lin_world[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//create link-local versions of p_minus_com and normal
							 | 
						||
| 
								 | 
							
									p_minus_com_local[0] = rot_from_world[0] * p_minus_com_world;
							 | 
						||
| 
								 | 
							
								    n_local_lin[0] = rot_from_world[0] * normal_lin_world;
							 | 
						||
| 
								 | 
							
									n_local_ang[0] = rot_from_world[0] * normal_ang_world;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Set remaining jac values to zero for now.
							 | 
						||
| 
								 | 
							
								    for (int i = 6; i < 6 + m_dofCount; ++i) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        jac[i] = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Qdot coefficients, if necessary.
							 | 
						||
| 
								 | 
							
								    if (num_links > 0 && link > -1) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // TODO: speed this up -- don't calculate for m_links we don't need.
							 | 
						||
| 
								 | 
							
								        // (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions,
							 | 
						||
| 
								 | 
							
								        // which is resulting in repeated work being done...)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // calculate required normals & positions in the local frames.
							 | 
						||
| 
								 | 
							
								        for (int i = 0; i < num_links; ++i) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // transform to local frame
							 | 
						||
| 
								 | 
							
								            const int parent = m_links[i].m_parent;
							 | 
						||
| 
								 | 
							
								            const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis);
							 | 
						||
| 
								 | 
							
								            rot_from_world[i+1] = mtx * rot_from_world[parent+1];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            n_local_lin[i+1] = mtx * n_local_lin[parent+1];
							 | 
						||
| 
								 | 
							
											n_local_ang[i+1] = mtx * n_local_ang[parent+1];
							 | 
						||
| 
								 | 
							
								            p_minus_com_local[i+1] = mtx * p_minus_com_local[parent+1] - m_links[i].m_cachedRVector;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// calculate the jacobian entry
							 | 
						||
| 
								 | 
							
											switch(m_links[i].m_jointType)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												case btMultibodyLink::eRevolute:
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(0));
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset] += n_local_ang[i+1].dot(m_links[i].getAxisTop(0));
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												case btMultibodyLink::ePrismatic:
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(0));
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												case btMultibodyLink::eSpherical:
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 0] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(0));
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 1] = n_local_lin[i+1].dot(m_links[i].getAxisTop(1).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(1));
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 2] = n_local_lin[i+1].dot(m_links[i].getAxisTop(2).cross(p_minus_com_local[i+1]) + m_links[i].getAxisBottom(2));
							 | 
						||
| 
								 | 
							
																		
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 0] += n_local_ang[i+1].dot(m_links[i].getAxisTop(0));
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 1] += n_local_ang[i+1].dot(m_links[i].getAxisTop(1));
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 2] += n_local_ang[i+1].dot(m_links[i].getAxisTop(2));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												case btMultibodyLink::ePlanar:
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 0] = n_local_lin[i+1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i+1]));// + m_links[i].getAxisBottom(0));
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 1] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(1));
							 | 
						||
| 
								 | 
							
													results[m_links[i].m_dofOffset + 2] = n_local_lin[i+1].dot(m_links[i].getAxisBottom(2));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												default:
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Now copy through to output.
							 | 
						||
| 
								 | 
							
										//printf("jac[%d] = ", link);
							 | 
						||
| 
								 | 
							
								        while (link != -1) 
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												jac[6 + m_links[link].m_dofOffset + dof] = results[m_links[link].m_dofOffset + dof];
							 | 
						||
| 
								 | 
							
												//printf("%.2f\t", jac[6 + m_links[link].m_dofOffset + dof]);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
											link = m_links[link].m_parent;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
										//printf("]\n");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::wakeUp()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_awake = true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::goToSleep()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    m_awake = false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									extern bool gDisableDeactivation;
							 | 
						||
| 
								 | 
							
								    if (!m_canSleep || gDisableDeactivation) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										m_awake = true;
							 | 
						||
| 
								 | 
							
										m_sleepTimer = 0;
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
							 | 
						||
| 
								 | 
							
								    btScalar motion = 0;
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < 6 + m_dofCount; ++i) 		
							 | 
						||
| 
								 | 
							
											motion += m_realBuf[i] * m_realBuf[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (motion < SLEEP_EPSILON) {
							 | 
						||
| 
								 | 
							
								        m_sleepTimer += timestep;
							 | 
						||
| 
								 | 
							
								        if (m_sleepTimer > SLEEP_TIMEOUT) {
							 | 
						||
| 
								 | 
							
								            goToSleep();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        m_sleepTimer = 0;
							 | 
						||
| 
								 | 
							
										if (!m_awake)
							 | 
						||
| 
								 | 
							
											wakeUp();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void	btMultiBody::forwardKinematics(btAlignedObjectArray<btQuaternion>& world_to_local,btAlignedObjectArray<btVector3>& local_origin)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									int num_links = getNumLinks();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Cached 3x3 rotation matrices from parent frame to this frame.
							 | 
						||
| 
								 | 
							
									btMatrix3x3* rot_from_parent =(btMatrix3x3 *) &m_matrixBuf[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rot_from_parent[0] = btMatrix3x3(m_baseQuat);				//m_baseQuat assumed to be alias!?
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int i = 0; i < num_links; ++i) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
									int nLinks = getNumLinks();
							 | 
						||
| 
								 | 
							
									///base + num m_links
							 | 
						||
| 
								 | 
							
									world_to_local.resize(nLinks+1);
							 | 
						||
| 
								 | 
							
									local_origin.resize(nLinks+1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									world_to_local[0] = getWorldToBaseRot();
							 | 
						||
| 
								 | 
							
									local_origin[0] = getBasePos();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int k=0;k<getNumLinks();k++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const int parent = getParent(k);
							 | 
						||
| 
								 | 
							
										world_to_local[k+1] = getParentToLocalRot(k) * world_to_local[parent+1];
							 | 
						||
| 
								 | 
							
										local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , getRVector(k)));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (int link=0;link<getNumLinks();link++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int index = link+1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btVector3 posr = local_origin[index];
							 | 
						||
| 
								 | 
							
										btScalar quat[4]={-world_to_local[index].x(),-world_to_local[index].y(),-world_to_local[index].z(),world_to_local[index].w()};
							 | 
						||
| 
								 | 
							
										btTransform tr;
							 | 
						||
| 
								 | 
							
										tr.setIdentity();
							 | 
						||
| 
								 | 
							
										tr.setOrigin(posr);
							 | 
						||
| 
								 | 
							
										tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
							 | 
						||
| 
								 | 
							
										getLink(link).m_cachedWorldTransform = tr;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void	btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion>& world_to_local,btAlignedObjectArray<btVector3>& local_origin)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									world_to_local.resize(getNumLinks()+1);
							 | 
						||
| 
								 | 
							
									local_origin.resize(getNumLinks()+1);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									world_to_local[0] = getWorldToBaseRot();
							 | 
						||
| 
								 | 
							
									local_origin[0] = getBasePos();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									if (getBaseCollider())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btVector3 posr = local_origin[0];
							 | 
						||
| 
								 | 
							
										//	float pos[4]={posr.x(),posr.y(),posr.z(),1};
							 | 
						||
| 
								 | 
							
										btScalar quat[4]={-world_to_local[0].x(),-world_to_local[0].y(),-world_to_local[0].z(),world_to_local[0].w()};
							 | 
						||
| 
								 | 
							
										btTransform tr;
							 | 
						||
| 
								 | 
							
										tr.setIdentity();
							 | 
						||
| 
								 | 
							
										tr.setOrigin(posr);
							 | 
						||
| 
								 | 
							
										tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										getBaseCollider()->setWorldTransform(tr);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int k=0;k<getNumLinks();k++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const int parent = getParent(k);
							 | 
						||
| 
								 | 
							
										world_to_local[k+1] = getParentToLocalRot(k) * world_to_local[parent+1];
							 | 
						||
| 
								 | 
							
										local_origin[k+1] = local_origin[parent+1] + (quatRotate(world_to_local[k+1].inverse() , getRVector(k)));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (int m=0;m<getNumLinks();m++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btMultiBodyLinkCollider* col = getLink(m).m_collider;
							 | 
						||
| 
								 | 
							
										if (col)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											int link = col->m_link;
							 | 
						||
| 
								 | 
							
											btAssert(link == m);
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											int index = link+1;
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											btVector3 posr = local_origin[index];
							 | 
						||
| 
								 | 
							
											//			float pos[4]={posr.x(),posr.y(),posr.z(),1};
							 | 
						||
| 
								 | 
							
											btScalar quat[4]={-world_to_local[index].x(),-world_to_local[index].y(),-world_to_local[index].z(),world_to_local[index].w()};
							 | 
						||
| 
								 | 
							
											btTransform tr;
							 | 
						||
| 
								 | 
							
											tr.setIdentity();
							 | 
						||
| 
								 | 
							
											tr.setOrigin(posr);
							 | 
						||
| 
								 | 
							
											tr.setRotation(btQuaternion(quat[0],quat[1],quat[2],quat[3]));
							 | 
						||
| 
								 | 
							
											
							 | 
						||
| 
								 | 
							
											col->setWorldTransform(tr);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int	btMultiBody::calculateSerializeBufferSize()	const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int sz = sizeof(btMultiBodyData);
							 | 
						||
| 
								 | 
							
									return sz;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									///fills the dataBuffer and returns the struct name (and 0 on failure)
							 | 
						||
| 
								 | 
							
								const char*	btMultiBody::serialize(void* dataBuffer, class btSerializer* serializer) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
										btMultiBodyData* mbd = (btMultiBodyData*) dataBuffer;
							 | 
						||
| 
								 | 
							
										getBaseWorldTransform().serialize(mbd->m_baseWorldTransform);
							 | 
						||
| 
								 | 
							
										mbd->m_baseMass = this->getBaseMass();
							 | 
						||
| 
								 | 
							
										getBaseInertia().serialize(mbd->m_baseInertia);
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											char* name = (char*) serializer->findNameForPointer(m_baseName);
							 | 
						||
| 
								 | 
							
											mbd->m_baseName = (char*)serializer->getUniquePointer(name);
							 | 
						||
| 
								 | 
							
											if (mbd->m_baseName)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												serializer->serializeName(name);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										mbd->m_numLinks = this->getNumLinks();
							 | 
						||
| 
								 | 
							
										if (mbd->m_numLinks)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											int sz = sizeof(btMultiBodyLinkData);
							 | 
						||
| 
								 | 
							
											int numElem = mbd->m_numLinks;
							 | 
						||
| 
								 | 
							
											btChunk* chunk = serializer->allocate(sz,numElem);
							 | 
						||
| 
								 | 
							
											btMultiBodyLinkData* memPtr = (btMultiBodyLinkData*)chunk->m_oldPtr;
							 | 
						||
| 
								 | 
							
											for (int i=0;i<numElem;i++,memPtr++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												memPtr->m_jointType = getLink(i).m_jointType;
							 | 
						||
| 
								 | 
							
												memPtr->m_dofCount = getLink(i).m_dofCount;
							 | 
						||
| 
								 | 
							
												memPtr->m_posVarCount = getLink(i).m_posVarCount;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia);
							 | 
						||
| 
								 | 
							
												memPtr->m_linkMass = getLink(i).m_mass;
							 | 
						||
| 
								 | 
							
												memPtr->m_parentIndex = getLink(i).m_parent;
							 | 
						||
| 
								 | 
							
												memPtr->m_jointDamping = getLink(i).m_jointDamping;
							 | 
						||
| 
								 | 
							
												memPtr->m_jointFriction = getLink(i).m_jointFriction;
							 | 
						||
| 
								 | 
							
												memPtr->m_jointLowerLimit = getLink(i).m_jointLowerLimit;
							 | 
						||
| 
								 | 
							
												memPtr->m_jointUpperLimit = getLink(i).m_jointUpperLimit;
							 | 
						||
| 
								 | 
							
												memPtr->m_jointMaxForce = getLink(i).m_jointMaxForce;
							 | 
						||
| 
								 | 
							
												memPtr->m_jointMaxVelocity = getLink(i).m_jointMaxVelocity;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												getLink(i).m_eVector.serialize(memPtr->m_parentComToThisComOffset);
							 | 
						||
| 
								 | 
							
												getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset);
							 | 
						||
| 
								 | 
							
												getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis);
							 | 
						||
| 
								 | 
							
												btAssert(memPtr->m_dofCount<=3);
							 | 
						||
| 
								 | 
							
												for (int dof = 0;dof<getLink(i).m_dofCount;dof++)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													getLink(i).getAxisBottom(dof).serialize(memPtr->m_jointAxisBottom[dof]);
							 | 
						||
| 
								 | 
							
													getLink(i).getAxisTop(dof).serialize(memPtr->m_jointAxisTop[dof]);
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													memPtr->m_jointTorque[dof] = getLink(i).m_jointTorque[dof];
							 | 
						||
| 
								 | 
							
													memPtr->m_jointVel[dof] = getJointVelMultiDof(i)[dof];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												int numPosVar = getLink(i).m_posVarCount;
							 | 
						||
| 
								 | 
							
												for (int posvar = 0; posvar < numPosVar;posvar++)
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													memPtr->m_jointPos[posvar] = getLink(i).m_jointPos[posvar];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													char* name = (char*) serializer->findNameForPointer(m_links[i].m_linkName);
							 | 
						||
| 
								 | 
							
													memPtr->m_linkName = (char*)serializer->getUniquePointer(name);
							 | 
						||
| 
								 | 
							
													if (memPtr->m_linkName)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														serializer->serializeName(name);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													char* name = (char*) serializer->findNameForPointer(m_links[i].m_jointName);
							 | 
						||
| 
								 | 
							
													memPtr->m_jointName = (char*)serializer->getUniquePointer(name);
							 | 
						||
| 
								 | 
							
													if (memPtr->m_jointName)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														serializer->serializeName(name);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												memPtr->m_linkCollider = (btCollisionObjectData*)serializer->getUniquePointer(getLink(i).m_collider);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											serializer->finalizeChunk(chunk,btMultiBodyLinkDataName,BT_ARRAY_CODE,(void*) &m_links[0]);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										mbd->m_links = mbd->m_numLinks? (btMultiBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Fill padding with zeros to appease msan.
							 | 
						||
| 
								 | 
							
								#ifdef BT_USE_DOUBLE_PRECISION
							 | 
						||
| 
								 | 
							
										memset(mbd->m_padding, 0, sizeof(mbd->m_padding));
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return btMultiBodyDataName;
							 | 
						||
| 
								 | 
							
								}
							 |