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"
23 #include "btBulletDynamicsCommon.h"
24 #include "LinearMath/btIDebugDraw.h"
25 #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
26 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
27 #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
30 #include "LinearMath/btQuickprof.h"
33 #include "PHY_IMotionState.h"
36 bool useIslands = true;
38 #ifdef NEW_BULLET_VEHICLE_SUPPORT
39 #include "BulletDynamics/Vehicle/btRaycastVehicle.h"
40 #include "BulletDynamics/Vehicle/btVehicleRaycaster.h"
41 #include "BulletDynamics/Vehicle/btWheelInfo.h"
42 #include "PHY_IVehicle.h"
43 btRaycastVehicle::btVehicleTuning gTuning;
45 #endif //NEW_BULLET_VEHICLE_SUPPORT
46 #include "LinearMath/btAabbUtil2.h"
50 void DrawRasterizerLine(const float* from,const float* to,int color);
54 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
58 #include <string.h> // for memset
60 #ifdef NEW_BULLET_VEHICLE_SUPPORT
61 class WrapperVehicle : public PHY_IVehicle
64 btRaycastVehicle* m_vehicle;
65 PHY_IPhysicsController* m_chassis;
69 WrapperVehicle(btRaycastVehicle* vehicle,PHY_IPhysicsController* chassis)
75 btRaycastVehicle* GetVehicle()
80 PHY_IPhysicsController* GetChassis()
85 virtual void AddWheel(
86 PHY_IMotionState* motionState,
87 PHY__Vector3 connectionPoint,
88 PHY__Vector3 downDirection,
89 PHY__Vector3 axleDirection,
90 float suspensionRestLength,
95 btVector3 connectionPointCS0(connectionPoint[0],connectionPoint[1],connectionPoint[2]);
96 btVector3 wheelDirectionCS0(downDirection[0],downDirection[1],downDirection[2]);
97 btVector3 wheelAxle(axleDirection[0],axleDirection[1],axleDirection[2]);
100 btWheelInfo& info = m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxle,
101 suspensionRestLength,wheelRadius,gTuning,hasSteering);
102 info.m_clientInfo = motionState;
108 int numWheels = GetNumWheels();
110 for (i=0;i<numWheels;i++)
112 btWheelInfo& info = m_vehicle->getWheelInfo(i);
113 PHY_IMotionState* motionState = (PHY_IMotionState*)info.m_clientInfo ;
114 // m_vehicle->updateWheelTransformsWS(info,false);
115 m_vehicle->updateWheelTransform(i,false);
116 btTransform trans = m_vehicle->getWheelInfo(i).m_worldTransform;
117 btQuaternion orn = trans.getRotation();
118 const btVector3& pos = trans.getOrigin();
119 motionState->setWorldOrientation(orn.x(),orn.y(),orn.z(),orn[3]);
120 motionState->setWorldPosition(pos.x(),pos.y(),pos.z());
125 virtual int GetNumWheels() const
127 return m_vehicle->getNumWheels();
130 virtual void GetWheelPosition(int wheelIndex,float& posX,float& posY,float& posZ) const
132 btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
133 posX = trans.getOrigin().x();
134 posY = trans.getOrigin().y();
135 posZ = trans.getOrigin().z();
137 virtual void GetWheelOrientationQuaternion(int wheelIndex,float& quatX,float& quatY,float& quatZ,float& quatW) const
139 btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex);
140 btQuaternion quat = trans.getRotation();
141 btMatrix3x3 orn2(quat);
143 quatX = trans.getRotation().x();
144 quatY = trans.getRotation().y();
145 quatZ = trans.getRotation().z();
146 quatW = trans.getRotation()[3];
154 virtual float GetWheelRotation(int wheelIndex) const
156 float rotation = 0.f;
158 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
160 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
161 rotation = info.m_rotation;
169 virtual int GetUserConstraintId() const
171 return m_vehicle->getUserConstraintId();
174 virtual int GetUserConstraintType() const
176 return m_vehicle->getUserConstraintType();
179 virtual void SetSteeringValue(float steering,int wheelIndex)
181 m_vehicle->setSteeringValue(steering,wheelIndex);
184 virtual void ApplyEngineForce(float force,int wheelIndex)
186 m_vehicle->applyEngineForce(force,wheelIndex);
189 virtual void ApplyBraking(float braking,int wheelIndex)
191 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
193 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
194 info.m_brake = braking;
198 virtual void SetWheelFriction(float friction,int wheelIndex)
200 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
202 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
203 info.m_frictionSlip = friction;
208 virtual void SetSuspensionStiffness(float suspensionStiffness,int wheelIndex)
210 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
212 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
213 info.m_suspensionStiffness = suspensionStiffness;
218 virtual void SetSuspensionDamping(float suspensionDamping,int wheelIndex)
220 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
222 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
223 info.m_wheelsDampingRelaxation = suspensionDamping;
227 virtual void SetSuspensionCompression(float suspensionCompression,int wheelIndex)
229 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
231 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
232 info.m_wheelsDampingCompression = suspensionCompression;
238 virtual void SetRollInfluence(float rollInfluence,int wheelIndex)
240 if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels()))
242 btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex);
243 info.m_rollInfluence = rollInfluence;
247 virtual void SetCoordinateSystem(int rightIndex,int upIndex,int forwardIndex)
249 m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex);
255 #endif //NEW_BULLET_VEHICLE_SUPPORT
257 class CcdOverlapFilterCallBack : public btOverlapFilterCallback
260 class CcdPhysicsEnvironment* m_physEnv;
262 CcdOverlapFilterCallBack(CcdPhysicsEnvironment* env) :
266 virtual ~CcdOverlapFilterCallBack()
269 // return true when pairs need collision
270 virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const;
274 void CcdPhysicsEnvironment::setDebugDrawer(btIDebugDraw* debugDrawer)
276 if (debugDrawer && m_dynamicsWorld)
277 m_dynamicsWorld->setDebugDrawer(debugDrawer);
278 m_debugDrawer = debugDrawer;
281 static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVector3& to,const btVector3& color)
283 btVector3 halfExtents = (to-from)* 0.5f;
284 btVector3 center = (to+from) *0.5f;
287 btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
292 pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
293 edgecoord[2]*halfExtents[2]);
296 int othercoord = j%3;
297 edgecoord[othercoord]*=-1.f;
298 pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
299 edgecoord[2]*halfExtents[2]);
302 debugDrawer->drawLine(pa,pb,color);
304 edgecoord = btVector3(-1.f,-1.f,-1.f);
317 CcdPhysicsEnvironment::CcdPhysicsEnvironment(btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
318 :m_scalingPropagated(false),
320 m_numTimeSubSteps(1),
324 m_enableSatCollisionDetection(false),
326 m_ownPairCache(NULL),
327 m_ownDispatcher(NULL),
328 m_filterCallback(NULL)
331 for (int i=0;i<PHY_NUM_RESPONSE;i++)
333 m_triggerCallbacks[i] = 0;
336 // m_collisionConfiguration = new btDefaultCollisionConfiguration();
337 m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
341 dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
342 m_ownDispatcher = dispatcher;
345 //m_broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000),btVector3(1000,1000,1000));
346 //m_broadphase = new btSimpleBroadphase();
347 m_broadphase = new btDbvtBroadphase();
349 m_filterCallback = new CcdOverlapFilterCallBack(this);
350 m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
352 setSolverType(1);//issues with quickstep and memory allocations
353 // m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
354 m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
357 m_gravity = btVector3(0.f,-10.f,0.f);
358 m_dynamicsWorld->setGravity(m_gravity);
363 void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
365 btRigidBody* body = ctrl->GetRigidBody();
366 btCollisionObject* obj = ctrl->GetCollisionObject();
368 //this m_userPointer is just used for triggers, see CallbackTriggers
369 obj->setUserPointer(ctrl);
371 body->setGravity( m_gravity );
373 m_controllers.insert(ctrl);
377 //use explicit group/filter for finer control over collision in bullet => near/radar sensor
378 m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
381 if (ctrl->GetSoftBody())
383 btSoftBody* softBody = ctrl->GetSoftBody();
384 m_dynamicsWorld->addSoftBody(softBody);
387 if (obj->getCollisionShape())
389 m_dynamicsWorld->addCollisionObject(obj,ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
393 if (obj->isStaticOrKinematicObject())
395 obj->setActivationState(ISLAND_SLEEPING);
399 //CollisionObject(body,ctrl->GetCollisionFilterGroup(),ctrl->GetCollisionFilterMask());
401 assert(obj->getBroadphaseHandle());
403 btBroadphaseInterface* scene = getBroadphase();
406 btCollisionShape* shapeinterface = ctrl->GetCollisionShape();
408 assert(shapeinterface);
410 const btTransform& t = ctrl->GetCollisionObject()->getWorldTransform();
413 btPoint3 minAabb,maxAabb;
415 shapeinterface->getAabb(t,minAabb,maxAabb);
417 float timeStep = 0.02f;
420 //extent it with the motion
424 btVector3 linMotion = body->getLinearVelocity()*timeStep;
426 float maxAabbx = maxAabb.getX();
427 float maxAabby = maxAabb.getY();
428 float maxAabbz = maxAabb.getZ();
429 float minAabbx = minAabb.getX();
430 float minAabby = minAabb.getY();
431 float minAabbz = minAabb.getZ();
433 if (linMotion.x() > 0.f)
434 maxAabbx += linMotion.x();
436 minAabbx += linMotion.x();
437 if (linMotion.y() > 0.f)
438 maxAabby += linMotion.y();
440 minAabby += linMotion.y();
441 if (linMotion.z() > 0.f)
442 maxAabbz += linMotion.z();
444 minAabbz += linMotion.z();
447 minAabb = btVector3(minAabbx,minAabby,minAabbz);
448 maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz);
455 void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl)
457 //also remove constraint
458 btRigidBody* body = ctrl->GetRigidBody();
461 m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
465 if (ctrl->GetSoftBody())
467 m_dynamicsWorld->removeSoftBody(ctrl->GetSoftBody());
470 m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
473 m_controllers.erase(ctrl);
475 if (ctrl->m_registerCount != 0)
476 printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount);
478 //remove it from the triggers
479 m_triggerControllers.erase(ctrl);
482 void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask)
484 // this function is used when the collisionning group of a controller is changed
485 // remove and add the collistioning object
486 btRigidBody* body = ctrl->GetRigidBody();
487 btCollisionObject* obj = ctrl->GetCollisionObject();
490 btVector3 inertia(0.0,0.0,0.0);
491 m_dynamicsWorld->removeCollisionObject(obj);
492 obj->setCollisionFlags(newCollisionFlags);
496 body->getCollisionShape()->calculateLocalInertia(newMass, inertia);
497 body->setMassProps(newMass, inertia);
499 m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
501 // to avoid nasty interaction, we must update the property of the controller as well
502 ctrl->m_cci.m_mass = newMass;
503 ctrl->m_cci.m_collisionFilterGroup = newCollisionGroup;
504 ctrl->m_cci.m_collisionFilterMask = newCollisionMask;
505 ctrl->m_cci.m_collisionFlags = newCollisionFlags;
508 void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctrl)
510 if (m_controllers.insert(ctrl).second)
512 btCollisionObject* obj = ctrl->GetCollisionObject();
513 obj->setUserPointer(ctrl);
514 m_dynamicsWorld->addCollisionObject(obj,
515 ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
519 void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ctrl)
521 if (m_controllers.erase(ctrl))
523 btRigidBody* body = ctrl->GetRigidBody();
526 m_dynamicsWorld->removeRigidBody(body);
529 if (ctrl->GetSoftBody())
533 m_dynamicsWorld->removeCollisionObject(body);
540 void CcdPhysicsEnvironment::beginFrame()
546 bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
548 std::set<CcdPhysicsController*>::iterator it;
551 for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
553 (*it)->SynchronizeMotionStates(timeStep);
556 float subStep = timeStep / float(m_numTimeSubSteps);
557 for (i=0;i<m_numTimeSubSteps;i++)
559 // m_dynamicsWorld->stepSimulation(subStep,20,1./240.);//perform always a full simulation step
560 m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step
563 for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
565 (*it)->SynchronizeMotionStates(timeStep);
568 for (i=0;i<m_wrapperVehicles.size();i++)
570 WrapperVehicle* veh = m_wrapperVehicles[i];
574 m_dynamicsWorld->debugDrawWorld();
583 void CcdPhysicsEnvironment::setDebugMode(int debugMode)
586 m_debugDrawer->setDebugMode(debugMode);
590 void CcdPhysicsEnvironment::setNumIterations(int numIter)
592 m_numIterations = numIter;
594 void CcdPhysicsEnvironment::setDeactivationTime(float dTime)
596 gDeactivationTime = dTime;
598 void CcdPhysicsEnvironment::setDeactivationLinearTreshold(float linTresh)
600 gLinearSleepingTreshold = linTresh;
602 void CcdPhysicsEnvironment::setDeactivationAngularTreshold(float angTresh)
604 gAngularSleepingTreshold = angTresh;
607 void CcdPhysicsEnvironment::setContactBreakingTreshold(float contactBreakingTreshold)
609 gContactBreakingThreshold = contactBreakingTreshold;
614 void CcdPhysicsEnvironment::setCcdMode(int ccdMode)
620 void CcdPhysicsEnvironment::setSolverSorConstant(float sor)
622 m_solverInfo.m_sor = sor;
625 void CcdPhysicsEnvironment::setSolverTau(float tau)
627 m_solverInfo.m_tau = tau;
629 void CcdPhysicsEnvironment::setSolverDamping(float damping)
631 m_solverInfo.m_damping = damping;
635 void CcdPhysicsEnvironment::setLinearAirDamping(float damping)
637 //gLinearAirDamping = damping;
640 void CcdPhysicsEnvironment::setUseEpa(bool epa)
645 void CcdPhysicsEnvironment::setSolverType(int solverType)
652 if (m_solverType != solverType)
655 m_solver = new btSequentialImpulseConstraintSolver();
656 // ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER);
663 if (m_solverType != solverType)
665 // m_solver = new OdeConstraintSolver();
672 m_solverType = solverType ;
677 void CcdPhysicsEnvironment::getGravity(PHY__Vector3& grav)
679 const btVector3& gravity = m_dynamicsWorld->getGravity();
680 grav[0] = gravity.getX();
681 grav[1] = gravity.getY();
682 grav[2] = gravity.getZ();
686 void CcdPhysicsEnvironment::setGravity(float x,float y,float z)
688 m_gravity = btVector3(x,y,z);
689 m_dynamicsWorld->setGravity(m_gravity);
696 static int gConstraintUid = 1;
698 //Following the COLLADA physics specification for constraints
699 int CcdPhysicsEnvironment::createUniversalD6Constraint(
700 class PHY_IPhysicsController* ctrlRef,class PHY_IPhysicsController* ctrlOther,
701 btTransform& frameInA,
702 btTransform& frameInB,
703 const btVector3& linearMinLimits,
704 const btVector3& linearMaxLimits,
705 const btVector3& angularMinLimits,
706 const btVector3& angularMaxLimits
710 //we could either add some logic to recognize ball-socket and hinge, or let that up to the user
711 //perhaps some warning or hint that hinge/ball-socket is more efficient?
713 btGeneric6DofConstraint* genericConstraint = 0;
714 CcdPhysicsController* ctrl0 = (CcdPhysicsController*) ctrlRef;
715 CcdPhysicsController* ctrl1 = (CcdPhysicsController*) ctrlOther;
717 btRigidBody* rb0 = ctrl0->GetRigidBody();
718 btRigidBody* rb1 = ctrl1->GetRigidBody();
724 bool useReferenceFrameA = true;
725 genericConstraint = new btGeneric6DofConstraint(
727 frameInA,frameInB,useReferenceFrameA);
728 genericConstraint->setLinearLowerLimit(linearMinLimits);
729 genericConstraint->setLinearUpperLimit(linearMaxLimits);
730 genericConstraint->setAngularLowerLimit(angularMinLimits);
731 genericConstraint->setAngularUpperLimit(angularMaxLimits);
734 // TODO: Implement single body case...
735 //No, we can use a fixed rigidbody in above code, rather then unnecessary duplation of code
739 if (genericConstraint)
741 // m_constraints.push_back(genericConstraint);
742 m_dynamicsWorld->addConstraint(genericConstraint);
744 genericConstraint->setUserConstraintId(gConstraintUid++);
745 genericConstraint->setUserConstraintType(PHY_GENERIC_6DOF_CONSTRAINT);
746 //64 bit systems can't cast pointer to int. could use size_t instead.
747 return genericConstraint->getUserConstraintId();
754 void CcdPhysicsEnvironment::removeConstraint(int constraintId)
758 int numConstraints = m_dynamicsWorld->getNumConstraints();
759 for (i=0;i<numConstraints;i++)
761 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
762 if (constraint->getUserConstraintId() == constraintId)
764 constraint->getRigidBodyA().activate();
765 constraint->getRigidBodyB().activate();
766 m_dynamicsWorld->removeConstraint(constraint);
773 struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
775 PHY_IRayCastFilterCallback& m_phyRayFilter;
776 const btCollisionShape* m_hitTriangleShape;
777 int m_hitTriangleIndex;
779 FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo)
780 : btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo),
781 m_phyRayFilter(phyRayFilter),
782 m_hitTriangleShape(NULL),
783 m_hitTriangleIndex(0)
787 virtual ~FilterClosestRayResultCallback()
791 virtual bool needsCollision(btBroadphaseProxy* proxy0) const
793 if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask))
795 if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask))
797 btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject;
798 CcdPhysicsController* phyCtrl = static_cast<CcdPhysicsController*>(object->getUserPointer());
799 if (phyCtrl == m_phyRayFilter.m_ignoreController)
801 return m_phyRayFilter.needBroadphaseRayCast(phyCtrl);
804 virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
806 CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer());
807 // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it
808 if (rayResult.m_localShapeInfo)
810 m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape();
811 m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex;
814 m_hitTriangleShape = NULL;
815 m_hitTriangleIndex = 0;
817 return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace);
822 PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
826 float minFraction = 1.f;
828 btVector3 rayFrom(fromX,fromY,fromZ);
829 btVector3 rayTo(toX,toY,toZ);
831 btVector3 hitPointWorld,normalWorld;
833 //Either Ray Cast with or without filtering
835 //btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo);
836 FilterClosestRayResultCallback rayCallback(filterCallback,rayFrom,rayTo);
839 PHY_RayCastResult result;
840 memset(&result, 0, sizeof(result));
842 // don't collision with sensor object
843 rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
844 //, ,filterCallback.m_faceNormal);
846 m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback);
847 if (rayCallback.hasHit())
849 CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(rayCallback.m_collisionObject->getUserPointer());
850 result.m_controller = controller;
851 result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX();
852 result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY();
853 result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ();
855 if (rayCallback.m_hitTriangleShape != NULL)
857 // identify the mesh polygon
858 CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo;
861 btCollisionShape* shape = controller->GetCollisionObject()->getCollisionShape();
862 if (shape->isCompound())
864 btCompoundShape* compoundShape = (btCompoundShape*)shape;
865 CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo;
866 // need to search which sub-shape has been hit
867 for (int i=0; i<compoundShape->getNumChildShapes(); i++)
869 shapeInfo = compoundShapeInfo->GetChildShape(i);
870 shape=compoundShape->getChildShape(i);
871 if (shape == rayCallback.m_hitTriangleShape)
875 if (shape == rayCallback.m_hitTriangleShape &&
876 rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size())
878 result.m_meshObject = shapeInfo->GetMesh();
879 result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex);
881 // Bullet returns the normal from "outside".
882 // If the user requests the real normal, compute it now
883 if (filterCallback.m_faceNormal)
885 // mesh shapes are shared and stored in the shapeInfo
886 btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape();
889 // this code is copied from Bullet
890 btVector3 triangle[3];
891 const unsigned char *vertexbase;
895 const unsigned char *indexbase;
898 PHY_ScalarType indicestype;
899 btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface();
901 meshInterface->getLockedReadOnlyVertexIndexBase(
912 unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride);
913 const btVector3& meshScaling = shape->getLocalScaling();
914 for (int j=2;j>=0;j--)
916 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
918 btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
920 triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
922 meshInterface->unLockReadOnlyVertexBase(0);
923 btVector3 triangleNormal;
924 triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
925 rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal;
931 if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON))
933 rayCallback.m_hitNormalWorld.normalize();
936 rayCallback.m_hitNormalWorld.setValue(1,0,0);
938 result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX();
939 result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY();
940 result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ();
941 filterCallback.reportHit(&result);
945 return result.m_controller;
950 int CcdPhysicsEnvironment::getNumContactPoints()
955 void CcdPhysicsEnvironment::getContactPoint(int i,float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
963 btBroadphaseInterface* CcdPhysicsEnvironment::getBroadphase()
965 return m_dynamicsWorld->getBroadphase();
968 btDispatcher* CcdPhysicsEnvironment::getDispatcher()
970 return m_dynamicsWorld->getDispatcher();
978 CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
981 #ifdef NEW_BULLET_VEHICLE_SUPPORT
982 m_wrapperVehicles.clear();
983 #endif //NEW_BULLET_VEHICLE_SUPPORT
985 //m_broadphase->DestroyScene();
986 //delete broadphase ? release reference on broadphase ?
988 //first delete scene, then dispatcher, because pairs have to release manifolds on the dispatcher
989 //delete m_dispatcher;
990 delete m_dynamicsWorld;
993 if (NULL != m_ownPairCache)
994 delete m_ownPairCache;
996 if (NULL != m_ownDispatcher)
997 delete m_ownDispatcher;
999 if (NULL != m_solver)
1002 if (NULL != m_debugDrawer)
1003 delete m_debugDrawer;
1005 if (NULL != m_filterCallback)
1006 delete m_filterCallback;
1008 if (NULL != m_collisionConfiguration)
1009 delete m_collisionConfiguration;
1011 if (NULL != m_broadphase)
1012 delete m_broadphase;
1016 void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float value0,float value1)
1018 btTypedConstraint* typedConstraint = getConstraintById(constraintId);
1019 switch (typedConstraint->getUserConstraintType())
1021 case PHY_GENERIC_6DOF_CONSTRAINT:
1023 //param = 1..12, min0,max0,min1,max1...min6,max6
1024 btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
1025 genCons->setLimit(param,value0,value1);
1034 btTypedConstraint* CcdPhysicsEnvironment::getConstraintById(int constraintId)
1037 int numConstraints = m_dynamicsWorld->getNumConstraints();
1039 for (i=0;i<numConstraints;i++)
1041 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
1042 if (constraint->getUserConstraintId()==constraintId)
1051 void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
1054 CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl;
1055 // addSensor() is a "light" function for bullet because it is used
1056 // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead
1057 //if (m_controllers.insert(ctrl1).second)
1059 // addCcdPhysicsController(ctrl1);
1061 enableCcdPhysicsController(ctrl1);
1063 //Collision filter/mask is now set at the time of the creation of the controller
1064 //force collision detection with everything, including static objects (might hurt performance!)
1065 //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::SensorTrigger;
1066 //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterGroup = btBroadphaseProxy::SensorTrigger;
1067 //todo: make this 'sensor'!
1069 requestCollisionCallback(ctrl);
1070 //printf("addSensor\n");
1073 void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl)
1075 CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl;
1076 if (ccdCtrl->Unregister())
1077 m_triggerControllers.erase(ccdCtrl);
1081 void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl)
1083 removeCollisionCallback(ctrl);
1085 disableCcdPhysicsController((CcdPhysicsController*)ctrl);
1088 void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)
1090 /* printf("addTouchCallback\n(response class = %i)\n",response_class);
1092 //map PHY_ convention into SM_ convention
1093 switch (response_class)
1095 case PHY_FH_RESPONSE:
1096 printf("PHY_FH_RESPONSE\n");
1098 case PHY_SENSOR_RESPONSE:
1099 printf("PHY_SENSOR_RESPONSE\n");
1101 case PHY_CAMERA_RESPONSE:
1102 printf("PHY_CAMERA_RESPONSE\n");
1104 case PHY_OBJECT_RESPONSE:
1105 printf("PHY_OBJECT_RESPONSE\n");
1107 case PHY_STATIC_RESPONSE:
1108 printf("PHY_STATIC_RESPONSE\n");
1116 m_triggerCallbacks[response_class] = callback;
1117 m_triggerCallbacksUserPtrs[response_class] = user;
1120 void CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl)
1122 CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl);
1124 if (ccdCtrl->Register())
1125 m_triggerControllers.insert(ccdCtrl);
1128 void CcdPhysicsEnvironment::CallbackTriggers()
1131 CcdPhysicsController* ctrl0=0,*ctrl1=0;
1133 if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)))
1135 //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback
1136 btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher();
1137 int numManifolds = dispatcher->getNumManifolds();
1138 for (int i=0;i<numManifolds;i++)
1140 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
1141 int numContacts = manifold->getNumContacts();
1144 btRigidBody* rb0 = static_cast<btRigidBody*>(manifold->getBody0());
1145 btRigidBody* rb1 = static_cast<btRigidBody*>(manifold->getBody1());
1146 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))
1148 for (int j=0;j<numContacts;j++)
1150 btVector3 color(1,0,0);
1151 const btManifoldPoint& cp = manifold->getContactPoint(j);
1153 m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
1156 btRigidBody* obj0 = rb0;
1157 btRigidBody* obj1 = rb1;
1159 //m_internalOwner is set in 'addPhysicsController'
1160 CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer());
1161 CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer());
1163 std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0);
1164 if (i == m_triggerControllers.end())
1166 i = m_triggerControllers.find(ctrl1);
1169 if (!(i == m_triggerControllers.end()))
1171 m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE],
1174 // Bullet does not refresh the manifold contact point for object without contact response
1175 // may need to remove this when a newer Bullet version is integrated
1176 if (!dispatcher->needsResponse(rb0, rb1))
1178 // Refresh algorithm fails sometimes when there is penetration
1179 // (usuall the case with ghost and sensor objects)
1180 // Let's just clear the manifold, in any case, it is recomputed on each frame.
1181 manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform());
1193 // This call back is called before a pair is added in the cache
1194 // Handy to remove objects that must be ignored by sensors
1195 bool CcdOverlapFilterCallBack::needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
1197 btCollisionObject *colObj0, *colObj1;
1198 CcdPhysicsController *sensorCtrl, *objCtrl;
1200 // first check the filters
1201 collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
1202 collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
1206 // additional check for sensor object
1207 if (proxy0->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
1209 // this is a sensor object, the other one can't be a sensor object because
1210 // they exclude each other in the above test
1211 assert(!(proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger));
1212 colObj0 = (btCollisionObject*)proxy0->m_clientObject;
1213 colObj1 = (btCollisionObject*)proxy1->m_clientObject;
1215 else if (proxy1->m_collisionFilterGroup & btBroadphaseProxy::SensorTrigger)
1217 colObj0 = (btCollisionObject*)proxy1->m_clientObject;
1218 colObj1 = (btCollisionObject*)proxy0->m_clientObject;
1224 if (!colObj0 || !colObj1)
1226 sensorCtrl = static_cast<CcdPhysicsController*>(colObj0->getUserPointer());
1227 objCtrl = static_cast<CcdPhysicsController*>(colObj1->getUserPointer());
1228 if (m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE])
1230 return m_physEnv->m_triggerCallbacks[PHY_BROADPH_RESPONSE](m_physEnv->m_triggerCallbacksUserPtrs[PHY_BROADPH_RESPONSE], sensorCtrl, objCtrl, 0);
1236 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1238 //complex constraint for vehicles
1239 PHY_IVehicle* CcdPhysicsEnvironment::getVehicleConstraint(int constraintId)
1243 int numVehicles = m_wrapperVehicles.size();
1244 for (i=0;i<numVehicles;i++)
1246 WrapperVehicle* wrapperVehicle = m_wrapperVehicles[i];
1247 if (wrapperVehicle->GetVehicle()->getUserConstraintId() == constraintId)
1248 return wrapperVehicle;
1254 #endif //NEW_BULLET_VEHICLE_SUPPORT
1257 int currentController = 0;
1258 int numController = 0;
1263 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position)
1266 CcdConstructionInfo cinfo;
1267 // memory leak! The shape is not deleted by Bullet and we cannot add it to the KX_Scene.m_shapes list
1268 cinfo.m_collisionShape = new btSphereShape(radius);
1269 cinfo.m_MotionState = 0;
1270 cinfo.m_physicsEnv = this;
1271 // declare this object as Dyamic rather then static!!
1272 // The reason as it is designed to detect all type of object, including static object
1273 // It would cause static-static message to be printed on the console otherwise
1274 cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE/* | btCollisionObject::CF_KINEMATIC_OBJECT*/;
1275 DefaultMotionState* motionState = new DefaultMotionState();
1276 cinfo.m_MotionState = motionState;
1277 // we will add later the possibility to select the filter from option
1278 cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
1279 cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
1280 motionState->m_worldTransform.setIdentity();
1281 motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
1283 CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
1285 return sphereController;
1288 int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl0,class PHY_IPhysicsController* ctrl1,PHY_ConstraintType type,
1289 float pivotX,float pivotY,float pivotZ,
1290 float axisX,float axisY,float axisZ,
1291 float axis1X,float axis1Y,float axis1Z,
1292 float axis2X,float axis2Y,float axis2Z
1297 CcdPhysicsController* c0 = (CcdPhysicsController*)ctrl0;
1298 CcdPhysicsController* c1 = (CcdPhysicsController*)ctrl1;
1300 btRigidBody* rb0 = c0 ? c0->GetRigidBody() : 0;
1301 btRigidBody* rb1 = c1 ? c1->GetRigidBody() : 0;
1303 bool rb0static = rb0 ? rb0->isStaticOrKinematicObject() : true;
1304 bool rb1static = rb1 ? rb1->isStaticOrKinematicObject() : true;
1307 if (rb0static && rb1static)
1310 btVector3 pivotInA(pivotX,pivotY,pivotZ);
1311 btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) :
1312 rb0->getCenterOfMassTransform() * pivotInA;
1313 btVector3 axisInA(axisX,axisY,axisZ);
1316 bool angularOnly = false;
1320 case PHY_POINT2POINT_CONSTRAINT:
1323 btPoint2PointConstraint* p2p = 0;
1327 p2p = new btPoint2PointConstraint(*rb0,
1328 *rb1,pivotInA,pivotInB);
1331 p2p = new btPoint2PointConstraint(*rb0,
1335 m_dynamicsWorld->addConstraint(p2p);
1336 // m_constraints.push_back(p2p);
1338 p2p->setUserConstraintId(gConstraintUid++);
1339 p2p->setUserConstraintType(type);
1340 //64 bit systems can't cast pointer to int. could use size_t instead.
1341 return p2p->getUserConstraintId();
1346 case PHY_GENERIC_6DOF_CONSTRAINT:
1348 btGeneric6DofConstraint* genericConstraint = 0;
1352 btTransform frameInA;
1353 btTransform frameInB;
1355 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
1356 if (axis1.length() == 0.0)
1358 btPlaneSpace1( axisInA, axis1, axis2 );
1361 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1362 axisInA.y(), axis1.y(), axis2.y(),
1363 axisInA.z(), axis1.z(), axis2.z() );
1364 frameInA.setOrigin( pivotInA );
1366 btTransform inv = rb1->getCenterOfMassTransform().inverse();
1368 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
1370 frameInB = inv * globalFrameA;
1371 bool useReferenceFrameA = true;
1373 genericConstraint = new btGeneric6DofConstraint(
1375 frameInA,frameInB,useReferenceFrameA);
1380 static btRigidBody s_fixedObject2( 0,0,0);
1381 btTransform frameInA;
1382 btTransform frameInB;
1384 btVector3 axis1, axis2;
1385 btPlaneSpace1( axisInA, axis1, axis2 );
1387 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1388 axisInA.y(), axis1.y(), axis2.y(),
1389 axisInA.z(), axis1.z(), axis2.z() );
1391 frameInA.setOrigin( pivotInA );
1393 ///frameInB in worldspace
1394 frameInB = rb0->getCenterOfMassTransform() * frameInA;
1396 bool useReferenceFrameA = true;
1397 genericConstraint = new btGeneric6DofConstraint(
1398 *rb0,s_fixedObject2,
1399 frameInA,frameInB,useReferenceFrameA);
1402 if (genericConstraint)
1404 //m_constraints.push_back(genericConstraint);
1405 m_dynamicsWorld->addConstraint(genericConstraint);
1406 genericConstraint->setUserConstraintId(gConstraintUid++);
1407 genericConstraint->setUserConstraintType(type);
1408 //64 bit systems can't cast pointer to int. could use size_t instead.
1409 return genericConstraint->getUserConstraintId();
1414 case PHY_CONE_TWIST_CONSTRAINT:
1416 btConeTwistConstraint* coneTwistContraint = 0;
1421 btTransform frameInA;
1422 btTransform frameInB;
1424 btVector3 axis1(axis1X,axis1Y,axis1Z), axis2(axis2X,axis2Y,axis2Z);
1425 if (axis1.length() == 0.0)
1427 btPlaneSpace1( axisInA, axis1, axis2 );
1430 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1431 axisInA.y(), axis1.y(), axis2.y(),
1432 axisInA.z(), axis1.z(), axis2.z() );
1433 frameInA.setOrigin( pivotInA );
1435 btTransform inv = rb1->getCenterOfMassTransform().inverse();
1437 btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
1439 frameInB = inv * globalFrameA;
1441 coneTwistContraint = new btConeTwistConstraint( *rb0,*rb1,
1447 static btRigidBody s_fixedObject2( 0,0,0);
1448 btTransform frameInA;
1449 btTransform frameInB;
1451 btVector3 axis1, axis2;
1452 btPlaneSpace1( axisInA, axis1, axis2 );
1454 frameInA.getBasis().setValue( axisInA.x(), axis1.x(), axis2.x(),
1455 axisInA.y(), axis1.y(), axis2.y(),
1456 axisInA.z(), axis1.z(), axis2.z() );
1458 frameInA.setOrigin( pivotInA );
1460 ///frameInB in worldspace
1461 frameInB = rb0->getCenterOfMassTransform() * frameInA;
1463 coneTwistContraint = new btConeTwistConstraint(
1464 *rb0,s_fixedObject2,
1468 if (coneTwistContraint)
1470 //m_constraints.push_back(genericConstraint);
1471 m_dynamicsWorld->addConstraint(coneTwistContraint);
1472 coneTwistContraint->setUserConstraintId(gConstraintUid++);
1473 coneTwistContraint->setUserConstraintType(type);
1474 //64 bit systems can't cast pointer to int. could use size_t instead.
1475 return coneTwistContraint->getUserConstraintId();
1482 case PHY_ANGULAR_CONSTRAINT:
1486 case PHY_LINEHINGE_CONSTRAINT:
1488 btHingeConstraint* hinge = 0;
1492 btVector3 axisInB = rb1 ?
1493 (rb1->getCenterOfMassTransform().getBasis().inverse()*(rb0->getCenterOfMassTransform().getBasis() * axisInA)) :
1494 rb0->getCenterOfMassTransform().getBasis() * axisInA;
1496 hinge = new btHingeConstraint(
1498 *rb1,pivotInA,pivotInB,axisInA,axisInB);
1503 hinge = new btHingeConstraint(*rb0,
1507 hinge->setAngularOnly(angularOnly);
1509 //m_constraints.push_back(hinge);
1510 m_dynamicsWorld->addConstraint(hinge);
1511 hinge->setUserConstraintId(gConstraintUid++);
1512 hinge->setUserConstraintType(type);
1513 //64 bit systems can't cast pointer to int. could use size_t instead.
1514 return hinge->getUserConstraintId();
1517 #ifdef NEW_BULLET_VEHICLE_SUPPORT
1519 case PHY_VEHICLE_CONSTRAINT:
1521 btRaycastVehicle::btVehicleTuning* tuning = new btRaycastVehicle::btVehicleTuning();
1522 btRigidBody* chassis = rb0;
1523 btDefaultVehicleRaycaster* raycaster = new btDefaultVehicleRaycaster(m_dynamicsWorld);
1524 btRaycastVehicle* vehicle = new btRaycastVehicle(*tuning,chassis,raycaster);
1525 WrapperVehicle* wrapperVehicle = new WrapperVehicle(vehicle,ctrl0);
1526 m_wrapperVehicles.push_back(wrapperVehicle);
1527 m_dynamicsWorld->addVehicle(vehicle);
1528 vehicle->setUserConstraintId(gConstraintUid++);
1529 vehicle->setUserConstraintType(type);
1530 return vehicle->getUserConstraintId();
1534 #endif //NEW_BULLET_VEHICLE_SUPPORT
1541 //btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB
1549 PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
1551 CcdConstructionInfo cinfo;
1553 // we don't need a CcdShapeConstructionInfo for this shape:
1554 // it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
1555 cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
1556 cinfo.m_MotionState = 0;
1557 cinfo.m_physicsEnv = this;
1558 cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
1559 DefaultMotionState* motionState = new DefaultMotionState();
1560 cinfo.m_MotionState = motionState;
1562 // we will add later the possibility to select the filter from option
1563 cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
1564 cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter;
1565 motionState->m_worldTransform.setIdentity();
1566 // motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2]));
1568 CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo);
1571 return sphereController;
1574 float CcdPhysicsEnvironment::getAppliedImpulse(int constraintid)
1577 int numConstraints = m_dynamicsWorld->getNumConstraints();
1578 for (i=0;i<numConstraints;i++)
1580 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
1581 if (constraint->getUserConstraintId() == constraintid)
1583 return constraint->getAppliedImpulse();