2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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:
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.
19 #include "CcdPhysicsEnvironment.h"
20 #include "CcdPhysicsController.h"
21 #include "CcdGraphicController.h"
24 #include "btBulletDynamicsCommon.h"
25 #include "LinearMath/btIDebugDraw.h"
26 #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
27 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
28 #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
29 #include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
32 #include "LinearMath/btQuickprof.h"
35 #include "PHY_IMotionState.h"
37 #define CCD_CONSTRAINT_DISABLE_LINKED_COLLISION 0x80
39 bool useIslands = true;
41 #ifdef NEW_BULLET_VEHICLE_SUPPORT
42 #include "BulletDynamics/Vehicle/btRaycastVehicle.h"
43 #include "BulletDynamics/Vehicle/btVehicleRaycaster.h"
44 #include "BulletDynamics/Vehicle/btWheelInfo.h"
45 #include "PHY_IVehicle.h"
46 btRaycastVehicle::btVehicleTuning gTuning;
48 #endif //NEW_BULLET_VEHICLE_SUPPORT
49 #include "LinearMath/btAabbUtil2.h"
53 void DrawRasterizerLine(const float* from,const float* to,int color);
57 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
61 #include <string.h> // for memset
63 #ifdef NEW_BULLET_VEHICLE_SUPPORT
64 class WrapperVehicle : public PHY_IVehicle
67 btRaycastVehicle* m_vehicle;
68 PHY_IPhysicsController* m_chassis;
72 WrapperVehicle(btRaycastVehicle* vehicle,PHY_IPhysicsController* chassis)
78 btRaycastVehicle* GetVehicle()
83 PHY_IPhysicsController* GetChassis()
88 virtual void AddWheel(
89 PHY_IMotionState* motionState,
90 PHY__Vector3 connectionPoint,
91 PHY__Vector3 downDirection,
92 PHY__Vector3 axleDirection,
93 float suspensionRestLength,
98 btVector3 connectionPointCS0(connectionPoint[0],connectionPoint[1],connectionPoint[2]);
99 btVector3 wheelDirectionCS0(downDirection[0],downDirection[1],downDirection[2]);
100 btVector3 wheelAxle(axleDirection[0],axleDirection[1],axleDirection[2]);
103 btWheelInfo& info = m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxle,
104 suspensionRestLength,wheelRadius,gTuning,hasSteering);
105 info.m_clientInfo = motionState;
111 int numWheels = GetNumWheels();
113 for (i=0;i<numWheels;i++)
115 btWheelInfo& info = m_vehicle->getWheelInfo(i);
116 PHY_IMotionState* motionState = (PHY_IMotionState*)info.m_clientInfo ;
117 // m_vehicle->updateWheelTransformsWS(info,false);
118 m_vehicle->updateWheelTransform(i,false);
119 btTransform trans = m_vehicle->getWheelInfo(i).m_worldTransform;
120 btQuaternion orn = trans.getRotation();
121 const btVector3& pos = trans.getOrigin();
122 motionState->setWorldOrientation(orn.x(),orn.y(),orn.z(),orn[3]);
123 motionState->setWorldPosition(pos.x(),pos.y(),pos.z());
128 virtual int GetNumWheels() const
130 return m_vehicle->getNumWheels();
133 virtual void GetWheelPosition(int wheelIndex,float& posX,float& posY,float& posZ) const
135 btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
136 posX = trans.getOrigin().x();
137 posY = trans.getOrigin().y();
138 posZ = trans.getOrigin().z();
140 virtual void GetWheelOrientationQuaternion(int wheelIndex,float& quatX,float& quatY,float& quatZ,float& quatW) const
142 btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
143 btQuaternion quat = trans.getRotation();
144 btMatrix3x3 orn2(quat);
146 quatX = trans.getRotation().x();
147 quatY = trans.getRotation().y();
148 quatZ = trans.getRotation().z();
149 quatW = trans.getRotation()[3];
157 virtual float GetWheelRotation(int wheelIndex) const
159 float rotation = 0.f;
161 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
163 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
164 rotation = info.m_rotation;
172 virtual int GetUserConstraintId() const
174 return m_vehicle->getUserConstraintId();
177 virtual int GetUserConstraintType() const
179 return m_vehicle->getUserConstraintType();
182 virtual void SetSteeringValue(float steering,int wheelIndex)
184 m_vehicle->setSteeringValue(steering,wheelIndex);
187 virtual void ApplyEngineForce(float force,int wheelIndex)
189 m_vehicle->applyEngineForce(force,wheelIndex);
192 virtual void ApplyBraking(float braking,int wheelIndex)
194 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
196 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
197 info.m_brake = braking;
201 virtual void SetWheelFriction(float friction,int wheelIndex)
203 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
205 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
206 info.m_frictionSlip = friction;
211 virtual void SetSuspensionStiffness(float suspensionStiffness,int wheelIndex)
213 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
215 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
216 info.m_suspensionStiffness = suspensionStiffness;
221 virtual void SetSuspensionDamping(float suspensionDamping,int wheelIndex)
223 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
225 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
226 info.m_wheelsDampingRelaxation = suspensionDamping;
230 virtual void SetSuspensionCompression(float suspensionCompression,int wheelIndex)
232 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
234 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
235 info.m_wheelsDampingCompression = suspensionCompression;
241 virtual void SetRollInfluence(float rollInfluence,int wheelIndex)
243 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
245 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
246 info.m_rollInfluence = rollInfluence;
250 virtual void SetCoordinateSystem(int rightIndex,int upIndex,int forwardIndex)
252 m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex);
258 #endif //NEW_BULLET_VEHICLE_SUPPORT
260 class CcdOverlapFilterCallBack : public btOverlapFilterCallback
263 class CcdPhysicsEnvironment* m_physEnv;
265 CcdOverlapFilterCallBack(CcdPhysicsEnvironment* env) :
269 virtual ~CcdOverlapFilterCallBack()
272 // return true when pairs need collision
273 virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const;
277 void CcdPhysicsEnvironment::setDebugDrawer(btIDebugDraw* debugDrawer)
279 if (debugDrawer && m_dynamicsWorld)
280 m_dynamicsWorld->setDebugDrawer(debugDrawer);
281 m_debugDrawer = debugDrawer;
284 static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVector3& to,const btVector3& color)
286 btVector3 halfExtents = (to-from)* 0.5f;
287 btVector3 center = (to+from) *0.5f;
290 btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
295 pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
296 edgecoord[2]*halfExtents[2]);
299 int othercoord = j%3;
300 edgecoord[othercoord]*=-1.f;
301 pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
302 edgecoord[2]*halfExtents[2]);
305 debugDrawer->drawLine(pa,pb,color);
307 edgecoord = btVector3(-1.f,-1.f,-1.f);
320 CcdPhysicsEnvironment::CcdPhysicsEnvironment(bool useDbvtCulling,btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
321 :m_cullingCache(NULL),
324 m_scalingPropagated(false),
325 m_numTimeSubSteps(1),
329 m_enableSatCollisionDetection(false),
331 m_ownPairCache(NULL),
332 m_filterCallback(NULL),
333 m_ownDispatcher(NULL)
336 for (int i=0;i<PHY_NUM_RESPONSE;i++)
338 m_triggerCallbacks[i] = 0;
341 // m_collisionConfiguration = new btDefaultCollisionConfiguration();
342 m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
343 //m_collisionConfiguration->setConvexConvexMultipointIterations();
347 btCollisionDispatcher* disp = new btCollisionDispatcher(m_collisionConfiguration);
349 btGImpactCollisionAlgorithm::registerAlgorithm(disp);
350 m_ownDispatcher = dispatcher;
353 //m_broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000),btVector3(1000,1000,1000));
354 //m_broadphase = new btSimpleBroadphase();
355 m_broadphase = new btDbvtBroadphase();
356 // avoid any collision in the culling tree
357 if (useDbvtCulling) {
358 m_cullingCache = new btNullPairCache();
359 m_cullingTree = new btDbvtBroadphase(m_cullingCache);
362 m_filterCallback = new CcdOverlapFilterCallBack(this);
363 m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
365 setSolverType(1);//issues with quickstep and memory allocations
366 // m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
367 m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
368 //m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f;
369 //m_dynamicsWorld->getSolverInfo().m_solverMode= SOLVER_USE_WARMSTARTING + SOLVER_USE_2_FRICTION_DIRECTIONS + SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING;
372 m_gravity = btVector3(0.f,-10.f,0.f);
373 m_dynamicsWorld->setGravity(m_gravity);
377 void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
379 btRigidBody* body = ctrl->GetRigidBody();
380 btCollisionObject* obj = ctrl->GetCollisionObject();
382 //this m_userPointer is just used for triggers, see CallbackTriggers
383 obj->setUserPointer(ctrl);
385 body->setGravity( m_gravity );
387 m_controllers.insert(ctrl);
391 //use explicit group/filter for finer control over collision in bullet => near/radar sensor
392 m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
395 if (ctrl->GetSoftBody())
397 btSoftBody* softBody = ctrl->GetSoftBody();
398 m_dynamicsWorld->addSoftBody(softBody);
401 if (obj->getCollisionShape())
403 m_dynamicsWorld->addCollisionObject(obj,ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
407 if (obj->isStaticOrKinematicObject())
409 obj->setActivationState(ISLAND_SLEEPING);
413 //CollisionObject(body,ctrl->GetCollisionFilterGroup(),ctrl->GetCollisionFilterMask());
415 assert(obj->getBroadphaseHandle());
417 btBroadphaseInterface* scene = getBroadphase();
420 btCollisionShape* shapeinterface = ctrl->GetCollisionShape();
422 assert(shapeinterface);
424 const btTransform& t = ctrl->GetCollisionObject()->getWorldTransform();
427 btVector3 minAabb,maxAabb;
429 shapeinterface->getAabb(t,minAabb,maxAabb);
431 float timeStep = 0.02f;
434 //extent it with the motion
438 btVector3 linMotion = body->getLinearVelocity()*timeStep;
440 float maxAabbx = maxAabb.getX();
441 float maxAabby = maxAabb.getY();
442 float maxAabbz = maxAabb.getZ();
443 float minAabbx = minAabb.getX();
444 float minAabby = minAabb.getY();
445 float minAabbz = minAabb.getZ();
447 if (linMotion.x() > 0.f)
448 maxAabbx += linMotion.x();
450 minAabbx += linMotion.x();
451 if (linMotion.y() > 0.f)
452 maxAabby += linMotion.y();
454 minAabby += linMotion.y();
455 if (linMotion.z() > 0.f)
456 maxAabbz += linMotion.z();
458 minAabbz += linMotion.z();
461 minAabb = btVector3(minAabbx,minAabby,minAabbz);
462 maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz);
471 void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl)
473 //also remove constraint
474 btRigidBody* body = ctrl->GetRigidBody();
477 m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
481 if (ctrl->GetSoftBody())
483 m_dynamicsWorld->removeSoftBody(ctrl->GetSoftBody());
486 m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
489 m_controllers.erase(ctrl);
491 if (ctrl->m_registerCount != 0)
492 printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount);
494 //remove it from the triggers
495 m_triggerControllers.erase(ctrl);
498 void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask)
500 // this function is used when the collisionning group of a controller is changed
501 // remove and add the collistioning object
502 btRigidBody* body = ctrl->GetRigidBody();
503 btCollisionObject* obj = ctrl->GetCollisionObject();
506 btVector3 inertia(0.0,0.0,0.0);
507 m_dynamicsWorld->removeCollisionObject(obj);
508 obj->setCollisionFlags(newCollisionFlags);
512 body->getCollisionShape()->calculateLocalInertia(newMass, inertia);
513 body->setMassProps(newMass, inertia);
515 m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
517 // to avoid nasty interaction, we must update the property of the controller as well
518 ctrl->m_cci.m_mass = newMass;
519 ctrl->m_cci.m_collisionFilterGroup = newCollisionGroup;
520 ctrl->m_cci.m_collisionFilterMask = newCollisionMask;
521 ctrl->m_cci.m_collisionFlags = newCollisionFlags;
524 void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctrl)
526 if (m_controllers.insert(ctrl).second)
528 btCollisionObject* obj = ctrl->GetCollisionObject();
529 obj->setUserPointer(ctrl);
530 m_dynamicsWorld->addCollisionObject(obj,
531 ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
535 void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ctrl)
537 if (m_controllers.erase(ctrl))
539 btRigidBody* body = ctrl->GetRigidBody();
542 m_dynamicsWorld->removeRigidBody(body);
545 if (ctrl->GetSoftBody())
549 m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
555 void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ctrl)
557 btCollisionObject* obj = ctrl->GetCollisionObject();
560 btBroadphaseProxy* proxy = obj->getBroadphaseHandle();
563 m_dynamicsWorld->getPairCache()->cleanProxyFromPairs(proxy,m_dynamicsWorld->getDispatcher());
568 void CcdPhysicsEnvironment::addCcdGraphicController(CcdGraphicController* ctrl)
574 ctrl->getAabb(minAabb, maxAabb);
576 ctrl->setBroadphaseHandle(m_cullingTree->createProxy(
579 INVALID_SHAPE_PROXYTYPE, // this parameter is not used
581 0, // this object does not collision with anything
583 NULL, // dispatcher => this parameter is not used
586 assert(ctrl->getBroadphaseHandle());
590 void CcdPhysicsEnvironment::removeCcdGraphicController(CcdGraphicController* ctrl)
594 btBroadphaseProxy* bp = ctrl->getBroadphaseHandle();
597 m_cullingTree->destroyProxy(bp,NULL);
598 ctrl->setBroadphaseHandle(0);
603 void CcdPhysicsEnvironment::beginFrame()
608 void CcdPhysicsEnvironment::debugDrawWorld()
610 if (m_dynamicsWorld->getDebugDrawer() && m_dynamicsWorld->getDebugDrawer()->getDebugMode() >0)
611 m_dynamicsWorld->debugDrawWorld();
614 bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
616 std::set<CcdPhysicsController*>::iterator it;
619 for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
621 (*it)->SynchronizeMotionStates(timeStep);
624 processFhSprings(curTime,timeStep);
626 float subStep = timeStep / float(m_numTimeSubSteps);
627 for (i=0;i<m_numTimeSubSteps;i++)
629 // m_dynamicsWorld->stepSimulation(subStep,20,1./240.);//perform always a full simulation step
630 m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step
633 for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
635 (*it)->SynchronizeMotionStates(timeStep);
638 //for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
640 // (*it)->SynchronizeMotionStates(timeStep);
643 for (i=0;i<m_wrapperVehicles.size();i++)
645 WrapperVehicle* veh = m_wrapperVehicles[i];
655 class ClosestRayResultCallbackNotMe : public btCollisionWorld::ClosestRayResultCallback
657 btCollisionObject* m_owner;
658 btCollisionObject* m_parent;
661 ClosestRayResultCallbackNotMe(const btVector3& rayFromWorld,const btVector3& rayToWorld,btCollisionObject* owner,btCollisionObject* parent)
662 :btCollisionWorld::ClosestRayResultCallback(rayFromWorld,rayToWorld),
669 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
671 //don't collide with self
672 if (proxy0->m_clientObject == m_owner)
675 if (proxy0->m_clientObject == m_parent)
678 return btCollisionWorld::ClosestRayResultCallback::needsCollision(proxy0);
683 void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
685 std::set<CcdPhysicsController*>::iterator it;
687 for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
689 CcdPhysicsController* ctrl = (*it);
690 btRigidBody* body = ctrl->GetRigidBody();
692 if (body && (ctrl->getConstructionInfo().m_do_fh || ctrl->getConstructionInfo().m_do_rot_fh))
694 //printf("has Fh or RotFh\n");
695 //re-implement SM_FhObject.cpp using btCollisionWorld::rayTest and info from ctrl->getConstructionInfo()
696 //send a ray from {0.0, 0.0, 0.0} towards {0.0, 0.0, -10.0}, in local coordinates
699 CcdPhysicsController* parentCtrl = ctrl->getParentCtrl();
700 btRigidBody* parentBody = parentCtrl?parentCtrl->GetRigidBody() : 0;
701 btRigidBody* cl_object = parentBody ? parentBody : body;
703 if (body->isStaticOrKinematicObject())
706 btVector3 rayDirLocal(0,0,-10);
709 //ctrl->GetRigidBody();
710 btVector3 rayFromWorld = body->getCenterOfMassPosition();
711 //btVector3 rayToWorld = rayFromWorld + body->getCenterOfMassTransform().getBasis() * rayDirLocal;
712 //ray always points down the z axis in world space...
713 btVector3 rayToWorld = rayFromWorld + rayDirLocal;
715 ClosestRayResultCallbackNotMe resultCallback(rayFromWorld,rayToWorld,body,parentBody);
717 m_dynamicsWorld->rayTest(rayFromWorld,rayToWorld,resultCallback);
718 if (resultCallback.hasHit())
720 //we hit this one: resultCallback.m_collisionObject;
721 CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(resultCallback.m_collisionObject->getUserPointer());
725 if (controller->getConstructionInfo().m_fh_distance < SIMD_EPSILON)
728 btRigidBody* hit_object = controller->GetRigidBody();
732 CcdConstructionInfo& hitObjShapeProps = controller->getConstructionInfo();
734 float distance = resultCallback.m_closestHitFraction*rayDirLocal.length()-ctrl->getConstructionInfo().m_radius;
735 if (distance >= hitObjShapeProps.m_fh_distance)
740 //btVector3 ray_dir = cl_object->getCenterOfMassTransform().getBasis()* rayDirLocal.normalized();
741 btVector3 ray_dir = rayDirLocal.normalized();
742 btVector3 normal = resultCallback.m_hitNormalWorld;
746 if (ctrl->getConstructionInfo().m_do_fh)
748 btVector3 lspot = cl_object->getCenterOfMassPosition()
749 + rayDirLocal * resultCallback.m_closestHitFraction;
754 lspot -= hit_object->getCenterOfMassPosition();
755 btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot);
756 btScalar rel_vel_ray = ray_dir.dot(rel_vel);
757 btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance;
759 btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring;
760 btScalar i_damp = rel_vel_ray * hitObjShapeProps.m_fh_damping;
762 cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir));
763 if (hitObjShapeProps.m_fh_normal)
765 cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir));
768 btVector3 lateral = rel_vel - rel_vel_ray * ray_dir;
771 if (ctrl->getConstructionInfo().m_do_anisotropic) {
772 //Bullet basis contains no scaling/shear etc.
773 const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis();
774 btVector3 loc_lateral = lateral * lcs;
775 const btVector3& friction_scaling = cl_object->getAnisotropicFriction();
776 loc_lateral *= friction_scaling;
777 lateral = lcs * loc_lateral;
780 btScalar rel_vel_lateral = lateral.length();
782 if (rel_vel_lateral > SIMD_EPSILON) {
783 btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction();
785 btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring);
787 btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass();
789 btVector3 friction = (rel_mom_lateral > max_friction) ?
790 -lateral * (max_friction / rel_vel_lateral) :
793 cl_object->applyCentralImpulse(friction);
798 if (ctrl->getConstructionInfo().m_do_rot_fh) {
799 btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2);
801 btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring;
802 btVector3 ang_vel = cl_object->getAngularVelocity();
804 // only rotations that tilt relative to the normal are damped
805 ang_vel -= ang_vel.dot(normal) * normal;
807 btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping;
809 cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp));
823 void CcdPhysicsEnvironment::setDebugMode(int debugMode)
826 m_debugDrawer->setDebugMode(debugMode);
830 void CcdPhysicsEnvironment::setNumIterations(int numIter)
832 m_numIterations = numIter;
834 void CcdPhysicsEnvironment::setDeactivationTime(float dTime)
836 gDeactivationTime = dTime;
838 void CcdPhysicsEnvironment::setDeactivationLinearTreshold(float linTresh)
840 gLinearSleepingTreshold = linTresh;
842 void CcdPhysicsEnvironment::setDeactivationAngularTreshold(float angTresh)
844 gAngularSleepingTreshold = angTresh;
847 void CcdPhysicsEnvironment::setContactBreakingTreshold(float contactBreakingTreshold)
849 gContactBreakingThreshold = contactBreakingTreshold;
854 void CcdPhysicsEnvironment::setCcdMode(int ccdMode)
860 void CcdPhysicsEnvironment::setSolverSorConstant(float sor)
862 m_solverInfo.m_sor = sor;
865 void CcdPhysicsEnvironment::setSolverTau(float tau)
867 m_solverInfo.m_tau = tau;
869 void CcdPhysicsEnvironment::setSolverDamping(float damping)
871 m_solverInfo.m_damping = damping;
875 void CcdPhysicsEnvironment::setLinearAirDamping(float damping)
877 //gLinearAirDamping = damping;
880 void CcdPhysicsEnvironment::setUseEpa(bool epa)
885 void CcdPhysicsEnvironment::setSolverType(int solverType)
892 if (m_solverType != solverType)
895 m_solver = new btSequentialImpulseConstraintSolver();
904 if (m_solverType != solverType)
906 // m_solver = new OdeConstraintSolver();
913 m_solverType = solverType ;
918 void CcdPhysicsEnvironment::getGravity(PHY__Vector3& grav)
920 const btVector3& gravity = m_dynamicsWorld->getGravity();
921 grav[0] = gravity.getX();
922 grav[1] = gravity.getY();
923 grav[2] = gravity.getZ();
927 void CcdPhysicsEnvironment::setGravity(float x,float y,float z)
929 m_gravity = btVector3(x,y,z);
930 m_dynamicsWorld->setGravity(m_gravity);
937 static int gConstraintUid = 1;
939 //Following the COLLADA physics specification for constraints
940 int CcdPhysicsEnvironment::createUniversalD6Constraint(
941 class PHY_IPhysicsController* ctrlRef,class PHY_IPhysicsController* ctrlOther,
942 btTransform& frameInA,
943 btTransform& frameInB,
944 const btVector3& linearMinLimits,
945 const btVector3& linearMaxLimits,
946 const btVector3& angularMinLimits,
947 const btVector3& angularMaxLimits,int flags
951 bool disableCollisionBetweenLinkedBodies = (0!=(flags & CCD_CONSTRAINT_DISABLE_LINKED_COLLISION));
953 //we could either add some logic to recognize ball-socket and hinge, or let that up to the user
954 //perhaps some warning or hint that hinge/ball-socket is more efficient?
957 btGeneric6DofConstraint* genericConstraint = 0;
958 CcdPhysicsController* ctrl0 = (CcdPhysicsController*) ctrlRef;
959 CcdPhysicsController* ctrl1 = (CcdPhysicsController*) ctrlOther;
961 btRigidBody* rb0 = ctrl0->GetRigidBody();
962 btRigidBody* rb1 = ctrl1->GetRigidBody();
968 bool useReferenceFrameA = true;
969 genericConstraint = new btGeneric6DofConstraint(
971 frameInA,frameInB,useReferenceFrameA);
972 genericConstraint->setLinearLowerLimit(linearMinLimits);
973 genericConstraint->setLinearUpperLimit(linearMaxLimits);
974 genericConstraint->setAngularLowerLimit(angularMinLimits);
975 genericConstraint->setAngularUpperLimit(angularMaxLimits);
978 // TODO: Implement single body case...
979 //No, we can use a fixed rigidbody in above code, rather then unnecessary duplation of code
983 if (genericConstraint)
985 // m_constraints.push_back(genericConstraint);
986 m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
988 genericConstraint->setUserConstraintId(gConstraintUid++);
989 genericConstraint->setUserConstraintType(PHY_GENERIC_6DOF_CONSTRAINT);
990 //64 bit systems can't cast pointer to int. could use size_t instead.
991 return genericConstraint->getUserConstraintId();
998 void CcdPhysicsEnvironment::removeConstraint(int constraintId)
1002 int numConstraints = m_dynamicsWorld->getNumConstraints();
1003 for (i=0;i<numConstraints;i++)
1005 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
1006 if (constraint->getUserConstraintId() == constraintId)
1008 constraint->getRigidBodyA().activate();
1009 constraint->getRigidBodyB().activate();
1010 m_dynamicsWorld->removeConstraint(constraint);
1017 struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
1019 PHY_IRayCastFilterCallback& m_phyRayFilter;
1020 const btCollisionShape* m_hitTriangleShape;
1021 int m_hitTriangleIndex;
1023 FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo)
1024 : btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo),
1025 m_phyRayFilter(phyRayFilter),
1026 m_hitTriangleShape(NULL),
1027 m_hitTriangleIndex(0)
1031 virtual ~FilterClosestRayResultCallback()
1035 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
1037 if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask))
1039 if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask))
1041 btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject;
1042 CcdPhysicsController* phyCtrl = static_cast<CcdPhysicsController*>(object->getUserPointer());
1043 if (phyCtrl == m_phyRayFilter.m_ignoreController)
1045 return m_phyRayFilter.needBroadphaseRayCast(phyCtrl);
1048 virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
1050 CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer());
1051 // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it
1052 if (rayResult.m_localShapeInfo)
1054 m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape();
1055 m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex;
1058 m_hitTriangleShape = NULL;
1059 m_hitTriangleIndex = 0;
1061 return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace);
1066 PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
1070 float minFraction = 1.f;
1072 btVector3 rayFrom(fromX,fromY,fromZ);
1073 btVector3 rayTo(toX,toY,toZ);
1075 btVector3 hitPointWorld,normalWorld;
1077 //Either Ray Cast with or without filtering
1079 //btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo);
1080 FilterClosestRayResultCallback rayCallback(filterCallback,rayFrom,rayTo);
1083 PHY_RayCastResult result;
1084 memset(&result, 0, sizeof(result));
1086 // don't collision with sensor object
1087 rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
1088 //, ,filterCallback.m_faceNormal);
1090 m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback);
1091 if (rayCallback.hasHit())
1093 CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(rayCallback.m_collisionObject->getUserPointer());
1094 result.m_controller = controller;
1095 result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX();
1096 result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY();
1097 result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ();
1099 if (rayCallback.m_hitTriangleShape != NULL)
1101 // identify the mesh polygon
1102 CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo;
1105 btCollisionShape* shape = controller->GetCollisionObject()->getCollisionShape();
1106 if (shape->isCompound())
1108 btCompoundShape* compoundShape = (btCompoundShape*)shape;
1109 CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo;
1110 // need to search which sub-shape has been hit
1111 for (int i=0; i<compoundShape->getNumChildShapes(); i++)
1113 shapeInfo = compoundShapeInfo->GetChildShape(i);
1114 shape=compoundShape->getChildShape(i);
1115 if (shape == rayCallback.m_hitTriangleShape)
1119 if (shape == rayCallback.m_hitTriangleShape &&
1120 rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size())
1122 result.m_meshObject = shapeInfo->GetMesh();
1123 result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex);
1125 // Bullet returns the normal from "outside".
1126 // If the user requests the real normal, compute it now
1127 if (filterCallback.m_faceNormal)
1129 // mesh shapes are shared and stored in the shapeInfo
1130 btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape();
1133 // this code is copied from Bullet
1134 btVector3 triangle[3];
1135 const unsigned char *vertexbase;
1137 PHY_ScalarType type;
1139 const unsigned char *indexbase;
1142 PHY_ScalarType indicestype;
1143 btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface();
1145 meshInterface->getLockedReadOnlyVertexIndexBase(
1156 unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride);
1157 const btVector3& meshScaling = shape->getLocalScaling();
1158 for (int j=2;j>=0;j--)
1160 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
1162 btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
1164 triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
1166 meshInterface->unLockReadOnlyVertexBase(0);
1167 btVector3 triangleNormal;
1168 triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
1169 rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal;
1175 if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON))
1177 rayCallback.m_hitNormalWorld.normalize();
1180 rayCallback.m_hitNormalWorld.setValue(1,0,0);
1182 result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX();
1183 result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY();
1184 result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ();
1185 filterCallback.reportHit(&result);
1189 return result.m_controller;
1192 struct DbvtCullingCallback : btDbvt::ICollide
1194 PHY_CullingCallback m_clientCallback;
1197 DbvtCullingCallback(PHY_CullingCallback clientCallback, void* userData)
1199 m_clientCallback = clientCallback;
1200 m_userData = userData;
1203 void Process(const btDbvtNode* node,btScalar depth)
1207 void Process(const btDbvtNode* leaf)
1209 btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data;
1210 // the client object is a graphic controller
1211 CcdGraphicController* ctrl = static_cast<CcdGraphicController*>(proxy->m_clientObject);
1212 KX_ClientObjectInfo* info = (KX_ClientObjectInfo*)ctrl->getNewClientInfo();
1214 (*m_clientCallback)(info, m_userData);
1218 bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes)
1222 DbvtCullingCallback dispatcher(callback, userData);
1223 btVector3 planes_n[5];
1224 btScalar planes_o[5];
1227 for (int i=0; i<nplanes; i++)
1229 planes_n[i].setValue(planes[i][0], planes[i][1], planes[i][2]);
1230 planes_o[i] = planes[i][3];
1232 btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher);
1233 btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);
1238 int CcdPhysicsEnvironment::getNumContactPoints()
1243 void CcdPhysicsEnvironment::getContactPoint(int i,float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
1251 btBroadphaseInterface* CcdPhysicsEnvironment::getBroadphase()
1253 return m_dynamicsWorld->getBroadphase();
1256 btDispatcher* CcdPhysicsEnvironment::getDispatcher()
1258 return m_dynamicsWorld->getDispatcher();
1266 CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
1269 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1270 m_wrapperVehicles.clear();
1271 #endif //NEW_BULLET_VEHICLE_SUPPORT
1273 //m_broadphase->DestroyScene();
1274 //delete broadphase ? release reference on broadphase ?
1276 //first delete scene, then dispatcher, because pairs have to release manifolds on the dispatcher
1277 //delete m_dispatcher;
1278 delete m_dynamicsWorld;
1281 if (NULL != m_ownPairCache)
1282 delete m_ownPairCache;
1284 if (NULL != m_ownDispatcher)
1285 delete m_ownDispatcher;
1287 if (NULL != m_solver)
1290 if (NULL != m_debugDrawer)
1291 delete m_debugDrawer;
1293 if (NULL != m_filterCallback)
1294 delete m_filterCallback;
1296 if (NULL != m_collisionConfiguration)
1297 delete m_collisionConfiguration;
1299 if (NULL != m_broadphase)
1300 delete m_broadphase;
1302 if (NULL != m_cullingTree)
1303 delete m_cullingTree;
1305 if (NULL != m_cullingCache)
1306 delete m_cullingCache;
1311 void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float value0,float value1)
1313 btTypedConstraint* typedConstraint = getConstraintById(constraintId);
1314 switch (typedConstraint->getUserConstraintType())
1316 case PHY_GENERIC_6DOF_CONSTRAINT:
1318 //param = 1..12, min0,max0,min1,max1...min6,max6
1319 btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
1320 genCons->setLimit(param,value0,value1);
1329 btTypedConstraint* CcdPhysicsEnvironment::getConstraintById(int constraintId)
1332 int numConstraints = m_dynamicsWorld->getNumConstraints();
1334 for (i=0;i<numConstraints;i++)
1336 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
1337 if (constraint->getUserConstraintId()==constraintId)
1346 void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
1349 CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl;
1350 // addSensor() is a "light" function for bullet because it is used
1351 // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead
1352 //if (m_controllers.insert(ctrl1).second)
1354 // addCcdPhysicsController(ctrl1);
1356 enableCcdPhysicsController(ctrl1);
1358 //Collision filter/mask is now set at the time of the creation of the controller
1359 //force collision detection with everything, including static objects (might hurt performance!)
1360 //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::SensorTrigger;
1361 //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterGroup = btBroadphaseProxy::SensorTrigger;
1362 //todo: make this 'sensor'!
1364 requestCollisionCallback(ctrl);
1365 //printf("addSensor\n");
1368 void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl)
1370 CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl;
1371 if (ccdCtrl->Unregister())
1372 m_triggerControllers.erase(ccdCtrl);
1376 void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl)
1378 removeCollisionCallback(ctrl);
1380 disableCcdPhysicsController((CcdPhysicsController*)ctrl);
1383 void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
1385 /* printf("addTouchCallback\n(response class = %i)\n",response_class);
1387 //map PHY_ convention into SM_ convention
1388 switch (response_class)
1390 case PHY_FH_RESPONSE:
1391 printf("PHY_FH_RESPONSE\n");
1393 case PHY_SENSOR_RESPONSE:
1394 printf("PHY_SENSOR_RESPONSE\n");
1396 case PHY_CAMERA_RESPONSE:
1397 printf("PHY_CAMERA_RESPONSE\n");
1399 case PHY_OBJECT_RESPONSE:
1400 printf("PHY_OBJECT_RESPONSE\n");
1402 case PHY_STATIC_RESPONSE:
1403 printf("PHY_STATIC_RESPONSE\n");
1411 m_triggerCallbacks[response_class] = callback;
1412 m_triggerCallbacksUserPtrs[response_class] = user;
1415 void CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl)
1417 CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl);
1419 if (ccdCtrl->Register())
1420 m_triggerControllers.insert(ccdCtrl);
1423 void CcdPhysicsEnvironment::CallbackTriggers()
1426 CcdPhysicsController* ctrl0=0,*ctrl1=0;
1428 if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)))
1430 //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
1431 btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
1432 int numManifolds = dispatcher->getNumManifolds();
1433 for (int i=0;i<numManifolds;i++)
1435 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
1436 int numContacts = manifold->getNumContacts();
1439 btRigidBody* rb0 = static_cast<btRigidBody*>(manifold->getBody0());
1440 btRigidBody* rb1 = static_cast<btRigidBody*>(manifold->getBody1());
1441 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))
1443 for (int j=0;j<numContacts;j++)
1445 btVector3 color(1,0,0);
1446 const btManifoldPoint& cp = manifold->getContactPoint(j);
1448 m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
1451 btRigidBody* obj0 = rb0;
1452 btRigidBody* obj1 = rb1;
1454 //m_internalOwner is set in 'addPhysicsController'
1455 CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer());
1456 CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer());
1458 std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0);
1459 if (i == m_triggerControllers.end())
1461 i = m_triggerControllers.find(ctrl1);
1464 if (!(i == m_triggerControllers.end()))
1466 m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
1469 // Bullet does not refresh the manifold contact point for object without contact response
1470 // may need to remove this when a newer Bullet version is integrated
1471 if (!dispatcher->needsResponse(rb0, rb1))
1473 // Refresh algorithm fails sometimes when there is penetration
1474 // (usuall the case with ghost and sensor objects)
1475 // Let's just clear the manifold, in any case, it is recomputed on each frame.
1476 manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
1488 // This call back is called before a pair is added in the cache
1489 // Handy to remove objects that must be ignored by sensors
1490 bool CcdOverlapFilterCallBack::needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
1492 btCollisionObject *colObj0, *colObj1;
1493 CcdPhysicsController *sensorCtrl, *objCtrl;
1495 // first check the filters
1496 collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
1497 collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
1501 // additional check for sensor object
1502 if (proxy0->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
1504 // this is a sensor object, the other one can't be a sensor object because
1505 // they exclude each other in the above test
1506 assert(!(proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger));
1507 colObj0 = (btCollisionObject*)proxy0->m_clientObject;
1508 colObj1 = (btCollisionObject*)proxy1->m_clientObject;
1510 else if (proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
1512 colObj0 = (btCollisionObject*)proxy1->m_clientObject;
1513 colObj1 = (btCollisionObject*)proxy0->m_clientObject;
1519 if (!colObj0 || !colObj1)
1521 sensorCtrl = static_cast<CcdPhysicsController*>(colObj0->getUserPointer());
1522 objCtrl = static_cast<CcdPhysicsController*>(colObj1->getUserPointer());
1523 if (m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE])
1525 return m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE](m_physEnv->m_triggerCallbacksUserPtrs[PHY_BROADPH_RESPONSE], sensorCtrl, objCtrl, 0);
1531 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1533 //complex constraint for vehicles
1534 PHY_IVehicle* CcdPhysicsEnvironment::getVehicleConstraint(int constraintId)
1538 int numVehicles = m_wrapperVehicles.size();
1539 for (i=0;i<numVehicles;i++)
1541 WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i];
1542 if (wrapperVehicle->GetVehicle()->getUserConstraintId() == constraintId)
1543 return wrapperVehicle;
1549 #endif //NEW_BULLET_VEHICLE_SUPPORT
1552 int currentController = 0;
1553 int numController = 0;
1558 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position)
1561 CcdConstructionInfo cinfo;
1562 memset(&cinfo, 0, sizeof(cinfo)); /* avoid uninitialized values */
1563 cinfo.m_collisionShape = new btSphereShape(radius); // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
1564 cinfo.m_MotionState = 0;
1565 cinfo.m_physicsEnv = this;
1566 // declare this object as Dyamic rather then static!!
1567 // The reason as it is designed to detect all type of object, including static object
1568 // It would cause static-static message to be printed on the console otherwise
1569 cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE/* | btCollisionObject::CF_KINEMATIC_OBJECT*/;
1570 DefaultMotionState* motionState = new DefaultMotionState();
1571 cinfo.m_MotionState = motionState;
1572 // we will add later the possibility to select the filter from option
1573 cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
1574 cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
1575 motionState->m_worldTransform.setIdentity();
1576 motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
1578 CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
1580 return sphereController;
1583 int findClosestNode(btSoftBody* sb,const btVector3& worldPoint);
1584 int findClosestNode(btSoftBody* sb,const btVector3& worldPoint)
1588 btSoftBody::tNodeArray& nodes(sb->m_nodes);
1589 float maxDistSqr = 1e30f;
1591 for (int n=0;n<nodes.size();n++)
1593 btScalar distSqr = (nodes[n].m_x - worldPoint).length2();
1594 if (distSqr<maxDistSqr)
1596 maxDistSqr = distSqr;
1603 int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl0,class PHY_IPhysicsController* ctrl1,PHY_ConstraintType type,
1604 float pivotX,float pivotY,float pivotZ,
1605 float axisX,float axisY,float axisZ,
1606 float axis1X,float axis1Y,float axis1Z,
1607 float axis2X,float axis2Y,float axis2Z,int flags
1611 bool disableCollisionBetweenLinkedBodies = (0!=(flags & CCD_CONSTRAINT_DISABLE_LINKED_COLLISION));
1615 CcdPhysicsController* c0 = (CcdPhysicsController*)ctrl0;
1616 CcdPhysicsController* c1 = (CcdPhysicsController*)ctrl1;
1618 btRigidBody* rb0 = c0 ? c0->GetRigidBody() : 0;
1619 btRigidBody* rb1 = c1 ? c1->GetRigidBody() : 0;
1624 bool rb0static = rb0 ? rb0->isStaticOrKinematicObject() : true;
1625 bool rb1static = rb1 ? rb1->isStaticOrKinematicObject() : true;
1627 btCollisionObject* colObj0 = c0->GetCollisionObject();
1633 btVector3 pivotInA(pivotX,pivotY,pivotZ);
1637 //it might be a soft body, let's try
1638 btSoftBody* sb0 = c0 ? c0->GetSoftBody() : 0;
1639 btSoftBody* sb1 = c1 ? c1->GetSoftBody() : 0;
1642 //not between two soft bodies?
1648 //either cluster or node attach, let's find closest node first
1649 //the soft body doesn't have a 'real' world transform, so get its initial world transform for now
1650 btVector3 pivotPointSoftWorld = sb0->m_initialWorldTransform(pivotInA);
1651 int node=findClosestNode(sb0,pivotPointSoftWorld);
1654 bool clusterconstaint = false;
1658 case PHY_LINEHINGE_CONSTRAINT:
1660 if (sb0->clusterCount() && rb1)
1662 btSoftBody::LJoint::Specs ls;
1664 ls.position=sb0->clusterCom(0);
1665 sb0->appendLinearJoint(ls,rb1);
1666 clusterconstaint = true;
1670 case PHY_GENERIC_6DOF_CONSTRAINT:
1672 if (sb0->clusterCount() && rb1)
1674 btSoftBody::AJoint::Specs as;
1677 as.axis.setValue(axisX,axisY,axisZ);
1678 sb0->appendAngularJoint(as,rb1);
1679 clusterconstaint = true;
1692 if (!clusterconstaint)
1696 sb0->appendAnchor(node,rb1,disableCollisionBetweenLinkedBodies);
1699 sb0->setMass(node,0.f);
1705 return 0;//can't remove soft body anchors yet
1710 btVector3 pivotPointAWorld = colObj0->getWorldTransform()(pivotInA);
1711 int node=findClosestNode(sb1,pivotPointAWorld);
1714 bool clusterconstaint = false;
1719 case PHY_LINEHINGE_CONSTRAINT:
1721 if (sb1->clusterCount() && rb0)
1723 btSoftBody::LJoint::Specs ls;
1725 ls.position=sb1->clusterCom(0);
1726 sb1->appendLinearJoint(ls,rb0);
1727 clusterconstaint = true;
1731 case PHY_GENERIC_6DOF_CONSTRAINT:
1733 if (sb1->clusterCount() && rb0)
1735 btSoftBody::AJoint::Specs as;
1738 as.axis.setValue(axisX,axisY,axisZ);
1739 sb1->appendAngularJoint(as,rb0);
1740 clusterconstaint = true;
1754 if (!clusterconstaint)
1758 sb1->appendAnchor(node,rb0,disableCollisionBetweenLinkedBodies);
1761 sb1->setMass(node,0.f);
1767 return 0;//can't remove soft body anchors yet
1770 if (rb0static && rb1static)
1781 btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) :
1782 rb0->getCenterOfMassTransform() * pivotInA;
1783 btVector3 axisInA(axisX,axisY,axisZ);
1786 bool angularOnly = false;
1790 case PHY_POINT2POINT_CONSTRAINT:
1793 btPoint2PointConstraint* p2p = 0;
1797 p2p = new btPoint2PointConstraint(*rb0,
1798 *rb1,pivotInA,pivotInB);
1801 p2p = new btPoint2PointConstraint(*rb0,
1805 m_dynamicsWorld->addConstraint(p2p,disableCollisionBetweenLinkedBodies);
1806 // m_constraints.push_back(p2p);
1808 p2p->setUserConstraintId(gConstraintUid++);
1809 p2p->setUserConstraintType(type);
1810 //64 bit systems can't cast pointer to int. could use size_t instead.
1811 return p2p->getUserConstraintId();
1816 case PHY_GENERIC_6DOF_CONSTRAINT:
1818 btGeneric6DofConstraint* genericConstraint = 0;
1822 btTransform frameInA;
1823 btTransform frameInB;
1825 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
1826 if (axis1.length() == 0.0)
1828 btPlaneSpace1( axisInA, axis1, axis2 );
1831 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1832 axisInA.y(), axis1.y(), axis2.y(),
1833 axisInA.z(), axis1.z(), axis2.z() );
1834 frameInA.setOrigin( pivotInA );
1836 btTransform inv = rb1->getCenterOfMassTransform().inverse();
1838 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
1840 frameInB = inv * globalFrameA;
1841 bool useReferenceFrameA = true;
1843 genericConstraint = new btGeneric6DofConstraint(
1845 frameInA,frameInB,useReferenceFrameA);
1850 static btRigidBody s_fixedObject2( 0,0,0);
1851 btTransform frameInA;
1852 btTransform frameInB;
1854 btVector3 axis1, axis2;
1855 btPlaneSpace1( axisInA, axis1, axis2 );
1857 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1858 axisInA.y(), axis1.y(), axis2.y(),
1859 axisInA.z(), axis1.z(), axis2.z() );
1861 frameInA.setOrigin( pivotInA );
1863 ///frameInB in worldspace
1864 frameInB = rb0->getCenterOfMassTransform() * frameInA;
1866 bool useReferenceFrameA = true;
1867 genericConstraint = new btGeneric6DofConstraint(
1868 *rb0,s_fixedObject2,
1869 frameInA,frameInB,useReferenceFrameA);
1872 if (genericConstraint)
1874 //m_constraints.push_back(genericConstraint);
1875 m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
1876 genericConstraint->setUserConstraintId(gConstraintUid++);
1877 genericConstraint->setUserConstraintType(type);
1878 //64 bit systems can't cast pointer to int. could use size_t instead.
1879 return genericConstraint->getUserConstraintId();
1884 case PHY_CONE_TWIST_CONSTRAINT:
1886 btConeTwistConstraint* coneTwistContraint = 0;
1891 btTransform frameInA;
1892 btTransform frameInB;
1894 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
1895 if (axis1.length() == 0.0)
1897 btPlaneSpace1( axisInA, axis1, axis2 );
1900 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1901 axisInA.y(), axis1.y(), axis2.y(),
1902 axisInA.z(), axis1.z(), axis2.z() );
1903 frameInA.setOrigin( pivotInA );
1905 btTransform inv = rb1->getCenterOfMassTransform().inverse();
1907 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
1909 frameInB = inv * globalFrameA;
1911 coneTwistContraint = new btConeTwistConstraint( *rb0,*rb1,
1917 static btRigidBody s_fixedObject2( 0,0,0);
1918 btTransform frameInA;
1919 btTransform frameInB;
1921 btVector3 axis1, axis2;
1922 btPlaneSpace1( axisInA, axis1, axis2 );
1924 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1925 axisInA.y(), axis1.y(), axis2.y(),
1926 axisInA.z(), axis1.z(), axis2.z() );
1928 frameInA.setOrigin( pivotInA );
1930 ///frameInB in worldspace
1931 frameInB = rb0->getCenterOfMassTransform() * frameInA;
1933 coneTwistContraint = new btConeTwistConstraint(
1934 *rb0,s_fixedObject2,
1938 if (coneTwistContraint)
1940 //m_constraints.push_back(genericConstraint);
1941 m_dynamicsWorld->addConstraint(coneTwistContraint,disableCollisionBetweenLinkedBodies);
1942 coneTwistContraint->setUserConstraintId(gConstraintUid++);
1943 coneTwistContraint->setUserConstraintType(type);
1944 //64 bit systems can't cast pointer to int. could use size_t instead.
1945 return coneTwistContraint->getUserConstraintId();
1952 case PHY_ANGULAR_CONSTRAINT:
1956 case PHY_LINEHINGE_CONSTRAINT:
1958 btHingeConstraint* hinge = 0;
1962 btVector3 axisInB = rb1 ?
1963 (rb1->getCenterOfMassTransform().getBasis().inverse()*(rb0->getCenterOfMassTransform().getBasis() * axisInA)) :
1964 rb0->getCenterOfMassTransform().getBasis() * axisInA;
1966 hinge = new btHingeConstraint(
1968 *rb1,pivotInA,pivotInB,axisInA,axisInB);
1973 hinge = new btHingeConstraint(*rb0,
1977 hinge->setAngularOnly(angularOnly);
1979 //m_constraints.push_back(hinge);
1980 m_dynamicsWorld->addConstraint(hinge,disableCollisionBetweenLinkedBodies);
1981 hinge->setUserConstraintId(gConstraintUid++);
1982 hinge->setUserConstraintType(type);
1983 //64 bit systems can't cast pointer to int. could use size_t instead.
1984 return hinge->getUserConstraintId();
1987 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1989 case PHY_VEHICLE_CONSTRAINT:
1991 btRaycastVehicle::btVehicleTuning* tuning = new btRaycastVehicle::btVehicleTuning();
1992 btRigidBody* chassis = rb0;
1993 btDefaultVehicleRaycaster* raycaster = new btDefaultVehicleRaycaster(m_dynamicsWorld);
1994 btRaycastVehicle* vehicle = new btRaycastVehicle(*tuning,chassis,raycaster);
1995 WrapperVehicle* wrapperVehicle = new WrapperVehicle(vehicle,ctrl0);
1996 m_wrapperVehicles.push_back(wrapperVehicle);
1997 m_dynamicsWorld->addVehicle(vehicle);
1998 vehicle->setUserConstraintId(gConstraintUid++);
1999 vehicle->setUserConstraintType(type);
2000 return vehicle->getUserConstraintId();
2004 #endif //NEW_BULLET_VEHICLE_SUPPORT
2011 //btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB
2019 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
2021 CcdConstructionInfo cinfo;
2022 memset(&cinfo, 0, sizeof(cinfo)); /* avoid uninitialized values */
2023 // we don't need a CcdShapeConstructionInfo for this shape:
2024 // it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
2025 cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
2026 cinfo.m_MotionState = 0;
2027 cinfo.m_physicsEnv = this;
2028 cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
2029 DefaultMotionState* motionState = new DefaultMotionState();
2030 cinfo.m_MotionState = motionState;
2032 // we will add later the possibility to select the filter from option
2033 cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
2034 cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
2035 motionState->m_worldTransform.setIdentity();
2036 // motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
2038 CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
2041 return sphereController;
2044 float CcdPhysicsEnvironment::getAppliedImpulse(int constraintid)
2047 int numConstraints = m_dynamicsWorld->getNumConstraints();
2048 for (i=0;i<numConstraints;i++)
2050 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
2051 if (constraint->getUserConstraintId() == constraintid)
2053 return constraint->getAppliedImpulse();