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
00029
00030 #ifndef ENT_3D_PHY_H
00031 #define ENT_3D_PHY_H
00032
00033 #include <PVLE/Config.h>
00034 #include <PVLE/Export.h>
00035
00036 class C3DPhy;
00037
00038 #include <osg/Referenced>
00039
00041 class C3DPhyCallback : public osg::Referenced {
00042 public:
00044 virtual bool operator()(C3DPhy * p3DPhy) =0;
00045
00046 protected:
00049 virtual ~C3DPhyCallback() {}
00050 };
00051
00052
00053
00054 #include <PVLE/Entity/GeomCollisionContainer.h>
00055 #include <PVLE/Entity/PhysicsUpdateCB.h>
00056 #include <PVLE/Entity/WeaponEnergy.h>
00057 #include <osg/Vec3>
00058 #include <osg/ref_ptr>
00059 #include <vector>
00060
00061 #ifdef PVLE_NETWORKING
00062 #include <tnl/tnlCertificate.h>
00063 #include <tnl/tnlNetObject.h>
00064 #endif
00065
00066
00067 namespace osg {
00068 class Group;
00069 class MatrixTransform;
00070 }
00071
00072
00073 #ifdef PVLE_3DPHY_USES_REF_PTR
00074 #include <PVLE/Physics/Geom.h>
00075 #include <PVLE/Physics/Space.h>
00076 #include <PVLE/Physics/Joint.h>
00077 #else
00078 namespace Physics {
00079 class Geom;
00080 class Space;
00081 class Joint;
00082 }
00083 #endif
00084
00085 class C3DPhyOwner;
00086 class Visitor;
00087 class PVLEPlayer;
00088 class PVLETeam;
00089
00119 #ifdef PVLE_NETWORKING
00120 class PVLE_EXPORT C3DPhy : public IGeomCollisionContainer, public TNL::NetObject {
00121 #else
00122 class PVLE_EXPORT C3DPhy : public IGeomCollisionContainer {
00123 #endif
00124 public:
00125
00126
00127 enum EInitOptions {
00128 INIT_NONE,
00129 INIT_BIND_ONCE,
00130 INIT_AUTO_BIND
00131 };
00132
00133 enum ECopyOptions {
00134 COPY_3D = 0x1,
00135 COPY_PHYSICS = 0x2,
00136 COPY_OWNER = 0x4,
00137 COPY_TTL = 0x8,
00138
00139
00140 COPY_DEFAULT = COPY_3D | COPY_PHYSICS,
00141 COPY_ALL = 0xffffffff
00142 };
00143
00145 C3DPhy(const C3DPhy * pInheritTeamAndPlayer = NULL);
00146
00148 C3DPhy(osg::MatrixTransform * pModel, Physics::Geom * pGeom, EInitOptions options = INIT_NONE, const C3DPhy * pInheritTeamAndPlayer = NULL);
00149
00151 C3DPhy(const C3DPhy & v, UINT copyOpts = COPY_DEFAULT);
00152
00153 virtual const char* className() const { return "C3DPhy"; }
00154 virtual EContainerType getType() const { return C3DPHY; }
00155 virtual C3DPhy * as3DPhy() { return this; }
00156
00159 osg::MatrixTransform * getModel() { return pModel; }
00160 operator osg::MatrixTransform*() { return pModel; }
00161 const osg::MatrixTransform * getModel() const { return pModel; }
00162 operator const osg::MatrixTransform*() const { return pModel; }
00163
00164 void setModel(osg::MatrixTransform * pModel) { this->pModel = pModel; }
00166
00169 #ifdef PVLE_3DPHY_USES_REF_PTR
00170
00171 typedef std::vector<osg::ref_ptr<Physics::Geom > > GeomList;
00172 typedef std::vector<osg::ref_ptr<Physics::Space> > SpaceList;
00173 typedef std::vector<osg::ref_ptr<Physics::Joint> > JointList;
00174 typedef std::vector<osg::ref_ptr<Physics::Body > > BodyList;
00175 #else
00176 typedef std::vector<Physics::Geom *> GeomList;
00177 typedef std::vector<Physics::Space *> SpaceList;
00178 typedef std::vector<Physics::Joint *> JointList;
00179 typedef std::vector<Physics::Body *> BodyList;
00180 #endif
00181
00182 UINT getNumGeoms() const { return vGeoms.size(); }
00183 UINT getNumJoints() const { return vJoints.size(); }
00184 UINT getNumSpaces() const { return vSpaces.size(); }
00185 UINT getNumAdditionalBodies() const { return vAdditionalBodies.size(); }
00186
00187 Physics::Geom * getGeom(UINT index) { return vGeoms[index]; }
00188 Physics::Joint * getJoint(UINT index) { return vJoints[index]; }
00189 Physics::Space * getSpace(UINT index) { return vSpaces[index]; }
00190 Physics::Body * getAdditionalBody(UINT index) { return vAdditionalBodies[index]; }
00191 const Physics::Geom * getGeom(UINT index) const { return vGeoms[index]; }
00192 const Physics::Joint * getJoint(UINT index) const { return vJoints[index]; }
00193 const Physics::Space * getSpace(UINT index) const { return vSpaces[index]; }
00194 const Physics::Body * getAdditionalBody(UINT index) const { return vAdditionalBodies[index]; }
00195
00196 GeomList getGeoms() { return vGeoms; }
00197 JointList getJoints() { return vJoints; }
00198 SpaceList getSpaces() { return vSpaces; }
00199 BodyList getAdditionalBodies() { return vAdditionalBodies; }
00200 const GeomList getGeoms() const { return vGeoms; }
00201 const JointList getJoints() const { return vJoints; }
00202 const SpaceList getSpaces() const { return vSpaces; }
00203 const BodyList getAdditionalBodies() const { return vAdditionalBodies; }
00204
00206 void addGeom(Physics::Geom * pGeom);
00207 void addSpace(Physics::Space * pSpace);
00209 void addBody(Physics::Body * pBody);
00210
00213 void bind(UINT numGeom);
00216 void bind();
00219 void set3DtoPhy(UINT numGeom);
00222 void set3DtoPhy();
00223
00225 void addJoint(Physics::Joint * pJoint) { ASSERT(pJoint); vJoints.push_back(pJoint); }
00226
00227
00229
00231 virtual void step(dReal stepSize) { if(ttl<0) return; ttl -= stepSize; if (ttl<0) { ttl=0; onTTLZero(); } }
00232
00235
00237 virtual bool hitBefore(Physics::Contact * pContacts, unsigned int nbContacts, Physics::Contact * pMaxEnergyContact, Physics::Geom & thisGeom, Physics::Geom & otherGeom, Physics::Body *& inout_pThisBody, Physics::Body *& inout_pOtherBody) { return true; }
00238
00240 virtual void hitAfter(Physics::Contact * pContacts, unsigned int nbContacts, Physics::Contact * pMaxEnergyContact, Physics::Geom & thisGeom, Physics::Geom & otherGeom, bool contactJointCreated);
00241
00245 void isHitBy(WeaponEnergy::EEneryType type, double energy, const osg::Vec3 & point) {
00246 switch (type) {
00247 case WeaponEnergy::RADIANT:
00248 isHitByRadiant(energy, point); return;
00249 case WeaponEnergy::PERFORANT:
00250 isHitByPerforant(energy, point); return;
00251 case WeaponEnergy::THERMAL:
00252 isHitByThermal(energy, point); return;
00253 case WeaponEnergy::CHEMICAL:
00254 isHitByChemical(energy, point); return;
00255 case WeaponEnergy::CINETIC:
00256 isHitByCinetic(energy, point); return;
00257 default:
00258 THROW_TRACED_EXCEPTION("Unknown energy type given as argument");
00259 }
00260 }
00261
00265 virtual void isHitByRadiant(double energy, const osg::Vec3 & point) {}
00266 virtual void isHitByPerforant(double energy, const osg::Vec3 & point) {}
00267 virtual void isHitByThermal(double energy, const osg::Vec3 & point) {}
00268 virtual void isHitByChemical(double energy, const osg::Vec3 & point) {}
00269
00271 virtual void isHitByCinetic(double energy, const osg::Vec3 & point) {}
00272
00277 void createPhysicsDebugView(bool enable);
00279
00281 C3DPhyOwner * get3DPhyOwner() { return p3DPhyOwner; }
00282 const C3DPhyOwner * get3DPhyOwner() const { return p3DPhyOwner; }
00283
00286
00288 void setTTL(double ttl) { this->ttl = ttl; }
00290 double getTTL() { return ttl; }
00292 virtual void onTTLZero();
00294
00297 void setDeleteCallback(C3DPhyCallback * pCB) { pDeleteCB = pCB; }
00298 C3DPhyCallback * getDeleteCallback() { return pDeleteCB.get(); }
00299 const C3DPhyCallback * getDeleteCallback() const { return pDeleteCB.get(); }
00301
00304
00305 PVLEPlayer * getPlayer() { return pPlayer; }
00306 const PVLEPlayer * getPlayer() const { return pPlayer; }
00307 void setPlayer(PVLEPlayer * pPlayer);
00308
00309 PVLETeam * getTeam() { return pTeam; }
00310 const PVLETeam * getTeam() const { return pTeam; }
00311 void setTeam(PVLETeam * pTeam);
00312
00313 void setTeamAndPlayer(const C3DPhy & v);
00314
00315
00316 void accept(Physics::Visitor & v);
00317
00324
00325
00327 bool hasReferenceFrameObject() const { return getReferenceFrameObjectNoThrow().second != NO_REF; }
00328
00329 void setPos(const osg::Vec3 & pos) { translate(pos - getPos()); }
00330 void translate(const osg::Vec3 & vec);
00332 osg::Vec3 getPos() const {
00333 std::pair<const void *, EReferenceType> ref = getReferenceFrameObject();
00334 if (ref.second == REF_ADDITIONAL_BODY) return dBodyGetPositionV(*static_cast<const Physics::Body *>(ref.first));
00335 else return dGeomGetPositionV(*static_cast<const Physics::Geom *>(ref.first));
00336 }
00337
00338 void setQuaternion(const osg::Quat & quat) { ASSERT(!vGeoms.empty()); rotate(quat / getQuaternion()); }
00339 void rotate(const osg::Quat & quat);
00341 osg::Quat getQuaternion() const {
00342 std::pair<const void *, EReferenceType> ref = getReferenceFrameObject();
00343 if (ref.second == REF_ADDITIONAL_BODY) return dBodyGetQuaternionV(*static_cast<const Physics::Body *>(ref.first));
00344 else return dGeomGetQuaternionV(*static_cast<const Physics::Geom *>(ref.first));
00345 }
00346
00348 typedef std::pair<osg::Vec3, osg::Quat> TReferenceFrame;
00350 TReferenceFrame getReferenceFrame() const {
00351 std::pair<const void *, EReferenceType> ref = getReferenceFrameObject();
00352 if (ref.second == REF_ADDITIONAL_BODY) return TReferenceFrame(dBodyGetPositionV(*static_cast<const Physics::Body *>(ref.first)), dBodyGetQuaternionV(*static_cast<const Physics::Body *>(ref.first)));
00353 else return TReferenceFrame(dGeomGetPositionV(*static_cast<const Physics::Geom *>(ref.first)), dGeomGetQuaternionV(*static_cast<const Physics::Geom *>(ref.first)));
00354 }
00355
00357 void setMatrix(const osg::Matrix & matrix) { setPos(matrix.getTrans()); setQuaternion(matrix.getRotate()); }
00359 osg::Matrix getMatrix() const { TReferenceFrame ref = getReferenceFrame(); return osg::Matrix::rotate(ref.second) * osg::Matrix::translate(ref.first); }
00361
00362 #ifdef PVLE_NETWORKING
00365
00368 enum EMaskBits {
00369 INITIAL_MASK = 0x01,
00370 MOVED = 0x02
00371 };
00372
00373 virtual TNL::U32 packUpdate(TNL::GhostConnection * pConnection, TNL::U32 mask, TNL::BitStream * pStream);
00374 virtual void unpackUpdate(TNL::GhostConnection * pConnection, TNL::BitStream * pStream);
00375 virtual void performScopeQuery(TNL::GhostConnection * pConnection);
00376
00377 virtual void onGhostRemove();
00378
00379 #endif
00380
00384 void markAsRemoved();
00385
00386 protected:
00387 #ifdef PVLE_3DPHY_USES_REF_PTR
00388 osg::ref_ptr<osg::MatrixTransform> pModel;
00389 #else
00390 osg::MatrixTransform * pModel;
00391 #endif
00392
00393 #ifndef REMOVE_DEV_FEATURES
00394 # ifdef PVLE_3DPHY_USES_REF_PTR
00395 osg::ref_ptr<osg::MatrixTransform> pModel_debug;
00396 # else
00397 osg::MatrixTransform * pModel_debug;
00398 # endif
00399 #endif
00400
00401 GeomList vGeoms;
00402 SpaceList vSpaces;
00403 JointList vJoints;
00404 BodyList vAdditionalBodies;
00405
00407 void markAsRemoved(Physics::Geom * pGeom);
00409 void markAsRemoved(Physics::Space * pSpace);
00411 void markAsRemoved(Physics::Joint * pJoint);
00413 void markAsRemoved(Physics::Body * pAdditionalBody);
00414
00415 friend class C3DPhyOwner;
00416 C3DPhyOwner * p3DPhyOwner;
00417 void set3DPhyOwner(C3DPhyOwner * p3DPhyOwner) { this->p3DPhyOwner = p3DPhyOwner; }
00418
00419 void clearBodyContactPos();
00420 double ttl;
00421
00422 osg::ref_ptr<C3DPhyCallback> pDeleteCB;
00423
00424 PVLEPlayer * pPlayer;
00425 PVLETeam * pTeam;
00426
00427
00428
00430 void attachBodies(const GeomList & vOriginalGeoms, const SpaceList & vOriginalSpaces, const BodyList & vOriginalAdditionnalBodies, Physics::Joint * pOriginalJoint, Physics::Joint * pCopyJoint);
00432 Physics::Geom * findGeomCopy(const GeomList & vOriginalGeoms, const SpaceList & vOriginalSpaces, const Physics::Geom * pOriginalGeom);
00434 Physics::Geom * findGeomCopyInSpace(const Physics::Space & originalSpace, const Physics::Space & copySpace, const Physics::Geom * pOriginalGeom);
00435
00437 enum EReferenceType { NO_REF, REF_GEOM, REF_GEOM_IN_SPACE, REF_ADDITIONAL_BODY };
00439 std::pair<const void *, EReferenceType> getReferenceFrameObject() const;
00441 std::pair<const void *, EReferenceType> getReferenceFrameObjectNoThrow() const;
00442
00443 #ifdef PVLE_NETWORKING
00446 void packBody(const Physics::Body * pBody, TNL::BitStream * pStream);
00447
00448
00449 void unpackBody(Physics::Body * pBody, TNL::BitStream * pStream);
00451 #endif
00452
00455 virtual ~C3DPhy() {
00456
00457 #ifdef _DEBUG // Only in debug because it can take time to cleanup the 3DPhy.
00458 if (!vJoints.empty()) THROW_TRACED_EXCEPTION("3DPhy still have joints upon destruction");
00459 if (!vAdditionalBodies.empty()) THROW_TRACED_EXCEPTION("3DPhy still have additional bodies upon destruction");
00460 #endif
00461 }
00462 };
00463
00464
00465
00466 #include <set>
00467 #include <vector>
00468 #include <boost/foreach.hpp>
00469
00476 class PVLE_EXPORT C3DPhyOwner : public osg::Referenced {
00477 public:
00478 C3DPhyOwner(osg::Group * pParentGroup, Physics::Space * pParentSpace) : pParentGroup(pParentGroup), pParentSpace(pParentSpace)
00479 #ifdef _DEBUG
00480 , lockCount(0)
00481 #endif
00482 {}
00483
00487 void addInScene(C3DPhy * p3DPhy);
00490 void addInSceneDelayed(C3DPhy * p3DPhy) { v3DPhyToAdd.push_back(p3DPhy); }
00493 void cancelDelayed3DPhys() { v3DPhyToAdd.clear(); }
00494
00498 void markAsRemoved(C3DPhy * p3DPhy);
00501 void markAsRemoved(C3DPhy * p3DPhy, Physics::Geom * pGeom);
00503 void markAsRemoved(C3DPhy * p3DPhy, Physics::Space * pSpace);
00505 void markAsRemoved(C3DPhy * p3DPhy, Physics::Joint * pJoint);
00507 void markAsRemoved(C3DPhy * p3DPhy, Physics::Body * pAdditionalBody);
00508
00510 bool exists(C3DPhy * p3DPhy) {
00511 ASSERT(p3DPhy->p3DPhyOwner == this);
00512 return v3DPhys.find(p3DPhy) != v3DPhys.end();
00513 }
00514
00516
00517
00518
00519
00520
00521
00522 osg::Group * getParentGroup() { return pParentGroup; }
00523 Physics::Space * getParentSpace() { return pParentSpace; }
00524
00526 void detatch(C3DPhy * p3DPhy);
00527
00531 void doDelayed3DPhy();
00534 void doDeletePhy();
00537 void doDeleteGfx();
00538
00542 void doNetworkClientRemove3DPhy(C3DPhy * p3DPhy);
00543
00545 virtual void step(dReal stepSize) { BOOST_FOREACH(C3DPhy * p3DPhy, v3DPhys) p3DPhy->step(stepSize); }
00546
00548 void createPhysicsDebugView(bool enable);
00549
00551 void clearBodyContactPos() { BOOST_FOREACH(C3DPhy * p3DPhy, v3DPhys) p3DPhy->clearBodyContactPos(); }
00552
00553 const std::set<C3DPhy *> & get3DPhys() const { return v3DPhys; }
00554
00557 bool isDeleting() { return bIsDeleting; }
00558
00559 protected:
00560 #ifdef _DEBUG
00561 UINT lockCount;
00562 #endif
00563 bool bIsDeleting;
00564
00565 osg::Group * pParentGroup;
00566 Physics::Space * pParentSpace;
00567
00568 typedef std::set<C3DPhy *> T3DPhySet;
00569 T3DPhySet v3DPhys;
00570 typedef std::set<osg::ref_ptr<C3DPhy> > T3DPhyToDeleteSet;
00571 T3DPhyToDeleteSet v3DPhyToDelete;
00572 typedef std::vector<osg::ref_ptr<C3DPhy> > T3DPhyToAdd;
00573 T3DPhyToAdd v3DPhyToAdd;
00574
00575 typedef std::vector<osg::MatrixTransform *> TNodesToDelete;
00576 TNodesToDelete vNodesToDelete;
00577 typedef std::vector<Physics::AbstractGeom *> TGeomsToDelete;
00578 TGeomsToDelete vGeomsToDelete;
00579 typedef std::vector<Physics::Joint *> TJointsToDelete;
00580 TJointsToDelete vJointsToDelete;
00581 typedef std::vector<Physics::Body *> TBodiesToDelete;
00582 TBodiesToDelete vBodiesToDelete;
00583
00585 void detatch_nodelete(C3DPhy * p3DPhy);
00586
00587 void addInSceneBase(C3DPhy * p3DPhy);
00588
00591 virtual ~C3DPhyOwner() {}
00592 };
00593
00594
00595 #endif // ENT_3D_PHY_H