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/Physics/Space.h>
00028 #include <PVLE/Entity/3DPhy.h>
00029 #include <PVLE/Physics/Visitor.h>
00030 #include <PVLE/Util/Assert.h>
00031
00032
00033 namespace Physics {
00034
00035
00036 Space::Space(const Space & v, UINT opts, IGeomCollisionContainer * pGeomsContainer, TDuplicatedBodiesMap * pDuplicatedBodies)
00037 : typeInfo(v.typeInfo), collided(false)
00038 {
00039 if (pGeomsContainer && !(opts & COPY_CHILDREN)) LOG_WARN << "Giving a collision container for a shallow space copy doesn't make sense (the given container is useless for the copy)." << std::endl;
00040
00041 init();
00042
00043
00044 if (opts & COPY_CHILDREN && !v.vGeoms.empty()) {
00045 BOOST_FOREACH(const AbstractGeom * pAGeom, v.vGeoms)
00046 add(clone(*pAGeom, opts, pGeomsContainer, pDuplicatedBodies));
00047 }
00048 }
00049
00050 Space::~Space() {
00051
00052 }
00053
00054 void Space::accept(Visitor & v) { v.apply(*this); }
00055
00056 void Space::traverse(Visitor & v) {
00057
00058 BOOST_FOREACH(AbstractGeom * pAGeom, vGeoms) pAGeom->accept(v);
00059 }
00060
00061
00062 void Space::add(AbstractGeom * pAbstractGeom) {
00063
00064
00065
00066
00067
00068
00069 ASSERT(pAbstractGeom != this);
00070 if (pAbstractGeom->getParentSpace()) {
00071 LOG_WARN << "[Performance warn] Cannot add an abstract geom that already has a parent space to another space." << std::endl;
00072 return;
00073 }
00074 #ifdef _DEBUG
00075 ASSERT(vGeoms.insert(pAbstractGeom).second);
00076 #else
00077 vGeoms.insert(pAbstractGeom);
00078 #endif
00079 dSpaceAdd(asSpaceId(), pAbstractGeom->id);
00080
00081
00082
00083 }
00084
00085 void Space::add(C3DPhy & r3DPhy) {
00086 Physics::AbstractGeom * p;
00087 BOOST_FOREACH(p, r3DPhy.getSpaces()) add(p);
00088 BOOST_FOREACH(p, r3DPhy.getGeoms()) add(p);
00089 }
00090
00091
00092 void Space::remove(AbstractGeom * pAbstractGeom) {
00093 ASSERT(vGeoms.find(pAbstractGeom) != vGeoms.end());
00094
00095 vGeoms.erase(pAbstractGeom);
00096 }
00097
00098 void Space::removeAll() {
00099
00100 vGeoms.clear();
00101 }
00102
00103 void Space::remove(C3DPhy & r3DPhy) {
00104 Physics::AbstractGeom * p;
00105 BOOST_FOREACH(p, r3DPhy.getGeoms()) remove(p);
00106 BOOST_FOREACH(p, r3DPhy.getSpaces()) remove(p);
00107 }
00108
00109 bool Space::isInSpace(AbstractGeom * pAbstractGeom) const {
00110 TListGeoms::const_iterator it = find(vGeoms.begin(), vGeoms.end(), pAbstractGeom);
00111 return it != vGeoms.end();
00112 }
00113
00114 void Space::init() {
00115 SpaceTypeInfo::ESpaceType type = typeInfo.getType();
00116 if (type == SpaceTypeInfo::SIMPLE) initSimple();
00117 else if (type == SpaceTypeInfo::QUAD) {
00118 const SpaceTypeInfo::QuadData & data = typeInfo.getQuadData();
00119 initQuad(data.worldBox, data.center, data.level);
00120 }
00121 else if (type == SpaceTypeInfo::HASH) {
00122 const SpaceTypeInfo::HashData & data = typeInfo.getHashData();
00123 initHash(data.minLevel, data.maxLevel);
00124 }
00125 else {
00126 ASSERT(type == SpaceTypeInfo::SWEEP_AND_PRUNE);
00127 initSweepAndPrune(typeInfo.getSweepAndPruneData().axisOrder);
00128 }
00129
00130 dSpaceSetCleanup(asSpaceId(), 0);
00131 dGeomSetData(id, this);
00132 }
00133
00134 void Space::initSimple() {
00135 id = (dGeomID)dSimpleSpaceCreate(0);
00136 }
00137
00138 void Space::initHash(UINT minLevel, UINT maxLevel) {
00139 id = (dGeomID)dHashSpaceCreate(0);
00140 dHashSpaceSetLevels(asSpaceId(), minLevel, maxLevel);
00141 }
00142
00143 void Space::initQuad(osg::Vec3 worldBox, osg::Vec3 center, UINT level) {
00144 dVector3 _center; toPhyVec3(center, _center);
00145 dVector3 _box; toPhyVec3(worldBox, _box);
00146 id = (dGeomID)dQuadTreeSpaceCreate(0, _center, _box, level);
00147 }
00148
00149 void Space::initSweepAndPrune(int axesOrder) {
00150 id = (dGeomID)dSweepAndPruneSpaceCreate(0, axesOrder);
00151 }
00152
00153 }