| 1 | #include "OgreOdePrecompiledHeaders.h" | 
|---|
| 2 | #include "OgreOdeSpace.h" | 
|---|
| 3 |  | 
|---|
| 4 | #include <OgreSceneManager.h> | 
|---|
| 5 |  | 
|---|
| 6 | #include "OgreOdeBody.h" | 
|---|
| 7 | #include "OgreOdeGeometry.h" | 
|---|
| 8 | #include "OgreOdeWorld.h" | 
|---|
| 9 | #include "OgreOdeCollision.h" | 
|---|
| 10 |  | 
|---|
| 11 | using namespace OgreOde; | 
|---|
| 12 | using namespace Ogre; | 
|---|
| 13 |  | 
|---|
| 14 | //------------------------------------------------------------------------------------------------ | 
|---|
| 15 | Space::Space(World *world, const Space* space) : | 
|---|
| 16 |     _internal_collisions (true), | 
|---|
| 17 |     _world(world) | 
|---|
| 18 | { | 
|---|
| 19 | } | 
|---|
| 20 | //------------------------------------------------------------------------------------------------ | 
|---|
| 21 | #if ODE_VERSION_MINOR > 9 | 
|---|
| 22 | Space::Class Space::getClass() | 
|---|
| 23 | { | 
|---|
| 24 |         return (Space::Class)(dSpaceGetClass(_space)); | 
|---|
| 25 | } | 
|---|
| 26 | #endif | 
|---|
| 27 | //------------------------------------------------------------------------------------------------ | 
|---|
| 28 | dSpaceID Space::getSpaceID() const | 
|---|
| 29 | { | 
|---|
| 30 |         return _space; | 
|---|
| 31 | } | 
|---|
| 32 | //------------------------------------------------------------------------------------------------ | 
|---|
| 33 | dSpaceID Space::getSpaceID(const Space* space) const | 
|---|
| 34 | { | 
|---|
| 35 |         if(space)  | 
|---|
| 36 |         return space->getSpaceID(); | 
|---|
| 37 |         return 0; | 
|---|
| 38 | } | 
|---|
| 39 | //------------------------------------------------------------------------------------------------ | 
|---|
| 40 | void Space::setAutoCleanup(bool on) | 
|---|
| 41 | { | 
|---|
| 42 |         dSpaceSetCleanup(_space,(on)?1:0); | 
|---|
| 43 | } | 
|---|
| 44 | //------------------------------------------------------------------------------------------------ | 
|---|
| 45 | bool Space::getAutoCleanup() | 
|---|
| 46 | { | 
|---|
| 47 |         return ((dSpaceGetCleanup(_space))?true:false);  | 
|---|
| 48 | } | 
|---|
| 49 | //------------------------------------------------------------------------------------------------ | 
|---|
| 50 | void Space::addGeometry(const Geometry& geometry) | 
|---|
| 51 | { | 
|---|
| 52 |         dSpaceAdd(_space,geometry.getGeometryID());  | 
|---|
| 53 | } | 
|---|
| 54 | //------------------------------------------------------------------------------------------------ | 
|---|
| 55 | void Space::removeGeometry(const Geometry& geometry) | 
|---|
| 56 | { | 
|---|
| 57 |         dSpaceRemove(_space,geometry.getGeometryID());  | 
|---|
| 58 | } | 
|---|
| 59 | //------------------------------------------------------------------------------------------------ | 
|---|
| 60 | bool Space::containsGeometry(const Geometry& geometry) | 
|---|
| 61 | { | 
|---|
| 62 |         return ((dSpaceQuery(_space,geometry.getGeometryID()))?true:false);  | 
|---|
| 63 | } | 
|---|
| 64 | //------------------------------------------------------------------------------------------------ | 
|---|
| 65 | int Space::getGeometryCount() | 
|---|
| 66 | { | 
|---|
| 67 |         return dSpaceGetNumGeoms(_space);  | 
|---|
| 68 | } | 
|---|
| 69 | //------------------------------------------------------------------------------------------------ | 
|---|
| 70 | Geometry* Space::getGeometry(int index) | 
|---|
| 71 | { | 
|---|
| 72 |         return (Geometry*) _world->getGeometryList().findItem((size_t)dSpaceGetGeom(_space,index));  | 
|---|
| 73 | } | 
|---|
| 74 | //------------------------------------------------------------------------------------------------ | 
|---|
| 75 | void Space::registerSpace() | 
|---|
| 76 | { | 
|---|
| 77 |         _world->getSpaceList().registerItem(this); | 
|---|
| 78 |         dGeomSetData((dGeomID)_space,(void*)this); | 
|---|
| 79 | } | 
|---|
| 80 | //------------------------------------------------------------------------------------------------ | 
|---|
| 81 | void Space::collide(void* data) | 
|---|
| 82 | { | 
|---|
| 83 |         if(_internal_collisions) | 
|---|
| 84 |         { | 
|---|
| 85 |                 dSpaceCollide(_space,data,World::collisionCallback); | 
|---|
| 86 |         } | 
|---|
| 87 | } | 
|---|
| 88 | //------------------------------------------------------------------------------------------------ | 
|---|
| 89 | void Space::collide(Space* space,void* data) | 
|---|
| 90 | { | 
|---|
| 91 |         dSpaceCollide2((dGeomID)_space,(dGeomID)(space->getSpaceID()),data,World::collisionCallback); | 
|---|
| 92 | } | 
|---|
| 93 | //------------------------------------------------------------------------------------------------ | 
|---|
| 94 | void Space::collide(Geometry* geometry,void* data) | 
|---|
| 95 | { | 
|---|
| 96 |         dSpaceCollide2((dGeomID)_space,geometry->getGeometryID(),data,World::collisionCallback); | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | //------------------------------------------------------------------------------------------------ | 
|---|
| 100 | void Space::collide(CollisionCallback* colCallback, bool useInternalCollisionFlag) | 
|---|
| 101 | { | 
|---|
| 102 |         if(useInternalCollisionFlag && !_internal_collisions) | 
|---|
| 103 |         { | 
|---|
| 104 |                 return; | 
|---|
| 105 |         } | 
|---|
| 106 |         void* data = colCallback;        | 
|---|
| 107 |         dSpaceCollide(_space, data, CollisionCallback::collisionCallback); | 
|---|
| 108 | } | 
|---|
| 109 | //------------------------------------------------------------------------------------------------ | 
|---|
| 110 | void Space::collide(CollisionCallback* colCallback, Space* space) | 
|---|
| 111 | { | 
|---|
| 112 |         void* data = colCallback;        | 
|---|
| 113 |         dSpaceCollide2((dGeomID)_space,(dGeomID)(space->getSpaceID()),data, CollisionCallback::collisionCallback); | 
|---|
| 114 | } | 
|---|
| 115 | //------------------------------------------------------------------------------------------------ | 
|---|
| 116 | void Space::collide(CollisionCallback* colCallback, Geometry* geometry, bool useInternalCollisionFlag) | 
|---|
| 117 | { | 
|---|
| 118 |         if(useInternalCollisionFlag && !_internal_collisions && geometry->getSpace() == this ) | 
|---|
| 119 |                 return; | 
|---|
| 120 |  | 
|---|
| 121 |         void* data = colCallback;        | 
|---|
| 122 |         dSpaceCollide2((dGeomID)_space, geometry->getGeometryID(), data, CollisionCallback::collisionCallback); | 
|---|
| 123 | } | 
|---|
| 124 |  | 
|---|
| 125 | //------------------------------------------------------------------------------------------------ | 
|---|
| 126 | void Space::setInternalCollisions(bool collide) | 
|---|
| 127 | { | 
|---|
| 128 |         _internal_collisions = collide; | 
|---|
| 129 | } | 
|---|
| 130 | //------------------------------------------------------------------------------------------------ | 
|---|
| 131 | bool Space::getInternalCollisions() | 
|---|
| 132 | { | 
|---|
| 133 |         return _internal_collisions; | 
|---|
| 134 | } | 
|---|
| 135 | //------------------------------------------------------------------------------------------------ | 
|---|
| 136 | const AxisAlignedBox& Space::getAxisAlignedBox() | 
|---|
| 137 | { | 
|---|
| 138 |         dReal aabb[6]; | 
|---|
| 139 |         dGeomGetAABB((dGeomID)_space,aabb); | 
|---|
| 140 |         _bounding_box.setExtents((Real)aabb[0],(Real)aabb[2],(Real)aabb[4],(Real)aabb[1],(Real)aabb[3],(Real)aabb[5]); | 
|---|
| 141 |         return _bounding_box; | 
|---|
| 142 | } | 
|---|
| 143 | //------------------------------------------------------------------------------------------------ | 
|---|
| 144 | size_t Space::getID() | 
|---|
| 145 | { | 
|---|
| 146 |         return (size_t)_space; | 
|---|
| 147 | } | 
|---|
| 148 | //------------------------------------------------------------------------------------------------ | 
|---|
| 149 | Space::~Space() | 
|---|
| 150 | { | 
|---|
| 151 |         _world->getSpaceList().unregisterItem((size_t)_space); | 
|---|
| 152 |         dSpaceDestroy(_space);  | 
|---|
| 153 | } | 
|---|
| 154 | //------------------------------------------------------------------------------------------------ | 
|---|
| 155 | SimpleSpace::SimpleSpace(World *world, const Space* space) : Space (world, space) | 
|---|
| 156 | { | 
|---|
| 157 |         _space = dSimpleSpaceCreate(getSpaceID(space));  | 
|---|
| 158 |         registerSpace(); | 
|---|
| 159 | } | 
|---|
| 160 | //------------------------------------------------------------------------------------------------ | 
|---|
| 161 | SimpleSpace::~SimpleSpace() | 
|---|
| 162 | { | 
|---|
| 163 | } | 
|---|
| 164 | //------------------------------------------------------------------------------------------------ | 
|---|
| 165 | HashTableSpace::HashTableSpace(World *world, const Space* space) : Space (world, space) | 
|---|
| 166 | { | 
|---|
| 167 |         _space = dHashSpaceCreate(getSpaceID(space));  | 
|---|
| 168 |         registerSpace(); | 
|---|
| 169 | } | 
|---|
| 170 | //------------------------------------------------------------------------------------------------ | 
|---|
| 171 | void HashTableSpace::setLevels(int min_level,int max_level) | 
|---|
| 172 | { | 
|---|
| 173 |         dHashSpaceSetLevels(_space,min_level,max_level);  | 
|---|
| 174 | } | 
|---|
| 175 | //------------------------------------------------------------------------------------------------ | 
|---|
| 176 | int HashTableSpace::getMinimumLevel() | 
|---|
| 177 | { | 
|---|
| 178 |         int min_level,max_level; | 
|---|
| 179 |         dHashSpaceGetLevels(_space,&min_level,&max_level); | 
|---|
| 180 |         return min_level; | 
|---|
| 181 | } | 
|---|
| 182 | //------------------------------------------------------------------------------------------------ | 
|---|
| 183 | int HashTableSpace::getMaximumLevel() | 
|---|
| 184 | { | 
|---|
| 185 |         int min_level,max_level; | 
|---|
| 186 |         dHashSpaceGetLevels(_space,&min_level,&max_level); | 
|---|
| 187 |         return max_level; | 
|---|
| 188 | } | 
|---|
| 189 | //------------------------------------------------------------------------------------------------ | 
|---|
| 190 | HashTableSpace::~HashTableSpace() | 
|---|
| 191 | { | 
|---|
| 192 | } | 
|---|
| 193 | //------------------------------------------------------------------------------------------------ | 
|---|
| 194 | #if ODE_VERSION_MINOR > 9 | 
|---|
| 195 | SweepAndPruneSpace::SweepAndPruneSpace(AxisOrder axisOrder, World *world, const Space* space) : Space (world, space) | 
|---|
| 196 | { | 
|---|
| 197 |         _space = dSweepAndPruneSpaceCreate(getSpaceID(space), axisOrder); | 
|---|
| 198 |         registerSpace(); | 
|---|
| 199 | } | 
|---|
| 200 | #endif | 
|---|
| 201 | //------------------------------------------------------------------------------------------------ | 
|---|
| 202 | QuadTreeSpace::QuadTreeSpace(const Ogre::Vector3& center,const Ogre::Vector3& extents,int depth,World *world, const Space* space) : Space (world, space) | 
|---|
| 203 | { | 
|---|
| 204 |         dVector3 c,e; | 
|---|
| 205 |          | 
|---|
| 206 |         c[0] = (dReal)center.x; | 
|---|
| 207 |         c[1] = (dReal)center.y; | 
|---|
| 208 |         c[2] = (dReal)center.z; | 
|---|
| 209 |  | 
|---|
| 210 |         e[0] = (dReal)extents.x; | 
|---|
| 211 |         e[1] = (dReal)extents.y; | 
|---|
| 212 |         e[2] = (dReal)extents.z; | 
|---|
| 213 |  | 
|---|
| 214 |         _space = dQuadTreeSpaceCreate(getSpaceID(space),c,e,depth);  | 
|---|
| 215 |         registerSpace(); | 
|---|
| 216 | } | 
|---|
| 217 | //------------------------------------------------------------------------------------------------ | 
|---|
| 218 | QuadTreeSpace::~QuadTreeSpace() | 
|---|
| 219 | { | 
|---|
| 220 | } | 
|---|
| 221 | //------------------------------------------------------------------------------------------------ | 
|---|
| 222 | OgreSceneManagerSpace::OgreSceneManagerSpace(const Ogre::Vector3& center, | 
|---|
| 223 |                                              const Ogre::Vector3& extents, | 
|---|
| 224 |                                              int depth, | 
|---|
| 225 |                                              Ogre::SceneManager *_scn_mgr, | 
|---|
| 226 |                                              World *world, const Space* space) :  | 
|---|
| 227 |         Space (world, space), | 
|---|
| 228 |         _scn_mgr(_scn_mgr) | 
|---|
| 229 | { | 
|---|
| 230 |     _intersection_query = _scn_mgr->createIntersectionQuery(); | 
|---|
| 231 |  | 
|---|
| 232 |     const std::set<Ogre::SceneQuery::WorldFragmentType> *supportedQueryTypes = _intersection_query->getSupportedWorldFragmentTypes(); | 
|---|
| 233 |     std::set<Ogre::SceneQuery::WorldFragmentType>::const_iterator it =  | 
|---|
| 234 |         supportedQueryTypes->find (Ogre::SceneQuery::WFT_PLANE_BOUNDED_REGION); | 
|---|
| 235 |     if (it != supportedQueryTypes->end()) | 
|---|
| 236 |     { | 
|---|
| 237 |         _intersection_query->setWorldFragmentType(Ogre::SceneQuery::WFT_PLANE_BOUNDED_REGION); | 
|---|
| 238 |         _scene_geometry = true; | 
|---|
| 239 |     } | 
|---|
| 240 |     else | 
|---|
| 241 |     { | 
|---|
| 242 |         _intersection_query->setWorldFragmentType(Ogre::SceneQuery::WFT_NONE); | 
|---|
| 243 |         _scene_geometry = false; | 
|---|
| 244 |     } | 
|---|
| 245 |  | 
|---|
| 246 |     // for now register a dummy space in ode. | 
|---|
| 247 |     // perhaps this step can be avoided.dVector3 c,e; | 
|---|
| 248 |  | 
|---|
| 249 |     dVector3 c; | 
|---|
| 250 |     c[0] = (dReal)center.x; | 
|---|
| 251 |     c[1] = (dReal)center.y; | 
|---|
| 252 |     c[2] = (dReal)center.z; | 
|---|
| 253 |  | 
|---|
| 254 |     dVector3 e; | 
|---|
| 255 |     e[0] = (dReal)extents.x; | 
|---|
| 256 |     e[1] = (dReal)extents.y; | 
|---|
| 257 |     e[2] = (dReal)extents.z; | 
|---|
| 258 |  | 
|---|
| 259 |     _space = dQuadTreeSpaceCreate(getSpaceID(space), c, e,depth);  | 
|---|
| 260 |     registerSpace(); | 
|---|
| 261 | } | 
|---|
| 262 | //------------------------------------------------------------------------------------------------ | 
|---|
| 263 | OgreSceneManagerSpace::~OgreSceneManagerSpace() | 
|---|
| 264 | { | 
|---|
| 265 |     delete _intersection_query; | 
|---|
| 266 | } | 
|---|
| 267 | //------------------------------------------------------------------------------------------------ | 
|---|
| 268 | void OgreSceneManagerSpace::collide(void* data) | 
|---|
| 269 | { | 
|---|
| 270 |     if(_internal_collisions) | 
|---|
| 271 |     { | 
|---|
| 272 |         // Collision detection | 
|---|
| 273 |         Ogre::IntersectionSceneQueryResult& results = _intersection_query->execute(); | 
|---|
| 274 |  | 
|---|
| 275 |         Body *body1, *body2; | 
|---|
| 276 |         Geometry *geom; | 
|---|
| 277 |         Ogre::UserDefinedObject *uo1, *uo2; | 
|---|
| 278 |  | 
|---|
| 279 |         // Movables to Movables | 
|---|
| 280 |         Ogre::SceneQueryMovableIntersectionList::iterator it, itend; | 
|---|
| 281 |         itend = results.movables2movables.end(); | 
|---|
| 282 |         for (it = results.movables2movables.begin(); it != itend; ++it) | 
|---|
| 283 |         { | 
|---|
| 284 |             /* debugging | 
|---|
| 285 |             MovableObject *mo1, *mo2; | 
|---|
| 286 |             mo1 = it->first; | 
|---|
| 287 |             mo2 = it->second; | 
|---|
| 288 |             */ | 
|---|
| 289 |  | 
|---|
| 290 |             // Get user defined objects (generic in OGRE) | 
|---|
| 291 |             uo1 = it->first->getUserObject(); | 
|---|
| 292 |             uo2 = it->second->getUserObject(); | 
|---|
| 293 |  | 
|---|
| 294 |             // Only perform collision if we have UserDefinedObject links | 
|---|
| 295 |             if (uo1 && uo2) | 
|---|
| 296 |             { | 
|---|
| 297 |                 bool isBody1 = false; | 
|---|
| 298 |                 if (uo1->getTypeName () == "Body") | 
|---|
| 299 |                     isBody1 = true; | 
|---|
| 300 |  | 
|---|
| 301 |                 bool isBody2 = false; | 
|---|
| 302 |                 if (uo2->getTypeName () == "Body") | 
|---|
| 303 |                     isBody2 = true; | 
|---|
| 304 |                 if (isBody1 || isBody2) | 
|---|
| 305 |                 { | 
|---|
| 306 |                     if (isBody2 && isBody1) | 
|---|
| 307 |                     { | 
|---|
| 308 |                         // Both are dynamic object | 
|---|
| 309 |                        body1 = static_cast<Body*>(uo1); | 
|---|
| 310 |                        body2 = static_cast<Body*>(uo2); | 
|---|
| 311 |  | 
|---|
| 312 |                         // Do detailed collision test | 
|---|
| 313 |                         body1->collide (data, body2); | 
|---|
| 314 |                     } | 
|---|
| 315 |                     else | 
|---|
| 316 |                     { | 
|---|
| 317 |                         // Both are dynamic object | 
|---|
| 318 |                         if (isBody1) | 
|---|
| 319 |                         { | 
|---|
| 320 |                             body1 = static_cast<Body*>     (uo1); | 
|---|
| 321 |                             geom  = static_cast<Geometry*> (uo2); | 
|---|
| 322 |                         } | 
|---|
| 323 |                         else | 
|---|
| 324 |                         { | 
|---|
| 325 |                             geom  = static_cast<Geometry*> (uo1); | 
|---|
| 326 |                             body1 = static_cast<Body*>     (uo2); | 
|---|
| 327 |                         } | 
|---|
| 328 |  | 
|---|
| 329 |                         // Do detailed collision test | 
|---|
| 330 |                         body1->collide(data, geom); | 
|---|
| 331 |                     } | 
|---|
| 332 |                 } | 
|---|
| 333 |             } | 
|---|
| 334 |         } | 
|---|
| 335 |  | 
|---|
| 336 |         // Movables to World | 
|---|
| 337 |         if (_scene_geometry) | 
|---|
| 338 |         { | 
|---|
| 339 |             Ogre::MovableObject *mo; | 
|---|
| 340 |             Ogre::SceneQuery::WorldFragment *wf; | 
|---|
| 341 |  | 
|---|
| 342 |             Ogre::SceneQueryMovableWorldFragmentIntersectionList::iterator wit, witend; | 
|---|
| 343 |             witend = results.movables2world.end(); | 
|---|
| 344 |             for (wit = results.movables2world.begin(); wit != witend; ++wit) | 
|---|
| 345 |             { | 
|---|
| 346 |                 mo = wit->first; | 
|---|
| 347 |                 wf = wit->second; | 
|---|
| 348 |  | 
|---|
| 349 |                 // Get user defined objects (generic in OGRE) | 
|---|
| 350 |                 uo1 = mo->getUserObject(); | 
|---|
| 351 |                 // Only perform collision if we have UserDefinedObject link | 
|---|
| 352 |                 // otherwise ... | 
|---|
| 353 |                 if (uo1) | 
|---|
| 354 |                 { | 
|---|
| 355 |                     // Cast to ApplicationObject | 
|---|
| 356 |                     if (uo1->getTypeName () == "Body") | 
|---|
| 357 |                     { | 
|---|
| 358 |                         body1 = static_cast<Body*>(uo1); | 
|---|
| 359 |                         body1->collidePlaneBounds(data, wf); | 
|---|
| 360 |                     } | 
|---|
| 361 | //                     else // static objects don't collide against Scene Geometry | 
|---|
| 362 | //                     { | 
|---|
| 363 | //                         geom = static_cast<Geometry*>(uo); | 
|---|
| 364 | //                         // Do detailed collision test | 
|---|
| 365 | //                     } | 
|---|
| 366 |                 } | 
|---|
| 367 |             } | 
|---|
| 368 |         } | 
|---|
| 369 |         // no need to use that one. | 
|---|
| 370 |         // dSpaceCollide(_space,data, World::collisionCallback); | 
|---|
| 371 |     } | 
|---|
| 372 | } | 
|---|