332 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| Copyright (c) 2003-2015 Erwin Coumans, Jakub Stepien
 | |
| 
 | |
| 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.
 | |
| */
 | |
| 
 | |
| ///These spatial algebra classes are used for btMultiBody, 
 | |
| ///see BulletDynamics/Featherstone
 | |
| 
 | |
| #ifndef BT_SPATIAL_ALGEBRA_H
 | |
| #define BT_SPATIAL_ALGEBRA_H
 | |
| 
 | |
| 
 | |
| #include "btMatrix3x3.h"
 | |
| 
 | |
| struct btSpatialForceVector
 | |
| {	
 | |
| 	btVector3 m_topVec, m_bottomVec;	
 | |
| 	//
 | |
| 	btSpatialForceVector() { setZero(); }
 | |
| 	btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
 | |
| 	btSpatialForceVector(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
 | |
| 	{
 | |
| 		setValue(ax, ay, az, lx, ly, lz);
 | |
| 	}
 | |
| 	//
 | |
| 	void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = linear; m_bottomVec = angular; }
 | |
| 	void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
 | |
| 	{
 | |
| 		m_bottomVec.setValue(ax, ay, az); m_topVec.setValue(lx, ly, lz);
 | |
| 	}
 | |
| 	//
 | |
| 	void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
 | |
| 	void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
 | |
| 	{
 | |
| 		m_bottomVec[0] += ax; m_bottomVec[1] += ay; m_bottomVec[2] += az;
 | |
| 		m_topVec[0] += lx; m_topVec[1] += ly; m_topVec[2] += lz;			
 | |
| 	}
 | |
| 	//
 | |
| 	const btVector3 & getLinear()  const { return m_topVec; }
 | |
| 	const btVector3 & getAngular() const { return m_bottomVec; }
 | |
| 	//
 | |
| 	void setLinear(const btVector3 &linear) { m_topVec = linear; }
 | |
| 	void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
 | |
| 	//
 | |
| 	void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
 | |
| 	void addLinear(const btVector3 &linear) { m_topVec += linear; }
 | |
| 	//
 | |
| 	void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
 | |
| 	//
 | |
| 	btSpatialForceVector & operator += (const btSpatialForceVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
 | |
| 	btSpatialForceVector & operator -= (const btSpatialForceVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
 | |
| 	btSpatialForceVector operator - (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
 | |
| 	btSpatialForceVector operator + (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
 | |
| 	btSpatialForceVector operator - () const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
 | |
| 	btSpatialForceVector operator * (const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }		
 | |
| 	//btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
 | |
| };
 | |
| 
 | |
| struct btSpatialMotionVector
 | |
| {
 | |
| 	btVector3 m_topVec, m_bottomVec;
 | |
| 	//
 | |
| 	btSpatialMotionVector() { setZero(); }
 | |
| 	btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}		
 | |
| 	//
 | |
| 	void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = angular; m_bottomVec = linear; }
 | |
| 	void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
 | |
| 	{
 | |
| 		m_topVec.setValue(ax, ay, az); m_bottomVec.setValue(lx, ly, lz);
 | |
| 	}
 | |
| 	//
 | |
| 	void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
 | |
| 	void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
 | |
| 	{
 | |
| 		m_topVec[0] += ax; m_topVec[1] += ay; m_topVec[2] += az;
 | |
| 		m_bottomVec[0] += lx; m_bottomVec[1] += ly; m_bottomVec[2] += lz;			
 | |
| 	}
 | |
| 	//	
 | |
| 	const btVector3 & getAngular() const { return m_topVec; }
 | |
| 	const btVector3 & getLinear() const { return m_bottomVec; }
 | |
| 	//
 | |
| 	void setAngular(const btVector3 &angular) { m_topVec = angular; }
 | |
| 	void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
 | |
| 	//
 | |
| 	void addAngular(const btVector3 &angular) { m_topVec += angular; }
 | |
| 	void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
 | |
| 	//
 | |
| 	void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
 | |
| 	//
 | |
| 	btScalar dot(const btSpatialForceVector &b) const
 | |
| 	{
 | |
| 		return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
 | |
| 	}
 | |
| 	//
 | |
| 	template<typename SpatialVectorType>
 | |
| 	void cross(const SpatialVectorType &b, SpatialVectorType &out) const
 | |
| 	{
 | |
| 		out.m_topVec = m_topVec.cross(b.m_topVec);
 | |
| 		out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
 | |
| 	}
 | |
| 	template<typename SpatialVectorType>
 | |
| 	SpatialVectorType cross(const SpatialVectorType &b) const
 | |
| 	{
 | |
| 		SpatialVectorType out;
 | |
| 		out.m_topVec = m_topVec.cross(b.m_topVec);
 | |
| 		out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
 | |
| 		return out;
 | |
| 	}
 | |
| 	//
 | |
| 	btSpatialMotionVector & operator += (const btSpatialMotionVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
 | |
| 	btSpatialMotionVector & operator -= (const btSpatialMotionVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
 | |
| 	btSpatialMotionVector & operator *= (const btScalar &s) { m_topVec *= s; m_bottomVec *= s; return *this; }
 | |
| 	btSpatialMotionVector operator - (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
 | |
| 	btSpatialMotionVector operator + (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
 | |
| 	btSpatialMotionVector operator - () const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
 | |
| 	btSpatialMotionVector operator * (const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
 | |
| };
 | |
| 
 | |
| struct btSymmetricSpatialDyad
 | |
| {
 | |
| 	btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
 | |
| 	//		
 | |
| 	btSymmetricSpatialDyad() { setIdentity(); }
 | |
| 	btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }			
 | |
| 	//
 | |
| 	void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
 | |
| 	{
 | |
| 		m_topLeftMat = topLeftMat;
 | |
| 		m_topRightMat = topRightMat;
 | |
| 		m_bottomLeftMat = bottomLeftMat;
 | |
| 	}
 | |
| 	//
 | |
| 	void addMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
 | |
| 	{
 | |
| 		m_topLeftMat += topLeftMat;
 | |
| 		m_topRightMat += topRightMat;
 | |
| 		m_bottomLeftMat += bottomLeftMat;
 | |
| 	}
 | |
| 	//
 | |
| 	void setIdentity() { m_topLeftMat.setIdentity(); m_topRightMat.setIdentity(); m_bottomLeftMat.setIdentity();  }
 | |
| 	//
 | |
| 	btSymmetricSpatialDyad & operator -= (const btSymmetricSpatialDyad &mat)
 | |
| 	{
 | |
| 		m_topLeftMat -= mat.m_topLeftMat;
 | |
| 		m_topRightMat -= mat.m_topRightMat;
 | |
| 		m_bottomLeftMat -= mat.m_bottomLeftMat;
 | |
| 		return *this; 
 | |
| 	}
 | |
| 	//
 | |
| 	btSpatialForceVector operator * (const btSpatialMotionVector &vec)
 | |
| 	{
 | |
| 		return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
 | |
| 	}
 | |
| };
 | |
| 
 | |
| struct btSpatialTransformationMatrix
 | |
| {
 | |
| 	btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
 | |
| 	btVector3 m_trnVec;
 | |
| 	//
 | |
| 	enum eOutputOperation
 | |
| 	{
 | |
| 		None = 0,
 | |
| 		Add = 1,
 | |
| 		Subtract = 2
 | |
| 	};
 | |
| 	//
 | |
| 	template<typename SpatialVectorType>
 | |
| 	void transform(	const SpatialVectorType &inVec,
 | |
|                       SpatialVectorType &outVec,
 | |
| 					eOutputOperation outOp = None)
 | |
| 	{
 | |
| 		if(outOp == None)
 | |
| 		{
 | |
| 			outVec.m_topVec = m_rotMat * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		else if(outOp == Add)
 | |
| 		{
 | |
| 			outVec.m_topVec += m_rotMat * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		else if(outOp == Subtract)
 | |
| 		{
 | |
| 			outVec.m_topVec -= m_rotMat * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		
 | |
| 	}
 | |
| 
 | |
| 	template<typename SpatialVectorType>
 | |
| 	void transformRotationOnly(	const SpatialVectorType &inVec,
 | |
| 								SpatialVectorType &outVec,
 | |
| 								eOutputOperation outOp = None)
 | |
| 	{
 | |
| 		if(outOp == None)
 | |
| 		{
 | |
| 			outVec.m_topVec = m_rotMat * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		else if(outOp == Add)
 | |
| 		{
 | |
| 			outVec.m_topVec += m_rotMat * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		else if(outOp == Subtract)
 | |
| 		{
 | |
| 			outVec.m_topVec -= m_rotMat * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		
 | |
| 	}
 | |
| 
 | |
| 	template<typename SpatialVectorType>
 | |
| 	void transformInverse(	const SpatialVectorType &inVec,
 | |
| 							SpatialVectorType &outVec,
 | |
| 							eOutputOperation outOp = None)
 | |
| 	{
 | |
| 		if(outOp == None)
 | |
| 		{
 | |
| 			outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
 | |
| 		}
 | |
| 		else if(outOp == Add)
 | |
| 		{
 | |
| 			outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
 | |
| 		}
 | |
| 		else if(outOp == Subtract)
 | |
| 		{
 | |
| 			outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
 | |
| 		}			
 | |
| 	}
 | |
| 
 | |
| 	template<typename SpatialVectorType>
 | |
| 	void transformInverseRotationOnly(	const SpatialVectorType &inVec,
 | |
| 										SpatialVectorType &outVec,
 | |
| 										eOutputOperation outOp = None)
 | |
| 	{
 | |
| 		if(outOp == None)
 | |
| 		{
 | |
| 			outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		else if(outOp == Add)
 | |
| 		{
 | |
| 			outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		else if(outOp == Subtract)
 | |
| 		{
 | |
| 			outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
 | |
| 			outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
 | |
| 		}
 | |
| 		
 | |
| 	}
 | |
| 
 | |
| 	void transformInverse(	const btSymmetricSpatialDyad &inMat,
 | |
| 							btSymmetricSpatialDyad &outMat,
 | |
| 							eOutputOperation outOp = None)
 | |
| 	{
 | |
| 		const btMatrix3x3 r_cross(	0, -m_trnVec[2], m_trnVec[1],
 | |
| 								m_trnVec[2], 0, -m_trnVec[0],
 | |
| 								-m_trnVec[1], m_trnVec[0], 0);
 | |
| 
 | |
| 
 | |
| 		if(outOp == None)
 | |
| 		{
 | |
| 			outMat.m_topLeftMat = m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
 | |
| 			outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
 | |
| 			outMat.m_bottomLeftMat = m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
 | |
| 		}
 | |
| 		else if(outOp == Add)
 | |
| 		{
 | |
| 			outMat.m_topLeftMat += m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
 | |
| 			outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
 | |
| 			outMat.m_bottomLeftMat += m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
 | |
| 		}
 | |
| 		else if(outOp == Subtract)
 | |
| 		{
 | |
| 			outMat.m_topLeftMat -= m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
 | |
| 			outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
 | |
| 			outMat.m_bottomLeftMat -= m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	template<typename SpatialVectorType>
 | |
| 	SpatialVectorType operator * (const SpatialVectorType &vec)
 | |
| 	{
 | |
| 		SpatialVectorType out;
 | |
| 		transform(vec, out);
 | |
| 		return out;
 | |
| 	}
 | |
| };
 | |
| 
 | |
| template<typename SpatialVectorType>
 | |
| void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
 | |
| {
 | |
| 	//output op maybe?
 | |
| 
 | |
| 	out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
 | |
| 	out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
 | |
| 	out.m_topLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
 | |
| 	//maybe simple a*spatTranspose(a) would be nicer?
 | |
| }
 | |
| 
 | |
| template<typename SpatialVectorType>
 | |
| btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
 | |
| {
 | |
| 	btSymmetricSpatialDyad out;
 | |
| 
 | |
| 	out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
 | |
| 	out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
 | |
| 	out.m_bottomLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
 | |
| 
 | |
| 	return out;
 | |
| 	//maybe simple a*spatTranspose(a) would be nicer?
 | |
| }
 | |
| 
 | |
| #endif //BT_SPATIAL_ALGEBRA_H
 | |
| 
 |