Home | History | Annotate | Download | only in ConstraintSolver
      1 /*
      2 Bullet Continuous Collision Detection and Physics Library
      3 Copyright (c) 2003-2010 Erwin Coumans  http://continuousphysics.com/Bullet/
      4 
      5 This software is provided 'as-is', without any express or implied warranty.
      6 In no event will the authors be held liable for any damages arising from the use of this software.
      7 Permission is granted to anyone to use this software for any purpose,
      8 including commercial applications, and to alter it and redistribute it freely,
      9 subject to the following restrictions:
     10 
     11 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.
     12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
     13 3. This notice may not be removed or altered from any source distribution.
     14 */
     15 
     16 #ifndef BT_TYPED_CONSTRAINT_H
     17 #define BT_TYPED_CONSTRAINT_H
     18 
     19 
     20 #include "LinearMath/btScalar.h"
     21 #include "btSolverConstraint.h"
     22 #include "BulletDynamics/Dynamics/btRigidBody.h"
     23 
     24 #ifdef BT_USE_DOUBLE_PRECISION
     25 #define btTypedConstraintData2		btTypedConstraintDoubleData
     26 #define btTypedConstraintDataName	"btTypedConstraintDoubleData"
     27 #else
     28 #define btTypedConstraintData2 		btTypedConstraintFloatData
     29 #define btTypedConstraintDataName  "btTypedConstraintFloatData"
     30 #endif //BT_USE_DOUBLE_PRECISION
     31 
     32 
     33 class btSerializer;
     34 
     35 //Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
     36 enum btTypedConstraintType
     37 {
     38 	POINT2POINT_CONSTRAINT_TYPE=3,
     39 	HINGE_CONSTRAINT_TYPE,
     40 	CONETWIST_CONSTRAINT_TYPE,
     41 	D6_CONSTRAINT_TYPE,
     42 	SLIDER_CONSTRAINT_TYPE,
     43 	CONTACT_CONSTRAINT_TYPE,
     44 	D6_SPRING_CONSTRAINT_TYPE,
     45 	GEAR_CONSTRAINT_TYPE,
     46 	FIXED_CONSTRAINT_TYPE,
     47 	D6_SPRING_2_CONSTRAINT_TYPE,
     48 	MAX_CONSTRAINT_TYPE
     49 };
     50 
     51 
     52 enum btConstraintParams
     53 {
     54 	BT_CONSTRAINT_ERP=1,
     55 	BT_CONSTRAINT_STOP_ERP,
     56 	BT_CONSTRAINT_CFM,
     57 	BT_CONSTRAINT_STOP_CFM
     58 };
     59 
     60 #if 1
     61 	#define btAssertConstrParams(_par) btAssert(_par)
     62 #else
     63 	#define btAssertConstrParams(_par)
     64 #endif
     65 
     66 
     67 ATTRIBUTE_ALIGNED16(struct)	btJointFeedback
     68 {
     69 	btVector3	m_appliedForceBodyA;
     70 	btVector3	m_appliedTorqueBodyA;
     71 	btVector3	m_appliedForceBodyB;
     72 	btVector3	m_appliedTorqueBodyB;
     73 };
     74 
     75 
     76 ///TypedConstraint is the baseclass for Bullet constraints and vehicles
     77 ATTRIBUTE_ALIGNED16(class) btTypedConstraint : public btTypedObject
     78 {
     79 	int	m_userConstraintType;
     80 
     81 	union
     82 	{
     83 		int	m_userConstraintId;
     84 		void* m_userConstraintPtr;
     85 	};
     86 
     87 	btScalar	m_breakingImpulseThreshold;
     88 	bool		m_isEnabled;
     89 	bool		m_needsFeedback;
     90 	int			m_overrideNumSolverIterations;
     91 
     92 
     93 	btTypedConstraint&	operator=(btTypedConstraint&	other)
     94 	{
     95 		btAssert(0);
     96 		(void) other;
     97 		return *this;
     98 	}
     99 
    100 protected:
    101 	btRigidBody&	m_rbA;
    102 	btRigidBody&	m_rbB;
    103 	btScalar	m_appliedImpulse;
    104 	btScalar	m_dbgDrawSize;
    105 	btJointFeedback*	m_jointFeedback;
    106 
    107 	///internal method used by the constraint solver, don't use them directly
    108 	btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact);
    109 
    110 
    111 public:
    112 
    113 	BT_DECLARE_ALIGNED_ALLOCATOR();
    114 
    115 	virtual ~btTypedConstraint() {};
    116 	btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA);
    117 	btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB);
    118 
    119 	struct btConstraintInfo1 {
    120 		int m_numConstraintRows,nub;
    121 	};
    122 
    123 	static btRigidBody& getFixedBody();
    124 
    125 	struct btConstraintInfo2 {
    126 		// integrator parameters: frames per second (1/stepsize), default error
    127 		// reduction parameter (0..1).
    128 		btScalar fps,erp;
    129 
    130 		// for the first and second body, pointers to two (linear and angular)
    131 		// n*3 jacobian sub matrices, stored by rows. these matrices will have
    132 		// been initialized to 0 on entry. if the second body is zero then the
    133 		// J2xx pointers may be 0.
    134 		btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
    135 
    136 		// elements to jump from one row to the next in J's
    137 		int rowskip;
    138 
    139 		// right hand sides of the equation J*v = c + cfm * lambda. cfm is the
    140 		// "constraint force mixing" vector. c is set to zero on entry, cfm is
    141 		// set to a constant value (typically very small or zero) value on entry.
    142 		btScalar *m_constraintError,*cfm;
    143 
    144 		// lo and hi limits for variables (set to -/+ infinity on entry).
    145 		btScalar *m_lowerLimit,*m_upperLimit;
    146 
    147 		// findex vector for variables. see the LCP solver interface for a
    148 		// description of what this does. this is set to -1 on entry.
    149 		// note that the returned indexes are relative to the first index of
    150 		// the constraint.
    151 		int *findex;
    152 		// number of solver iterations
    153 		int m_numIterations;
    154 
    155 		//damping of the velocity
    156 		btScalar	m_damping;
    157 	};
    158 
    159 	int	getOverrideNumSolverIterations() const
    160 	{
    161 		return m_overrideNumSolverIterations;
    162 	}
    163 
    164 	///override the number of constraint solver iterations used to solve this constraint
    165 	///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations
    166 	void setOverrideNumSolverIterations(int overideNumIterations)
    167 	{
    168 		m_overrideNumSolverIterations = overideNumIterations;
    169 	}
    170 
    171 	///internal method used by the constraint solver, don't use them directly
    172 	virtual void	buildJacobian() {};
    173 
    174 	///internal method used by the constraint solver, don't use them directly
    175 	virtual	void	setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep)
    176 	{
    177         (void)ca;
    178         (void)solverBodyA;
    179         (void)solverBodyB;
    180         (void)timeStep;
    181 	}
    182 
    183 	///internal method used by the constraint solver, don't use them directly
    184 	virtual void getInfo1 (btConstraintInfo1* info)=0;
    185 
    186 	///internal method used by the constraint solver, don't use them directly
    187 	virtual void getInfo2 (btConstraintInfo2* info)=0;
    188 
    189 	///internal method used by the constraint solver, don't use them directly
    190 	void	internalSetAppliedImpulse(btScalar appliedImpulse)
    191 	{
    192 		m_appliedImpulse = appliedImpulse;
    193 	}
    194 	///internal method used by the constraint solver, don't use them directly
    195 	btScalar	internalGetAppliedImpulse()
    196 	{
    197 		return m_appliedImpulse;
    198 	}
    199 
    200 
    201 	btScalar	getBreakingImpulseThreshold() const
    202 	{
    203 		return 	m_breakingImpulseThreshold;
    204 	}
    205 
    206 	void	setBreakingImpulseThreshold(btScalar threshold)
    207 	{
    208 		m_breakingImpulseThreshold = threshold;
    209 	}
    210 
    211 	bool	isEnabled() const
    212 	{
    213 		return m_isEnabled;
    214 	}
    215 
    216 	void	setEnabled(bool enabled)
    217 	{
    218 		m_isEnabled=enabled;
    219 	}
    220 
    221 
    222 	///internal method used by the constraint solver, don't use them directly
    223 	virtual	void	solveConstraintObsolete(btSolverBody& /*bodyA*/,btSolverBody& /*bodyB*/,btScalar	/*timeStep*/) {};
    224 
    225 
    226 	const btRigidBody& getRigidBodyA() const
    227 	{
    228 		return m_rbA;
    229 	}
    230 	const btRigidBody& getRigidBodyB() const
    231 	{
    232 		return m_rbB;
    233 	}
    234 
    235 	btRigidBody& getRigidBodyA()
    236 	{
    237 		return m_rbA;
    238 	}
    239 	btRigidBody& getRigidBodyB()
    240 	{
    241 		return m_rbB;
    242 	}
    243 
    244 	int getUserConstraintType() const
    245 	{
    246 		return m_userConstraintType ;
    247 	}
    248 
    249 	void	setUserConstraintType(int userConstraintType)
    250 	{
    251 		m_userConstraintType = userConstraintType;
    252 	};
    253 
    254 	void	setUserConstraintId(int uid)
    255 	{
    256 		m_userConstraintId = uid;
    257 	}
    258 
    259 	int getUserConstraintId() const
    260 	{
    261 		return m_userConstraintId;
    262 	}
    263 
    264 	void	setUserConstraintPtr(void* ptr)
    265 	{
    266 		m_userConstraintPtr = ptr;
    267 	}
    268 
    269 	void*	getUserConstraintPtr()
    270 	{
    271 		return m_userConstraintPtr;
    272 	}
    273 
    274 	void	setJointFeedback(btJointFeedback* jointFeedback)
    275 	{
    276 		m_jointFeedback = jointFeedback;
    277 	}
    278 
    279 	const btJointFeedback* getJointFeedback() const
    280 	{
    281 		return m_jointFeedback;
    282 	}
    283 
    284 	btJointFeedback* getJointFeedback()
    285 	{
    286 		return m_jointFeedback;
    287 	}
    288 
    289 
    290 	int getUid() const
    291 	{
    292 		return m_userConstraintId;
    293 	}
    294 
    295 	bool	needsFeedback() const
    296 	{
    297 		return m_needsFeedback;
    298 	}
    299 
    300 	///enableFeedback will allow to read the applied linear and angular impulse
    301 	///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
    302 	void	enableFeedback(bool needsFeedback)
    303 	{
    304 		m_needsFeedback = needsFeedback;
    305 	}
    306 
    307 	///getAppliedImpulse is an estimated total applied impulse.
    308 	///This feedback could be used to determine breaking constraints or playing sounds.
    309 	btScalar	getAppliedImpulse() const
    310 	{
    311 		btAssert(m_needsFeedback);
    312 		return m_appliedImpulse;
    313 	}
    314 
    315 	btTypedConstraintType getConstraintType () const
    316 	{
    317 		return btTypedConstraintType(m_objectType);
    318 	}
    319 
    320 	void setDbgDrawSize(btScalar dbgDrawSize)
    321 	{
    322 		m_dbgDrawSize = dbgDrawSize;
    323 	}
    324 	btScalar getDbgDrawSize()
    325 	{
    326 		return m_dbgDrawSize;
    327 	}
    328 
    329 	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
    330 	///If no axis is provided, it uses the default axis for this constraint.
    331 	virtual	void	setParam(int num, btScalar value, int axis = -1) = 0;
    332 
    333 	///return the local value of parameter
    334 	virtual	btScalar getParam(int num, int axis = -1) const = 0;
    335 
    336 	virtual	int	calculateSerializeBufferSize() const;
    337 
    338 	///fills the dataBuffer and returns the struct name (and 0 on failure)
    339 	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
    340 
    341 };
    342 
    343 // returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits
    344 // all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI])
    345 SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
    346 {
    347 	if(angleLowerLimitInRadians >= angleUpperLimitInRadians)
    348 	{
    349 		return angleInRadians;
    350 	}
    351 	else if(angleInRadians < angleLowerLimitInRadians)
    352 	{
    353 		btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians));
    354 		btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians));
    355 		return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI);
    356 	}
    357 	else if(angleInRadians > angleUpperLimitInRadians)
    358 	{
    359 		btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians));
    360 		btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians));
    361 		return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians;
    362 	}
    363 	else
    364 	{
    365 		return angleInRadians;
    366 	}
    367 }
    368 
    369 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
    370 struct	btTypedConstraintFloatData
    371 {
    372 	btRigidBodyFloatData		*m_rbA;
    373 	btRigidBodyFloatData		*m_rbB;
    374 	char	*m_name;
    375 
    376 	int	m_objectType;
    377 	int	m_userConstraintType;
    378 	int	m_userConstraintId;
    379 	int	m_needsFeedback;
    380 
    381 	float	m_appliedImpulse;
    382 	float	m_dbgDrawSize;
    383 
    384 	int	m_disableCollisionsBetweenLinkedBodies;
    385 	int	m_overrideNumSolverIterations;
    386 
    387 	float	m_breakingImpulseThreshold;
    388 	int		m_isEnabled;
    389 
    390 };
    391 
    392 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
    393 
    394 #define BT_BACKWARDS_COMPATIBLE_SERIALIZATION
    395 #ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
    396 ///this structure is not used, except for loading pre-2.82 .bullet files
    397 struct	btTypedConstraintData
    398 {
    399 	btRigidBodyData		*m_rbA;
    400 	btRigidBodyData		*m_rbB;
    401 	char	*m_name;
    402 
    403 	int	m_objectType;
    404 	int	m_userConstraintType;
    405 	int	m_userConstraintId;
    406 	int	m_needsFeedback;
    407 
    408 	float	m_appliedImpulse;
    409 	float	m_dbgDrawSize;
    410 
    411 	int	m_disableCollisionsBetweenLinkedBodies;
    412 	int	m_overrideNumSolverIterations;
    413 
    414 	float	m_breakingImpulseThreshold;
    415 	int		m_isEnabled;
    416 
    417 };
    418 #endif //BACKWARDS_COMPATIBLE
    419 
    420 struct	btTypedConstraintDoubleData
    421 {
    422 	btRigidBodyDoubleData		*m_rbA;
    423 	btRigidBodyDoubleData		*m_rbB;
    424 	char	*m_name;
    425 
    426 	int	m_objectType;
    427 	int	m_userConstraintType;
    428 	int	m_userConstraintId;
    429 	int	m_needsFeedback;
    430 
    431 	double	m_appliedImpulse;
    432 	double	m_dbgDrawSize;
    433 
    434 	int	m_disableCollisionsBetweenLinkedBodies;
    435 	int	m_overrideNumSolverIterations;
    436 
    437 	double	m_breakingImpulseThreshold;
    438 	int		m_isEnabled;
    439 	char	padding[4];
    440 
    441 };
    442 
    443 
    444 SIMD_FORCE_INLINE	int	btTypedConstraint::calculateSerializeBufferSize() const
    445 {
    446 	return sizeof(btTypedConstraintData2);
    447 }
    448 
    449 
    450 
    451 class btAngularLimit
    452 {
    453 private:
    454 	btScalar
    455 		m_center,
    456 		m_halfRange,
    457 		m_softness,
    458 		m_biasFactor,
    459 		m_relaxationFactor,
    460 		m_correction,
    461 		m_sign;
    462 
    463 	bool
    464 		m_solveLimit;
    465 
    466 public:
    467 	/// Default constructor initializes limit as inactive, allowing free constraint movement
    468 	btAngularLimit()
    469 		:m_center(0.0f),
    470 		m_halfRange(-1.0f),
    471 		m_softness(0.9f),
    472 		m_biasFactor(0.3f),
    473 		m_relaxationFactor(1.0f),
    474 		m_correction(0.0f),
    475 		m_sign(0.0f),
    476 		m_solveLimit(false)
    477 	{}
    478 
    479 	/// Sets all limit's parameters.
    480 	/// When low > high limit becomes inactive.
    481 	/// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
    482 	void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f);
    483 
    484 	/// Checks conastaint angle against limit. If limit is active and the angle violates the limit
    485 	/// correction is calculated.
    486 	void test(const btScalar angle);
    487 
    488 	/// Returns limit's softness
    489 	inline btScalar getSoftness() const
    490 	{
    491 		return m_softness;
    492 	}
    493 
    494 	/// Returns limit's bias factor
    495 	inline btScalar getBiasFactor() const
    496 	{
    497 		return m_biasFactor;
    498 	}
    499 
    500 	/// Returns limit's relaxation factor
    501 	inline btScalar getRelaxationFactor() const
    502 	{
    503 		return m_relaxationFactor;
    504 	}
    505 
    506 	/// Returns correction value evaluated when test() was invoked
    507 	inline btScalar getCorrection() const
    508 	{
    509 		return m_correction;
    510 	}
    511 
    512 	/// Returns sign value evaluated when test() was invoked
    513 	inline btScalar getSign() const
    514 	{
    515 		return m_sign;
    516 	}
    517 
    518 	/// Gives half of the distance between min and max limit angle
    519 	inline btScalar getHalfRange() const
    520 	{
    521 		return m_halfRange;
    522 	}
    523 
    524 	/// Returns true when the last test() invocation recognized limit violation
    525 	inline bool isLimit() const
    526 	{
    527 		return m_solveLimit;
    528 	}
    529 
    530 	/// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
    531 	/// returned is modified so it equals to the limit closest to given angle.
    532 	void fit(btScalar& angle) const;
    533 
    534 	/// Returns correction value multiplied by sign value
    535 	btScalar getError() const;
    536 
    537 	btScalar getLow() const;
    538 
    539 	btScalar getHigh() const;
    540 
    541 };
    542 
    543 
    544 
    545 #endif //BT_TYPED_CONSTRAINT_H
    546