Home | History | Annotate | Download | only in LinearMath
      1 /*
      2 Copyright (c) 2003-2015 Erwin Coumans, Jakub Stepien
      3 
      4 This software is provided 'as-is', without any express or implied warranty.
      5 In no event will the authors be held liable for any damages arising from the use of this software.
      6 Permission is granted to anyone to use this software for any purpose,
      7 including commercial applications, and to alter it and redistribute it freely,
      8 subject to the following restrictions:
      9 
     10 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.
     11 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
     12 3. This notice may not be removed or altered from any source distribution.
     13 */
     14 
     15 ///These spatial algebra classes are used for btMultiBody,
     16 ///see BulletDynamics/Featherstone
     17 
     18 #ifndef BT_SPATIAL_ALGEBRA_H
     19 #define BT_SPATIAL_ALGEBRA_H
     20 
     21 
     22 #include "btMatrix3x3.h"
     23 
     24 struct btSpatialForceVector
     25 {
     26 	btVector3 m_topVec, m_bottomVec;
     27 	//
     28 	btSpatialForceVector() { setZero(); }
     29 	btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
     30 	btSpatialForceVector(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
     31 	{
     32 		setValue(ax, ay, az, lx, ly, lz);
     33 	}
     34 	//
     35 	void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = linear; m_bottomVec = angular; }
     36 	void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
     37 	{
     38 		m_bottomVec.setValue(ax, ay, az); m_topVec.setValue(lx, ly, lz);
     39 	}
     40 	//
     41 	void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
     42 	void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
     43 	{
     44 		m_bottomVec[0] += ax; m_bottomVec[1] += ay; m_bottomVec[2] += az;
     45 		m_topVec[0] += lx; m_topVec[1] += ly; m_topVec[2] += lz;
     46 	}
     47 	//
     48 	const btVector3 & getLinear()  const { return m_topVec; }
     49 	const btVector3 & getAngular() const { return m_bottomVec; }
     50 	//
     51 	void setLinear(const btVector3 &linear) { m_topVec = linear; }
     52 	void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
     53 	//
     54 	void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
     55 	void addLinear(const btVector3 &linear) { m_topVec += linear; }
     56 	//
     57 	void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
     58 	//
     59 	btSpatialForceVector & operator += (const btSpatialForceVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
     60 	btSpatialForceVector & operator -= (const btSpatialForceVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
     61 	btSpatialForceVector operator - (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
     62 	btSpatialForceVector operator + (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
     63 	btSpatialForceVector operator - () const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
     64 	btSpatialForceVector operator * (const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
     65 	//btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
     66 };
     67 
     68 struct btSpatialMotionVector
     69 {
     70 	btVector3 m_topVec, m_bottomVec;
     71 	//
     72 	btSpatialMotionVector() { setZero(); }
     73 	btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
     74 	//
     75 	void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = angular; m_bottomVec = linear; }
     76 	void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
     77 	{
     78 		m_topVec.setValue(ax, ay, az); m_bottomVec.setValue(lx, ly, lz);
     79 	}
     80 	//
     81 	void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
     82 	void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
     83 	{
     84 		m_topVec[0] += ax; m_topVec[1] += ay; m_topVec[2] += az;
     85 		m_bottomVec[0] += lx; m_bottomVec[1] += ly; m_bottomVec[2] += lz;
     86 	}
     87 	//
     88 	const btVector3 & getAngular() const { return m_topVec; }
     89 	const btVector3 & getLinear() const { return m_bottomVec; }
     90 	//
     91 	void setAngular(const btVector3 &angular) { m_topVec = angular; }
     92 	void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
     93 	//
     94 	void addAngular(const btVector3 &angular) { m_topVec += angular; }
     95 	void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
     96 	//
     97 	void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
     98 	//
     99 	btScalar dot(const btSpatialForceVector &b) const
    100 	{
    101 		return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
    102 	}
    103 	//
    104 	template<typename SpatialVectorType>
    105 	void cross(const SpatialVectorType &b, SpatialVectorType &out) const
    106 	{
    107 		out.m_topVec = m_topVec.cross(b.m_topVec);
    108 		out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
    109 	}
    110 	template<typename SpatialVectorType>
    111 	SpatialVectorType cross(const SpatialVectorType &b) const
    112 	{
    113 		SpatialVectorType out;
    114 		out.m_topVec = m_topVec.cross(b.m_topVec);
    115 		out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
    116 		return out;
    117 	}
    118 	//
    119 	btSpatialMotionVector & operator += (const btSpatialMotionVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
    120 	btSpatialMotionVector & operator -= (const btSpatialMotionVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
    121 	btSpatialMotionVector & operator *= (const btScalar &s) { m_topVec *= s; m_bottomVec *= s; return *this; }
    122 	btSpatialMotionVector operator - (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
    123 	btSpatialMotionVector operator + (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
    124 	btSpatialMotionVector operator - () const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
    125 	btSpatialMotionVector operator * (const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
    126 };
    127 
    128 struct btSymmetricSpatialDyad
    129 {
    130 	btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
    131 	//
    132 	btSymmetricSpatialDyad() { setIdentity(); }
    133 	btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
    134 	//
    135 	void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
    136 	{
    137 		m_topLeftMat = topLeftMat;
    138 		m_topRightMat = topRightMat;
    139 		m_bottomLeftMat = bottomLeftMat;
    140 	}
    141 	//
    142 	void addMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
    143 	{
    144 		m_topLeftMat += topLeftMat;
    145 		m_topRightMat += topRightMat;
    146 		m_bottomLeftMat += bottomLeftMat;
    147 	}
    148 	//
    149 	void setIdentity() { m_topLeftMat.setIdentity(); m_topRightMat.setIdentity(); m_bottomLeftMat.setIdentity();  }
    150 	//
    151 	btSymmetricSpatialDyad & operator -= (const btSymmetricSpatialDyad &mat)
    152 	{
    153 		m_topLeftMat -= mat.m_topLeftMat;
    154 		m_topRightMat -= mat.m_topRightMat;
    155 		m_bottomLeftMat -= mat.m_bottomLeftMat;
    156 		return *this;
    157 	}
    158 	//
    159 	btSpatialForceVector operator * (const btSpatialMotionVector &vec)
    160 	{
    161 		return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
    162 	}
    163 };
    164 
    165 struct btSpatialTransformationMatrix
    166 {
    167 	btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
    168 	btVector3 m_trnVec;
    169 	//
    170 	enum eOutputOperation
    171 	{
    172 		None = 0,
    173 		Add = 1,
    174 		Subtract = 2
    175 	};
    176 	//
    177 	template<typename SpatialVectorType>
    178 	void transform(	const SpatialVectorType &inVec,
    179                       SpatialVectorType &outVec,
    180 					eOutputOperation outOp = None)
    181 	{
    182 		if(outOp == None)
    183 		{
    184 			outVec.m_topVec = m_rotMat * inVec.m_topVec;
    185 			outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
    186 		}
    187 		else if(outOp == Add)
    188 		{
    189 			outVec.m_topVec += m_rotMat * inVec.m_topVec;
    190 			outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
    191 		}
    192 		else if(outOp == Subtract)
    193 		{
    194 			outVec.m_topVec -= m_rotMat * inVec.m_topVec;
    195 			outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
    196 		}
    197 
    198 	}
    199 
    200 	template<typename SpatialVectorType>
    201 	void transformRotationOnly(	const SpatialVectorType &inVec,
    202 								SpatialVectorType &outVec,
    203 								eOutputOperation outOp = None)
    204 	{
    205 		if(outOp == None)
    206 		{
    207 			outVec.m_topVec = m_rotMat * inVec.m_topVec;
    208 			outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
    209 		}
    210 		else if(outOp == Add)
    211 		{
    212 			outVec.m_topVec += m_rotMat * inVec.m_topVec;
    213 			outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
    214 		}
    215 		else if(outOp == Subtract)
    216 		{
    217 			outVec.m_topVec -= m_rotMat * inVec.m_topVec;
    218 			outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
    219 		}
    220 
    221 	}
    222 
    223 	template<typename SpatialVectorType>
    224 	void transformInverse(	const SpatialVectorType &inVec,
    225 							SpatialVectorType &outVec,
    226 							eOutputOperation outOp = None)
    227 	{
    228 		if(outOp == None)
    229 		{
    230 			outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
    231 			outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
    232 		}
    233 		else if(outOp == Add)
    234 		{
    235 			outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
    236 			outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
    237 		}
    238 		else if(outOp == Subtract)
    239 		{
    240 			outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
    241 			outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
    242 		}
    243 	}
    244 
    245 	template<typename SpatialVectorType>
    246 	void transformInverseRotationOnly(	const SpatialVectorType &inVec,
    247 										SpatialVectorType &outVec,
    248 										eOutputOperation outOp = None)
    249 	{
    250 		if(outOp == None)
    251 		{
    252 			outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
    253 			outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
    254 		}
    255 		else if(outOp == Add)
    256 		{
    257 			outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
    258 			outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
    259 		}
    260 		else if(outOp == Subtract)
    261 		{
    262 			outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
    263 			outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
    264 		}
    265 
    266 	}
    267 
    268 	void transformInverse(	const btSymmetricSpatialDyad &inMat,
    269 							btSymmetricSpatialDyad &outMat,
    270 							eOutputOperation outOp = None)
    271 	{
    272 		const btMatrix3x3 r_cross(	0, -m_trnVec[2], m_trnVec[1],
    273 								m_trnVec[2], 0, -m_trnVec[0],
    274 								-m_trnVec[1], m_trnVec[0], 0);
    275 
    276 
    277 		if(outOp == None)
    278 		{
    279 			outMat.m_topLeftMat = m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
    280 			outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
    281 			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;
    282 		}
    283 		else if(outOp == Add)
    284 		{
    285 			outMat.m_topLeftMat += m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
    286 			outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
    287 			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;
    288 		}
    289 		else if(outOp == Subtract)
    290 		{
    291 			outMat.m_topLeftMat -= m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
    292 			outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
    293 			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;
    294 		}
    295 	}
    296 
    297 	template<typename SpatialVectorType>
    298 	SpatialVectorType operator * (const SpatialVectorType &vec)
    299 	{
    300 		SpatialVectorType out;
    301 		transform(vec, out);
    302 		return out;
    303 	}
    304 };
    305 
    306 template<typename SpatialVectorType>
    307 void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
    308 {
    309 	//output op maybe?
    310 
    311 	out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
    312 	out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
    313 	out.m_topLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
    314 	//maybe simple a*spatTranspose(a) would be nicer?
    315 }
    316 
    317 template<typename SpatialVectorType>
    318 btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
    319 {
    320 	btSymmetricSpatialDyad out;
    321 
    322 	out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
    323 	out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
    324 	out.m_bottomLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
    325 
    326 	return out;
    327 	//maybe simple a*spatTranspose(a) would be nicer?
    328 }
    329 
    330 #endif //BT_SPATIAL_ALGEBRA_H
    331 
    332