mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 23:21:15 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			389 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			389 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
 |