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),
668 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
670 //don't collide with self
671 if (proxy0->m_clientObject == m_owner)
674 if (proxy0->m_clientObject == m_parent)
677 return btCollisionWorld::ClosestRayResultCallback::needsCollision(proxy0);
682 void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
684 std::set<CcdPhysicsController*>::iterator it;
686 for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
688 CcdPhysicsController* ctrl = (*it);
689 btRigidBody* body = ctrl->GetRigidBody();
691 if (body && (ctrl->getConstructionInfo().m_do_fh || ctrl->getConstructionInfo().m_do_rot_fh))
693 //printf("has Fh or RotFh\n");
694 //re-implement SM_FhObject.cpp using btCollisionWorld::rayTest and info from ctrl->getConstructionInfo()
695 //send a ray from {0.0, 0.0, 0.0} towards {0.0, 0.0, -10.0}, in local coordinates
698 CcdPhysicsController* parentCtrl = ctrl->getParentCtrl();
699 btRigidBody* parentBody = parentCtrl?parentCtrl->GetRigidBody() : 0;
700 btRigidBody* cl_object = parentBody ? parentBody : body;
702 if (body->isStaticOrKinematicObject())
705 btVector3 rayDirLocal(0,0,-10);
708 //ctrl->GetRigidBody();
709 btVector3 rayFromWorld = body->getCenterOfMassPosition();
710 //btVector3 rayToWorld = rayFromWorld + body->getCenterOfMassTransform().getBasis() * rayDirLocal;
711 //ray always points down the z axis in world space...
712 btVector3 rayToWorld = rayFromWorld + rayDirLocal;
714 ClosestRayResultCallbackNotMe resultCallback(rayFromWorld,rayToWorld,body,parentBody);
716 m_dynamicsWorld->rayTest(rayFromWorld,rayToWorld,resultCallback);
717 if (resultCallback.hasHit())
719 //we hit this one: resultCallback.m_collisionObject;
720 CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(resultCallback.m_collisionObject->getUserPointer());
724 if (controller->getConstructionInfo().m_fh_distance < SIMD_EPSILON)
727 btRigidBody* hit_object = controller->GetRigidBody();
731 CcdConstructionInfo& hitObjShapeProps = controller->getConstructionInfo();
733 float distance = resultCallback.m_closestHitFraction*rayDirLocal.length()-ctrl->getConstructionInfo().m_radius;
734 if (distance >= hitObjShapeProps.m_fh_distance)
739 //btVector3 ray_dir = cl_object->getCenterOfMassTransform().getBasis()* rayDirLocal.normalized();
740 btVector3 ray_dir = rayDirLocal.normalized();
741 btVector3 normal = resultCallback.m_hitNormalWorld;
745 if (ctrl->getConstructionInfo().m_do_fh)
747 btVector3 lspot = cl_object->getCenterOfMassPosition()
748 + rayDirLocal * resultCallback.m_closestHitFraction;
753 lspot -= hit_object->getCenterOfMassPosition();
754 btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot);
755 btScalar rel_vel_ray = ray_dir.dot(rel_vel);
756 btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance;
758 btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring;
759 btScalar i_damp = rel_vel_ray * hitObjShapeProps.m_fh_damping;
761 cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir));
762 if (hitObjShapeProps.m_fh_normal)
764 cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir));
767 btVector3 lateral = rel_vel - rel_vel_ray * ray_dir;
770 if (ctrl->getConstructionInfo().m_do_anisotropic) {
771 //Bullet basis contains no scaling/shear etc.
772 const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis();
773 btVector3 loc_lateral = lateral * lcs;
774 const btVector3& friction_scaling = cl_object->getAnisotropicFriction();
775 loc_lateral *= friction_scaling;
776 lateral = lcs * loc_lateral;
779 btScalar rel_vel_lateral = lateral.length();
781 if (rel_vel_lateral > SIMD_EPSILON) {
782 btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction();
784 btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring);
786 btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass();
788 btVector3 friction = (rel_mom_lateral > max_friction) ?
789 -lateral * (max_friction / rel_vel_lateral) :
792 cl_object->applyCentralImpulse(friction);
797 if (ctrl->getConstructionInfo().m_do_rot_fh) {
798 btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2);
800 btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring;
801 btVector3 ang_vel = cl_object->getAngularVelocity();
803 // only rotations that tilt relative to the normal are damped
804 ang_vel -= ang_vel.dot(normal) * normal;
806 btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping;
808 cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp));
822 void CcdPhysicsEnvironment::setDebugMode(int debugMode)
825 m_debugDrawer->setDebugMode(debugMode);
829 void CcdPhysicsEnvironment::setNumIterations(int numIter)
831 m_numIterations = numIter;
833 void CcdPhysicsEnvironment::setDeactivationTime(float dTime)
835 gDeactivationTime = dTime;
837 void CcdPhysicsEnvironment::setDeactivationLinearTreshold(float linTresh)
839 gLinearSleepingTreshold = linTresh;
841 void CcdPhysicsEnvironment::setDeactivationAngularTreshold(float angTresh)
843 gAngularSleepingTreshold = angTresh;
846 void CcdPhysicsEnvironment::setContactBreakingTreshold(float contactBreakingTreshold)
848 gContactBreakingThreshold = contactBreakingTreshold;
853 void CcdPhysicsEnvironment::setCcdMode(int ccdMode)
859 void CcdPhysicsEnvironment::setSolverSorConstant(float sor)
861 m_solverInfo.m_sor = sor;
864 void CcdPhysicsEnvironment::setSolverTau(float tau)
866 m_solverInfo.m_tau = tau;
868 void CcdPhysicsEnvironment::setSolverDamping(float damping)
870 m_solverInfo.m_damping = damping;
874 void CcdPhysicsEnvironment::setLinearAirDamping(float damping)
876 //gLinearAirDamping = damping;
879 void CcdPhysicsEnvironment::setUseEpa(bool epa)
884 void CcdPhysicsEnvironment::setSolverType(int solverType)
891 if (m_solverType != solverType)
894 m_solver = new btSequentialImpulseConstraintSolver();
903 if (m_solverType != solverType)
905 // m_solver = new OdeConstraintSolver();
912 m_solverType = solverType ;
917 void CcdPhysicsEnvironment::getGravity(PHY__Vector3& grav)
919 const btVector3& gravity = m_dynamicsWorld->getGravity();
920 grav[0] = gravity.getX();
921 grav[1] = gravity.getY();
922 grav[2] = gravity.getZ();
926 void CcdPhysicsEnvironment::setGravity(float x,float y,float z)
928 m_gravity = btVector3(x,y,z);
929 m_dynamicsWorld->setGravity(m_gravity);
936 static int gConstraintUid = 1;
938 //Following the COLLADA physics specification for constraints
939 int CcdPhysicsEnvironment::createUniversalD6Constraint(
940 class PHY_IPhysicsController* ctrlRef,class PHY_IPhysicsController* ctrlOther,
941 btTransform& frameInA,
942 btTransform& frameInB,
943 const btVector3& linearMinLimits,
944 const btVector3& linearMaxLimits,
945 const btVector3& angularMinLimits,
946 const btVector3& angularMaxLimits,int flags
950 bool disableCollisionBetweenLinkedBodies = (0!=(flags & CCD_CONSTRAINT_DISABLE_LINKED_COLLISION));
952 //we could either add some logic to recognize ball-socket and hinge, or let that up to the user
953 //perhaps some warning or hint that hinge/ball-socket is more efficient?
956 btGeneric6DofConstraint* genericConstraint = 0;
957 CcdPhysicsController* ctrl0 = (CcdPhysicsController*) ctrlRef;
958 CcdPhysicsController* ctrl1 = (CcdPhysicsController*) ctrlOther;
960 btRigidBody* rb0 = ctrl0->GetRigidBody();
961 btRigidBody* rb1 = ctrl1->GetRigidBody();
967 bool useReferenceFrameA = true;
968 genericConstraint = new btGeneric6DofConstraint(
970 frameInA,frameInB,useReferenceFrameA);
971 genericConstraint->setLinearLowerLimit(linearMinLimits);
972 genericConstraint->setLinearUpperLimit(linearMaxLimits);
973 genericConstraint->setAngularLowerLimit(angularMinLimits);
974 genericConstraint->setAngularUpperLimit(angularMaxLimits);
977 // TODO: Implement single body case...
978 //No, we can use a fixed rigidbody in above code, rather then unnecessary duplation of code
982 if (genericConstraint)
984 // m_constraints.push_back(genericConstraint);
985 m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
987 genericConstraint->setUserConstraintId(gConstraintUid++);
988 genericConstraint->setUserConstraintType(PHY_GENERIC_6DOF_CONSTRAINT);
989 //64 bit systems can't cast pointer to int. could use size_t instead.
990 return genericConstraint->getUserConstraintId();
997 void CcdPhysicsEnvironment::removeConstraint(int constraintId)
1001 int numConstraints = m_dynamicsWorld->getNumConstraints();
1002 for (i=0;i<numConstraints;i++)
1004 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
1005 if (constraint->getUserConstraintId() == constraintId)
1007 constraint->getRigidBodyA().activate();
1008 constraint->getRigidBodyB().activate();
1009 m_dynamicsWorld->removeConstraint(constraint);
1016 struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
1018 PHY_IRayCastFilterCallback& m_phyRayFilter;
1019 const btCollisionShape* m_hitTriangleShape;
1020 int m_hitTriangleIndex;
1022 FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo)
1023 : btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo),
1024 m_phyRayFilter(phyRayFilter),
1025 m_hitTriangleShape(NULL),
1026 m_hitTriangleIndex(0)
1030 virtual ~FilterClosestRayResultCallback()
1034 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
1036 if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask))
1038 if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask))
1040 btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject;
1041 CcdPhysicsController* phyCtrl = static_cast<CcdPhysicsController*>(object->getUserPointer());
1042 if (phyCtrl == m_phyRayFilter.m_ignoreController)
1044 return m_phyRayFilter.needBroadphaseRayCast(phyCtrl);
1047 virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
1049 CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer());
1050 // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it
1051 if (rayResult.m_localShapeInfo)
1053 m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape();
1054 m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex;
1057 m_hitTriangleShape = NULL;
1058 m_hitTriangleIndex = 0;
1060 return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace);
1065 PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
1069 float minFraction = 1.f;
1071 btVector3 rayFrom(fromX,fromY,fromZ);
1072 btVector3 rayTo(toX,toY,toZ);
1074 btVector3 hitPointWorld,normalWorld;
1076 //Either Ray Cast with or without filtering
1078 //btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo);
1079 FilterClosestRayResultCallback rayCallback(filterCallback,rayFrom,rayTo);
1082 PHY_RayCastResult result;
1083 memset(&result, 0, sizeof(result));
1085 // don't collision with sensor object
1086 rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
1087 //, ,filterCallback.m_faceNormal);
1089 m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback);
1090 if (rayCallback.hasHit())
1092 CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(rayCallback.m_collisionObject->getUserPointer());
1093 result.m_controller = controller;
1094 result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX();
1095 result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY();
1096 result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ();
1098 if (rayCallback.m_hitTriangleShape != NULL)
1100 // identify the mesh polygon
1101 CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo;
1104 btCollisionShape* shape = controller->GetCollisionObject()->getCollisionShape();
1105 if (shape->isCompound())
1107 btCompoundShape* compoundShape = (btCompoundShape*)shape;
1108 CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo;
1109 // need to search which sub-shape has been hit
1110 for (int i=0; i<compoundShape->getNumChildShapes(); i++)
1112 shapeInfo = compoundShapeInfo->GetChildShape(i);
1113 shape=compoundShape->getChildShape(i);
1114 if (shape == rayCallback.m_hitTriangleShape)
1118 if (shape == rayCallback.m_hitTriangleShape &&
1119 rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size())
1121 result.m_meshObject = shapeInfo->GetMesh();
1122 result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex);
1124 // Bullet returns the normal from "outside".
1125 // If the user requests the real normal, compute it now
1126 if (filterCallback.m_faceNormal)
1128 // mesh shapes are shared and stored in the shapeInfo
1129 btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape();
1132 // this code is copied from Bullet
1133 btVector3 triangle[3];
1134 const unsigned char *vertexbase;
1136 PHY_ScalarType type;
1138 const unsigned char *indexbase;
1141 PHY_ScalarType indicestype;
1142 btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface();
1144 meshInterface->getLockedReadOnlyVertexIndexBase(
1155 unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride);
1156 const btVector3& meshScaling = shape->getLocalScaling();
1157 for (int j=2;j>=0;j--)
1159 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
1161 btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
1163 triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
1165 meshInterface->unLockReadOnlyVertexBase(0);
1166 btVector3 triangleNormal;
1167 triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
1168 rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal;
1174 if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON))
1176 rayCallback.m_hitNormalWorld.normalize();
1179 rayCallback.m_hitNormalWorld.setValue(1,0,0);
1181 result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX();
1182 result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY();
1183 result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ();
1184 filterCallback.reportHit(&result);
1188 return result.m_controller;
1191 struct DbvtCullingCallback : btDbvt::ICollide
1193 PHY_CullingCallback m_clientCallback;
1196 DbvtCullingCallback(PHY_CullingCallback clientCallback, void* userData)
1198 m_clientCallback = clientCallback;
1199 m_userData = userData;
1202 void Process(const btDbvtNode* node,btScalar depth)
1206 void Process(const btDbvtNode* leaf)
1208 btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data;
1209 // the client object is a graphic controller
1210 CcdGraphicController* ctrl = static_cast<CcdGraphicController*>(proxy->m_clientObject);
1211 KX_ClientObjectInfo* info = (KX_ClientObjectInfo*)ctrl->getNewClientInfo();
1213 (*m_clientCallback)(info, m_userData);
1217 bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes)
1221 DbvtCullingCallback dispatcher(callback, userData);
1222 btVector3 planes_n[5];
1223 btScalar planes_o[5];
1226 for (int i=0; i<nplanes; i++)
1228 planes_n[i].setValue(planes[i][0], planes[i][1], planes[i][2]);
1229 planes_o[i] = planes[i][3];
1231 btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher);
1232 btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher);
1237 int CcdPhysicsEnvironment::getNumContactPoints()
1242 void CcdPhysicsEnvironment::getContactPoint(int i,float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
1250 btBroadphaseInterface* CcdPhysicsEnvironment::getBroadphase()
1252 return m_dynamicsWorld->getBroadphase();
1255 btDispatcher* CcdPhysicsEnvironment::getDispatcher()
1257 return m_dynamicsWorld->getDispatcher();
1265 CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
1268 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1269 m_wrapperVehicles.clear();
1270 #endif //NEW_BULLET_VEHICLE_SUPPORT
1272 //m_broadphase->DestroyScene();
1273 //delete broadphase ? release reference on broadphase ?
1275 //first delete scene, then dispatcher, because pairs have to release manifolds on the dispatcher
1276 //delete m_dispatcher;
1277 delete m_dynamicsWorld;
1280 if (NULL != m_ownPairCache)
1281 delete m_ownPairCache;
1283 if (NULL != m_ownDispatcher)
1284 delete m_ownDispatcher;
1286 if (NULL != m_solver)
1289 if (NULL != m_debugDrawer)
1290 delete m_debugDrawer;
1292 if (NULL != m_filterCallback)
1293 delete m_filterCallback;
1295 if (NULL != m_collisionConfiguration)
1296 delete m_collisionConfiguration;
1298 if (NULL != m_broadphase)
1299 delete m_broadphase;
1301 if (NULL != m_cullingTree)
1302 delete m_cullingTree;
1304 if (NULL != m_cullingCache)
1305 delete m_cullingCache;
1310 void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float value0,float value1)
1312 btTypedConstraint* typedConstraint = getConstraintById(constraintId);
1313 switch (typedConstraint->getUserConstraintType())
1315 case PHY_GENERIC_6DOF_CONSTRAINT:
1317 //param = 1..12, min0,max0,min1,max1...min6,max6
1318 btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
1319 genCons->setLimit(param,value0,value1);
1328 btTypedConstraint* CcdPhysicsEnvironment::getConstraintById(int constraintId)
1331 int numConstraints = m_dynamicsWorld->getNumConstraints();
1333 for (i=0;i<numConstraints;i++)
1335 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
1336 if (constraint->getUserConstraintId()==constraintId)
1345 void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
1348 CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl;
1349 // addSensor() is a "light" function for bullet because it is used
1350 // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead
1351 //if (m_controllers.insert(ctrl1).second)
1353 // addCcdPhysicsController(ctrl1);
1355 enableCcdPhysicsController(ctrl1);
1357 //Collision filter/mask is now set at the time of the creation of the controller
1358 //force collision detection with everything, including static objects (might hurt performance!)
1359 //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::SensorTrigger;
1360 //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterGroup = btBroadphaseProxy::SensorTrigger;
1361 //todo: make this 'sensor'!
1363 requestCollisionCallback(ctrl);
1364 //printf("addSensor\n");
1367 void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl)
1369 CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl;
1370 if (ccdCtrl->Unregister())
1371 m_triggerControllers.erase(ccdCtrl);
1375 void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl)
1377 removeCollisionCallback(ctrl);
1379 disableCcdPhysicsController((CcdPhysicsController*)ctrl);
1382 void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
1384 /* printf("addTouchCallback\n(response class = %i)\n",response_class);
1386 //map PHY_ convention into SM_ convention
1387 switch (response_class)
1389 case PHY_FH_RESPONSE:
1390 printf("PHY_FH_RESPONSE\n");
1392 case PHY_SENSOR_RESPONSE:
1393 printf("PHY_SENSOR_RESPONSE\n");
1395 case PHY_CAMERA_RESPONSE:
1396 printf("PHY_CAMERA_RESPONSE\n");
1398 case PHY_OBJECT_RESPONSE:
1399 printf("PHY_OBJECT_RESPONSE\n");
1401 case PHY_STATIC_RESPONSE:
1402 printf("PHY_STATIC_RESPONSE\n");
1410 m_triggerCallbacks[response_class] = callback;
1411 m_triggerCallbacksUserPtrs[response_class] = user;
1414 void CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl)
1416 CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl);
1418 if (ccdCtrl->Register())
1419 m_triggerControllers.insert(ccdCtrl);
1422 void CcdPhysicsEnvironment::CallbackTriggers()
1425 CcdPhysicsController* ctrl0=0,*ctrl1=0;
1427 if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)))
1429 //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
1430 btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
1431 int numManifolds = dispatcher->getNumManifolds();
1432 for (int i=0;i<numManifolds;i++)
1434 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
1435 int numContacts = manifold->getNumContacts();
1438 btRigidBody* rb0 = static_cast<btRigidBody*>(manifold->getBody0());
1439 btRigidBody* rb1 = static_cast<btRigidBody*>(manifold->getBody1());
1440 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))
1442 for (int j=0;j<numContacts;j++)
1444 btVector3 color(1,0,0);
1445 const btManifoldPoint& cp = manifold->getContactPoint(j);
1447 m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
1450 btRigidBody* obj0 = rb0;
1451 btRigidBody* obj1 = rb1;
1453 //m_internalOwner is set in 'addPhysicsController'
1454 CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer());
1455 CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer());
1457 std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0);
1458 if (i == m_triggerControllers.end())
1460 i = m_triggerControllers.find(ctrl1);
1463 if (!(i == m_triggerControllers.end()))
1465 m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
1468 // Bullet does not refresh the manifold contact point for object without contact response
1469 // may need to remove this when a newer Bullet version is integrated
1470 if (!dispatcher->needsResponse(rb0, rb1))
1472 // Refresh algorithm fails sometimes when there is penetration
1473 // (usuall the case with ghost and sensor objects)
1474 // Let's just clear the manifold, in any case, it is recomputed on each frame.
1475 manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
1487 // This call back is called before a pair is added in the cache
1488 // Handy to remove objects that must be ignored by sensors
1489 bool CcdOverlapFilterCallBack::needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
1491 btCollisionObject *colObj0, *colObj1;
1492 CcdPhysicsController *sensorCtrl, *objCtrl;
1494 // first check the filters
1495 collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
1496 collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
1500 // additional check for sensor object
1501 if (proxy0->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
1503 // this is a sensor object, the other one can't be a sensor object because
1504 // they exclude each other in the above test
1505 assert(!(proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger));
1506 colObj0 = (btCollisionObject*)proxy0->m_clientObject;
1507 colObj1 = (btCollisionObject*)proxy1->m_clientObject;
1509 else if (proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
1511 colObj0 = (btCollisionObject*)proxy1->m_clientObject;
1512 colObj1 = (btCollisionObject*)proxy0->m_clientObject;
1518 if (!colObj0 || !colObj1)
1520 sensorCtrl = static_cast<CcdPhysicsController*>(colObj0->getUserPointer());
1521 objCtrl = static_cast<CcdPhysicsController*>(colObj1->getUserPointer());
1522 if (m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE])
1524 return m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE](m_physEnv->m_triggerCallbacksUserPtrs[PHY_BROADPH_RESPONSE], sensorCtrl, objCtrl, 0);
1530 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1532 //complex constraint for vehicles
1533 PHY_IVehicle* CcdPhysicsEnvironment::getVehicleConstraint(int constraintId)
1537 int numVehicles = m_wrapperVehicles.size();
1538 for (i=0;i<numVehicles;i++)
1540 WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i];
1541 if (wrapperVehicle->GetVehicle()->getUserConstraintId() == constraintId)
1542 return wrapperVehicle;
1548 #endif //NEW_BULLET_VEHICLE_SUPPORT
1551 int currentController = 0;
1552 int numController = 0;
1557 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position)
1560 CcdConstructionInfo cinfo;
1561 // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
1562 cinfo.m_collisionShape = new btSphereShape(radius);
1563 cinfo.m_MotionState = 0;
1564 cinfo.m_physicsEnv = this;
1565 // declare this object as Dyamic rather then static!!
1566 // The reason as it is designed to detect all type of object, including static object
1567 // It would cause static-static message to be printed on the console otherwise
1568 cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE/* | btCollisionObject::CF_KINEMATIC_OBJECT*/;
1569 DefaultMotionState* motionState = new DefaultMotionState();
1570 cinfo.m_MotionState = motionState;
1571 // we will add later the possibility to select the filter from option
1572 cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
1573 cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
1574 motionState->m_worldTransform.setIdentity();
1575 motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
1577 CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
1579 return sphereController;
1582 int findClosestNode(btSoftBody* sb,const btVector3& worldPoint);
1583 int findClosestNode(btSoftBody* sb,const btVector3& worldPoint)
1587 btSoftBody::tNodeArray& nodes(sb->m_nodes);
1588 float maxDistSqr = 1e30f;
1590 for (int n=0;n<nodes.size();n++)
1592 btScalar distSqr = (nodes[n].m_x - worldPoint).length2();
1593 if (distSqr<maxDistSqr)
1595 maxDistSqr = distSqr;
1602 int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl0,class PHY_IPhysicsController* ctrl1,PHY_ConstraintType type,
1603 float pivotX,float pivotY,float pivotZ,
1604 float axisX,float axisY,float axisZ,
1605 float axis1X,float axis1Y,float axis1Z,
1606 float axis2X,float axis2Y,float axis2Z,int flags
1610 bool disableCollisionBetweenLinkedBodies = (0!=(flags & CCD_CONSTRAINT_DISABLE_LINKED_COLLISION));
1614 CcdPhysicsController* c0 = (CcdPhysicsController*)ctrl0;
1615 CcdPhysicsController* c1 = (CcdPhysicsController*)ctrl1;
1617 btRigidBody* rb0 = c0 ? c0->GetRigidBody() : 0;
1618 btRigidBody* rb1 = c1 ? c1->GetRigidBody() : 0;
1623 bool rb0static = rb0 ? rb0->isStaticOrKinematicObject() : true;
1624 bool rb1static = rb1 ? rb1->isStaticOrKinematicObject() : true;
1626 btCollisionObject* colObj0 = c0->GetCollisionObject();
1632 btVector3 pivotInA(pivotX,pivotY,pivotZ);
1636 //it might be a soft body, let's try
1637 btSoftBody* sb0 = c0 ? c0->GetSoftBody() : 0;
1638 btSoftBody* sb1 = c1 ? c1->GetSoftBody() : 0;
1641 //not between two soft bodies?
1647 //either cluster or node attach, let's find closest node first
1648 //the soft body doesn't have a 'real' world transform, so get its initial world transform for now
1649 btVector3 pivotPointSoftWorld = sb0->m_initialWorldTransform(pivotInA);
1650 int node=findClosestNode(sb0,pivotPointSoftWorld);
1653 bool clusterconstaint = false;
1657 case PHY_LINEHINGE_CONSTRAINT:
1659 if (sb0->clusterCount() && rb1)
1661 btSoftBody::LJoint::Specs ls;
1663 ls.position=sb0->clusterCom(0);
1664 sb0->appendLinearJoint(ls,rb1);
1665 clusterconstaint = true;
1669 case PHY_GENERIC_6DOF_CONSTRAINT:
1671 if (sb0->clusterCount() && rb1)
1673 btSoftBody::AJoint::Specs as;
1676 as.axis.setValue(axisX,axisY,axisZ);
1677 sb0->appendAngularJoint(as,rb1);
1678 clusterconstaint = true;
1691 if (!clusterconstaint)
1695 sb0->appendAnchor(node,rb1,disableCollisionBetweenLinkedBodies);
1698 sb0->setMass(node,0.f);
1704 return 0;//can't remove soft body anchors yet
1709 btVector3 pivotPointAWorld = colObj0->getWorldTransform()(pivotInA);
1710 int node=findClosestNode(sb1,pivotPointAWorld);
1713 bool clusterconstaint = false;
1718 case PHY_LINEHINGE_CONSTRAINT:
1720 if (sb1->clusterCount() && rb0)
1722 btSoftBody::LJoint::Specs ls;
1724 ls.position=sb1->clusterCom(0);
1725 sb1->appendLinearJoint(ls,rb0);
1726 clusterconstaint = true;
1730 case PHY_GENERIC_6DOF_CONSTRAINT:
1732 if (sb1->clusterCount() && rb0)
1734 btSoftBody::AJoint::Specs as;
1737 as.axis.setValue(axisX,axisY,axisZ);
1738 sb1->appendAngularJoint(as,rb0);
1739 clusterconstaint = true;
1753 if (!clusterconstaint)
1757 sb1->appendAnchor(node,rb0,disableCollisionBetweenLinkedBodies);
1760 sb1->setMass(node,0.f);
1766 return 0;//can't remove soft body anchors yet
1769 if (rb0static && rb1static)
1780 btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) :
1781 rb0->getCenterOfMassTransform() * pivotInA;
1782 btVector3 axisInA(axisX,axisY,axisZ);
1785 bool angularOnly = false;
1789 case PHY_POINT2POINT_CONSTRAINT:
1792 btPoint2PointConstraint* p2p = 0;
1796 p2p = new btPoint2PointConstraint(*rb0,
1797 *rb1,pivotInA,pivotInB);
1800 p2p = new btPoint2PointConstraint(*rb0,
1804 m_dynamicsWorld->addConstraint(p2p,disableCollisionBetweenLinkedBodies);
1805 // m_constraints.push_back(p2p);
1807 p2p->setUserConstraintId(gConstraintUid++);
1808 p2p->setUserConstraintType(type);
1809 //64 bit systems can't cast pointer to int. could use size_t instead.
1810 return p2p->getUserConstraintId();
1815 case PHY_GENERIC_6DOF_CONSTRAINT:
1817 btGeneric6DofConstraint* genericConstraint = 0;
1821 btTransform frameInA;
1822 btTransform frameInB;
1824 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
1825 if (axis1.length() == 0.0)
1827 btPlaneSpace1( axisInA, axis1, axis2 );
1830 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1831 axisInA.y(), axis1.y(), axis2.y(),
1832 axisInA.z(), axis1.z(), axis2.z() );
1833 frameInA.setOrigin( pivotInA );
1835 btTransform inv = rb1->getCenterOfMassTransform().inverse();
1837 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
1839 frameInB = inv * globalFrameA;
1840 bool useReferenceFrameA = true;
1842 genericConstraint = new btGeneric6DofConstraint(
1844 frameInA,frameInB,useReferenceFrameA);
1849 static btRigidBody s_fixedObject2( 0,0,0);
1850 btTransform frameInA;
1851 btTransform frameInB;
1853 btVector3 axis1, axis2;
1854 btPlaneSpace1( axisInA, axis1, axis2 );
1856 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1857 axisInA.y(), axis1.y(), axis2.y(),
1858 axisInA.z(), axis1.z(), axis2.z() );
1860 frameInA.setOrigin( pivotInA );
1862 ///frameInB in worldspace
1863 frameInB = rb0->getCenterOfMassTransform() * frameInA;
1865 bool useReferenceFrameA = true;
1866 genericConstraint = new btGeneric6DofConstraint(
1867 *rb0,s_fixedObject2,
1868 frameInA,frameInB,useReferenceFrameA);
1871 if (genericConstraint)
1873 //m_constraints.push_back(genericConstraint);
1874 m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies);
1875 genericConstraint->setUserConstraintId(gConstraintUid++);
1876 genericConstraint->setUserConstraintType(type);
1877 //64 bit systems can't cast pointer to int. could use size_t instead.
1878 return genericConstraint->getUserConstraintId();
1883 case PHY_CONE_TWIST_CONSTRAINT:
1885 btConeTwistConstraint* coneTwistContraint = 0;
1890 btTransform frameInA;
1891 btTransform frameInB;
1893 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
1894 if (axis1.length() == 0.0)
1896 btPlaneSpace1( axisInA, axis1, axis2 );
1899 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1900 axisInA.y(), axis1.y(), axis2.y(),
1901 axisInA.z(), axis1.z(), axis2.z() );
1902 frameInA.setOrigin( pivotInA );
1904 btTransform inv = rb1->getCenterOfMassTransform().inverse();
1906 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
1908 frameInB = inv * globalFrameA;
1910 coneTwistContraint = new btConeTwistConstraint( *rb0,*rb1,
1916 static btRigidBody s_fixedObject2( 0,0,0);
1917 btTransform frameInA;
1918 btTransform frameInB;
1920 btVector3 axis1, axis2;
1921 btPlaneSpace1( axisInA, axis1, axis2 );
1923 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1924 axisInA.y(), axis1.y(), axis2.y(),
1925 axisInA.z(), axis1.z(), axis2.z() );
1927 frameInA.setOrigin( pivotInA );
1929 ///frameInB in worldspace
1930 frameInB = rb0->getCenterOfMassTransform() * frameInA;
1932 coneTwistContraint = new btConeTwistConstraint(
1933 *rb0,s_fixedObject2,
1937 if (coneTwistContraint)
1939 //m_constraints.push_back(genericConstraint);
1940 m_dynamicsWorld->addConstraint(coneTwistContraint,disableCollisionBetweenLinkedBodies);
1941 coneTwistContraint->setUserConstraintId(gConstraintUid++);
1942 coneTwistContraint->setUserConstraintType(type);
1943 //64 bit systems can't cast pointer to int. could use size_t instead.
1944 return coneTwistContraint->getUserConstraintId();
1951 case PHY_ANGULAR_CONSTRAINT:
1955 case PHY_LINEHINGE_CONSTRAINT:
1957 btHingeConstraint* hinge = 0;
1961 btVector3 axisInB = rb1 ?
1962 (rb1->getCenterOfMassTransform().getBasis().inverse()*(rb0->getCenterOfMassTransform().getBasis() * axisInA)) :
1963 rb0->getCenterOfMassTransform().getBasis() * axisInA;
1965 hinge = new btHingeConstraint(
1967 *rb1,pivotInA,pivotInB,axisInA,axisInB);
1972 hinge = new btHingeConstraint(*rb0,
1976 hinge->setAngularOnly(angularOnly);
1978 //m_constraints.push_back(hinge);
1979 m_dynamicsWorld->addConstraint(hinge,disableCollisionBetweenLinkedBodies);
1980 hinge->setUserConstraintId(gConstraintUid++);
1981 hinge->setUserConstraintType(type);
1982 //64 bit systems can't cast pointer to int. could use size_t instead.
1983 return hinge->getUserConstraintId();
1986 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1988 case PHY_VEHICLE_CONSTRAINT:
1990 btRaycastVehicle::btVehicleTuning* tuning = new btRaycastVehicle::btVehicleTuning();
1991 btRigidBody* chassis = rb0;
1992 btDefaultVehicleRaycaster* raycaster = new btDefaultVehicleRaycaster(m_dynamicsWorld);
1993 btRaycastVehicle* vehicle = new btRaycastVehicle(*tuning,chassis,raycaster);
1994 WrapperVehicle* wrapperVehicle = new WrapperVehicle(vehicle,ctrl0);
1995 m_wrapperVehicles.push_back(wrapperVehicle);
1996 m_dynamicsWorld->addVehicle(vehicle);
1997 vehicle->setUserConstraintId(gConstraintUid++);
1998 vehicle->setUserConstraintType(type);
1999 return vehicle->getUserConstraintId();
2003 #endif //NEW_BULLET_VEHICLE_SUPPORT
2010 //btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB
2018 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
2020 CcdConstructionInfo cinfo;
2022 // we don't need a CcdShapeConstructionInfo for this shape:
2023 // it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
2024 cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
2025 cinfo.m_MotionState = 0;
2026 cinfo.m_physicsEnv = this;
2027 cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
2028 DefaultMotionState* motionState = new DefaultMotionState();
2029 cinfo.m_MotionState = motionState;
2031 // we will add later the possibility to select the filter from option
2032 cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
2033 cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
2034 motionState->m_worldTransform.setIdentity();
2035 // motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
2037 CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
2040 return sphereController;
2043 float CcdPhysicsEnvironment::getAppliedImpulse(int constraintid)
2046 int numConstraints = m_dynamicsWorld->getNumConstraints();
2047 for (i=0;i<numConstraints;i++)
2049 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
2050 if (constraint->getUserConstraintId() == constraintid)
2052 return constraint->getAppliedImpulse();