00001
00002 #include "random_utils/LogManager.h"
00003 #include "random_utils/ThreadSafeCanvas.h"
00004
00005 #include "PhysicsManager.h"
00006 #include "PhysicsBody.h"
00007
00008 namespace vrsode
00009 {
00010
00011 PhysicsManager* PhysicsManager::m_instance = 0;
00012 bool PhysicsManager::m_keepRunning = true;
00013 double PhysicsManager::m_stepSize = 0.02;
00014 double PhysicsManager::m_stepTime = 0.004;
00015 unsigned int PhysicsManager::m_updateResolution = 1;
00016 bool PhysicsManager::m_runningMultiThreaded = false;
00017 SDL_Thread* PhysicsManager::m_thread = 0;
00018
00019 const unsigned int g_initialCollisionCategory = 0xFFFF0000;
00020 const unsigned int g_initialCollisionPartnerCategories = 0xFFFF0000;
00021
00022 static void
00023 NearCallback(void* p_data, dGeomID p_geomOne, dGeomID p_geomTwo);
00024
00025 PhysicsManager::PhysicsManager()
00026 {
00027 m_initialised = false;
00028 m_performanceAutoAdjust = false;
00029 m_maxCollisionContacts = 16;
00030 init();
00031 }
00032
00033 PhysicsManager::~PhysicsManager()
00034 {
00035 if(m_initialised)
00036 release();
00037 }
00038
00039 void
00040 PhysicsManager::registerCollisionBody(VRS::SO<CollisionBody> p_object)
00041 {
00042 m_collisionBodies.push_back(p_object);
00043
00044 p_object->setCollisionCategory(g_initialCollisionCategory);
00045 p_object->setCollisionPartnerCategories(
00046 g_initialCollisionPartnerCategories);
00047 }
00048
00049 void
00050 PhysicsManager::registerPhysicsBody(VRS::SO<PhysicsBody> p_object)
00051 {
00052 m_physicsBodies.push_back(p_object);
00053
00054 p_object->setCollisionCategory(g_initialCollisionCategory);
00055 p_object->setCollisionPartnerCategories(
00056 g_initialCollisionPartnerCategories);
00057 }
00058
00059 void
00060 PhysicsManager::unregisterCollisionBody(VRS::SO<CollisionBody> p_object)
00061 {
00062 std::vector<VRS::SO<CollisionBody> >::iterator it;
00063 it = findCollisionBody(p_object);
00064
00065 if(it != m_collisionBodies.end())
00066 m_collisionBodies.erase(it);
00067
00068 if(p_object->geomId())
00069 dSpaceRemove(spaceId(), p_object->geomId());
00070 }
00071
00072 void
00073 PhysicsManager::unregisterPhysicsBody(VRS::SO<PhysicsBody> p_object)
00074 {
00075 std::vector<VRS::SO<PhysicsBody> >::iterator it;
00076 it = findPhysicsBody(p_object);
00077
00078 if(it != m_physicsBodies.end())
00079 m_physicsBodies.erase(it);
00080
00081 if(p_object->geomId())
00082 dSpaceRemove(spaceId(), p_object->geomId());
00083 }
00084
00085 const bool
00086 PhysicsManager::isInitialised() const
00087 {
00088 return m_initialised;
00089 }
00090
00091 const dSpaceID
00092 PhysicsManager::spaceId() const
00093 {
00094 return m_spaceId;
00095 }
00096
00097 const dWorldID
00098 PhysicsManager::worldId() const
00099 {
00100 return m_worldId;
00101 }
00102
00103 const unsigned int
00104 PhysicsManager::maxCollisionContacts() const
00105 {
00106 return m_maxCollisionContacts;
00107 }
00108
00109 void
00110 PhysicsManager::setMaxCollisionContacts(unsigned int p_maxCollisionContacts)
00111 {
00112 m_maxCollisionContacts = p_maxCollisionContacts;
00113 }
00114
00115 const dJointGroupID
00116 PhysicsManager::collisionContactGroupId() const
00117 {
00118 return m_collisionContactGroupId;
00119 }
00120
00121 const std::vector<VRS::SO<PhysicsBody> >&
00122 PhysicsManager::physicsBodies() const
00123 {
00124 return m_physicsBodies;
00125 }
00126
00127 const std::vector<VRS::SO<CollisionBody> >&
00128 PhysicsManager::collisionBodies() const
00129 {
00130 return m_collisionBodies;
00131 }
00132
00133 unsigned int
00134 PhysicsManager::physicsBodyCount() const
00135 {
00136 return m_physicsBodies.size();
00137 }
00138
00139 unsigned int
00140 PhysicsManager::collisionBodyCount() const
00141 {
00142 return m_collisionBodies.size();
00143 }
00144
00145 void
00146 PhysicsManager::init()
00147 {
00148 m_worldId = dWorldCreate();
00149 m_spaceId = dHashSpaceCreate(0);
00150
00151 m_collisionContactGroupId = dJointGroupCreate(0);
00152
00153
00154
00155 dWorldSetERP(m_worldId, 0.9);
00156 dWorldSetCFM(m_worldId, 0.0001);
00157 dWorldSetGravity(m_worldId, 0.0, -9.81, 0.0);
00158 dWorldSetAutoDisableFlag(m_worldId, true);
00159 dWorldSetAutoDisableLinearThreshold(m_worldId, 0.01);
00160 dWorldSetAutoDisableAngularThreshold(m_worldId, 0.01);
00161 dWorldSetAutoDisableSteps(m_worldId, 10);
00162 dWorldSetAutoDisableTime(m_worldId, 0);
00163 dWorldSetContactMaxCorrectingVel(m_worldId, dInfinity);
00164 dWorldSetContactSurfaceLayer(m_worldId, 0.001);
00165
00166 m_initialised = true;
00167 }
00168
00169 void
00170 PhysicsManager::tick(double p_stepSize)
00171 {
00172 if(!isInitialised())
00173 return;
00174 {
00175 std::vector<VRS::SO<CollisionBody> >::iterator it;
00176 for(it = m_collisionBodies.begin(); it != m_collisionBodies.end(); it++)
00177 (*it)->update();
00178 }
00179
00180 {
00181 std::vector<VRS::SO<PhysicsBody> >::iterator it;
00182 for(it = m_physicsBodies.begin(); it != m_physicsBodies.end(); it++)
00183 (*it)->update();
00184 }
00185
00186 dSpaceCollide(m_spaceId, 0, &NearCallback);
00187 dWorldStep(m_worldId, p_stepSize);
00188 dJointGroupEmpty(m_collisionContactGroupId);
00189 }
00190
00191 void
00192 PhysicsManager::update()
00193 {
00194 lock();
00195 tick(stepSize() / (double)updateResolution());
00196 unlock();
00197 }
00198
00199 void
00200 PhysicsManager::update(double p_stepSize)
00201 {
00202 for(unsigned int i = 0; i < updateResolution(); i++)
00203 tick(p_stepSize / (double)updateResolution());
00204
00205 applyTransformations();
00206 }
00207
00208 void
00209 PhysicsManager::release()
00210 {
00211 if(!isInitialised())
00212 return;
00213
00214 dJointGroupEmpty(m_collisionContactGroupId);
00215 dJointGroupDestroy(m_collisionContactGroupId);
00216 dWorldDestroy(m_worldId);
00217 dSpaceDestroy(m_spaceId);
00218 dCloseODE();
00219
00220 m_initialised = false;
00221 }
00222
00223 void
00224 PhysicsManager::applyTransformations()
00225 {
00226 std::vector<VRS::SO<PhysicsBody> >::iterator it;
00227 for(it = m_physicsBodies.begin(); it != m_physicsBodies.end(); it++)
00228 (*it)->syncTransformationsToVRS();
00229 }
00230
00231 std::vector<VRS::SO<PhysicsBody> >::iterator
00232 PhysicsManager::findPhysicsBody(VRS::SO<PhysicsBody> p_physicsBody)
00233 {
00234 std::vector<VRS::SO<PhysicsBody> >::iterator it;
00235
00236 for(it = m_physicsBodies.begin(); it != m_physicsBodies.end(); it++)
00237 if(*it == p_physicsBody)
00238 return it;
00239
00240 return m_physicsBodies.end();
00241 }
00242
00243 std::vector<VRS::SO<CollisionBody> >::iterator
00244 PhysicsManager::findCollisionBody(VRS::SO<CollisionBody> p_collisionBody)
00245 {
00246 std::vector<VRS::SO<CollisionBody> >::iterator it;
00247
00248 for(it = m_collisionBodies.begin(); it != m_collisionBodies.end(); it++)
00249 if(*it == p_collisionBody)
00250 return it;
00251
00252 return m_collisionBodies.end();
00253 }
00254
00255 void
00256 PhysicsManager::setDebugNodesGlobal(bool p_debugNodes)
00257 {
00258 std::vector<VRS::SO<PhysicsBody> >::iterator it1;
00259 std::vector<VRS::SO<CollisionBody> >::iterator it2;
00260
00261 for(it1 = m_physicsBodies.begin(); it1 != m_physicsBodies.end(); it1++)
00262 (*it1)->setDebugNode(p_debugNodes);
00263 for(it2 = m_collisionBodies.begin(); it2 != m_collisionBodies.end(); it2++)
00264 (*it2)->setDebugNode(p_debugNodes);
00265 }
00266
00267 static void
00268 NearCallback(void* p_data, dGeomID p_geomOne, dGeomID p_geomTwo)
00269 {
00270 unsigned int maxContacts = PhysicsManager::get()->maxCollisionContacts();
00271
00272 if(dGeomGetBody(p_geomOne) && dGeomGetBody(p_geomTwo))
00273 if(dAreConnected(dGeomGetBody(p_geomOne), dGeomGetBody(p_geomTwo)))
00274 return;
00275
00276 if (dGeomIsSpace(p_geomOne) || dGeomIsSpace(p_geomTwo))
00277 {
00278 dSpaceCollide2(p_geomOne, p_geomTwo, p_data, &NearCallback);
00279
00280 if(dGeomIsSpace(p_geomOne))
00281 dSpaceCollide((dSpaceID)p_geomOne, p_data, &NearCallback);
00282
00283 if(dGeomIsSpace(p_geomTwo))
00284 dSpaceCollide((dSpaceID)p_geomTwo, p_data, &NearCallback);
00285
00286 return;
00287 }
00288
00289 VRS::SO<CollisionBody> bodyOne = (CollisionBody*)dGeomGetData(p_geomOne);
00290 VRS::SO<CollisionBody> bodyTwo = (CollisionBody*)dGeomGetData(p_geomTwo);
00291 VRS::SO<Surface> surfaceOne = bodyOne ? bodyOne->surface() : 0;
00292 VRS::SO<Surface> surfaceTwo = bodyTwo ? bodyTwo->surface() : 0;
00293
00294
00295 unsigned long bodyOneCategory = bodyOne->collisionCategory();
00296 unsigned long bodyOnePartners = bodyOne->collisionPartnerCategories();
00297 unsigned long bodyTwoCategory = bodyTwo->collisionCategory();
00298 unsigned long bodyTwoPartners = bodyTwo->collisionPartnerCategories();
00299
00300
00301 if((bodyOneCategory&bodyTwoPartners) && (bodyTwoCategory&bodyOnePartners))
00302 {
00303 dContact contacts[maxContacts];
00304 unsigned int numberOfContacts =
00305 dCollide(p_geomOne, p_geomTwo, maxContacts,
00306 &(contacts[0].geom), sizeof(dContact));
00307
00308 for (unsigned int i = 0; i < numberOfContacts; i++)
00309 {
00310 contacts[i].surface.mode =
00311 dContactSoftERP | dContactSoftCFM | dContactBounce |
00312 dContactApprox1 | dContactSlip1 | dContactSlip2;
00313
00314
00315 if(!surfaceOne || !surfaceTwo)
00316 {
00317 rErr("no surface, using hardcoded default values...");
00318 contacts[i].surface.slip1 = 0.1;
00319 contacts[i].surface.slip2 = 0.1;
00320 contacts[i].surface.mu = dInfinity;
00321 contacts[i].surface.bounce = 0.0;
00322 contacts[i].surface.bounce_vel = dInfinity;
00323 contacts[i].surface.soft_erp = 0.99;
00324 contacts[i].surface.soft_cfm = 0.02;
00325 }
00326
00327 else if(!surfaceOne->ghostMode() && !surfaceTwo->ghostMode())
00328 {
00329
00330 contacts[i].surface.slip1 =
00331 fmax(surfaceOne->slip1(), surfaceTwo->slip1());
00332
00333
00334 contacts[i].surface.slip2 =
00335 fmax(surfaceOne->slip2(), surfaceTwo->slip2());
00336
00337
00338 contacts[i].surface.mu =
00339 fmax(surfaceOne->mu(), surfaceTwo->mu());
00340
00341
00342 contacts[i].surface.bounce =
00343 fmax(surfaceOne->bounce(), surfaceTwo->bounce());
00344
00345
00346 contacts[i].surface.bounce =
00347 fmin(surfaceOne->bounceVelocity(),
00348 surfaceTwo->bounceVelocity());
00349
00350
00351 contacts[i].surface.soft_erp =
00352 (surfaceOne->softErp() + surfaceTwo->softErp()) / 2.0;
00353
00354
00355 contacts[i].surface.soft_cfm =
00356 surfaceOne->softCfm() + surfaceTwo->softCfm() / 2.0;
00357 }
00358
00359
00360 if(!surfaceOne->ghostMode() && !surfaceTwo->ghostMode())
00361 {
00362 dJointID contact = dJointCreateContact(
00363 PhysicsManager::get()->worldId(),
00364 PhysicsManager::get()->collisionContactGroupId(),
00365 &contacts[i]);
00366
00367 dJointAttach(contact, dGeomGetBody(contacts[i].geom.g1),
00368 dGeomGetBody(contacts[i].geom.g2));
00369 }
00370 }
00371
00372
00373 if(bodyOne && bodyTwo)
00374 {
00375 bodyOne->handleCollision(bodyTwo);
00376 bodyTwo->handleCollision(bodyOne);
00377 }
00378 }
00379 }
00380
00381 void
00382 PhysicsManager::setStepSize(double p_value)
00383 {
00384 m_stepSize = p_value;
00385 }
00386
00387 double
00388 PhysicsManager::stepSize()
00389 {
00390 return m_stepSize;
00391 }
00392
00393 void
00394 PhysicsManager::setStepTime(double p_value)
00395 {
00396 m_stepTime = p_value;
00397 }
00398
00399 double
00400 PhysicsManager::stepTime()
00401 {
00402 return m_stepTime;
00403 }
00404
00405 bool
00406 PhysicsManager::keepRunning()
00407 {
00408 return m_keepRunning;
00409 }
00410
00411 void
00412 PhysicsManager::stop()
00413 {
00414 m_keepRunning = false;
00415 }
00416
00417 int
00418 PhysicsManager::updateWorker(void* p_data)
00419 {
00420
00421 PhysicsManager* physicsManager = (PhysicsManager*)p_data;
00422
00423 const int performanceAdjustmentThreshold = 25;
00424 int performanceMeter = 0;
00425 double timeTemp;
00426 double updateTime;
00427
00428 while(physicsManager->keepRunning())
00429 {
00430 timeTemp = physicsManager->currentTime();
00431 for(unsigned int i = 0; i < m_updateResolution; i++)
00432 physicsManager->update();
00433
00434 if(m_runningMultiThreaded)
00435 random_utils::ThreadSafeCanvas::get()->sleep();
00436
00437 physicsManager->applyTransformations();
00438
00439 if(m_runningMultiThreaded)
00440 random_utils::ThreadSafeCanvas::get()->wakeUp();
00441
00442 updateTime = physicsManager->currentTime() - timeTemp;
00443
00444 if(physicsManager->performanceAutoAdjust())
00445 {
00446
00447 if(updateTime > physicsManager->stepTime())
00448 performanceMeter--;
00449
00450
00451 if((updateTime * 5.0) < physicsManager->stepTime())
00452 performanceMeter++;
00453
00454
00455 if(performanceMeter > performanceAdjustmentThreshold)
00456 {
00457
00458 performanceMeter = 0;
00459
00460
00461 physicsManager->setUpdateResolution(
00462 (physicsManager->updateResolution()) + 1);
00463
00464 std::cout << "+++ " << "increasing update resolution, now: "
00465 << physicsManager->updateResolution() << std::endl;
00466 }
00467
00468
00469 if(performanceMeter < -performanceAdjustmentThreshold)
00470 {
00471
00472 performanceMeter = 0;
00473
00474
00475 if(physicsManager->updateResolution() > 1)
00476 {
00477 physicsManager->setUpdateResolution(
00478 (physicsManager->updateResolution()) - 1);
00479 std::cout << "--- " << "decreasing update resolution, now: "
00480 << physicsManager->updateResolution() << std::endl;
00481 }
00482 else
00483 std::cout << "!!! BAD PERFORMANCE !!!" << std::endl
00484 << "no more real time performance tweaking possible"
00485 << std::endl;
00486
00487 }
00488 }
00489 else if(physicsManager->stepTime() - updateTime > 0)
00490 SDL_Delay((unsigned long)((physicsManager->stepTime() -
00491 updateTime) * 1000.0));
00492 }
00493
00494 return 0;
00495 }
00496
00497 double
00498 PhysicsManager::currentTime()
00499 {
00500 return SDL_GetTicks() / 1000.0;
00501 }
00502
00503 void
00504 PhysicsManager::setPerformanceAutoAdjust(bool p_value)
00505 {
00506 m_performanceAutoAdjust = p_value;
00507 }
00508
00509 void
00510 PhysicsManager::setUpdateSpeed(double p_updateSpeed)
00511 {
00512 double currentSpeed = updateSpeed();
00513
00514 m_stepSize *= (p_updateSpeed / currentSpeed);
00515 }
00516
00517 double
00518 PhysicsManager::updateSpeed()
00519 {
00520 return m_stepSize / m_stepTime;
00521 }
00522
00523 void
00524 PhysicsManager::setUpdateResolution(unsigned int p_updateResolution)
00525 {
00526 m_updateResolution = p_updateResolution;
00527 }
00528
00529 unsigned int
00530 PhysicsManager::updateResolution()
00531 {
00532 return m_updateResolution;
00533 }
00534
00535 bool
00536 PhysicsManager::performanceAutoAdjust()
00537 {
00538 return m_performanceAutoAdjust;
00539 }
00540
00541 bool
00542 PhysicsManager::runningMultiThreaded()
00543 {
00544 return m_runningMultiThreaded;
00545 }
00546
00547 std::string
00548 PhysicsManager::odeVersionString()
00549 {
00550 return std::string(PACKAGE_STRING);
00551 }
00552
00553 }