00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <uwsim/BulletPhysics.h>
00014
00015 #if BT_BULLET_VERSION > 279
00016 #include "BulletDynamics/MLCPSolvers/btDantzigSolver.h"
00017 #include "BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h"
00018 #include "BulletDynamics/MLCPSolvers/btMLCPSolver.h"
00019 #endif
00020
00021
00022 unsigned int vehicleCollidesWith(COL_OBJECTS);
00023 unsigned int objectsCollidesWith(COL_EVERYTHING);
00024
00025
00026 class MirrorMotionState : public btMotionState
00027 {
00028 public:
00029 MirrorMotionState(btRigidBody * copied)
00030 {
00031 copy=copied;
00032 }
00033
00034 virtual void getWorldTransform(btTransform &worldTrans) const
00035 {
00036 copy->getMotionState()->getWorldTransform(worldTrans);
00037 }
00038
00039 virtual void setWorldTransform(const btTransform &worldTrans)
00040 {
00041
00042 }
00043
00044 protected:
00045 btRigidBody * copy;
00046
00047 };
00048
00049
00050 btRigidBody* BulletPhysics::copyObject(btRigidBody * copied)
00051 {
00052
00053 btVector3 inertia;
00054 copied->getCollisionShape()->calculateLocalInertia(1.0/copied->getInvMass(), inertia);
00055
00056 MirrorMotionState* motion = new MirrorMotionState(copied);
00057 btRigidBody::btRigidBodyConstructionInfo rb(1.0/copied->getInvMass(), motion,copied->getCollisionShape(),inertia);
00058 btRigidBody* body = new btRigidBody(rb);
00059
00060 CollisionDataType * colData = new CollisionDataType("copied", "copied", 1);
00061 body->setUserPointer(colData);
00062
00063
00064
00065 body->setDamping(copied->getLinearDamping(), copied->getAngularDamping());
00066
00067
00068 dynamicsWorld->addRigidBody(body);
00069
00070
00071 dynamicsWorld->btCollisionWorld::removeCollisionObject(body);
00072 dynamicsWorld->addCollisionObject(body, short(COL_VEHICLE), short(vehicleCollidesWith));
00073
00074 body->setActivationState(DISABLE_DEACTIVATION);
00075
00076
00077 return (body);
00078 }
00079
00080
00081 class MyMotionState : public btMotionState
00082 {
00083 public:
00084
00085 MyMotionState(osg::Node * obj, osg::MatrixTransform *root)
00086 {
00087 transf = root;
00088 object = obj;
00089 }
00090
00091 void setNode(osg::Node *node)
00092 {
00093 object = node;
00094 }
00095
00096 virtual void getWorldTransform(btTransform &worldTrans) const
00097 {
00098 boost::shared_ptr<osg::Matrix> mat = getWorldCoords(object);
00099
00100 mat->preMultScale(osg::Vec3d(1.0/mat->getScale().x(),1.0/mat->getScale().y(),1.0/mat->getScale().z()));
00101 worldTrans = osgbCollision::asBtTransform(*mat);
00102 }
00103
00104 virtual void setWorldTransform(const btTransform &worldTrans)
00105 {
00106
00107 boost::shared_ptr<osg::Matrix> mat = getWorldCoords(transf->getParent(0));
00108
00109
00110 osg::Matrixd worldMatrix;
00111 btQuaternion rot = worldTrans.getRotation();
00112 btVector3 pos = worldTrans.getOrigin();
00113 worldMatrix.makeRotate(osg::Quat(rot.x(), rot.y(), rot.z(), rot.w()));
00114 worldMatrix.setTrans(osg::Vec3d(pos.x(), pos.y(), pos.z()));
00115
00116 worldMatrix.preMultScale(osg::Vec3d(mat->getScale().x(),mat->getScale().y(),mat->getScale().z()));
00117
00118
00119 osg::Matrixd rootmat = worldMatrix * (mat->inverse(*mat));
00120
00121
00122 transf->setMatrix(rootmat);
00123 }
00124
00125 protected:
00126 osg::Node * object;
00127 osg::MatrixTransform *transf;
00128
00129 };
00130
00131 void BulletPhysics::stepSimulation(btScalar timeStep, int maxSubSteps = 1,
00132 btScalar fixedTimeStep = btScalar(1.) / btScalar(60.))
00133 {
00134
00135
00136
00137 physicsStep=1;
00138 callbackManager->substep=0;
00139 ((btDynamicsWorld*)dynamicsWorld)->stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
00140 physicsStep=0;
00141 }
00142
00143 void BulletPhysics::printManifolds()
00144 {
00145
00146 for (int i = 0; i < dispatcher->getNumManifolds(); i++)
00147 {
00148 btCollisionObject* colObj0 = (btCollisionObject*)dispatcher->getManifoldByIndexInternal(i)->getBody0();
00149 btCollisionObject* colObj1 = (btCollisionObject*)dispatcher->getManifoldByIndexInternal(i)->getBody1();
00150 CollisionDataType * nombre = (CollisionDataType *)colObj0->getUserPointer();
00151 CollisionDataType * nombre2 = (CollisionDataType *)colObj1->getUserPointer();
00152 double min = 999999;
00153 for (int j = 0; j < dispatcher->getManifoldByIndexInternal(i)->getNumContacts(); j++)
00154 if (dispatcher->getManifoldByIndexInternal(i)->getContactPoint(j).getDistance() < min)
00155 min = dispatcher->getManifoldByIndexInternal(i)->getContactPoint(j).getDistance();
00156 if (min < 999999)
00157 {
00158 std::cout << i << " ";
00159 if (nombre)
00160 std::cout << nombre->name << " " << " ";
00161 if (nombre2)
00162 std::cout << nombre2->name;
00163 std::cout << " " << min << std::endl;
00164 }
00165 }
00166 }
00167
00168
00169 void preTickCallback(btDynamicsWorld *world, btScalar timeStep)
00170 {
00171 BulletPhysics::TickCallbackManager *w = static_cast<BulletPhysics::TickCallbackManager *>(world->getWorldUserInfo());
00172 w->physicsInternalPreProcessCallback(timeStep);
00173 }
00174
00175
00176 void postTickCallback(btDynamicsWorld *world, btScalar timeStep)
00177 {
00178 BulletPhysics::TickCallbackManager *w = static_cast<BulletPhysics::TickCallbackManager *>(world->getWorldUserInfo());
00179 w->physicsInternalPostProcessCallback(timeStep);
00180 }
00181
00182
00183 BulletPhysics::BulletPhysics(PhysicsConfig physicsConfig, osgOcean::OceanTechnique* oceanSurf)
00184 {
00185 collisionConfiguration = new btDefaultCollisionConfiguration();
00186 dispatcher = new btCollisionDispatcher(collisionConfiguration);
00187
00188 #if BT_BULLET_VERSION <= 279
00189 solver = new btSequentialImpulseConstraintSolver();
00190 #else
00191 if(physicsConfig.solver==PhysicsConfig::Dantzig){
00192 btDantzigSolver* mlcp = new btDantzigSolver();
00193 solver = new btMLCPSolver(mlcp);
00194 }
00195
00196 else if(physicsConfig.solver==PhysicsConfig::SolveProjectedGauss){
00197 btSolveProjectedGaussSeidel* mlcp = new btSolveProjectedGaussSeidel;
00198 solver = new btMLCPSolver(mlcp);
00199 }
00200
00201 else if(physicsConfig.solver==PhysicsConfig::SequentialImpulse){
00202 solver = new btSequentialImpulseConstraintSolver();
00203 }
00204 #endif
00205
00206
00207 btVector3 worldAabbMin(-10000, -10000, -10000);
00208 btVector3 worldAabbMax(10000, 10000, 10000);
00209 inter = new btAxisSweep3(worldAabbMin, worldAabbMax, 1000);
00210
00211 dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, inter, solver, collisionConfiguration);
00212 dynamicsWorld->getDispatchInfo().m_enableSPU = true;
00213
00214 btVector3 gravity(physicsConfig.gravity[0], physicsConfig.gravity[1], physicsConfig.gravity[2]);
00215 if (physicsConfig.gravity[0] == 0 && physicsConfig.gravity[1] == 0 && physicsConfig.gravity[2] == 0)
00216 {
00217 gravity = UWSIM_DEFAULT_GRAVITY;
00218 }
00219
00220 dynamicsWorld->setGravity(gravity);
00221 oceanSurface = oceanSurf;
00222
00223
00224
00225
00226
00227
00228
00229 callbackManager= new TickCallbackManager();
00230 dynamicsWorld->setInternalTickCallback(preTickCallback, static_cast<void *>(callbackManager),true);
00231 dynamicsWorld->setInternalTickCallback(postTickCallback, static_cast<void *>(callbackManager));
00232 }
00233
00234
00235 int BulletPhysics::TickCallbackManager::addForceSensor(btRigidBody * copy, btRigidBody * target)
00236 {
00237 ForceSensorcbInfo fs;
00238 fs.target=target;
00239 fs.copy=copy;
00240 forceSensors.push_back(fs);
00241
00242 return forceSensors.size()-1;
00243 }
00244
00245
00246 void BulletPhysics::TickCallbackManager::getForceSensorSpeed(int forceSensor, double linSpeed[3],double angSpeed[3])
00247 {
00248 linSpeed[0]=forceSensors[forceSensor].linFinal.x()-forceSensors[forceSensor].linInitial.x();
00249 linSpeed[1]=forceSensors[forceSensor].linFinal.y()-forceSensors[forceSensor].linInitial.y();
00250 linSpeed[2]=forceSensors[forceSensor].linFinal.z()-forceSensors[forceSensor].linInitial.z();
00251
00252 angSpeed[0]=forceSensors[forceSensor].angFinal.x()-forceSensors[forceSensor].angInitial.x();
00253 angSpeed[1]=forceSensors[forceSensor].angFinal.y()-forceSensors[forceSensor].angInitial.y();
00254 angSpeed[2]=forceSensors[forceSensor].angFinal.z()-forceSensors[forceSensor].angInitial.z();
00255 }
00256
00257
00258 void BulletPhysics::TickCallbackManager::preTickForceSensors()
00259 {
00260 for(int i=0;i<forceSensors.size();i++)
00261 {
00262 forceSensors[i].copy->setCenterOfMassTransform(forceSensors[i].target->getCenterOfMassTransform());
00263 forceSensors[i].copy->clearForces();
00264 forceSensors[i].copy->setLinearVelocity(forceSensors[i].target->getLinearVelocity());
00265 forceSensors[i].copy->setAngularVelocity(forceSensors[i].target->getAngularVelocity());
00266 forceSensors[i].linInitial=forceSensors[i].copy->getLinearVelocity();
00267 forceSensors[i].angInitial=forceSensors[i].copy->getAngularVelocity();
00268 }
00269 }
00270
00271
00272 void BulletPhysics::TickCallbackManager::postTickForceSensors()
00273 {
00274 for(int i=0;i<forceSensors.size();i++)
00275 {
00276 forceSensors[i].linFinal=forceSensors[i].copy->getLinearVelocity();
00277 forceSensors[i].angFinal=forceSensors[i].copy->getAngularVelocity();
00278 }
00279 }
00280
00281
00282
00283 void BulletPhysics::TickCallbackManager::physicsInternalPreProcessCallback(btScalar timeStep)
00284 {
00285 if (substep==0){
00286 preTickForceSensors();
00287 }
00288 }
00289
00290
00291 void BulletPhysics::TickCallbackManager::physicsInternalPostProcessCallback(btScalar timeStep)
00292 {
00293 postTickForceSensors();
00294 substep++;
00295 }
00296
00297 btCollisionShape* BulletPhysics::GetCSFromOSG(osg::Node * node, collisionShapeType_t ctype)
00298 {
00299 btCollisionShape* cs = NULL;
00300
00301 if (ctype == SHAPE_BOX)
00302 cs = osgbCollision::btBoxCollisionShapeFromOSG(node);
00303 else if (ctype == SHAPE_SPHERE)
00304 cs = osgbCollision::btSphereCollisionShapeFromOSG(node);
00305 else if (ctype == SHAPE_COMPOUND_TRIMESH)
00306 cs = osgbCollision::btCompoundShapeFromOSGGeodes(node, CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE);
00307 else if (ctype == SHAPE_COMPOUND_BOX)
00308 cs = osgbCollision::btCompoundShapeFromOSGGeodes(node, BOX_SHAPE_PROXYTYPE);
00309 else if (ctype == SHAPE_COMPOUND_CYLINDER)
00310 cs = osgbCollision::btCompoundShapeFromOSGGeodes(node, CYLINDER_SHAPE_PROXYTYPE);
00311 else if (ctype == SHAPE_TRIMESH)
00312 cs = osgbCollision::btTriMeshCollisionShapeFromOSG(node);
00313
00314 return cs;
00315 }
00316
00317 btRigidBody* BulletPhysics::addObject(osg::MatrixTransform *root, osg::Node *node, CollisionDataType * data,
00318 boost::shared_ptr<PhysicProperties> pp, osg::Node * colShape)
00319 {
00320
00321 if (!pp)
00322 {
00323 pp.reset(new PhysicProperties);
00324 pp->init();
00325 if (data->isVehicle)
00326 {
00327 pp->isKinematic = 1;
00328 pp->csType = "compound box";
00329 pp->mass = 0;
00330 }
00331 }
00332
00333 collisionShapeType_t ctype = SHAPE_BOX;
00334
00335 if (pp->csType == "box")
00336 ctype = BulletPhysics::SHAPE_BOX;
00337 else if (pp->csType == "sphere")
00338 ctype = BulletPhysics::SHAPE_SPHERE;
00339 else if (pp->csType == "compound box")
00340 ctype = BulletPhysics::SHAPE_COMPOUND_BOX;
00341 else if (pp->csType == "compound cylinder")
00342 ctype = BulletPhysics::SHAPE_COMPOUND_CYLINDER;
00343 else if (pp->csType == "trimesh")
00344 ctype = BulletPhysics::SHAPE_TRIMESH;
00345 else if (pp->csType == "compound trimesh")
00346 ctype = BulletPhysics::SHAPE_COMPOUND_TRIMESH;
00347 else
00348 OSG_WARN << data->name << " has an unknown collision shape type: " << pp->csType
00349 << ". Using default box shape(dynamic) trimesh(kinematic). Check xml file, allowed collision shapes are 'box' 'compound box' 'trimesh' 'compound trimesh' 'compound cylinder."
00350 << std::endl;
00351
00352 btCollisionShape* cs;
00353 if (colShape == NULL)
00354 cs = GetCSFromOSG(node, ctype);
00355 else
00356 cs = GetCSFromOSG(colShape, ctype);
00357
00358
00359 boost::shared_ptr<osg::Matrix> mat = getWorldCoords(node);
00360 cs->setLocalScaling(btVector3(mat->getScale().x(),mat->getScale().y(),mat->getScale().z()));
00361
00362 btVector3 inertia = btVector3(pp->inertia[0], pp->inertia[1], pp->inertia[2]);
00363
00364 MyMotionState* motion = new MyMotionState(node, root);
00365 if (inertia.length() == 0)
00366 cs->calculateLocalInertia(pp->mass, inertia);
00367 btRigidBody::btRigidBodyConstructionInfo rb(pp->mass, motion, cs, inertia);
00368 btRigidBody* body = new btRigidBody(rb);
00369 body->setUserPointer(data);
00370
00371 if (pp->maxAngularLimit[0] >= pp->minAngularLimit[0] || pp->maxAngularLimit[1] >= pp->minAngularLimit[1]
00372 || pp->maxAngularLimit[1] >= pp->minAngularLimit[1] || pp->maxLinearLimit[0] >= pp->minLinearLimit[0]
00373 || pp->maxLinearLimit[1] >= pp->minLinearLimit[1] || pp->maxLinearLimit[1] >= pp->minLinearLimit[1])
00374 {
00375 btRigidBody* pBodyB = new btRigidBody(0, motion, 0);
00376 pBodyB->setActivationState(DISABLE_DEACTIVATION);
00377
00378 btTransform frameInA, frameInB;
00379 frameInA = btTransform::getIdentity();
00380 frameInB = btTransform::getIdentity();
00381 if (pp->minAngularLimit[1] < pp->maxAngularLimit[1])
00382 {
00383 if (not (pp->minAngularLimit[0] < pp->maxAngularLimit[0] or pp->minAngularLimit[2] < pp->maxAngularLimit[2]))
00384 {
00385 frameInA.getBasis().setEulerZYX(0, 0, 1.57);
00386 frameInB.getBasis().setEulerZYX(0, 0, 1.57);
00387 double aux = pp->minAngularLimit[0];
00388 pp->minAngularLimit[0] = pp->minAngularLimit[1];
00389 pp->minAngularLimit[1] = aux;
00390 aux = pp->maxAngularLimit[0];
00391 pp->maxAngularLimit[0] = pp->maxAngularLimit[1];
00392 pp->maxAngularLimit[1] = aux;
00393 }
00394 else if (pp->minAngularLimit[1] <= -1.50 || pp->minAngularLimit[1] >= 1.50)
00395 {
00396 std::cerr << "Constraints in Y axis must be between -PI/2 PI/2" << std::endl;
00397 exit(0);
00398 }
00399 }
00400
00401 btGeneric6DofConstraint* pGen6DOF = new btGeneric6DofConstraint(*body, *pBodyB, frameInA, frameInB, true);
00402 pGen6DOF->setLinearLowerLimit(btVector3(pp->minLinearLimit[0], pp->minLinearLimit[1], pp->minLinearLimit[2]));
00403 pGen6DOF->setLinearUpperLimit(btVector3(pp->maxLinearLimit[0], pp->maxLinearLimit[1], pp->maxLinearLimit[2]));
00404
00405 pGen6DOF->setAngularLowerLimit(btVector3(pp->minAngularLimit[0], pp->minAngularLimit[1], pp->minAngularLimit[2]));
00406 pGen6DOF->setAngularUpperLimit(btVector3(pp->maxAngularLimit[0], pp->maxAngularLimit[1], pp->maxAngularLimit[2]));
00407
00408 dynamicsWorld->addConstraint(pGen6DOF, true);
00409 }
00410
00411
00412
00413
00414 body->setDamping(pp->linearDamping, pp->angularDamping);
00415
00416
00417 dynamicsWorld->addRigidBody(body);
00418 if (data->isVehicle)
00419 {
00420 dynamicsWorld->btCollisionWorld::removeCollisionObject(body);
00421 dynamicsWorld->addCollisionObject(body, short(COL_VEHICLE), short(vehicleCollidesWith));
00422 }
00423 else
00424 {
00425 dynamicsWorld->btCollisionWorld::removeCollisionObject(body);
00426 dynamicsWorld->addCollisionObject(body, short(COL_OBJECTS), short(objectsCollidesWith));
00427 }
00428
00429 body->setActivationState(DISABLE_DEACTIVATION);
00430 if (pp->isKinematic)
00431 {
00432 body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
00433 }
00434
00435 return (body);
00436 }
00437
00438 int BulletPhysics::getNumCollisions()
00439 {
00440 return dispatcher->getNumManifolds();
00441 }
00442
00443 btPersistentManifold * BulletPhysics::getCollision(int i)
00444 {
00445 return dispatcher->getManifoldByIndexInternal(i);
00446 }
00447
00448 void BulletPhysics::cleanManifolds()
00449 {
00450
00451 for (int i = 0; i < dispatcher->getNumManifolds(); i++)
00452 {
00453 btPersistentManifold * col = dispatcher->getManifoldByIndexInternal(i);
00454
00455 for (int j = 0; j < col->getNumContacts(); j++)
00456 if (col->getContactPoint(j).getLifeTime() > 300)
00457 col->removeContactPoint(j);
00458
00459 }
00460 }