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
00026
00027 #include <PVLE/Entity/3DPhy.h>
00028
00029 #include <osg/MatrixTransform>
00030
00031 #include <PVLE/Game/PVLEPlayer.h>
00032 #include <PVLE/Game/PVLETeam.h>
00033 #include <PVLE/Physics/Contact.h>
00034 #include <PVLE/Physics/Joint.h>
00035 #include <PVLE/Physics/Body.h>
00036 #include <PVLE/Physics/Space.h>
00037 #include <PVLE/Physics/Visitor.h>
00038 #include <PVLE/Physics/CombinedTraversal.h>
00039 #include <PVLE/3D/Commons.h>
00040 #include <PVLE/3D/CollectNodesVisitor.h>
00041 #include <PVLE/3D/Utility3D.h>
00042
00043
00044
00045
00046 #ifndef REMOVE_DEV_FEATURES
00047
00049 class DirtyDebugGeodeCallback : public Physics::GHChangeCallback {
00050 public:
00051 DirtyDebugGeodeCallback(bool init_dirty = false) : dirty(init_dirty) {}
00052 virtual void operator()(Physics::GeometryHandler * pGH) { dirty = true; traverse(pGH); }
00053 bool dirty;
00054 };
00055
00056 #include <osg/CullFace>
00057 #include <osg/BlendFunc>
00058 #include <osg/Geode>
00059 #include <osg/Depth>
00060
00069 class PhysicsDebugUpdateCB : public PhysicsUpdateCB {
00070 public:
00071 PhysicsDebugUpdateCB(Physics::Geom * pGeom) : PhysicsUpdateCB(pGeom) {}
00072 virtual void operator() (osg::Node * pNode, osg::NodeVisitor * pNV) {
00073 boost::polymorphic_downcast<osg::MatrixTransform *>(pNode)->setMatrix(pGeom->getMatrix());
00074 osg::StateSet * pStateSet = boost::polymorphic_downcast<osg::MatrixTransform *>(pNode)->getOrCreateStateSet();
00075
00076
00077 static const float alpha = .4f;
00078 static const osg::Vec4 BE_GE(.9f, .2f, .2f, alpha);
00079 static const osg::Vec4 BD_GE(.2f, .2f, .9f, alpha);
00080 static const osg::Vec4 BE_GD(.3f, .9f, .2f, alpha);
00081 static const osg::Vec4 BD_GD(.4f, .4f, .4f, alpha);
00082 bool ge = dGeomIsEnabled(*pGeom)!=0;
00083 bool be = pGeom->getBody() && dBodyIsEnabled(*pGeom->getBody());
00084 setColor(pStateSet, be ? (ge ? BE_GE : BE_GD) : (ge ? BD_GE : BD_GD));
00085 pStateSet->setAttributeAndModes(new osg::CullFace(osg::CullFace::FRONT_AND_BACK), osg::StateAttribute::OFF);
00086 pStateSet->setAttributeAndModes(new osg::BlendFunc(osg::BlendFunc::ONE, osg::BlendFunc::ONE_MINUS_SRC_ALPHA));
00087 pStateSet->setAttributeAndModes(new osg::Depth(osg::Depth::LEQUAL, 0, 1, false));
00088 pStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
00089
00090
00091
00092
00093 Physics::GeometryHandler * pGH = pGeom->getHandler();
00094 DirtyDebugGeodeCallback * dirtyCallback = boost::polymorphic_downcast<DirtyDebugGeodeCallback *>(pGH->pChangeCallback.get());
00095 if (dirtyCallback->dirty) {
00096
00097 dirtyCallback->dirty = false;
00098
00099 osg::Geode * pGeode = boost::polymorphic_downcast<osg::Geode *>(boost::polymorphic_downcast<osg::MatrixTransform *>(pNode)->getChild(0));
00100 osg::Shape * pShape = NULL;
00101 if (pGH->type() != Physics::GeometryHandler::MESH) pShape = pGeode->getDrawable(0)->getShape();
00102
00103 std::pair<dReal, dReal> params;
00104 switch (pGH->type()) {
00105 case Physics::GeometryHandler::BOX:
00106 boost::polymorphic_downcast<osg::Box *>(pShape)->setHalfLengths(boost::polymorphic_downcast<Physics::BoxHandler *>(pGH)->getSize()/2.f);
00107 break;
00108 case Physics::GeometryHandler::SPHERE:
00109 boost::polymorphic_downcast<osg::Sphere *>(pShape)->setRadius(boost::polymorphic_downcast<Physics::SphereHandler *>(pGH)->getRadius());
00110 break;
00111 case Physics::GeometryHandler::CAPSULE:
00112 params = boost::polymorphic_downcast<Physics::CapsuleHandler *>(pGH)->getParams();
00113 boost::polymorphic_downcast<osg::Capsule *>(pShape)->set(osg::Vec3(0,0,0), params.first, params.second);
00114 break;
00115 case Physics::GeometryHandler::CYLINDER:
00116 case Physics::GeometryHandler::RAY:
00117 params = boost::polymorphic_downcast<Physics::CylinderHandler *>(pGH)->getParams();
00118 boost::polymorphic_downcast<osg::Cylinder *>(pShape)->set(osg::Vec3(0,0,0), params.first, params.second);
00119 break;
00120
00121
00122 case Physics::GeometryHandler::MESH:
00123
00124 pGeode->setDrawable(0, new osg::Geometry(*(boost::polymorphic_downcast<Physics::MeshHandler *>(pGH)->getGeometry()), osg::CopyOp::DEEP_COPY_ALL));
00125 break;
00126 default:
00127 THROW_TRACED_EXCEPTION("Not implemented - Error on creation");
00128 }
00129 ASSERT(pGeode->getNumDrawables() == 1);
00130 pGeode->getDrawable(0)->setUseDisplayList(false);
00131 }
00132
00133 traverse(pNode, pNV);
00134 }
00135 };
00136
00137 #include <PVLE/3D/RemoveStatesetsVisitor.h>
00138
00139 #endif
00140
00141
00142
00143
00144
00145 #ifdef PVLE_NETWORKING
00146 #include <tnl/tnlGhostConnection.h>
00147 #include <PVLE/Network/NetConverters.h>
00148
00149
00150
00151 void C3DPhy::packBody(const Physics::Body * pBody, TNL::BitStream * pStream) {
00152 Net::write(pStream, dBodyGetPositionV(*pBody));
00153 Net::write(pStream, dBodyGetQuaternionV(*pBody));
00154 Net::write(pStream, dBodyGetLinearVelV(*pBody));
00155 Net::write(pStream, dBodyGetAngularVelV(*pBody));
00156 }
00157
00158 void C3DPhy::unpackBody(Physics::Body * pBody, TNL::BitStream * pStream) {
00159 osg::Vec3 pos, vel, avel;
00160 osg::Quat quat;
00161
00162 Net::read(pStream, pos);
00163 Net::read(pStream, quat);
00164 Net::read(pStream, vel);
00165 Net::read(pStream, avel);
00166
00167 dBodyEnable(*pBody);
00168 dBodySetPosition(*pBody, pos);
00169 dBodySetQuaternion(*pBody, quat);
00170 dBodySetLinearVel(*pBody, vel);
00171 dBodySetAngularVel(*pBody, avel);
00172 }
00173
00174 TNL::U32 C3DPhy::packUpdate(TNL::GhostConnection *, TNL::U32 mask, TNL::BitStream * pStream) {
00175
00176 if (pStream->writeFlag((mask & MOVED) != 0)) {
00177
00178 #ifdef _DEBUG
00179
00180 {
00181 pStream->write(static_cast<UINT>(vGeoms.size()));
00182 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) pStream->writeFlag(pGeom->getBody() != NULL);
00183 pStream->write(static_cast<UINT>(vAdditionalBodies.size()));
00184 }
00185 #endif
00186
00187 Physics::Body * pBody = NULL;
00188 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) {
00189 pBody = pGeom->getBody();
00190 if (pBody) packBody(pBody, pStream);
00191 }
00192 BOOST_FOREACH(pBody, vAdditionalBodies) packBody(pBody, pStream);
00193
00194 mask &= ~MOVED;
00195 }
00196
00197 return mask;
00198 }
00199
00200 void C3DPhy::unpackUpdate(TNL::GhostConnection *, TNL::BitStream * pStream) {
00201
00202 if (pStream->readFlag()) {
00203 #ifdef _DEBUG
00204
00205 {
00206 UINT nb;
00207 pStream->read(&nb);
00208 ASSERT(nb == vGeoms.size());
00209 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) ASSERT(pStream->readFlag() == (pGeom->getBody() != NULL));
00210 pStream->read(&nb);
00211 ASSERT(nb == vAdditionalBodies.size());
00212 }
00213 #endif
00214
00215 Physics::Body * pBody = NULL;
00216 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) {
00217 pBody = pGeom->getBody();
00218 if (pBody) unpackBody(pBody, pStream);
00219 }
00220 BOOST_FOREACH(pBody, vAdditionalBodies) unpackBody(pBody, pStream);
00221 }
00222 }
00223
00224 void C3DPhy::performScopeQuery(TNL::GhostConnection * pConnection) {
00225 ASSERT(false && "Implementation error - C3DPhy is not supposed to be a reference for scope query. Use Player instead.");
00226 }
00227
00228 void C3DPhy::onGhostRemove() {
00229
00230
00231 if (p3DPhyOwner) p3DPhyOwner->doNetworkClientRemove3DPhy(this);
00232 ASSERT(_refCount == 0);
00233 }
00234 #endif
00235
00236
00237 C3DPhy::C3DPhy(const C3DPhy * pInheritTeamAndPlayer) :
00238 pModel(NULL), p3DPhyOwner(NULL), ttl(-1), pPlayer(NULL), pTeam(NULL)
00239 #ifndef REMOVE_DEV_FEATURES
00240 , pModel_debug(NULL)
00241 #endif
00242 {
00243
00244
00245 if (pInheritTeamAndPlayer) setTeamAndPlayer(*pInheritTeamAndPlayer);
00246 }
00247
00248 C3DPhy::C3DPhy(osg::MatrixTransform * pModel, Physics::Geom * pGeom, EInitOptions options, const C3DPhy * pInheritTeamAndPlayer) :
00249 pModel(pModel), p3DPhyOwner(NULL), ttl(-1), pPlayer(NULL), pTeam(NULL)
00250 #ifndef REMOVE_DEV_FEATURES
00251 , pModel_debug(NULL)
00252 #endif
00253 {
00254
00255
00256 if (pGeom) addGeom(pGeom);
00257 if (options == INIT_BIND_ONCE) set3DtoPhy();
00258 else if (options == INIT_AUTO_BIND) bind();
00259 if (pInheritTeamAndPlayer) setTeamAndPlayer(*pInheritTeamAndPlayer);
00260 }
00261
00262
00263 C3DPhy::C3DPhy(const C3DPhy & v, UINT copyOpts) :
00264 pModel(NULL), p3DPhyOwner(NULL), ttl(-1), pPlayer(NULL), pTeam(NULL)
00265 #ifndef REMOVE_DEV_FEATURES
00266 , pModel_debug(NULL)
00267 #endif
00268 {
00269
00270
00271 const UINT modelCopyOpts = osg::CopyOp::DEEP_COPY_NODES | osg::CopyOp::DEEP_COPY_OBJECTS | osg::CopyOp::DEEP_COPY_STATEATTRIBUTES | osg::CopyOp::DEEP_COPY_STATESETS;
00272 const UINT ageomCopyOpts = Physics::AbstractGeom::COPY_ALL;
00273
00274
00275 if (copyOpts & COPY_TTL) ttl = v.ttl;
00276
00277
00278 setTeamAndPlayer(v);
00279
00280
00281 if (copyOpts & COPY_3D) {
00282 if (v.pModel) pModel = new osg::MatrixTransform(*(v.pModel), modelCopyOpts);
00283 #ifndef REMOVE_DEV_FEATURES
00284 if (v.pModel_debug) pModel_debug = new osg::MatrixTransform(*(v.pModel_debug), modelCopyOpts);
00285 #endif
00286 }
00287
00288
00289 if (copyOpts & COPY_PHYSICS) {
00290 Physics::TDuplicatedBodiesMap duplicatedBodies;
00291 Physics::TDuplicatedBodiesMap * pDuplicatedBodies = &duplicatedBodies;
00292
00293
00294 ASSERT(vSpaces.size() == 0);
00295 BOOST_FOREACH(Physics::Space * pSpace, v.vSpaces) {
00296 vSpaces.push_back(new Physics::Space(*pSpace, ageomCopyOpts, this, pDuplicatedBodies));
00297 }
00298
00299 BOOST_FOREACH(const Physics::Geom * pGeom, v.vGeoms) {
00300 vGeoms.push_back(new Physics::Geom(*pGeom, ageomCopyOpts, this, pDuplicatedBodies));
00301 }
00302
00303 Physics::TDuplicatedBodiesMap::iterator dupIt;
00304 BOOST_FOREACH(const Physics::Body * pBody, v.vAdditionalBodies) {
00305 dupIt = duplicatedBodies.find(pBody);
00306 if (dupIt != duplicatedBodies.end()) {
00307 vAdditionalBodies.push_back(new Physics::Body(*pBody));
00308
00309 }
00310 }
00311
00312 BOOST_FOREACH(Physics::Joint * pJoint, v.vJoints) {
00313 vJoints.push_back(new Physics::Joint(*pJoint));
00314 }
00315
00316
00317
00318
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 for(JointList::const_iterator it = v.vJoints.begin(), itEnd = v.vJoints.end(), itCopy = vJoints.begin(); it != itEnd; ++it, ++itCopy) {
00330 attachBodies(v.vGeoms, v.vSpaces, v.vAdditionalBodies, *it, *itCopy);
00331 }
00332
00333
00334 if (copyOpts & COPY_3D) {
00335
00336
00337
00338
00339
00340
00341 CollectNodesVisitor collectOriginal;
00342 CollectNodesVisitor collectCopy;
00343 v.pModel->accept(collectOriginal);
00344 pModel->accept(collectCopy);
00345 ASSERT(collectOriginal.nodes.size() == collectCopy.nodes.size());
00346
00347 const osg::NodeCallback * pOriginalCB;
00348 const PhysicsUpdateCB * pOriginalPhysicsCB;
00349
00350
00351
00352
00353 Physics::Geom * pGeomCopy;
00354 std::vector<osg::Node *>::iterator itCopy = collectCopy.nodes.begin();
00355 for(std::vector<osg::Node *>::const_iterator it = collectOriginal.nodes.begin(), itEnd = collectOriginal.nodes.end(); it != itEnd; ++it, ++itCopy) {
00356 if (*it == *itCopy) continue;
00357 (*itCopy)->setUpdateCallback(NULL);
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 for(pOriginalCB = (*it)->getUpdateCallback(); pOriginalCB; pOriginalCB = pOriginalCB->getNestedCallback()) {
00377 pOriginalPhysicsCB = dynamic_cast<const PhysicsUpdateCB *>(pOriginalCB);
00378 if (pOriginalPhysicsCB) {
00379
00380 pGeomCopy = findGeomCopy(v.vGeoms, v.vSpaces, pOriginalPhysicsCB->getGeom());
00381 if (pGeomCopy) {
00382
00383 (*itCopy)->setUpdateCallback(new PhysicsUpdateCB(pGeomCopy));
00384
00385 break;
00386 }
00387 }
00388 }
00389 }
00390 }
00391 }
00392
00393
00394 if ((copyOpts & COPY_OWNER) && v.p3DPhyOwner) v.p3DPhyOwner->addInScene(this);
00395
00396
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00413 class FindBodiesCopy {
00414 public:
00415 FindBodiesCopy(const Physics::Body * pOriginalBody1, const Physics::Body * pOriginalBody2)
00416 : pOriginalBody1(pOriginalBody1), pOriginalBody2(pOriginalBody2), pCopyBody1(NULL), pCopyBody2(NULL), body1Found(false), body2Found(false)
00417 {
00418 body1Found = (pOriginalBody1 == NULL);
00419 body2Found = (pOriginalBody2 == NULL);
00420 }
00421
00422 inline bool operator()(Physics::Geom * pA, Physics::Geom * pB) {
00423 return operator()(pA->getBody(), pB->getBody());
00424 }
00425
00426 bool operator()(Physics::Body * pA, Physics::Body * pB) {
00427
00428 if (pA) {
00429
00430 if (!body1Found && pA == pOriginalBody1) {
00431 pCopyBody1 = pB;
00432 body1Found = true;
00433 if (body2Found) return false;
00434 }
00435 if (!body2Found && pA == pOriginalBody2) {
00436 pCopyBody2 = pB;
00437 body2Found = true;
00438 if (body1Found) return false;
00439 }
00440 }
00441 return true;
00442 }
00443
00444
00445 Physics::Body * pCopyBody1, * pCopyBody2;
00446 bool body1Found, body2Found;
00447
00448 const Physics::Body * const pOriginalBody1;
00449 const Physics::Body * const pOriginalBody2;
00450 };
00451
00452
00453
00454 void C3DPhy::attachBodies(const GeomList & vOriginalGeoms, const SpaceList & vOriginalSpaces, const BodyList & vOriginalAdditionnalBodies, Physics::Joint * pOriginalJoint, Physics::Joint * pCopyJoint) {
00455
00456 FindBodiesCopy finder(pOriginalJoint->getBody1(), pOriginalJoint->getBody2());
00457
00458
00459 for(BodyList::const_iterator itBody = vOriginalAdditionnalBodies.begin(), itBodyEnd = vOriginalAdditionnalBodies.end(), itBodyCopy = vAdditionalBodies.begin(); itBody != itBodyEnd; ++itBody, ++itBodyCopy) {
00460 if (!finder(*itBody, *itBodyCopy)) break;
00461 }
00462
00463 if (!(finder.body1Found && finder.body2Found)) {
00464
00465 for(GeomList::const_iterator itGeom = vOriginalGeoms.begin(), itGeomEnd = vOriginalGeoms.end(), itGeomCopy = vGeoms.begin(); itGeom != itGeomEnd; ++itGeom, ++itGeomCopy) {
00466 if (!finder(*itGeom, *itGeomCopy)) break;
00467 }
00468
00469
00470 if (!(finder.body1Found && finder.body2Found)) {
00471 for(SpaceList::const_iterator itSpace = vOriginalSpaces.begin(), itSpaceEnd = vOriginalSpaces.end(), itSpaceCopy = vSpaces.begin(); itSpace != itSpaceEnd; ++itSpace, ++itSpaceCopy) {
00472 combinedTraversal(**itSpace, **itSpaceCopy, finder);
00473 if (finder.body1Found && finder.body2Found) break;
00474 }
00475 }
00476 }
00477
00478
00479 if (finder.body1Found && finder.body2Found) {
00480 pCopyJoint->attach(finder.pCopyBody1, finder.pCopyBody2);
00481 pCopyJoint->copyParameters(*pOriginalJoint);
00482 }
00483 else
00484 LOG_INFO << "3DPhy copy - A joint was not attached because bodies where not found inside the same 3DPhy" << std::endl;
00485 }
00486
00487
00490 class FindGeomCopy {
00491 public:
00492 FindGeomCopy(const Physics::Geom * pOriginalGeom) : pOriginalGeom(pOriginalGeom), pCopyGeom(NULL) {}
00493 bool operator()(Physics::Geom * pA, Physics::Geom * pB) {
00494 if (pA == pOriginalGeom) {
00495 pCopyGeom = pB;
00496 return false;
00497 }
00498 return true;
00499 }
00500
00501 Physics::Geom * pCopyGeom;
00502
00503 protected:
00504 const Physics::Geom * pOriginalGeom;
00505 };
00506
00507
00508 Physics::Geom * C3DPhy::findGeomCopy(const GeomList & vOriginalGeoms, const SpaceList & vOriginalSpaces, const Physics::Geom * pOriginalGeom) {
00509
00510 for(GeomList::const_iterator itGeom = vOriginalGeoms.begin(), itGeomEnd = vOriginalGeoms.end(), itGeomCopy = vGeoms.begin(); itGeom != itGeomEnd; ++itGeom, ++itGeomCopy) {
00511 if (*itGeom == pOriginalGeom) return *itGeomCopy;
00512 }
00513
00514 FindGeomCopy finder(pOriginalGeom);
00515 for(SpaceList::const_iterator itSpace = vOriginalSpaces.begin(), itSpaceEnd = vOriginalSpaces.end(), itSpaceCopy = vSpaces.begin(); itSpace != itSpaceEnd; ++itSpace, ++itSpaceCopy) {
00516 combinedTraversal(**itSpace, **itSpaceCopy, finder);
00517 if (finder.pCopyGeom) return finder.pCopyGeom;
00518 }
00519 return NULL;
00520 }
00521
00522
00523
00524 void C3DPhy::addGeom(Physics::Geom * pGeom) {
00525 ASSERT(pGeom);
00526 ASSERT(std::find(vGeoms.begin(), vGeoms.end(), pGeom) == vGeoms.end());
00527 vGeoms.push_back(pGeom);
00528 #ifdef _DEBUG
00529 IGeomCollisionContainer * pCC = pGeom->getCollisionContainer();
00530 if (pCC && pCC != this) LOG_WARN << "3D-Phy is having a geom with already another collision container." << std::endl;
00531 #endif
00532 if (!pGeom->getCollisionContainer()) pGeom->setCollisionContainer(this);
00533 }
00534
00535 void C3DPhy::addSpace(Physics::Space * pSpace) {
00536 ASSERT(pSpace);
00537 ASSERT(std::find(vSpaces.begin(), vSpaces.end(), pSpace) == vSpaces.end());
00538 if (pSpace->getParentSpace()) {
00539 LOG_WARN << "[Performance warn] Cannot add a space that already has a parent space to a 3DPhy." << std::endl;
00540 return;
00541 }
00542 vSpaces.push_back(pSpace);
00543 }
00544
00545 void C3DPhy::addBody(Physics::Body * pBody) { ASSERT(pBody); vAdditionalBodies.push_back(pBody); }
00546
00547 void C3DPhy::bind() {
00548 #ifdef _DEBUG
00549 if (vGeoms.size() >1) LOG_NOTICE << "bind() called on a 3D-Phy that has multiple geoms : Using only the first one." << std::endl;
00550 #endif
00551 bind(0);
00552 }
00553
00554 void C3DPhy::bind(UINT numGeom) {
00555 ASSERT(vGeoms.size() >0);
00556 pModel->setUpdateCallback(new PhysicsUpdateCB(vGeoms[numGeom]));
00557 }
00558
00559 void C3DPhy::set3DtoPhy() {
00560 #ifdef _DEBUG
00561 if (vGeoms.size() >1) LOG_NOTICE << "set3DtoPhy() called on a 3D-Phy that has multiple geoms : Using only the first one." << std::endl;
00562 #endif
00563 set3DtoPhy(0);
00564 }
00565
00566 void C3DPhy::set3DtoPhy(UINT numGeom) {
00567 ASSERT(vGeoms.size() >0);
00568 pModel->setMatrix(vGeoms[numGeom]->getMatrix());
00569 }
00570
00571
00572 void C3DPhy::hitAfter(Physics::Contact * pContacts, unsigned int nbContacts, Physics::Contact * pMaxEnergyContact, Physics::Geom & thisGeom, Physics::Geom & otherGeom, bool contactJointCreated) {
00573
00574
00575
00576
00577
00578
00579
00580 if (contactJointCreated) isHitByCinetic(pMaxEnergyContact->arithmeticCineticEnergy, pMaxEnergyContact->getPos());
00581 }
00582
00583
00584 void C3DPhy::onTTLZero() {
00585 if (!pDeleteCB.valid() || (*pDeleteCB)(this)) {
00586 if (p3DPhyOwner) p3DPhyOwner->markAsRemoved(this);
00587 }
00588 }
00589
00590 void C3DPhy::setPlayer(PVLEPlayer * pPlayer) {
00591 this->pPlayer = pPlayer;
00592 this->pTeam = pPlayer ? pPlayer->getTeam() : NULL;
00593 }
00594
00595 void C3DPhy::setTeam(PVLETeam * pTeam) {
00596 if (this->pTeam == pTeam) return;
00597 this->pTeam = pTeam;
00598 pPlayer = NULL;
00599 }
00600
00601 void C3DPhy::setTeamAndPlayer(const C3DPhy & v) {
00602 ASSERT(!v.pPlayer || v.pPlayer->getTeam() == v.getTeam());
00603 pTeam = v.pTeam;
00604 pPlayer = v.pPlayer;
00605 }
00606
00607 void C3DPhy::createPhysicsDebugView(bool enable) {
00608 #ifndef REMOVE_DEV_FEATURES
00609 if (enable) {
00610 if (!pModel_debug) {
00611
00612 pModel_debug = new osg::MatrixTransform();
00613 ASSERT(p3DPhyOwner);
00614 p3DPhyOwner->getParentGroup()->addChild(pModel_debug);
00615
00616 osg::MatrixTransform * pNodeTemp;
00617 Physics::GeometryHandler * pGH;
00618 std::pair<dReal, dReal> params;
00619
00620
00621 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) {
00622 pGH = pGeom->getHandler();
00623 switch (pGH->type()) {
00624 case Physics::GeometryHandler::BOX:
00625 pNodeTemp = createShapeGeodeBox(boost::polymorphic_downcast<Physics::BoxHandler *>(pGH)->getSize());
00626 break;
00627 case Physics::GeometryHandler::SPHERE:
00628 pNodeTemp = createShapeGeodeSphere(boost::polymorphic_downcast<Physics::SphereHandler *>(pGH)->getRadius());
00629 break;
00630 case Physics::GeometryHandler::CAPSULE:
00631 params = boost::polymorphic_downcast<Physics::CapsuleHandler *>(pGH)->getParams();
00632 pNodeTemp = createShapeGeodeCapsule(params.first, params.second);
00633 break;
00634 case Physics::GeometryHandler::CYLINDER:
00635 params = boost::polymorphic_downcast<Physics::CylinderHandler *>(pGH)->getParams();
00636 pNodeTemp = createShapeGeodeCylinder(params.first, params.second);
00637 break;
00638 case Physics::GeometryHandler::RAY:
00639 {
00640
00641
00642
00643
00644
00645
00646
00647 pNodeTemp = createShapeGeodeCylinder(.1, boost::polymorphic_downcast<Physics::RayHandler *>(pGH)->getLength());
00648 }
00649 break;
00650 case Physics::GeometryHandler::MESH:
00651 {
00652 osg::Geode * pGeode = new osg::Geode();
00653 pGeode->addDrawable(new osg::Geometry(*(boost::polymorphic_downcast<Physics::MeshHandler *>(pGH)->getGeometry()), osg::CopyOp::DEEP_COPY_ALL));
00654 osg::ref_ptr<osg::NodeVisitor> nv = new RemoveStatesetsVisitor();
00655 pGeode->accept(*nv.get());
00656
00657 pNodeTemp = new osg::MatrixTransform();
00658 pNodeTemp->addChild(pGeode);
00659 }
00660 break;
00661 default:
00662 pNodeTemp = NULL;
00663 }
00664
00665 if (pNodeTemp) {
00666
00667 pNodeTemp->setUpdateCallback(new PhysicsDebugUpdateCB(pGeom));
00668 pGH->addOrSetChangeCallback(new DirtyDebugGeodeCallback());
00669 pModel_debug->addChild(pNodeTemp);
00670 }
00671 }
00672 }
00673 } else {
00674 if (pModel_debug) {
00675
00676 p3DPhyOwner->getParentGroup()->removeChild(pModel_debug);
00677 pModel_debug = NULL;
00678 }
00679 }
00680 #endif
00681 }
00682
00683
00684 void C3DPhy::clearBodyContactPos() {
00685 Physics::Body * pBody;
00686 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) {
00687 pBody = pGeom->getBody();
00688 if (pBody) pBody->contactPos.clear();
00689 }
00690 }
00691
00692
00693 void C3DPhy::accept(Physics::Visitor & v) {
00694
00695 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) pGeom->accept(v);
00696
00697 BOOST_FOREACH(Physics::Space * pSpace, vSpaces) pSpace->accept(v);
00698
00699 BOOST_FOREACH(Physics::Body * pBody, vAdditionalBodies) pBody->accept(v);
00700
00701 BOOST_FOREACH(Physics::Joint * pJoint, vJoints) pJoint->accept(v);
00702 }
00703
00704
00706 class GeomTranslateVisitor : public Physics::Visitor {
00707 public:
00708 GeomTranslateVisitor(const osg::Vec3 & vec) : vec(vec) {}
00709 virtual void apply(Physics::Geom & geom) {
00710 geom.translate(vec);
00711 traverse(geom);
00712 }
00713 protected:
00714 const osg::Vec3 & vec;
00715 };
00716
00717
00718 void C3DPhy::translate(const osg::Vec3 & vec) {
00719
00720 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) pGeom->translate(vec);
00721
00722 GeomTranslateVisitor tv(vec);
00723 BOOST_FOREACH(Physics::Space * pSpace, vSpaces) pSpace->accept(tv);
00724
00725 BOOST_FOREACH(Physics::Body * pBody, vAdditionalBodies) pBody->translate(vec);
00726
00727 BOOST_FOREACH(Physics::Joint * pJoint, vJoints) pJoint->translate(vec);
00728
00729
00730 }
00731
00732
00734 class GeomRotateVisitor : public Physics::Visitor {
00735 public:
00736 GeomRotateVisitor(const osg::Quat & quat, const osg::Vec3 & center) : quat(quat), center(center) {}
00737 virtual void apply(Physics::Geom & geom) {
00738 geom.rotate(quat, center);
00739 traverse(geom);
00740 }
00741 protected:
00742 const osg::Quat & quat;
00743 const osg::Vec3 & center;
00744 };
00745
00746 void C3DPhy::rotate(const osg::Quat & quat) {
00747 const osg::Vec3 center = getPos();
00748
00749
00750 BOOST_FOREACH(Physics::Geom * pGeom, vGeoms) pGeom->rotate(quat, center);
00751
00752 GeomRotateVisitor rv(quat, center);
00753 BOOST_FOREACH(Physics::Space * pSpace, vSpaces) pSpace->accept(rv);
00754
00755 BOOST_FOREACH(Physics::Body * pBody, vAdditionalBodies) pBody->rotate(quat, center);
00756
00757
00758
00759
00760 }
00761
00762
00764 class FindVisitor : public Physics::Visitor {
00765 public:
00766 FindVisitor() : result(NULL) {}
00767 virtual void apply(Physics::Geom & geom) {
00768 if (!result) result = &geom;
00769
00770 }
00771
00772 const Physics::Geom * result;
00773 };
00774
00775 std::pair<const void *, C3DPhy::EReferenceType> C3DPhy::getReferenceFrameObject() const {
00776 std::pair<const void *, C3DPhy::EReferenceType> ref( getReferenceFrameObjectNoThrow() );
00777 if (ref.second == NO_REF) {
00778
00779 THROW_TRACED_EXCEPTION("No reference frame exists in the 3D-Phy (needs a geom or an additional body). Use hasReferenceFrameObject() to check this.");
00780 }
00781 return ref;
00782 }
00783
00784 std::pair<const void *, C3DPhy::EReferenceType> C3DPhy::getReferenceFrameObjectNoThrow() const {
00785
00786 if (!vGeoms.empty()) return std::pair<const void *, EReferenceType>(vGeoms[0], REF_GEOM);
00787
00788
00789 FindVisitor fg;
00790 BOOST_FOREACH(Physics::Space * pSpace, vSpaces) {
00791 pSpace->accept(fg);
00792 if (fg.result) return std::pair<const void *, EReferenceType>(fg.result, REF_GEOM_IN_SPACE);
00793 }
00794
00795
00796 if (!vAdditionalBodies.empty()) return std::pair<const void *, EReferenceType>(vAdditionalBodies[0], REF_ADDITIONAL_BODY);
00797
00798 return std::pair<const void *, EReferenceType>(NULL, NO_REF);
00799 }
00800
00801
00802 void C3DPhy::markAsRemoved() { ASSERT(p3DPhyOwner); p3DPhyOwner->markAsRemoved(this); }
00803 void C3DPhy::markAsRemoved(Physics::Geom * pGeom) { ASSERT(p3DPhyOwner); p3DPhyOwner->markAsRemoved(this, pGeom); }
00804 void C3DPhy::markAsRemoved(Physics::Space * pSpace) { ASSERT(p3DPhyOwner); p3DPhyOwner->markAsRemoved(this, pSpace); }
00805 void C3DPhy::markAsRemoved(Physics::Joint * pJoint) { ASSERT(p3DPhyOwner); p3DPhyOwner->markAsRemoved(this, pJoint); }
00806 void C3DPhy::markAsRemoved(Physics::Body * pAdditionalBody) { ASSERT(p3DPhyOwner); p3DPhyOwner->markAsRemoved(this, pAdditionalBody); }
00807
00808
00809
00810
00811 #ifdef _DEBUG
00812 #define C3DPHY_LOCK ++lockCount
00813 #else
00814 #define C3DPHY_LOCK ((void)0)
00815 #endif
00816
00817 #ifdef _DEBUG
00818 #define C3DPHY_UNLOCK --lockCount
00819 #else
00820 #define C3DPHY_UNLOCK ((void)0)
00821 #endif
00822
00823 #ifdef _DEBUG
00824 #define C3DPHY_LOCK_CHECK ASSERT(lockCount == 0)
00825 #else
00826 #define C3DPHY_LOCK_CHECK ((void)0)
00827 #endif
00828
00829
00830 #include <osg/Group>
00831 #include <PVLE/Physics/Space.h>
00832
00833 void C3DPhyOwner::addInScene(C3DPhy * p3DPhy) {
00834 ASSERT(p3DPhy);
00835 if (p3DPhy->get3DPhyOwner()) THROW_TRACED_EXCEPTION("Cannot own (and add to scene) a 3D-Phy that already have a 3D-Phy owner");
00836 p3DPhy->set3DPhyOwner(this);
00837
00838 C3DPHY_LOCK_CHECK;
00839 #ifdef _DEBUG
00840 ASSERT(v3DPhys.insert(p3DPhy).second);
00841 #else
00842 v3DPhys.insert(p3DPhy);
00843 #endif
00844 p3DPhy->ref();
00845
00846 pParentGroup->addChild(*p3DPhy);
00847 pParentSpace->add(*p3DPhy);
00848 }
00849
00850
00851 void C3DPhyOwner::markAsRemoved(C3DPhy * p3DPhy) {
00852
00853 ASSERT(p3DPhy);
00854 C3DPHY_LOCK_CHECK;
00855 v3DPhyToDelete.insert(p3DPhy);
00856 }
00857
00858
00859 void C3DPhyOwner::markAsRemoved(C3DPhy * p3DPhy, Physics::Geom * pGeom) {
00860 C3DPHY_LOCK_CHECK;
00861 ASSERT(pGeom);
00862 C3DPhy::GeomList::iterator it = std::find(p3DPhy->vGeoms.begin(), p3DPhy->vGeoms.end(), pGeom);
00863 ASSERT(it != p3DPhy->vGeoms.end());
00864 p3DPhy->vGeoms.erase(it);
00865 ASSERT(std::find(vGeomsToDelete.begin(), vGeomsToDelete.end(), pGeom) == vGeomsToDelete.end());
00866 vGeomsToDelete.push_back(pGeom);
00867 }
00868
00869
00870 void C3DPhyOwner::markAsRemoved(C3DPhy * p3DPhy, Physics::Space * pSpace) {
00871 C3DPHY_LOCK_CHECK;
00872 ASSERT(pSpace);
00873 C3DPhy::SpaceList::iterator it = std::find(p3DPhy->vSpaces.begin(), p3DPhy->vSpaces.end(), pSpace);
00874 ASSERT(it != p3DPhy->vSpaces.end());
00875 p3DPhy->vSpaces.erase(it);
00876 ASSERT(std::find(vGeomsToDelete.begin(), vGeomsToDelete.end(), pSpace) == vGeomsToDelete.end());
00877 vGeomsToDelete.push_back(pSpace);
00878 }
00879
00880
00881 void C3DPhyOwner::markAsRemoved(C3DPhy * p3DPhy, Physics::Joint * pJoint) {
00882 C3DPHY_LOCK_CHECK;
00883 ASSERT(pJoint);
00884 C3DPhy::JointList::iterator it = std::find(p3DPhy->vJoints.begin(), p3DPhy->vJoints.end(), pJoint);
00885 ASSERT(it != p3DPhy->vJoints.end());
00886 p3DPhy->vJoints.erase(it);
00887 ASSERT(std::find(vJointsToDelete.begin(), vJointsToDelete.end(), pJoint) == vJointsToDelete.end());
00888 vJointsToDelete.push_back(pJoint);
00889 }
00890
00891
00892 void C3DPhyOwner::markAsRemoved(C3DPhy * p3DPhy, Physics::Body * pAdditionalBody) {
00893 C3DPHY_LOCK_CHECK;
00894 ASSERT(pAdditionalBody);
00895 C3DPhy::BodyList::iterator it = std::find(p3DPhy->vAdditionalBodies.begin(), p3DPhy->vAdditionalBodies.end(), pAdditionalBody);
00896 ASSERT(it != p3DPhy->vAdditionalBodies.end());
00897 p3DPhy->vAdditionalBodies.erase(it);
00898 ASSERT(std::find(vBodiesToDelete.begin(), vBodiesToDelete.end(), pAdditionalBody) == vBodiesToDelete.end());
00899 vBodiesToDelete.push_back(pAdditionalBody);
00900 }
00901
00902
00903 void C3DPhyOwner::detatch(C3DPhy * p3DPhy) {
00904 p3DPhy->set3DPhyOwner(NULL);
00905 p3DPhy->unref();
00906 #ifdef _DEBUG
00907 ASSERT(v3DPhys.erase(p3DPhy) >0);
00908 #else
00909 v3DPhys.erase(p3DPhy);
00910 #endif
00911 }
00912
00913 void C3DPhyOwner::detatch_nodelete(C3DPhy * p3DPhy) {
00914 p3DPhy->set3DPhyOwner(NULL);
00915 p3DPhy->unref_nodelete();
00916 #ifdef _DEBUG
00917 ASSERT(v3DPhys.erase(p3DPhy) >0);
00918 #else
00919 v3DPhys.erase(p3DPhy);
00920 #endif
00921 }
00922
00923
00924 void C3DPhyOwner::doDelayed3DPhy() {
00925 bIsDeleting = true;
00926
00927 for(T3DPhyToDeleteSet::iterator it=v3DPhyToDelete.begin(), itEnd=v3DPhyToDelete.end(); it!=itEnd; ++it) {
00928
00929 C3DPhy * p3DPhy = it->get();
00930
00931 ASSERT(p3DPhy->referenceCount() >= 2);
00932 if (p3DPhy->referenceCount() <= 2) {
00933 C3DPHY_LOCK_CHECK;
00934 if (p3DPhy->getModel()) {
00935 #ifdef PVLE_3DPHY_USES_REF_PTR
00936 ASSERT(p3DPhy->getModel()->referenceCount() >= 2);
00937 #endif
00938 vNodesToDelete.push_back(p3DPhy->getModel());
00939 }
00940 #ifndef REMOVE_DEV_FEATURES
00941 if (p3DPhy->pModel_debug) {
00942 # ifdef PVLE_3DPHY_USES_REF_PTR
00943 ASSERT(p3DPhy->pModel_debug->referenceCount() >= 2);
00944 # endif
00945 vNodesToDelete.push_back(p3DPhy->pModel_debug);
00946 }
00947 #endif
00948 vGeomsToDelete.insert (vGeomsToDelete.end(), p3DPhy->vGeoms.begin(), p3DPhy->vGeoms.end());
00949 vGeomsToDelete.insert (vGeomsToDelete.end(), p3DPhy->vSpaces.begin(), p3DPhy->vSpaces.end());
00950 vJointsToDelete.insert(vJointsToDelete.end(), p3DPhy->vJoints.begin(), p3DPhy->vJoints.end());
00951 vBodiesToDelete.insert(vBodiesToDelete.end(), p3DPhy->vAdditionalBodies.begin(), p3DPhy->vAdditionalBodies.end());
00952
00953 #ifdef _DEBUG // Only in debug because it can take time to cleanup the 3DPhy (See C3DPhy destructor).
00954 p3DPhy->vJoints.clear();
00955 p3DPhy->vAdditionalBodies.clear();
00956 #endif
00957 }
00958
00959
00960 detatch(p3DPhy);
00961 }
00962 C3DPHY_LOCK;
00963 v3DPhyToDelete.clear();
00964 C3DPHY_UNLOCK;
00965
00966
00967 BOOST_FOREACH(osg::ref_ptr<C3DPhy> & p3DPhy, v3DPhyToAdd) {
00968 addInScene(p3DPhy.get());
00969 }
00970 C3DPHY_LOCK;
00971 v3DPhyToAdd.clear();
00972 C3DPHY_UNLOCK;
00973
00974 bIsDeleting = false;
00975 }
00976
00977 void C3DPhyOwner::doDeleteGfx() {
00978 bIsDeleting = true;
00979
00980 BOOST_FOREACH(osg::MatrixTransform * pNode, vNodesToDelete) {
00981 if (pNode) {
00982 #ifdef _DEBUG
00983 ASSERT(pParentGroup->removeChild(pNode));
00984 #else
00985 pParentGroup->removeChild(pNode);
00986 #endif
00987 }
00988 }
00989
00990 C3DPHY_LOCK;
00991 vNodesToDelete.clear();
00992 C3DPHY_UNLOCK;
00993
00994 bIsDeleting = false;
00995 }
00996
00997 void C3DPhyOwner::doDeletePhy() {
00998 bIsDeleting = true;
00999
01000
01001
01002 BOOST_FOREACH(Physics::AbstractGeom * pAGeom, vGeomsToDelete) {
01003 if (pAGeom) {
01004 ASSERT((pAGeom)->getParentSpace() == pParentSpace);
01005
01006
01007 pParentSpace->remove(pAGeom);
01008 }
01009 }
01010 C3DPHY_LOCK;
01011 vGeomsToDelete.clear();
01012 C3DPHY_UNLOCK;
01013
01014
01015 BOOST_FOREACH(Physics::Body * pBody, vBodiesToDelete) {
01016 ASSERT(pBody);
01017 delete pBody;
01018 }
01019 C3DPHY_LOCK;
01020 vBodiesToDelete.clear();
01021 C3DPHY_UNLOCK;
01022
01023
01024 BOOST_FOREACH(Physics::Joint * pJoint, vJointsToDelete) {
01025 ASSERT(pJoint);
01026 delete pJoint;
01027 }
01028 C3DPHY_LOCK;
01029 vJointsToDelete.clear();
01030 C3DPHY_UNLOCK;
01031
01032 bIsDeleting = false;
01033 }
01034
01035
01036 void C3DPhyOwner::doNetworkClientRemove3DPhy(C3DPhy * p3DPhy) {
01037 C3DPHY_LOCK_CHECK;
01038 bIsDeleting = true;
01039
01040
01041 vNodesToDelete.push_back(p3DPhy->getModel());
01042 #ifndef REMOVE_DEV_FEATURES
01043 vNodesToDelete.push_back(p3DPhy->pModel_debug);
01044 #endif
01045 vGeomsToDelete.insert (vGeomsToDelete.end(), p3DPhy->vGeoms.begin(), p3DPhy->vGeoms.end());
01046 vGeomsToDelete.insert (vGeomsToDelete.end(), p3DPhy->vSpaces.begin(), p3DPhy->vSpaces.end());
01047 vJointsToDelete.insert(vJointsToDelete.end(), p3DPhy->vJoints.begin(), p3DPhy->vJoints.end());
01048 vBodiesToDelete.insert(vBodiesToDelete.end(), p3DPhy->vAdditionalBodies.begin(), p3DPhy->vAdditionalBodies.end());
01049
01050
01051 detatch_nodelete(p3DPhy);
01052 bIsDeleting = false;
01053 }
01054
01055 void C3DPhyOwner::createPhysicsDebugView(bool enable) {
01056 #ifndef REMOVE_DEV_FEATURES
01057 BOOST_FOREACH(C3DPhy * p3DPhy, v3DPhys) {
01058 p3DPhy->createPhysicsDebugView(enable);
01059 }
01060 #endif
01061 }