diff options
Diffstat (limited to 'source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp')
-rw-r--r-- | source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp | 182 |
1 files changed, 170 insertions, 12 deletions
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index bc69fe85eff..25defbd5587 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -251,6 +251,22 @@ public: }; #endif //NEW_BULLET_VEHICLE_SUPPORT +class CcdOverlapFilterCallBack : public btOverlapFilterCallback +{ +private: + class CcdPhysicsEnvironment* m_physEnv; +public: + CcdOverlapFilterCallBack(CcdPhysicsEnvironment* env) : + m_physEnv(env) + { + } + virtual ~CcdOverlapFilterCallBack() + { + } + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const; +}; + void CcdPhysicsEnvironment::setDebugDrawer(btIDebugDraw* debugDrawer) { @@ -302,7 +318,11 @@ m_numTimeSubSteps(1), m_ccdMode(0), m_solverType(-1), m_profileTimings(0), -m_enableSatCollisionDetection(false) +m_enableSatCollisionDetection(false), +m_solver(NULL), +m_ownPairCache(NULL), +m_ownDispatcher(NULL), +m_filterCallback(NULL) { for (int i=0;i<PHY_NUM_RESPONSE;i++) @@ -310,8 +330,10 @@ m_enableSatCollisionDetection(false) m_triggerCallbacks[i] = 0; } if (!dispatcher) + { dispatcher = new btCollisionDispatcher(); - + m_ownDispatcher = dispatcher; + } if(!pairCache) { @@ -321,14 +343,16 @@ m_enableSatCollisionDetection(false) btVector3 worldMax(10000,10000,10000); pairCache = new btAxisSweep3(worldMin,worldMax); - + // remember that this was allocated by us so that we can release it + m_ownPairCache = pairCache; //broadphase = new btSimpleBroadphase(); } + m_filterCallback = new CcdOverlapFilterCallBack(this); + pairCache->setOverlapFilterCallback(m_filterCallback); setSolverType(1);//issues with quickstep and memory allocations - - m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,new btSequentialImpulseConstraintSolver()); + m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,m_solver); m_debugDrawer = 0; m_gravity = btVector3(0.f,-10.f,0.f); m_dynamicsWorld->setGravity(m_gravity); @@ -346,7 +370,8 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) body->setGravity( m_gravity ); m_controllers.push_back(ctrl); - m_dynamicsWorld->addRigidBody(body); + //use explicit group/filter for finer control over collision in bullet => near/radar sensor + m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); if (body->isStaticOrKinematicObject()) { body->setActivationState(ISLAND_SLEEPING); @@ -778,7 +803,20 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() delete m_dynamicsWorld; + if (NULL != m_ownPairCache) + delete m_ownPairCache; + + if (NULL != m_ownDispatcher) + delete m_ownDispatcher; + + if (NULL != m_solver) + delete m_solver; + if (NULL != m_debugDrawer) + delete m_debugDrawer; + + if (NULL != m_filterCallback) + delete m_filterCallback; } @@ -841,9 +879,10 @@ void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) { addCcdPhysicsController(ctrl1); } + //Collision filter/mask is now set at the time of the creation of the controller //force collision detection with everything, including static objects (might hurt performance!) - ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterMask = btBroadphaseProxy::AllFilter; - ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterGroup = btBroadphaseProxy::AllFilter; + //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::SensorTrigger; + //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterGroup = btBroadphaseProxy::SensorTrigger; //todo: make this 'sensor'! requestCollisionCallback(ctrl); @@ -962,9 +1001,47 @@ void CcdPhysicsEnvironment::CallbackTriggers() } - - - +// This call back is called before a pair is added in the cache +// Handy to remove objects that must be ignored by sensors +bool CcdOverlapFilterCallBack::needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const +{ + btCollisionObject *colObj0, *colObj1; + CcdPhysicsController *sensorCtrl, *objCtrl; + bool collides; + // first check the filters + collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + if (!collides) + return false; + + // additional check for sensor object + if (proxy0->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger) + { + // this is a sensor object, the other one can't be a sensor object because + // they exclude each other in the above test + assert(!(proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)); + colObj0 = (btCollisionObject*)proxy0->m_clientObject; + colObj1 = (btCollisionObject*)proxy1->m_clientObject; + } + else if (proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger) + { + colObj0 = (btCollisionObject*)proxy1->m_clientObject; + colObj1 = (btCollisionObject*)proxy0->m_clientObject; + } + else + { + return true; + } + if (!colObj0 || !colObj1) + return false; + sensorCtrl = static_cast<CcdPhysicsController*>(colObj0->getUserPointer()); + objCtrl = static_cast<CcdPhysicsController*>(colObj1->getUserPointer()); + if (m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE]) + { + return m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE](m_physEnv->m_triggerCallbacksUserPtrs[PHY_BROADPH_RESPONSE], sensorCtrl, objCtrl, 0); + } + return true; +} #ifdef NEW_BULLET_VEHICLE_SUPPORT @@ -998,12 +1075,19 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radi { CcdConstructionInfo cinfo; + // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list cinfo.m_collisionShape = new btSphereShape(radius); cinfo.m_MotionState = 0; cinfo.m_physicsEnv = this; - cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE | btCollisionObject::CF_KINEMATIC_OBJECT; + // declare this object as Dyamic rather then static!! + // The reason as it is designed to detect all type of object, including static object + // It would cause static-static message to be printed on the console otherwise + cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE/* | btCollisionObject::CF_KINEMATIC_OBJECT*/; DefaultMotionState* motionState = new DefaultMotionState(); cinfo.m_MotionState = motionState; + // we will add later the possibility to select the filter from option + cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; + cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter; motionState->m_worldTransform.setIdentity(); motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2])); @@ -1137,6 +1221,74 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl break; } + case PHY_CONE_TWIST_CONSTRAINT: + { + btConeTwistConstraint* coneTwistContraint = 0; + + + if (rb1) + { + btTransform frameInA; + btTransform frameInB; + + btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z); + if (axis1.length() == 0.0) + { + btPlaneSpace1( axisInA, axis1, axis2 ); + } + + frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(), + axisInA.y(), axis1.y(), axis2.y(), + axisInA.z(), axis1.z(), axis2.z() ); + frameInA.setOrigin( pivotInA ); + + btTransform inv = rb1->getCenterOfMassTransform().inverse(); + + btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA; + + frameInB = inv * globalFrameA; + + coneTwistContraint = new btConeTwistConstraint( *rb0,*rb1, + frameInA,frameInB); + + + } else + { + static btRigidBody s_fixedObject2( 0,0,0); + btTransform frameInA; + btTransform frameInB; + + btVector3 axis1, axis2; + btPlaneSpace1( axisInA, axis1, axis2 ); + + frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(), + axisInA.y(), axis1.y(), axis2.y(), + axisInA.z(), axis1.z(), axis2.z() ); + + frameInA.setOrigin( pivotInA ); + + ///frameInB in worldspace + frameInB = rb0->getCenterOfMassTransform() * frameInA; + + coneTwistContraint = new btConeTwistConstraint( + *rb0,s_fixedObject2, + frameInA,frameInB); + } + + if (coneTwistContraint) + { + //m_constraints.push_back(genericConstraint); + m_dynamicsWorld->addConstraint(coneTwistContraint); + coneTwistContraint->setUserConstraintId(gConstraintUid++); + coneTwistContraint->setUserConstraintType(type); + //64 bit systems can't cast pointer to int. could use size_t instead. + return coneTwistContraint->getUserConstraintId(); + } + + + + break; + } case PHY_ANGULAR_CONSTRAINT: angularOnly = true; @@ -1207,12 +1359,18 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight) { CcdConstructionInfo cinfo; + //This is a memory leak: Bullet does not delete the shape and it cannot be added to + //the KX_Scene.m_shapes list -- too bad but that's not a lot of data cinfo.m_collisionShape = new btConeShape(coneradius,coneheight); cinfo.m_MotionState = 0; cinfo.m_physicsEnv = this; cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE; DefaultMotionState* motionState = new DefaultMotionState(); cinfo.m_MotionState = motionState; + + // we will add later the possibility to select the filter from option + cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; + cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter; motionState->m_worldTransform.setIdentity(); // motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2])); |