/plugins/bulletrave/bulletspace.h

https://github.com/ThunderPower/openrave · C Header · 508 lines · 400 code · 62 blank · 46 comment · 49 complexity · 3ac029059eecae51440f942730a37afd MD5 · raw file

  1. // -*- coding: utf-8 -*-
  2. // Copyright (C) 2006-2011 Rosen Diankov <rosen.diankov@gmail.com>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. // Contributors: 2010 Nick Hillier, Katrina Monkley CSIRO Autonomous Systems Lab, 2010-2011 Max Argus
  17. // 2013 Theodoros Stouraitis and Praveen Ramanujam
  18. #ifndef OPENRAVE_BULLET_SPACE
  19. #define OPENRAVE_BULLET_SPACE
  20. #include "plugindefs.h"
  21. #include <btBulletCollisionCommon.h>
  22. #include <btBulletDynamicsCommon.h>
  23. #include <BulletCollision/Gimpact/btGImpactShape.h>
  24. #include <BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h>
  25. #include <BulletCollision/CollisionShapes/btShapeHull.h>
  26. //#include <BulletCollision/Gimpact/btConcaveConcaveCollisionAlgorithm.h>
  27. // groups bits for bullet
  28. #define ENABLED_GROUP 1 // mask ENABLED_GROUP
  29. #define DISABLED_GROUP 256 // mask 0
  30. // manages a space of bullet objects
  31. class BulletSpace : public boost::enable_shared_from_this<BulletSpace>
  32. {
  33. inline boost::weak_ptr<BulletSpace> weak_space() {
  34. return shared_from_this();
  35. }
  36. public:
  37. // information about the kinematics of the body
  38. class KinBodyInfo : public UserData
  39. {
  40. public:
  41. class LINK : public btMotionState
  42. {
  43. public:
  44. virtual ~LINK() {
  45. }
  46. virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const
  47. {
  48. //centerOfMassWorldTrans = m_centerOfMassOffset.inverse() * m_graphicsWorldTrans;
  49. centerOfMassWorldTrans = GetBtTransform(plink->GetTransform()*tlocal);
  50. }
  51. virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
  52. {
  53. //m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
  54. //RAVELOG_INFO(plink->GetName()); //This info is eats up the terminal
  55. plink->SetTransform(GetTransform(centerOfMassWorldTrans)*tlocal.inverse());
  56. }
  57. boost::shared_ptr<btCollisionObject> obj;
  58. boost::shared_ptr<btRigidBody> _rigidbody;
  59. boost::shared_ptr<btCollisionShape> shape;
  60. list<boost::shared_ptr<btCollisionShape> > listchildren;
  61. list<boost::shared_ptr<btStridingMeshInterface> > listmeshes;
  62. KinBody::LinkPtr plink;
  63. Transform tlocal; /// local offset transform to account for inertias not aligned to axes
  64. };
  65. KinBodyInfo(boost::shared_ptr<btCollisionWorld> world, bool bPhysics) : _world(world), _bPhysics(bPhysics) {
  66. nLastStamp = 0;
  67. _worlddynamics = boost::dynamic_pointer_cast<btDiscreteDynamicsWorld>(_world);
  68. }
  69. virtual ~KinBodyInfo() {
  70. Reset();
  71. }
  72. void Reset()
  73. {
  74. FOREACH(itlink, vlinks) {
  75. if( _bPhysics && !(*itlink)->plink->IsStatic()) {
  76. _worlddynamics->removeRigidBody((*itlink)->_rigidbody.get());
  77. }
  78. else {
  79. _world->removeCollisionObject((*itlink)->obj.get());
  80. }
  81. }
  82. FOREACH(itjoint,_mapjoints) {
  83. _worlddynamics->removeConstraint(itjoint->second.get());
  84. }
  85. _mapjoints.clear(); // have to remove constraints first
  86. vlinks.resize(0);
  87. _geometrycallback.reset();
  88. }
  89. KinBodyPtr pbody; ///< body associated with this structure
  90. int nLastStamp;
  91. std::vector<boost::shared_ptr<LINK> > vlinks; ///< if body is disabled, then geom is static (it can't be connected to a joint!)
  92. ///< the pointer to this Link is the userdata
  93. typedef std::map< KinBody::JointConstPtr, boost::shared_ptr<btTypedConstraint> > MAPJOINTS;
  94. MAPJOINTS _mapjoints;
  95. UserDataPtr _geometrycallback;
  96. boost::weak_ptr<BulletSpace> _bulletspace;
  97. private:
  98. boost::shared_ptr<btCollisionWorld> _world;
  99. boost::shared_ptr<btDiscreteDynamicsWorld> _worlddynamics;
  100. bool _bPhysics;
  101. };
  102. typedef boost::shared_ptr<KinBodyInfo> KinBodyInfoPtr;
  103. typedef boost::shared_ptr<KinBodyInfo const> KinBodyInfoConstPtr;
  104. typedef boost::function<KinBodyInfoPtr(KinBodyConstPtr)> GetInfoFn;
  105. typedef boost::function<void (KinBodyInfoPtr)> SynchronizeCallbackFn;
  106. BulletSpace(EnvironmentBasePtr penv, const GetInfoFn& infofn, bool bPhysics) : _penv(penv), GetInfo(infofn), _bPhysics(bPhysics) {
  107. }
  108. virtual ~BulletSpace() {
  109. }
  110. bool InitEnvironment(boost::shared_ptr<btCollisionWorld> world)
  111. {
  112. _world = world;
  113. _worlddynamics = boost::dynamic_pointer_cast<btDiscreteDynamicsWorld>(_world);
  114. btGImpactCollisionAlgorithm::registerAlgorithm((btCollisionDispatcher*)_world->getDispatcher());
  115. //btConcaveConcaveCollisionAlgorithm::registerAlgorithm(_world->getDispatcher());
  116. return true;
  117. }
  118. void DestroyEnvironment()
  119. {
  120. _world.reset();
  121. _worlddynamics.reset();
  122. }
  123. KinBodyInfoPtr InitKinBody(KinBodyPtr pbody, KinBodyInfoPtr pinfo = KinBodyInfoPtr(), btScalar fmargin=0.0005) // -> changed fmargin because penetration was too little. For collision the values needs to be changed. There will be an XML interface for fmargin.
  124. {
  125. // create all ode bodies and joints
  126. if( !pinfo ) {
  127. pinfo.reset(new KinBodyInfo(_world,_bPhysics));
  128. }
  129. pinfo->Reset();
  130. pinfo->pbody = pbody;
  131. pinfo->_bulletspace = weak_space();
  132. pinfo->vlinks.reserve(pbody->GetLinks().size());
  133. FOREACHC(itlink, pbody->GetLinks()) {
  134. boost::shared_ptr<KinBodyInfo::LINK> link(new KinBodyInfo::LINK());
  135. btCompoundShape* pshapeparent = new btCompoundShape();
  136. link->shape.reset(pshapeparent);
  137. pshapeparent->setMargin(fmargin); // need to set margin very small for collision : 0.000001
  138. // add all the correct geometry objects
  139. FOREACHC(itgeom, (*itlink)->GetGeometries()) {
  140. boost::shared_ptr<btCollisionShape> child;
  141. KinBody::Link::GeometryPtr geom = *itgeom;
  142. switch(geom->GetType()) {
  143. case GT_Box:
  144. child.reset(new btBoxShape(GetBtVector(geom->GetBoxExtents())));
  145. break;
  146. case GT_Sphere:
  147. child.reset(new btSphereShape(geom->GetSphereRadius()));
  148. break;
  149. case GT_Cylinder:
  150. // cylinder axis aligned to Y
  151. child.reset(new btCylinderShapeZ(btVector3(geom->GetCylinderRadius(),geom->GetCylinderRadius(),geom->GetCylinderHeight()*0.5f)));
  152. break;
  153. case GT_TriMesh: {
  154. if( geom->GetCollisionMesh().indices.size() >= 3 ) {
  155. btTriangleMesh* ptrimesh = new btTriangleMesh();
  156. // for some reason adding indices makes everything crash
  157. for(size_t i = 0; i < geom->GetCollisionMesh().indices.size(); i += 3) {
  158. ptrimesh->addTriangle(GetBtVector(geom->GetCollisionMesh().vertices[i]), GetBtVector(geom->GetCollisionMesh().vertices[i+1]), GetBtVector(geom->GetCollisionMesh().vertices[i+2]));
  159. }
  160. //child.reset(new btBvhTriangleMeshShape(ptrimesh, true, true)); // doesn't do tri-tri collisions!
  161. if( _bPhysics ) {
  162. RAVELOG_DEBUG("converting triangle mesh to convex hull for physics\n");
  163. boost::shared_ptr<btConvexShape> pconvexbuilder(new btConvexTriangleMeshShape(ptrimesh));
  164. pconvexbuilder->setMargin(fmargin);
  165. //Create a hull shape to approximate Trimesh
  166. boost::shared_ptr<btShapeHull> hull(new btShapeHull(pconvexbuilder.get()));
  167. hull->buildHull(fmargin);
  168. btConvexHullShape* convexShape = new btConvexHullShape();
  169. convexShape->setLocalScaling(btVector3(1,1,1));
  170. //ofstream f((*itlink)->GetName().c_str());
  171. for (int i=0; i< hull->numVertices(); i++) {
  172. convexShape->addPoint(hull->getVertexPointer()[i]);
  173. //f << hull->getVertexPointer()[i].getX() << " " << hull->getVertexPointer()[i].getY() << " " << hull->getVertexPointer()[i].getZ() << endl;
  174. }
  175. child.reset(convexShape);
  176. delete ptrimesh;
  177. }
  178. else {
  179. btGImpactMeshShape* pgimpact = new btGImpactMeshShape(ptrimesh);
  180. pgimpact->setMargin(fmargin); // need to set margin very small (we're not simulating anyway)
  181. pgimpact->updateBound();
  182. child.reset(pgimpact);
  183. link->listmeshes.push_back(boost::shared_ptr<btStridingMeshInterface>(ptrimesh));
  184. }
  185. }
  186. break;
  187. }
  188. default:
  189. break;
  190. }
  191. if( !child ) {
  192. RAVELOG_WARN("did not create geom type 0x%x\n", geom->GetType());
  193. continue;
  194. }
  195. link->listchildren.push_back(child);
  196. child->setMargin(fmargin); // need to set margin very small (we're not simulating anyway)
  197. pshapeparent->addChildShape(GetBtTransform(geom->GetTransform()), child.get());
  198. }
  199. link->plink = *itlink;
  200. link->tlocal = (*itlink)->GetLocalMassFrame();
  201. if( _bPhysics ) {
  202. // set the mass and inertia and extract the eigenvectors of the tensor
  203. btVector3 localInertia = GetBtVector((*itlink)->GetPrincipalMomentsOfInertia());
  204. dReal mass = (*itlink)->GetMass();
  205. // -> bullet expects static objects to have zero mass
  206. if((*itlink)->IsStatic()){
  207. mass = 0;
  208. }
  209. if( mass < 0 ) {
  210. RAVELOG_WARN(str(boost::format("body %s:%s mass is %f. filling dummy values")%pbody->GetName()%(*itlink)->GetName()%mass));
  211. mass = 1e-7;
  212. }
  213. else if( (*itlink)->GetPrincipalMomentsOfInertia().lengthsqr3() <= 0 ) {
  214. localInertia = btVector3(1e-7,1e-7,1e-7);
  215. }
  216. btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,link.get(),pshapeparent,localInertia);
  217. rbInfo.m_startWorldTransform = GetBtTransform((*itlink)->GetTransform()*link->tlocal);
  218. link->_rigidbody.reset(new btRigidBody(rbInfo));
  219. link->obj = link->_rigidbody;
  220. }
  221. else {
  222. link->obj.reset(new btCollisionObject());
  223. link->obj->setCollisionShape(pshapeparent);
  224. link->obj->setWorldTransform(GetBtTransform((*itlink)->GetTransform()*link->tlocal));
  225. }
  226. link->obj->setUserPointer(link.get());
  227. // Dynamic (moving) rigidbodies: positive mass, every simulation frame the dynamics will update its world transform
  228. // Static rigidbodies: zero mass, cannot move but just collide
  229. // Kinematic rigidbodies: zero mass, can be animated by the user, but there will be only one-way interaction
  230. link->obj->setCollisionFlags((*itlink)->IsStatic() ? btCollisionObject::CF_KINEMATIC_OBJECT : 0);
  231. // --> check for static
  232. if( _bPhysics && !(*itlink)->IsStatic() ) {
  233. _worlddynamics->addRigidBody(link->_rigidbody.get());
  234. }
  235. else {
  236. _world->addCollisionObject(link->obj.get());
  237. }
  238. //Activates all kinematic objects added to btDiscreteDynamicsWorld
  239. //link->body->setActivationState(DISABLE_DEACTIVATION);
  240. link->obj->activate(true);
  241. pinfo->vlinks.push_back(link);
  242. }
  243. if( _bPhysics ) {
  244. vector<KinBody::JointPtr> vbodyjoints; vbodyjoints.reserve(pbody->GetJoints().size()+pbody->GetPassiveJoints().size());
  245. vbodyjoints.insert(vbodyjoints.end(),pbody->GetJoints().begin(),pbody->GetJoints().end());
  246. vbodyjoints.insert(vbodyjoints.end(),pbody->GetPassiveJoints().begin(),pbody->GetPassiveJoints().end());
  247. FOREACH(itjoint, vbodyjoints) {
  248. btRigidBody* body0 = NULL, *body1 = NULL;
  249. if( !!(*itjoint)->GetFirstAttached() ) {
  250. body0 = dynamic_cast<btRigidBody*>(pinfo->vlinks.at((*itjoint)->GetFirstAttached()->GetIndex())->obj.get());
  251. }
  252. if( !!(*itjoint)->GetSecondAttached() ) {
  253. body1 = dynamic_cast<btRigidBody*>(pinfo->vlinks.at((*itjoint)->GetSecondAttached()->GetIndex())->obj.get());
  254. }
  255. if( !body0 || !body1 ) {
  256. RAVELOG_ERROR(str(boost::format("joint %s needs to be attached to two bodies!\n")%(*itjoint)->GetName()));
  257. continue;
  258. }
  259. Transform t0inv = GetTransform(body0->getWorldTransform()).inverse();
  260. Transform t1inv = GetTransform(body1->getWorldTransform()).inverse();
  261. boost::shared_ptr<btTypedConstraint> joint;
  262. switch((*itjoint)->GetType()) {
  263. case KinBody::JointHinge: {
  264. btVector3 pivotInA = GetBtVector(t0inv * (*itjoint)->GetAnchor());
  265. btVector3 pivotInB = GetBtVector(t1inv * (*itjoint)->GetAnchor());
  266. btVector3 axisInA = GetBtVector(t0inv.rotate((*itjoint)->GetAxis(0)));
  267. btVector3 axisInB = GetBtVector(t1inv.rotate((*itjoint)->GetAxis(0)));
  268. boost::shared_ptr<btHingeConstraint> hinge(new btHingeConstraint(*body0, *body1, pivotInA, pivotInB, axisInA, axisInB));
  269. //hinge->setParam(BT_CONSTRAINT_STOP_ERP,0.8);
  270. //hinge->setParam(BT_CONSTRAINT_STOP_CFM,0);
  271. //hinge->setParam(BT_CONSTRAINT_CFM,0);
  272. vector<dReal> vupper,vlower;
  273. (*itjoint)->GetLimits(vlower,vupper);
  274. hinge->setLimit(vlower.at(0),vupper.at(0),0.9f,0.9f,1.0f);
  275. if( !(*itjoint)->IsCircular(0) ) {
  276. vector<dReal> vlower, vupper;
  277. (*itjoint)->GetLimits(vlower,vupper);
  278. btScalar orInitialAngle = (*itjoint)->GetValue(0);
  279. btScalar btInitialAngle = hinge->getHingeAngle();
  280. btScalar lower_adj, upper_adj;
  281. btScalar diff = (btInitialAngle + orInitialAngle);
  282. lower_adj = diff - vupper.at(0);
  283. upper_adj = diff - vlower.at(0);
  284. hinge->setLimit(lower_adj,upper_adj);
  285. }
  286. joint = hinge;
  287. break;
  288. }
  289. case KinBody::JointSlider: {
  290. Transform tslider; tslider.rot = quatRotateDirection(Vector(1,0,0),(*itjoint)->GetAxis(0));
  291. btTransform frameInA = GetBtTransform(t0inv*tslider);
  292. btTransform frameInB = GetBtTransform(t1inv*tslider);
  293. joint.reset(new btSliderConstraint(*body0, *body1, frameInA, frameInB, true));
  294. break;
  295. }
  296. case KinBody::JointSpherical: {
  297. btVector3 pivotInA = GetBtVector(t0inv * (*itjoint)->GetAnchor());
  298. btVector3 pivotInB = GetBtVector(t1inv * (*itjoint)->GetAnchor());
  299. boost::shared_ptr<btPoint2PointConstraint> spherical(new btPoint2PointConstraint(*body0, *body1, pivotInA, pivotInB));
  300. joint = spherical;
  301. break;
  302. }
  303. case KinBody::JointUniversal:
  304. RAVELOG_ERROR("universal joint not supported by bullet\n");
  305. break;
  306. case KinBody::JointHinge2:
  307. RAVELOG_ERROR("hinge2 joint not supported by bullet\n");
  308. break;
  309. default:
  310. RAVELOG_ERROR("unknown joint type 0x%8.8x\n", (*itjoint)->GetType());
  311. break;
  312. }
  313. if( !!joint ) {
  314. KinBody::LinkPtr plink0 = (*itjoint)->GetFirstAttached(), plink1 = (*itjoint)->GetSecondAttached();
  315. int minindex = min(plink0->GetIndex(), plink1->GetIndex());
  316. int maxindex = max(plink0->GetIndex(), plink1->GetIndex());
  317. bool bIgnoreCollision = pbody->GetAdjacentLinks().find(minindex|(maxindex<<16)) != pbody->GetAdjacentLinks().end() || plink0->IsRigidlyAttached(plink0);
  318. _worlddynamics->addConstraint(joint.get(), bIgnoreCollision);
  319. pinfo->_mapjoints[*itjoint] = joint;
  320. }
  321. }
  322. }
  323. pinfo->_geometrycallback = pbody->RegisterChangeCallback(KinBody::Prop_LinkGeometry, boost::bind(&BulletSpace::GeometryChangedCallback,boost::bind(&utils::sptr_from<BulletSpace>, weak_space()),KinBodyWeakPtr(pbody)));
  324. _Synchronize(pinfo);
  325. return pinfo;
  326. }
  327. void Synchronize()
  328. {
  329. vector<KinBodyPtr> vbodies;
  330. _penv->GetBodies(vbodies);
  331. FOREACHC(itbody, vbodies) {
  332. KinBodyInfoPtr pinfo = GetInfo(*itbody);
  333. BOOST_ASSERT( pinfo->pbody == *itbody );
  334. if( pinfo->nLastStamp != (*itbody)->GetUpdateStamp() ) {
  335. _Synchronize(pinfo);
  336. }
  337. }
  338. }
  339. void Synchronize(KinBodyConstPtr pbody)
  340. {
  341. KinBodyInfoPtr pinfo = GetInfo(pbody);
  342. BOOST_ASSERT( pinfo->pbody == pbody );
  343. if( pinfo->nLastStamp != pbody->GetUpdateStamp() ) {
  344. _Synchronize(pinfo);
  345. }
  346. }
  347. boost::shared_ptr<btCollisionObject> GetLinkBody(KinBody::LinkConstPtr plink)
  348. {
  349. KinBodyInfoPtr pinfo = GetInfo(plink->GetParent());
  350. BOOST_ASSERT(pinfo->pbody == plink->GetParent() );
  351. return pinfo->vlinks.at(plink->GetIndex())->obj;
  352. }
  353. boost::shared_ptr<btTypedConstraint> GetJoint(KinBody::JointConstPtr pjoint)
  354. {
  355. KinBodyInfoPtr pinfo = GetInfo(pjoint->GetParent());
  356. BOOST_ASSERT(pinfo->pbody == pjoint->GetParent() );
  357. KinBodyInfo::MAPJOINTS::const_iterator it;
  358. it = pinfo->_mapjoints.find(pjoint); // --> fixed bug
  359. BOOST_ASSERT(it != pinfo->_mapjoints.end());
  360. return it->second;
  361. }
  362. void SetSynchronizationCallback(const SynchronizeCallbackFn &synccallback) {
  363. _synccallback = synccallback;
  364. }
  365. static inline Transform GetTransform(const btTransform &t)
  366. {
  367. return Transform(Vector(t.getRotation().getW(), t.getRotation().getX(), t.getRotation().getY(), t.getRotation().getZ()), Vector(t.getOrigin().getX(), t.getOrigin().getY(), t.getOrigin().getZ()));
  368. }
  369. static inline btTransform GetBtTransform(const Transform &t)
  370. {
  371. OPENRAVE_ASSERT_OP(RaveFabs(t.rot.lengthsqr4()-1),<=,0.01);
  372. return btTransform(btQuaternion(t.rot.y,t.rot.z,t.rot.w,t.rot.x),GetBtVector(t.trans));
  373. }
  374. static inline btVector3 GetBtVector(const Vector &v)
  375. {
  376. return btVector3(v.x,v.y,v.z);
  377. }
  378. bool IsInitialized() {
  379. // return !!_world;
  380. return !!_worlddynamics;
  381. }
  382. private:
  383. void _Synchronize(KinBodyInfoPtr pinfo)
  384. {
  385. vector<Transform> vtrans;
  386. std::vector<int> dofbranches;
  387. pinfo->pbody->GetLinkTransformations(vtrans,dofbranches);
  388. pinfo->nLastStamp = pinfo->pbody->GetUpdateStamp();
  389. BOOST_ASSERT( vtrans.size() == pinfo->vlinks.size() );
  390. for(size_t i = 0; i < vtrans.size(); ++i) {
  391. pinfo->vlinks[i]->obj->getWorldTransform() = GetBtTransform(vtrans[i]*pinfo->vlinks[i]->tlocal);
  392. }
  393. if( !!_synccallback ) {
  394. _synccallback(pinfo);
  395. }
  396. }
  397. virtual void GeometryChangedCallback(KinBodyWeakPtr _pbody)
  398. {
  399. EnvironmentMutex::scoped_lock lock(_penv->GetMutex());
  400. KinBodyPtr pbody(_pbody);
  401. KinBodyInfoPtr pinfo = GetInfo(pbody);
  402. if( !pinfo ) {
  403. return;
  404. }
  405. BOOST_ASSERT(boost::shared_ptr<BulletSpace>(pinfo->_bulletspace) == shared_from_this());
  406. BOOST_ASSERT(pinfo->pbody==pbody);
  407. InitKinBody(pbody,pinfo);
  408. }
  409. EnvironmentBasePtr _penv;
  410. GetInfoFn GetInfo;
  411. boost::shared_ptr<btCollisionWorld> _world;
  412. boost::shared_ptr<btDiscreteDynamicsWorld> _worlddynamics;
  413. SynchronizeCallbackFn _synccallback;
  414. bool _bPhysics;
  415. };
  416. static KinBody::LinkPtr GetLinkFromCollision(btCollisionObject* co) {
  417. BOOST_ASSERT(co != NULL);
  418. return static_cast<BulletSpace::KinBodyInfo::LINK*>(co->getUserPointer())->plink;
  419. }
  420. static KinBody::LinkPtr GetLinkFromProxy(btBroadphaseProxy* proxy) {
  421. return GetLinkFromCollision(static_cast<btCollisionObject*>(proxy->m_clientObject));
  422. }
  423. class OpenRAVEFilterCallback : public btOverlapFilterCallback
  424. {
  425. public:
  426. virtual bool CheckLinks(KinBody::LinkPtr plink0, KinBody::LinkPtr plink1) const = 0;
  427. virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
  428. {
  429. BOOST_ASSERT( static_cast<btCollisionObject*>(proxy0->m_clientObject) != NULL );
  430. BOOST_ASSERT( static_cast<btCollisionObject*>(proxy1->m_clientObject) != NULL );
  431. KinBody::LinkPtr plink0 = GetLinkFromProxy(proxy0);
  432. KinBody::LinkPtr plink1 = GetLinkFromProxy(proxy1);
  433. if( !plink0->IsEnabled() || !plink1->IsEnabled() ) {
  434. return false;
  435. }
  436. return CheckLinks(plink0,plink1);
  437. }
  438. };
  439. #ifdef RAVE_REGISTER_BOOST
  440. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  441. BOOST_TYPEOF_REGISTER_TYPE(BulletSpace)
  442. BOOST_TYPEOF_REGISTER_TYPE(BulletSpace::KinBodyInfo)
  443. BOOST_TYPEOF_REGISTER_TYPE(BulletSpace::KinBodyInfo::LINK)
  444. BOOST_TYPEOF_REGISTER_TYPE(dJointID)
  445. #endif
  446. #endif