diff options
Diffstat (limited to 'source/gameengine/Physics/Bullet')
4 files changed, 136 insertions, 22 deletions
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 4fd1f10fad6..8ecb586f77e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -697,6 +697,35 @@ CcdPhysicsController::~CcdPhysicsController() } } +void CcdPhysicsController::SimulationTick(float timestep) +{ + btRigidBody *body = GetRigidBody(); + if (!body || body->isStaticObject()) + return; + + // Clamp linear velocity + if (m_cci.m_clamp_vel_max > 0.0f || m_cci.m_clamp_vel_min > 0.0f) { + const btVector3 &linvel = body->getLinearVelocity(); + btScalar len = linvel.length(); + + if (m_cci.m_clamp_vel_max > 0.0f && len > m_cci.m_clamp_vel_max) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len)); + else if (m_cci.m_clamp_vel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_vel_min) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); + } + + // Clamp angular velocity + if (m_cci.m_clamp_angvel_max > 0.0f || m_cci.m_clamp_angvel_min > 0.0f) { + const btVector3 &angvel = body->getAngularVelocity(); + btScalar len = angvel.length(); + + if (m_cci.m_clamp_angvel_max > 0.0f && len > m_cci.m_clamp_angvel_max) + body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_max / len)); + else if (m_cci.m_clamp_angvel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_angvel_min) + body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_min / len)); + } +} + /** * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding') @@ -732,19 +761,6 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) if (body && !body->isStaticObject()) { - - if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0)) - { - const btVector3& linvel = body->getLinearVelocity(); - float len= linvel.length(); - - if ((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max)) - body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len)); - - else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min)) - body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); - } - const btTransform& xform = body->getCenterOfMassTransform(); const btMatrix3x3& worldOri = xform.getBasis(); const btVector3& worldPos = xform.getOrigin(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index b1d38763fbb..c49ae8d20e1 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -236,6 +236,8 @@ struct CcdConstructionInfo m_mass(0.f), m_clamp_vel_min(-1.f), m_clamp_vel_max(-1.f), + m_clamp_angvel_min(0.0f), + m_clamp_angvel_max(0.0f), m_restitution(0.1f), m_friction(0.5f), m_linearDamping(0.1f), @@ -302,6 +304,8 @@ struct CcdConstructionInfo btScalar m_mass; btScalar m_clamp_vel_min; btScalar m_clamp_vel_max; + btScalar m_clamp_angvel_min; // Minimum angular velocity, in radians/sec. + btScalar m_clamp_angvel_max; // Maximum angular velocity, in radians/sec. btScalar m_restitution; btScalar m_friction; btScalar m_linearDamping; @@ -579,6 +583,13 @@ protected: * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding') */ virtual bool SynchronizeMotionStates(float time); + + /** + * Called for every physics simulation step. Use this method for + * things like limiting linear and angular velocity. + */ + void SimulationTick(float timestep); + /** * WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding') */ @@ -701,6 +712,23 @@ protected: return m_cci.m_clamp_vel_max; } + virtual void SetAngularVelocityMin(float val) + { + m_cci.m_clamp_angvel_min = val; + } + virtual float GetAngularVelocityMin() const + { + return m_cci.m_clamp_angvel_min; + } + virtual void SetAngularVelocityMax(float val) + { + m_cci.m_clamp_angvel_max = val; + } + virtual float GetAngularVelocityMax() const + { + return m_cci.m_clamp_angvel_max; + } + bool WantsSleeping(); void UpdateDeactivation(float timeStep); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 89c8c124bc8..759e8bd6f7e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -410,6 +410,10 @@ m_ccdMode(0), m_solverType(-1), m_profileTimings(0), m_enableSatCollisionDetection(false), +m_deactivationTime(2.0f), +m_linearDeactivationThreshold(0.8f), +m_angularDeactivationThreshold(1.0f), +m_contactBreakingThreshold(0.02f), m_solver(NULL), m_ownPairCache(NULL), m_filterCallback(NULL), @@ -452,6 +456,7 @@ m_scalingPropagated(false) SetSolverType(1);//issues with quickstep and memory allocations // m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld->setInternalTickCallback(&CcdPhysicsEnvironment::StaticSimulationSubtickCallback, this); //m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f; //m_dynamicsWorld->getSolverInfo().m_solverMode= SOLVER_USE_WARMSTARTING + SOLVER_USE_2_FRICTION_DIRECTIONS + SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING; @@ -471,8 +476,10 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) //this m_userPointer is just used for triggers, see CallbackTriggers obj->setUserPointer(ctrl); - if (body) - body->setGravity( m_gravity ); + if (body) { + body->setGravity(m_gravity); + body->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold); + } if (body) { @@ -677,11 +684,31 @@ void CcdPhysicsEnvironment::DebugDrawWorld() m_dynamicsWorld->debugDrawWorld(); } +void CcdPhysicsEnvironment::StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep) +{ + // Get the pointer to the CcdPhysicsEnvironment associated with this Bullet world. + CcdPhysicsEnvironment *this_ = static_cast<CcdPhysicsEnvironment*>(world->getWorldUserInfo()); + this_->SimulationSubtickCallback(timeStep); +} + +void CcdPhysicsEnvironment::SimulationSubtickCallback(btScalar timeStep) +{ + std::set<CcdPhysicsController*>::iterator it; + + for (it = m_controllers.begin(); it != m_controllers.end(); it++) { + (*it)->SimulationTick(timeStep); + } +} + bool CcdPhysicsEnvironment::ProceedDeltaTime(double curTime,float timeStep,float interval) { std::set<CcdPhysicsController*>::iterator it; int i; + // Update Bullet global variables. + gDeactivationTime = m_deactivationTime; + gContactBreakingThreshold = m_contactBreakingThreshold; + for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { (*it)->SynchronizeMotionStates(timeStep); @@ -901,21 +928,32 @@ void CcdPhysicsEnvironment::SetNumIterations(int numIter) } void CcdPhysicsEnvironment::SetDeactivationTime(float dTime) { - gDeactivationTime = dTime; + m_deactivationTime = dTime; } void CcdPhysicsEnvironment::SetDeactivationLinearTreshold(float linTresh) { - gLinearSleepingTreshold = linTresh; + m_linearDeactivationThreshold = linTresh; + + // Update from all controllers. + for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) { + if ((*it)->GetRigidBody()) + (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold); + } } void CcdPhysicsEnvironment::SetDeactivationAngularTreshold(float angTresh) { - gAngularSleepingTreshold = angTresh; + m_angularDeactivationThreshold = angTresh; + + // Update from all controllers. + for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) { + if ((*it)->GetRigidBody()) + (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold); + } } void CcdPhysicsEnvironment::SetContactBreakingTreshold(float contactBreakingTreshold) { - gContactBreakingThreshold = contactBreakingTreshold; - + m_contactBreakingThreshold = contactBreakingTreshold; } @@ -1065,7 +1103,10 @@ int CcdPhysicsEnvironment::CreateUniversalD6Constraint( void CcdPhysicsEnvironment::RemoveConstraint(int constraintId) { - + // For soft body constraints + if (constraintId == 0) + return; + int i; int numConstraints = m_dynamicsWorld->getNumConstraints(); for (i=0;i<numConstraints;i++) @@ -2009,6 +2050,9 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param) { btTypedConstraint* typedConstraint = GetConstraintById(constraintId); + if (!typedConstraint) + return 0.0f; + switch (typedConstraint->getUserConstraintType()) { case PHY_GENERIC_6DOF_CONSTRAINT: @@ -2048,6 +2092,9 @@ float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param) void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float value0,float value1) { btTypedConstraint* typedConstraint = GetConstraintById(constraintId); + if (!typedConstraint) + return; + switch (typedConstraint->getUserConstraintType()) { case PHY_GENERIC_6DOF_CONSTRAINT: @@ -2157,6 +2204,9 @@ void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId) { + // For soft body constraints + if (constraintId == 0) + return NULL; int numConstraints = m_dynamicsWorld->getNumConstraints(); int i; @@ -2225,7 +2275,7 @@ void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCal bool CcdPhysicsEnvironment::RequestCollisionCallback(PHY_IPhysicsController* ctrl) { CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl); - return !ccdCtrl->Register(); + return ccdCtrl->Register(); } void CcdPhysicsEnvironment::CallbackTriggers() @@ -2937,6 +2987,10 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float conera float CcdPhysicsEnvironment::getAppliedImpulse(int constraintid) { + // For soft body constraints + if (constraintid == 0) + return 0.0f; + int i; int numConstraints = m_dynamicsWorld->getNumConstraints(); for (i=0;i<numConstraints;i++) @@ -3094,6 +3148,8 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject ci.m_mass = isbulletdyna ? shapeprops->m_mass : 0.f; ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min; ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max; + ci.m_clamp_angvel_min = shapeprops->m_clamp_angvel_min; + ci.m_clamp_angvel_max = shapeprops->m_clamp_angvel_max; ci.m_stepHeight = isbulletchar ? shapeprops->m_step_height : 0.f; ci.m_jumpSpeed = isbulletchar ? shapeprops->m_jump_speed : 0.f; ci.m_fallSpeed = isbulletchar ? shapeprops->m_fall_speed : 0.f; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index e1988478b71..3d7e3943f98 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -52,6 +52,7 @@ class btBroadphaseInterface; struct btDbvtBroadphase; class btOverlappingPairCache; class btIDebugDraw; +class btDynamicsWorld; class PHY_IVehicle; class CcdOverlapFilterCallBack; class CcdShapeConstructionInfo; @@ -87,6 +88,11 @@ protected: int m_profileTimings; bool m_enableSatCollisionDetection; + float m_deactivationTime; + float m_linearDeactivationThreshold; + float m_angularDeactivationThreshold; + float m_contactBreakingThreshold; + void ProcessFhSprings(double curTime,float timeStep); public: @@ -129,6 +135,14 @@ protected: /// Perform an integration step of duration 'timeStep'. virtual bool ProceedDeltaTime(double curTime,float timeStep,float interval); + /** + * Called by Bullet for every physical simulation (sub)tick. + * Our constructor registers this callback to Bullet, which stores a pointer to 'this' in + * the btDynamicsWorld::getWorldUserInfo() pointer. + */ + static void StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep); + void SimulationSubtickCallback(btScalar timeStep); + virtual void DebugDrawWorld(); // virtual bool proceedDeltaTimeOneStep(float timeStep); |