680 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			680 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /*
 | ||
|  | Bullet Continuous Collision Detection and Physics Library | ||
|  | Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
 | ||
|  | 
 | ||
|  | 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. | ||
|  | */ | ||
|  | 
 | ||
|  | /*
 | ||
|  | 2014 May: btGeneric6DofSpring2Constraint is created from the original (2.82.2712) btGeneric6DofConstraint by Gabor Puhr and Tamas Umenhoffer | ||
|  | Pros: | ||
|  | - Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled) | ||
|  | - Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring) | ||
|  | - Servo motor functionality | ||
|  | - Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision) | ||
|  | - Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2) | ||
|  | 
 | ||
|  | Cons: | ||
|  | - It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation. | ||
|  | - At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.) | ||
|  | */ | ||
|  | 
 | ||
|  | /// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
 | ||
|  | /// Added support for generic constraint solver through getInfo1/getInfo2 methods
 | ||
|  | 
 | ||
|  | /*
 | ||
|  | 2007-09-09 | ||
|  | btGeneric6DofConstraint Refactored by Francisco Le?n | ||
|  | email: projectileman@yahoo.com | ||
|  | http://gimpact.sf.net
 | ||
|  | */ | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifndef BT_GENERIC_6DOF_CONSTRAINT2_H
 | ||
|  | #define BT_GENERIC_6DOF_CONSTRAINT2_H
 | ||
|  | 
 | ||
|  | #include "LinearMath/btVector3.h"
 | ||
|  | #include "btJacobianEntry.h"
 | ||
|  | #include "btTypedConstraint.h"
 | ||
|  | 
 | ||
|  | class btRigidBody; | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifdef BT_USE_DOUBLE_PRECISION
 | ||
|  | #define btGeneric6DofSpring2ConstraintData2		btGeneric6DofSpring2ConstraintDoubleData2
 | ||
|  | #define btGeneric6DofSpring2ConstraintDataName	"btGeneric6DofSpring2ConstraintDoubleData2"
 | ||
|  | #else
 | ||
|  | #define btGeneric6DofSpring2ConstraintData2		btGeneric6DofSpring2ConstraintData
 | ||
|  | #define btGeneric6DofSpring2ConstraintDataName	"btGeneric6DofSpring2ConstraintData"
 | ||
|  | #endif //BT_USE_DOUBLE_PRECISION
 | ||
|  | 
 | ||
|  | enum RotateOrder | ||
|  | { | ||
|  | 	RO_XYZ=0, | ||
|  | 	RO_XZY, | ||
|  | 	RO_YXZ, | ||
|  | 	RO_YZX, | ||
|  | 	RO_ZXY, | ||
|  | 	RO_ZYX | ||
|  | }; | ||
|  | 
 | ||
