forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			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
 | ||
|  | 
 |