00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <physics/CollisionState>
00026
00027 #include <physics/ODESolidSystem>
00028 #include <physics/ODECollisionCuller>
00029 #include <physics/ODECollisionDetector>
00030 #include <physics/SolidCollisionResponseHandler>
00031 #include <physics/NullCollisionResponseHandler>
00032 #include <physics/ODECollidableGroup>
00033 #include <physics/ODESolid>
00034 #include <physics/ODESolidConnectedCollidableBody>
00035
00036 #include <physics/ODEConstraintGroup>
00037 #include <physics/ODEFixedConstraint>
00038 #include <physics/ODEContactConstraint>
00039 #include <physics/ODEBallJoint>
00040 #include <physics/ODEHingeJoint>
00041 #include <physics/ODEDoubleHingeJoint>
00042 #include <physics/ODESliderJoint>
00043 #include <physics/ODEUniversalJoint>
00044
00045 #include <physics/ODEMotor>
00046
00047 using physics::ODESolidSystem;
00048
00049
00050 using physics::Collider;
00051 using physics::CollisionCuller;
00052 using physics::CollisionDetector;
00053 using physics::ODECollisionDetector;
00054 using physics::Collidable;
00055 using physics::CollidableGroup;
00056 using physics::ODECollidableGroup;
00057 using physics::ODECollisionCuller;
00058 using physics::Solid;
00059 using physics::ODESolid;
00060 using physics::ODESolidConnectedCollidableBody;
00061 using physics::ConstraintGroup;
00062 using physics::ODEConstraintGroup;
00063 using physics::CollisionResponseHandler;
00064 using physics::SolidCollisionResponseHandler;
00065
00066 using physics::FixedConstraint;
00067 using physics::ContactConstraint;
00068 using physics::BallJoint;
00069 using physics::HingeJoint;
00070 using physics::DoubleHingeJoint;
00071 using physics::SliderJoint;
00072 using physics::UniversalJoint;
00073 using physics::Motor;
00074
00075 using physics::ODEFixedConstraint;
00076 using physics::ODEBallJoint;
00077 using physics::ODEHingeJoint;
00078 using physics::ODEDoubleHingeJoint;
00079 using physics::ODESliderJoint;
00080 using physics::ODEUniversalJoint;
00081 using physics::ODEMotor;
00082
00083
00084
00085 ODESolidSystem::ODESolidSystem()
00086 : active(true), preSimulateCalled(false)
00087 {
00088 worldID = dWorldCreate();
00089
00090 collisionCuller = ref<CollisionCuller>(NewObj ODECollisionCuller());
00091 collisionDetector = ref<CollisionDetector>(NewObj ODECollisionDetector());
00092 collisionHandler = ref<CollisionResponseHandler>(NewObj SolidCollisionResponseHandler(ref<SolidSystem>(this), collisionDetector));
00093
00094 collisionCuller->addPotentialCollisionListener(collisionDetector);
00095 collisionDetector->addPotentialCollisionListener(ref<ODESolidSystem>(this));
00096
00097 }
00098
00099 ODESolidSystem::ODESolidSystem(const ODESolidSystem& ss)
00100 : SolidSystem(ss), active(ss.active), preSimulateCalled(false)
00101 {
00102 Unimplemented;
00103 }
00104
00105
00106 ODESolidSystem::~ODESolidSystem()
00107 {
00108
00109
00110 ConstraintGroups::iterator g = constraintGroups.begin();
00111 ConstraintGroups::iterator end = constraintGroups.end();
00112 while (g != end) {
00113 (*g)->clear();
00114 ++g;
00115 }
00116 constraintGroups.clear();
00117
00118 setGround(ref<Solid>(0),Point3());
00119
00120 solids.clear();
00121
00122 collisionCuller = ref<CollisionCuller>(0);
00123 collisionDetector = ref<CollisionDetector>(0);
00124 collisionHandler = ref<CollisionResponseHandler>(0);
00125
00126 dWorldDestroy(worldID);
00127 }
00128
00129
00130
00131
00132
00133
00134 ref<Solid> ODESolidSystem::createSolid(ref<const Shape> shape, ref<const Material> material)
00135 {
00136 return ref<Solid>(NewNamedObj("ODESolid") ODESolid(shape, material));
00137 }
00138
00139
00140 ref<ConstraintGroup> ODESolidSystem::createConstraintGroup()
00141 {
00142 return ref<ConstraintGroup>(NewNamedObj("ODEConstraintGroup") ODEConstraintGroup(worldID));
00143 }
00144
00145
00146 ref<BallJoint> ODESolidSystem::createBallJoint()
00147 {
00148 return ref<BallJoint>(NewNamedObj("ODEBallJoint") ODEBallJoint());
00149 }
00150
00151 ref<HingeJoint> ODESolidSystem::createHingeJoint()
00152 {
00153 return ref<HingeJoint>(NewNamedObj("ODEHingeJoint") ODEHingeJoint());
00154 }
00155
00156 ref<DoubleHingeJoint> ODESolidSystem::createDoubleHingeJoint()
00157 {
00158 return ref<DoubleHingeJoint>(NewNamedObj("ODEDoubleHingeJoint") ODEDoubleHingeJoint());
00159 }
00160
00161 ref<SliderJoint> ODESolidSystem::createSliderJoint()
00162 {
00163 return ref<SliderJoint>(NewNamedObj("ODESliderJoint") ODESliderJoint());
00164 }
00165
00166 ref<UniversalJoint> ODESolidSystem::createUniversalJoint()
00167 {
00168 return ref<UniversalJoint>(NewNamedObj("ODEUniversalJoint") ODEUniversalJoint());
00169 }
00170
00171
00172 ref<FixedConstraint> ODESolidSystem::createFixedConstraint()
00173 {
00174 return ref<FixedConstraint>(NewNamedObj("ODEFixedConstraint") ODEFixedConstraint());
00175 }
00176
00177 ref<ContactConstraint> ODESolidSystem::createContactConstraint()
00178 {
00179 return ref<ContactConstraint>(NewNamedObj("ODEContactConstraint") ODEContactConstraint());
00180 }
00181
00182
00183 ref<Motor> ODESolidSystem::createMotor()
00184 {
00185 return ref<ODEMotor>(NewNamedObj("ODEMotor") ODEMotor());
00186 }
00187
00188
00189 void ODESolidSystem::setGround(ref<Solid> ground, const Point3& position)
00190 {
00191 if (this->ground) {
00192 dJointDestroy(groundJoint);
00193 ref<Solid> cground = this->ground;
00194 this->ground = ref<Solid>(0);
00195 removeSolid(cground);
00196 }
00197
00198 if (ground) {
00199 addSolid(ground);
00200 this->ground = ground;
00201 ground->setPosition(position);
00202 groundJoint = dJointCreateFixed(worldID,0);
00203 ref<ODESolid> osolid = narrow_ref<ODESolid>(ground);
00204 dJointAttach(groundJoint, osolid->bodyID, 0);
00205 dJointSetFixed(groundJoint);
00206 }
00207
00208 }
00209
00210
00211 ref<Solid> ODESolidSystem::getGround() const
00212 {
00213 return ground;
00214 }
00215
00216
00217 void ODESolidSystem::setGravity(const Vector3& v)
00218 {
00219 dWorldSetGravity(worldID, v.x, v.y, v.z);
00220 }
00221
00222
00223 void ODESolidSystem::addSolid(ref<Solid> solid)
00224 {
00225 if ((!solid) || (solid && (solid == ground)))
00226 throw std::invalid_argument(Exception("solid must be non-null (and cannot be the ground Solid)"));
00227
00228 ref<ODESolid> osolid = narrow_ref<ODESolid>(solid);
00229 osolid->create(worldID);
00230 solids.push_back(solid);
00231
00232 updateVisual();
00233 }
00234
00235
00236 void ODESolidSystem::removeSolid(ref<const Solid> solid)
00237 {
00238 if ((!solid) || (solid && (solid == ground)))
00239 throw std::invalid_argument(Exception("solid must be non-null (and cannot be the ground Solid)"));
00240
00241 ref<const ODESolid> osolid = narrow_ref<const ODESolid>(solid);
00242 if (osolid->worldID != worldID)
00243 throw std::invalid_argument(Exception("Solid doesn't belong to this SolidSystem"));
00244 osolid->destroy();
00245 solids.remove(solid);
00246
00247 updateVisual();
00248 }
00249
00250
00251
00252 void ODESolidSystem::addConstraintGroup(ref<ConstraintGroup> group)
00253 {
00254 ref<ODEConstraintGroup> ogroup = narrow_ref<ODEConstraintGroup>(group);
00255 if (ogroup->getWorldID() != worldID)
00256 throw std::invalid_argument(Exception("ConstraintGroup doesn't belong to this SolidSystem"));
00257 constraintGroups.push_back(ogroup);
00258 }
00259
00260
00261 void ODESolidSystem::removeConstraintGroup(ref<const ConstraintGroup> group)
00262 {
00263 ref<const ODEConstraintGroup> ogroup = narrow_ref<const ODEConstraintGroup>(group);
00264 if (ogroup->getWorldID() != worldID)
00265 throw std::invalid_argument(Exception("ConstraintGroup doesn't belong to this SolidSystem"));
00266
00267 constraintGroups.ConstraintGroups::remove(ogroup);
00268 }
00269
00270
00271 void ODESolidSystem::setCollisionCuller(ref<CollisionCuller> collisionCuller)
00272 {
00273
00274 this->collisionCuller->removePotentialCollisionListener(collisionDetector);
00275
00276
00277 this->collisionCuller = collisionCuller;
00278 collisionCuller->addPotentialCollisionListener(collisionDetector);
00279 }
00280
00281
00282 ref<CollisionCuller> ODESolidSystem::getCollisionCuller() const
00283 {
00284 return collisionCuller;
00285 }
00286
00287
00288 void ODESolidSystem::setCollisionDetector(ref<CollisionDetector> collisionDetector)
00289 {
00290
00291 collisionCuller->removePotentialCollisionListener(this->collisionDetector);
00292 this->collisionDetector->removePotentialCollisionListener(ref<ODESolidSystem>(this));
00293
00294
00295 this->collisionDetector = collisionDetector;
00296 collisionCuller->addPotentialCollisionListener(collisionDetector);
00297 collisionDetector->addPotentialCollisionListener(ref<ODESolidSystem>(this));
00298 }
00299
00300
00301 ref<CollisionDetector> ODESolidSystem::getCollisionDetector() const
00302 {
00303 return collisionDetector;
00304 }
00305
00306
00307 void ODESolidSystem::setCollisionResponseHandler(ref<CollisionResponseHandler> collisionResponseHandler)
00308 {
00309 collisionHandler = collisionResponseHandler;
00310 }
00311
00312 ref<CollisionResponseHandler> ODESolidSystem::getCollisionResponseHandler() const
00313 {
00314 return collisionHandler;
00315 }
00316
00317
00318
00319 void ODESolidSystem::setParameter(const String& name, Real value)
00320 {
00321 if (name == String("ERP"))
00322 dWorldSetERP(worldID, value);
00323 else if (name == String("CFM"))
00324 dWorldSetCFM(worldID, value);
00325 else
00326 SolidSystem::setParameter(name, value);
00327 }
00328
00329
00330
00331
00332 void ODESolidSystem::reset()
00333 {
00334 collisionHandler->reset();
00335 }
00336
00337 void ODESolidSystem::potentialCollision(ref<const Collidable> collidable1, ref<const Collidable> collidable2)
00338 {
00339 if (collisionListenMode == HandleCollisions) {
00340 collisionHandler->potentialCollision(collidable1, collidable2);
00341 }
00342 else {
00343
00344 if (!collidable1->isInterpenetrationNormal() && !collidable2->isInterpenetrationNormal())
00345 initiallyPenetratingPairs.push_back( std::make_pair<ref<const Collidable>, ref<const Collidable> >(collidable1, collidable2) );
00346 }
00347 }
00348
00349
00350 void ODESolidSystem::preSimulate()
00351 {
00352
00353
00354 initialPenetrations = false;
00355 collisionListenMode = RecordInterpenetrations;
00356 initiallyPenetratingPairs.clear();
00357
00358 if (collisionCuller != 0) {
00359 collisionCuller->collisionEnable(true);
00360 if (collidable == 0)
00361 collidable = createCollidable();
00362 collisionCuller->reset();
00363 collisionCuller->collide(collidable);
00364 }
00365
00366 if (initialPenetrations) {
00367 Consoleln("The initial configuration of some Solids is one of inter-penetration (see log) - system inactivated.");
00368 active=false;
00369 collisionCuller->collisionEnable(false);
00370 }
00371
00372
00373 PenetratingPairs::const_iterator ppair = initiallyPenetratingPairs.begin();
00374 PenetratingPairs::const_iterator end = initiallyPenetratingPairs.end();
00375 while (ppair != end) {
00376 const CollidablePair& pair(*ppair);
00377 collisionCuller->collisionEnable(false, pair.first, pair.second);
00378
00379
00380 String name1("unnamed"), name2("unnamed");
00381 if ( instanceof(*pair.first, const ODESolidConnectedCollidableBody))
00382 name1 = narrow_ref<const ODESolidConnectedCollidableBody>(pair.first)->getName();
00383 if ( instanceof(*pair.second, const ODESolidConnectedCollidableBody))
00384 name2 = narrow_ref<const ODESolidConnectedCollidableBody>(pair.second)->getName();
00385
00386 Logln("Warning: Disabling collisions between CollidableBodies '" << name1 << "' and '" << name2 << "' as they are initiallly penetrating.");
00387
00388 ++ppair;
00389 }
00390
00391
00392 initiallyPenetratingPairs.clear();
00393 collisionListenMode = HandleCollisions;
00394
00395 preSimulateCalled = true;
00396 }
00397
00398
00399 void ODESolidSystem::simulateForSimTime(const base::Time& dt)
00400 {
00401 Assertm(preSimulateCalled,"preSimulate() called before simulateForSimTime()");
00402
00403
00404 if (collisionCuller != 0) {
00405
00406 if (collidable != 0) {
00407 collisionCuller->reset();
00408 collisionCuller->collide(collidable);
00409 }
00410 }
00411
00412 if (active && (dt>0))
00413 dWorldStep(worldID, dt.seconds());
00414
00415 if (node != 0) {
00416
00417 Solids::iterator s = solids.begin();
00418 Solids::iterator end = solids.end();
00419 while (s != end) {
00420 ref<ODESolid> solid = narrow_ref<ODESolid>(*s);
00421 solid->updateVisual();
00422
00423 ++s;
00424 }
00425 }
00426 }
00427
00428
00429
00430
00431
00432 osg::Node* ODESolidSystem::createOSGVisual(Visual::Attributes visualAttributes) const
00433 {
00434 if ((node!=0) && (attributes==visualAttributes))
00435 return &(*node);
00436
00437 node = new osg::Group();
00438 node->setName("ODESolidSystem");
00439
00440 attributes = visualAttributes;
00441
00442 updateVisual();
00443
00444 return &(*node);
00445 }
00446
00447
00448 void ODESolidSystem::updateVisual() const
00449 {
00450 if (node==0) return;
00451
00452
00453
00454 while (node->getNumChildren() > 0)
00455 node->removeChild(node->getChild(0));
00456
00457
00458 Solids::const_iterator_const s = solids.const_begin();
00459 Solids::const_iterator_const end = solids.const_end();
00460 while (s != end) {
00461 ref<const Solid> solid = *s;
00462 if (solid->visualTypeSupported(Visual::OSGVisual))
00463 node->addChild(solid->createOSGVisual(attributes));
00464 ++s;
00465 }
00466
00467
00468 if (collisionDetector)
00469 if (collisionDetector->visualTypeSupported(Visual::OSGVisual))
00470 node->addChild(collisionDetector->createOSGVisual(attributes));
00471
00472 }
00473
00474
00475 ref<Collidable> ODESolidSystem::createCollidable(CollidableFlags flags)
00476 {
00477
00478
00479 ref<ODECollidableGroup> group(NewObj ODECollidableGroup());
00480
00481 Solids::const_iterator s = solids.begin();
00482 Solids::const_iterator end = solids.end();
00483 while (s != end) {
00484 ref<Solid> solid = *s;
00485 group->addCollidable( solid->createCollidable(flags) );
00486 ++s;
00487 }
00488
00489 return group;
00490 }
00491