|  | class btRotationalLimitMotor2 | ||
|  | { | ||
|  | public: | ||
|  | // upper < lower means free
 | ||
|  | // upper == lower means locked
 | ||
|  | // upper > lower means limited
 | ||
|  | 	btScalar m_loLimit; | ||
|  | 	btScalar m_hiLimit; | ||
|  | 	btScalar m_bounce; | ||
|  | 	btScalar m_stopERP; | ||
|  | 	btScalar m_stopCFM; | ||
|  | 	btScalar m_motorERP; | ||
|  | 	btScalar m_motorCFM; | ||
|  | 	bool     m_enableMotor; | ||
|  | 	btScalar m_targetVelocity; | ||
|  | 	btScalar m_maxMotorForce; | ||
|  | 	bool     m_servoMotor; | ||
|  | 	btScalar m_servoTarget; | ||
|  | 	bool     m_enableSpring; | ||
|  | 	btScalar m_springStiffness; | ||
|  | 	bool     m_springStiffnessLimited; | ||
|  | 	btScalar m_springDamping; | ||
|  | 	bool     m_springDampingLimited; | ||
|  | 	btScalar m_equilibriumPoint; | ||
|  | 
 | ||
|  | 	btScalar m_currentLimitError; | ||
|  | 	btScalar m_currentLimitErrorHi; | ||
|  | 	btScalar m_currentPosition; | ||
|  | 	int      m_currentLimit; | ||
|  | 
 | ||
|  | 	btRotationalLimitMotor2() | ||
|  | 	{ | ||
|  | 		m_loLimit                = 1.0f; | ||
|  | 		m_hiLimit                = -1.0f; | ||
|  | 		m_bounce                 = 0.0f; | ||
|  | 		m_stopERP                = 0.2f; | ||
|  | 		m_stopCFM                = 0.f; | ||
|  | 		m_motorERP               = 0.9f; | ||
|  | 		m_motorCFM               = 0.f; | ||
|  | 		m_enableMotor            = false; | ||
|  | 		m_targetVelocity         = 0; | ||
|  | 		m_maxMotorForce          = 0.1f; | ||
|  | 		m_servoMotor             = false; | ||
|  | 		m_servoTarget            = 0; | ||
|  | 		m_enableSpring           = false; | ||
|  | 		m_springStiffness        = 0; | ||
|  | 		m_springStiffnessLimited = false; | ||
|  | 		m_springDamping          = 0; | ||
|  | 		m_springDampingLimited   = false; | ||
|  | 		m_equilibriumPoint       = 0; | ||
|  | 
 | ||
|  | 		m_currentLimitError   = 0; | ||
|  | 		m_currentLimitErrorHi = 0; | ||
|  | 		m_currentPosition     = 0; | ||
|  | 		m_currentLimit        = 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	btRotationalLimitMotor2(const btRotationalLimitMotor2 & limot) | ||
|  | 	{ | ||
|  | 		m_loLimit                = limot.m_loLimit; | ||
|  | 		m_hiLimit                = limot.m_hiLimit; | ||
|  | 		m_bounce                 = limot.m_bounce; | ||
|  | 		m_stopERP                = limot.m_stopERP; | ||
|  | 		m_stopCFM                = limot.m_stopCFM; | ||
|  | 		m_motorERP               = limot.m_motorERP; | ||
|  | 		m_motorCFM               = limot.m_motorCFM; | ||
|  | 		m_enableMotor            = limot.m_enableMotor; | ||
|  | 		m_targetVelocity         = limot.m_targetVelocity; | ||
|  | 		m_maxMotorForce          = limot.m_maxMotorForce; | ||
|  | 		m_servoMotor             = limot.m_servoMotor; | ||
|  | 		m_servoTarget            = limot.m_servoTarget; | ||
|  | 		m_enableSpring           = limot.m_enableSpring; | ||
|  | 		m_springStiffness        = limot.m_springStiffness; | ||
|  | 		m_springStiffnessLimited = limot.m_springStiffnessLimited; | ||
|  | 		m_springDamping          = limot.m_springDamping; | ||
|  | 		m_springDampingLimited   = limot.m_springDampingLimited; | ||
|  | 		m_equilibriumPoint       = limot.m_equilibriumPoint; | ||
|  | 
 | ||
|  | 		m_currentLimitError   = limot.m_currentLimitError; | ||
|  | 		m_currentLimitErrorHi = limot.m_currentLimitErrorHi; | ||
|  | 		m_currentPosition     = limot.m_currentPosition; | ||
|  | 		m_currentLimit        = limot.m_currentLimit; | ||
|  | 	} | ||
|  | 
 | ||
|  | 
 | ||
|  | 	bool isLimited() | ||
|  | 	{ | ||
|  | 		if(m_loLimit > m_hiLimit) return false; | ||
|  | 		return true; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void testLimitValue(btScalar test_value); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | class btTranslationalLimitMotor2 | ||
|  | { | ||
|  | public: | ||
|  | // upper < lower means free
 | ||
|  | // upper == lower means locked
 | ||
|  | // upper > lower means limited
 | ||
|  | 	btVector3 m_lowerLimit; | ||
|  | 	btVector3 m_upperLimit; | ||
|  | 	btVector3 m_bounce; | ||
|  | 	btVector3 m_stopERP; | ||
|  | 	btVector3 m_stopCFM; | ||
|  | 	btVector3 m_motorERP; | ||
|  | 	btVector3 m_motorCFM; | ||
|  | 	bool      m_enableMotor[3]; | ||
|  | 	bool      m_servoMotor[3]; | ||
|  | 	bool      m_enableSpring[3]; | ||
|  | 	btVector3 m_servoTarget; | ||
|  | 	btVector3 m_springStiffness; | ||
|  | 	bool      m_springStiffnessLimited[3]; | ||
|  | 	btVector3 m_springDamping; | ||
|  | 	bool      m_springDampingLimited[3]; | ||
|  | 	btVector3 m_equilibriumPoint; | ||
|  | 	btVector3 m_targetVelocity; | ||
|  | 	btVector3 m_maxMotorForce; | ||
|  | 
 | ||
|  | 	btVector3 m_currentLimitError; | ||
|  | 	btVector3 m_currentLimitErrorHi; | ||
|  | 	btVector3 m_currentLinearDiff; | ||
|  | 	int       m_currentLimit[3]; | ||
|  | 
 | ||
|  | 	btTranslationalLimitMotor2() | ||
|  | 	{ | ||
|  | 		m_lowerLimit         .setValue(0.f , 0.f , 0.f ); | ||
|  | 		m_upperLimit         .setValue(0.f , 0.f , 0.f ); | ||
|  | 		m_bounce             .setValue(0.f , 0.f , 0.f ); | ||
|  | 		m_stopERP            .setValue(0.2f, 0.2f, 0.2f); | ||
|  | 		m_stopCFM            .setValue(0.f , 0.f , 0.f ); | ||
|  | 		m_motorERP           .setValue(0.9f, 0.9f, 0.9f); | ||
|  | 		m_motorCFM           .setValue(0.f , 0.f , 0.f ); | ||
|  | 
 | ||
|  | 		m_currentLimitError  .setValue(0.f , 0.f , 0.f ); | ||
|  | 		m_currentLimitErrorHi.setValue(0.f , 0.f , 0.f ); | ||
|  | 		m_currentLinearDiff  .setValue(0.f , 0.f , 0.f ); | ||
|  | 
 | ||
|  | 		for(int i=0; i < 3; i++)  | ||
|  | 		{ | ||
|  | 			m_enableMotor[i]            = false; | ||
|  | 			m_servoMotor[i]             = false; | ||
|  | 			m_enableSpring[i]           = false; | ||
|  | 			m_servoTarget[i]            = btScalar(0.f); | ||
|  | 			m_springStiffness[i]        = btScalar(0.f); | ||
|  | 			m_springStiffnessLimited[i] = false; | ||
|  | 			m_springDamping[i]          = btScalar(0.f); | ||
|  | 			m_springDampingLimited[i]   = false; | ||
|  | 			m_equilibriumPoint[i]       = btScalar(0.f); | ||
|  | 			m_targetVelocity[i]         = btScalar(0.f); | ||
|  | 			m_maxMotorForce[i]          = btScalar(0.f); | ||
|  | 			 | ||
|  | 			m_currentLimit[i]     = 0; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	btTranslationalLimitMotor2(const btTranslationalLimitMotor2 & other ) | ||
|  | 	{ | ||
|  | 		m_lowerLimit          = other.m_lowerLimit; | ||
|  | 		m_upperLimit          = other.m_upperLimit; | ||
|  | 		m_bounce              = other.m_bounce; | ||
|  | 		m_stopERP             = other.m_stopERP; | ||
|  | 		m_stopCFM             = other.m_stopCFM; | ||
|  | 		m_motorERP            = other.m_motorERP; | ||
|  | 		m_motorCFM            = other.m_motorCFM; | ||
|  | 		 | ||
|  | 		m_currentLimitError   = other.m_currentLimitError; | ||
|  | 		m_currentLimitErrorHi = other.m_currentLimitErrorHi; | ||
|  | 		m_currentLinearDiff   = other.m_currentLinearDiff; | ||
|  | 
 | ||
|  | 		for(int i=0; i < 3; i++)  | ||
|  | 		{ | ||
|  | 			m_enableMotor[i]            = other.m_enableMotor[i]; | ||
|  | 			m_servoMotor[i]             = other.m_servoMotor[i]; | ||
|  | 			m_enableSpring[i]           = other.m_enableSpring[i]; | ||
|  | 			m_servoTarget[i]            = other.m_servoTarget[i]; | ||
|  | 			m_springStiffness[i]        = other.m_springStiffness[i]; | ||
|  | 			m_springStiffnessLimited[i] = other.m_springStiffnessLimited[i]; | ||
|  | 			m_springDamping[i]          = other.m_springDamping[i]; | ||
|  | 			m_springDampingLimited[i]   = other.m_springDampingLimited[i]; | ||
|  | 			m_equilibriumPoint[i]       = other.m_equilibriumPoint[i]; | ||
|  | 			m_targetVelocity[i]         = other.m_targetVelocity[i]; | ||
|  | 			m_maxMotorForce[i]          = other.m_maxMotorForce[i]; | ||
|  | 
 | ||
|  | 			m_currentLimit[i]     = other.m_currentLimit[i]; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	inline bool isLimited(int limitIndex) | ||
|  | 	{ | ||
|  | 		return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void testLimitValue(int limitIndex, btScalar test_value); | ||
|  | }; | ||
|  | 
 | ||
|  | enum bt6DofFlags2 | ||
|  | { | ||
|  | 	BT_6DOF_FLAGS_CFM_STOP2 = 1, | ||
|  | 	BT_6DOF_FLAGS_ERP_STOP2 = 2, | ||
|  | 	BT_6DOF_FLAGS_CFM_MOTO2 = 4, | ||
|  | 	BT_6DOF_FLAGS_ERP_MOTO2 = 8 | ||
|  | }; | ||
|  | #define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis
 | ||
|  | 
 | ||
|  | 
 | ||
|  | ATTRIBUTE_ALIGNED16(class) btGeneric6DofSpring2Constraint : public btTypedConstraint | ||
|  | { | ||
|  | protected: | ||
|  | 
 | ||
|  | 	btTransform m_frameInA; | ||
|  | 	btTransform m_frameInB; | ||
|  | 
 | ||
|  | 	btJacobianEntry m_jacLinear[3]; | ||
|  | 	btJacobianEntry m_jacAng[3]; | ||
|  | 
 | ||
|  | 	btTranslationalLimitMotor2 m_linearLimits; | ||
|  | 	btRotationalLimitMotor2 m_angularLimits[3]; | ||
|  | 
 | ||
|  | 	RotateOrder m_rotateOrder; | ||
|  | 
 | ||
|  | protected: | ||
|  | 
 | ||
|  | 	btTransform  m_calculatedTransformA; | ||
|  | 	btTransform  m_calculatedTransformB; | ||
|  | 	btVector3    m_calculatedAxisAngleDiff; | ||
|  | 	btVector3    m_calculatedAxis[3]; | ||
|  | 	btVector3    m_calculatedLinearDiff; | ||
|  | 	btScalar     m_factA; | ||
|  | 	btScalar     m_factB; | ||
|  | 	bool         m_hasStaticBody; | ||
|  | 	int          m_flags; | ||
|  | 
 | ||
|  | 	btGeneric6DofSpring2Constraint&	operator=(btGeneric6DofSpring2Constraint&) | ||
|  | 	{ | ||
|  | 		btAssert(0); | ||
|  | 		return *this; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); | ||
|  | 	int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB); | ||
|  | 
 | ||
|  | 	void calculateLinearInfo(); | ||
|  | 	void calculateAngleInfo(); | ||
|  | 	void testAngularLimitMotor(int axis_index); | ||
|  | 
 | ||
|  | 	void calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA,const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed); | ||
|  | 	int get_limit_motor_info2(btRotationalLimitMotor2* limot, | ||
|  | 		const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB, | ||
|  | 		btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false); | ||
|  | 
 | ||
|  | public: | ||
|  | 
 | ||
|  | 	BT_DECLARE_ALIGNED_ALLOCATOR(); | ||
|  | 
 | ||
|  |     btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ); | ||
|  |     btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ); | ||
|  | 
 | ||
|  | 	virtual void buildJacobian() {} | ||
|  | 	virtual void getInfo1 (btConstraintInfo1* info); | ||
|  | 	virtual void getInfo2 (btConstraintInfo2* info); | ||
|  | 	virtual int calculateSerializeBufferSize() const; | ||
|  | 	virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const; | ||
|  | 
 | ||
|  | 	btRotationalLimitMotor2* getRotationalLimitMotor(int index) { return &m_angularLimits[index]; } | ||
|  | 	btTranslationalLimitMotor2* getTranslationalLimitMotor() { return &m_linearLimits; } | ||
|  | 
 | ||
|  | 	// Calculates the global transform for the joint offset for body A an B, and also calculates the angle differences between the bodies.
 | ||
|  | 	void calculateTransforms(const btTransform& transA,const btTransform& transB); | ||
|  | 	void calculateTransforms(); | ||
|  | 
 | ||
|  | 	// Gets the global transform of the offset for body A
 | ||
|  | 	const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } | ||
|  | 	// Gets the global transform of the offset for body B
 | ||
|  | 	const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } | ||
|  | 
 | ||
|  | 	const btTransform & getFrameOffsetA() const { return m_frameInA; } | ||
|  | 	const btTransform & getFrameOffsetB() const { return m_frameInB; } | ||
|  | 
 | ||
|  | 	btTransform & getFrameOffsetA() { return m_frameInA; } | ||
|  | 	btTransform & getFrameOffsetB() { return m_frameInB; } | ||
|  | 
 | ||
|  | 	// Get the rotation axis in global coordinates ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
 | ||
|  | 	btVector3 getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; } | ||
|  | 
 | ||
|  | 	// Get the relative Euler angle ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
 | ||
|  | 	btScalar getAngle(int axis_index) const { return m_calculatedAxisAngleDiff[axis_index]; } | ||
|  | 
 | ||
|  | 	// Get the relative position of the constraint pivot ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
 | ||
|  | 	btScalar getRelativePivotPosition(int axis_index) const { return m_calculatedLinearDiff[axis_index]; } | ||
|  | 
 | ||
|  | 	void setFrames(const btTransform & frameA, const btTransform & frameB); | ||
|  | 
 | ||
|  | 	void setLinearLowerLimit(const btVector3& linearLower) { m_linearLimits.m_lowerLimit = linearLower; } | ||
|  | 	void getLinearLowerLimit(btVector3& linearLower) { linearLower = m_linearLimits.m_lowerLimit; } | ||
|  | 	void setLinearUpperLimit(const btVector3& linearUpper) { m_linearLimits.m_upperLimit = linearUpper; } | ||
|  | 	void getLinearUpperLimit(btVector3& linearUpper) { linearUpper = m_linearLimits.m_upperLimit; } | ||
|  | 
 | ||
|  | 	void setAngularLowerLimit(const btVector3& angularLower) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++)  | ||
|  | 			m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void setAngularLowerLimitReversed(const btVector3& angularLower) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++)  | ||
|  | 			m_angularLimits[i].m_hiLimit = btNormalizeAngle(-angularLower[i]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void getAngularLowerLimit(btVector3& angularLower) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++)  | ||
|  | 			angularLower[i] = m_angularLimits[i].m_loLimit; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void getAngularLowerLimitReversed(btVector3& angularLower) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++) | ||
|  | 			angularLower[i] = -m_angularLimits[i].m_hiLimit; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void setAngularUpperLimit(const btVector3& angularUpper) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++) | ||
|  | 			m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void setAngularUpperLimitReversed(const btVector3& angularUpper) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++) | ||
|  | 			m_angularLimits[i].m_loLimit = btNormalizeAngle(-angularUpper[i]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void getAngularUpperLimit(btVector3& angularUpper) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++) | ||
|  | 			angularUpper[i] = m_angularLimits[i].m_hiLimit; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void getAngularUpperLimitReversed(btVector3& angularUpper) | ||
|  | 	{ | ||
|  | 		for(int i = 0; i < 3; i++) | ||
|  | 			angularUpper[i] = -m_angularLimits[i].m_loLimit; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	//first 3 are linear, next 3 are angular
 | ||
|  | 
 | ||
|  | 	void setLimit(int axis, btScalar lo, btScalar hi) | ||
|  | 	{ | ||
|  | 		if(axis<3) | ||
|  | 		{ | ||
|  | 			m_linearLimits.m_lowerLimit[axis] = lo; | ||
|  | 			m_linearLimits.m_upperLimit[axis] = hi; | ||
|  | 		} | ||
|  | 		else | ||
|  | 		{ | ||
|  | 			lo = btNormalizeAngle(lo); | ||
|  | 			hi = btNormalizeAngle(hi); | ||
|  | 			m_angularLimits[axis-3].m_loLimit = lo; | ||
|  | 			m_angularLimits[axis-3].m_hiLimit = hi; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void setLimitReversed(int axis, btScalar lo, btScalar hi) | ||
|  | 	{ | ||
|  | 		if(axis<3) | ||
|  | 		{ | ||
|  | 			m_linearLimits.m_lowerLimit[axis] = lo; | ||
|  | 			m_linearLimits.m_upperLimit[axis] = hi; | ||
|  | 		} | ||
|  | 		else | ||
|  | 		{ | ||
|  | 			lo = btNormalizeAngle(lo); | ||
|  | 			hi = btNormalizeAngle(hi); | ||
|  | 			m_angularLimits[axis-3].m_hiLimit = -lo; | ||
|  | 			m_angularLimits[axis-3].m_loLimit = -hi; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	bool isLimited(int limitIndex) | ||
|  | 	{ | ||
|  | 		if(limitIndex<3) | ||
|  | 		{ | ||
|  | 			return m_linearLimits.isLimited(limitIndex); | ||
|  | 		} | ||
|  | 		return m_angularLimits[limitIndex-3].isLimited(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	void setRotationOrder(RotateOrder order) { m_rotateOrder = order; } | ||
|  | 	RotateOrder getRotationOrder() { return m_rotateOrder; } | ||
|  | 
 | ||
|  | 	void setAxis( const btVector3& axis1, const btVector3& axis2); | ||
|  | 
 | ||
|  | 	void setBounce(int index, btScalar bounce); | ||
|  | 
 | ||
|  | 	void enableMotor(int index, bool onOff); | ||
|  | 	void setServo(int index, bool onOff); // set the type of the motor (servo or not) (the motor has to be turned on for servo also)
 | ||
|  | 	void setTargetVelocity(int index, btScalar velocity); | ||
|  | 	void setServoTarget(int index, btScalar target); | ||
|  | 	void setMaxMotorForce(int index, btScalar force); | ||
|  | 
 | ||
|  | 	void enableSpring(int index, bool onOff); | ||
|  | 	void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely
 | ||
|  | 	void setDamping(int index, btScalar damping, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up
 | ||
|  | 	void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
 | ||
|  | 	void setEquilibriumPoint(int index);  // set the current constraint position/orientation as an equilibrium point for given DOF
 | ||
|  | 	void setEquilibriumPoint(int index, btScalar val); | ||
|  | 
 | ||
|  | 	//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
 | ||
|  | 	//If no axis is provided, it uses the default axis for this constraint.
 | ||
|  | 	virtual void setParam(int num, btScalar value, int axis = -1); | ||
|  | 	virtual btScalar getParam(int num, int axis = -1) const; | ||
|  |      | ||
|  |     static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); | ||
|  |     static bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); | ||
|  |     static bool matrixToEulerXZY(const btMatrix3x3& mat,btVector3& xyz); | ||
|  |     static bool matrixToEulerYXZ(const btMatrix3x3& mat,btVector3& xyz); | ||
|  |     static bool matrixToEulerYZX(const btMatrix3x3& mat,btVector3& xyz); | ||
|  |     static bool matrixToEulerZXY(const btMatrix3x3& mat,btVector3& xyz); | ||
|  |     static bool matrixToEulerZYX(const btMatrix3x3& mat,btVector3& xyz); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | struct btGeneric6DofSpring2ConstraintData | ||
|  | { | ||
|  | 	btTypedConstraintData m_typeConstraintData; | ||
|  | 	btTransformFloatData m_rbAFrame; | ||
|  | 	btTransformFloatData m_rbBFrame; | ||
|  | 
 | ||
|  | 	btVector3FloatData m_linearUpperLimit; | ||
|  | 	btVector3FloatData m_linearLowerLimit; | ||
|  | 	btVector3FloatData m_linearBounce; | ||
|  | 	btVector3FloatData m_linearStopERP; | ||
|  | 	btVector3FloatData m_linearStopCFM; | ||
|  | 	btVector3FloatData m_linearMotorERP; | ||
|  | 	btVector3FloatData m_linearMotorCFM; | ||
|  | 	btVector3FloatData m_linearTargetVelocity; | ||
|  | 	btVector3FloatData m_linearMaxMotorForce; | ||
|  | 	btVector3FloatData m_linearServoTarget; | ||
|  | 	btVector3FloatData m_linearSpringStiffness; | ||
|  | 	btVector3FloatData m_linearSpringDamping; | ||
|  | 	btVector3FloatData m_linearEquilibriumPoint; | ||
|  | 	char               m_linearEnableMotor[4]; | ||
|  | 	char               m_linearServoMotor[4]; | ||
|  | 	char               m_linearEnableSpring[4]; | ||
|  | 	char               m_linearSpringStiffnessLimited[4]; | ||
|  | 	char               m_linearSpringDampingLimited[4]; | ||
|  | 	char               m_padding1[4]; | ||
|  | 
 | ||
|  | 	btVector3FloatData m_angularUpperLimit; | ||
|  | 	btVector3FloatData m_angularLowerLimit; | ||
|  | 	btVector3FloatData m_angularBounce; | ||
|  | 	btVector3FloatData m_angularStopERP; | ||
|  | 	btVector3FloatData m_angularStopCFM; | ||
|  | 	btVector3FloatData m_angularMotorERP; | ||
|  | 	btVector3FloatData m_angularMotorCFM; | ||
|  | 	btVector3FloatData m_angularTargetVelocity; | ||
|  | 	btVector3FloatData m_angularMaxMotorForce; | ||
|  | 	btVector3FloatData m_angularServoTarget; | ||
|  | 	btVector3FloatData m_angularSpringStiffness; | ||
|  | 	btVector3FloatData m_angularSpringDamping; | ||
|  | 	btVector3FloatData m_angularEquilibriumPoint; | ||
|  | 	char               m_angularEnableMotor[4]; | ||
|  | 	char               m_angularServoMotor[4]; | ||
|  | 	char               m_angularEnableSpring[4]; | ||
|  | 	char               m_angularSpringStiffnessLimited[4]; | ||
|  | 	char               m_angularSpringDampingLimited[4]; | ||
|  | 
 | ||
|  | 	int                m_rotateOrder; | ||
|  | }; | ||
|  | 
 | ||
|  | struct btGeneric6DofSpring2ConstraintDoubleData2 | ||
|  | { | ||
|  | 	btTypedConstraintDoubleData m_typeConstraintData; | ||
|  | 	btTransformDoubleData m_rbAFrame; | ||
|  | 	btTransformDoubleData m_rbBFrame; | ||
|  | 
 | ||
|  | 	btVector3DoubleData m_linearUpperLimit; | ||
|  | 	btVector3DoubleData m_linearLowerLimit; | ||
|  | 	btVector3DoubleData m_linearBounce; | ||
|  | 	btVector3DoubleData m_linearStopERP; | ||
|  | 	btVector3DoubleData m_linearStopCFM; | ||
|  | 	btVector3DoubleData m_linearMotorERP; | ||
|  | 	btVector3DoubleData m_linearMotorCFM; | ||
|  | 	btVector3DoubleData m_linearTargetVelocity; | ||
|  | 	btVector3DoubleData m_linearMaxMotorForce; | ||
|  | 	btVector3DoubleData m_linearServoTarget; | ||
|  | 	btVector3DoubleData m_linearSpringStiffness; | ||
|  | 	btVector3DoubleData m_linearSpringDamping; | ||
|  | 	btVector3DoubleData m_linearEquilibriumPoint; | ||
|  | 	char                m_linearEnableMotor[4]; | ||
|  | 	char                m_linearServoMotor[4]; | ||
|  | 	char                m_linearEnableSpring[4]; | ||
|  | 	char                m_linearSpringStiffnessLimited[4]; | ||
|  | 	char                m_linearSpringDampingLimited[4]; | ||
|  | 	char                m_padding1[4]; | ||
|  | 
 | ||
|  | 	btVector3DoubleData m_angularUpperLimit; | ||
|  | 	btVector3DoubleData m_angularLowerLimit; | ||
|  | 	btVector3DoubleData m_angularBounce; | ||
|  | 	btVector3DoubleData m_angularStopERP; | ||
|  | 	btVector3DoubleData m_angularStopCFM; | ||
|  | 	btVector3DoubleData m_angularMotorERP; | ||
|  | 	btVector3DoubleData m_angularMotorCFM; | ||
|  | 	btVector3DoubleData m_angularTargetVelocity; | ||
|  | 	btVector3DoubleData m_angularMaxMotorForce; | ||
|  | 	btVector3DoubleData m_angularServoTarget; | ||
|  | 	btVector3DoubleData m_angularSpringStiffness; | ||
|  | 	btVector3DoubleData m_angularSpringDamping; | ||
|  | 	btVector3DoubleData m_angularEquilibriumPoint; | ||
|  | 	char                m_angularEnableMotor[4]; | ||
|  | 	char                m_angularServoMotor[4]; | ||
|  | 	char                m_angularEnableSpring[4]; | ||
|  | 	char                m_angularSpringStiffnessLimited[4]; | ||
|  | 	char                m_angularSpringDampingLimited[4]; | ||
|  | 
 | ||
|  | 	int                 m_rotateOrder; | ||
|  | }; | ||
|  | 
 | ||
|  | SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSize() const | ||
|  | { | ||
|  | 	return sizeof(btGeneric6DofSpring2ConstraintData2); | ||
|  | } | ||
|  | 
 | ||
|  | SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* dataBuffer, btSerializer* serializer) const | ||
|  | { | ||
|  | 	btGeneric6DofSpring2ConstraintData2* dof = (btGeneric6DofSpring2ConstraintData2*)dataBuffer; | ||
|  | 	btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer); | ||
|  | 
 | ||
|  | 	m_frameInA.serialize(dof->m_rbAFrame); | ||
|  | 	m_frameInB.serialize(dof->m_rbBFrame); | ||
|  | 
 | ||
|  | 	int i; | ||
|  | 	for (i=0;i<3;i++) | ||
|  | 	{ | ||
|  | 		dof->m_angularLowerLimit.m_floats[i]       = m_angularLimits[i].m_loLimit; | ||
|  | 		dof->m_angularUpperLimit.m_floats[i]       = m_angularLimits[i].m_hiLimit; | ||
|  | 		dof->m_angularBounce.m_floats[i]           = m_angularLimits[i].m_bounce; | ||
|  | 		dof->m_angularStopERP.m_floats[i]          = m_angularLimits[i].m_stopERP; | ||
|  | 		dof->m_angularStopCFM.m_floats[i]          = m_angularLimits[i].m_stopCFM; | ||
|  | 		dof->m_angularMotorERP.m_floats[i]         = m_angularLimits[i].m_motorERP; | ||
|  | 		dof->m_angularMotorCFM.m_floats[i]         = m_angularLimits[i].m_motorCFM; | ||
|  | 		dof->m_angularTargetVelocity.m_floats[i]   = m_angularLimits[i].m_targetVelocity; | ||
|  | 		dof->m_angularMaxMotorForce.m_floats[i]    = m_angularLimits[i].m_maxMotorForce; | ||
|  | 		dof->m_angularServoTarget.m_floats[i]      = m_angularLimits[i].m_servoTarget; | ||
|  | 		dof->m_angularSpringStiffness.m_floats[i]  = m_angularLimits[i].m_springStiffness; | ||
|  | 		dof->m_angularSpringDamping.m_floats[i]    = m_angularLimits[i].m_springDamping; | ||
|  | 		dof->m_angularEquilibriumPoint.m_floats[i] = m_angularLimits[i].m_equilibriumPoint; | ||
|  | 	} | ||
|  | 	dof->m_angularLowerLimit.m_floats[3]       = 0; | ||
|  | 	dof->m_angularUpperLimit.m_floats[3]       = 0; | ||
|  | 	dof->m_angularBounce.m_floats[3]           = 0; | ||
|  | 	dof->m_angularStopERP.m_floats[3]          = 0; | ||
|  | 	dof->m_angularStopCFM.m_floats[3]          = 0; | ||
|  | 	dof->m_angularMotorERP.m_floats[3]         = 0; | ||
|  | 	dof->m_angularMotorCFM.m_floats[3]         = 0; | ||
|  | 	dof->m_angularTargetVelocity.m_floats[3]   = 0; | ||
|  | 	dof->m_angularMaxMotorForce.m_floats[3]    = 0; | ||
|  | 	dof->m_angularServoTarget.m_floats[3]      = 0; | ||
|  | 	dof->m_angularSpringStiffness.m_floats[3]  = 0; | ||
|  | 	dof->m_angularSpringDamping.m_floats[3]    = 0; | ||
|  | 	dof->m_angularEquilibriumPoint.m_floats[3] = 0; | ||
|  | 	for (i=0;i<4;i++) | ||
|  | 	{ | ||
|  | 		dof->m_angularEnableMotor[i]            = i < 3 ? ( m_angularLimits[i].m_enableMotor ? 1 : 0 ) : 0; | ||
|  | 		dof->m_angularServoMotor[i]             = i < 3 ? ( m_angularLimits[i].m_servoMotor ? 1 : 0 ) : 0; | ||
|  | 		dof->m_angularEnableSpring[i]           = i < 3 ? ( m_angularLimits[i].m_enableSpring ? 1 : 0 ) : 0; | ||
|  | 		dof->m_angularSpringStiffnessLimited[i] = i < 3 ? ( m_angularLimits[i].m_springStiffnessLimited ? 1 : 0 ) : 0; | ||
|  | 		dof->m_angularSpringDampingLimited[i]   = i < 3 ? ( m_angularLimits[i].m_springDampingLimited ? 1 : 0 ) : 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	m_linearLimits.m_lowerLimit.serialize( dof->m_linearLowerLimit ); | ||
|  | 	m_linearLimits.m_upperLimit.serialize( dof->m_linearUpperLimit ); | ||
|  | 	m_linearLimits.m_bounce.serialize( dof->m_linearBounce ); | ||
|  | 	m_linearLimits.m_stopERP.serialize( dof->m_linearStopERP ); | ||
|  | 	m_linearLimits.m_stopCFM.serialize( dof->m_linearStopCFM ); | ||
|  | 	m_linearLimits.m_motorERP.serialize( dof->m_linearMotorERP ); | ||
|  | 	m_linearLimits.m_motorCFM.serialize( dof->m_linearMotorCFM ); | ||
|  | 	m_linearLimits.m_targetVelocity.serialize( dof->m_linearTargetVelocity ); | ||
|  | 	m_linearLimits.m_maxMotorForce.serialize( dof->m_linearMaxMotorForce ); | ||
|  | 	m_linearLimits.m_servoTarget.serialize( dof->m_linearServoTarget ); | ||
|  | 	m_linearLimits.m_springStiffness.serialize( dof->m_linearSpringStiffness ); | ||
|  | 	m_linearLimits.m_springDamping.serialize( dof->m_linearSpringDamping ); | ||
|  | 	m_linearLimits.m_equilibriumPoint.serialize( dof->m_linearEquilibriumPoint ); | ||
|  | 	for (i=0;i<4;i++) | ||
|  | 	{ | ||
|  | 		dof->m_linearEnableMotor[i]            = i < 3 ? ( m_linearLimits.m_enableMotor[i] ? 1 : 0 ) : 0; | ||
|  | 		dof->m_linearServoMotor[i]             = i < 3 ? ( m_linearLimits.m_servoMotor[i] ? 1 : 0 ) : 0; | ||
|  | 		dof->m_linearEnableSpring[i]           = i < 3 ? ( m_linearLimits.m_enableSpring[i] ? 1 : 0 ) : 0; | ||
|  | 		dof->m_linearSpringStiffnessLimited[i] = i < 3 ? ( m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0 ) : 0; | ||
|  | 		dof->m_linearSpringDampingLimited[i]   = i < 3 ? ( m_linearLimits.m_springDampingLimited[i] ? 1 : 0 ) : 0; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	dof->m_rotateOrder = m_rotateOrder; | ||
|  | 
 | ||
|  | 	dof->m_padding1[0] = 0; | ||
|  | 	dof->m_padding1[1] = 0; | ||
|  | 	dof->m_padding1[2] = 0; | ||
|  | 	dof->m_padding1[3] = 0; | ||
|  | 
 | ||
|  | 	return btGeneric6DofSpring2ConstraintDataName; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #endif //BT_GENERIC_6DOF_CONSTRAINT_H
 |