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
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "map-dynamics.h"
00037
00038 #include "aesop-physics/aesop-physics.h"
00039 #include "datahash/datahash_util.h"
00040 #include "perf/perf.h"
00041 #include "physics-loader/physics-loader.h"
00042
00043
00044 namespace aesop {
00045
00046
00047
00048 ObjectContext::~ObjectContext(void) throw() { }
00049 MapDynamics::~MapDynamics(void) throw() { }
00050
00052
00053
00054
00056
00057
00058 struct obj_context_t {
00059 obj_context_t(void) throw() { this->clear(); }
00060 void clear(void) throw() {
00061 instance = NULL;
00062 dyn = NULL;
00063 context = NULL;
00064 }
00065
00066 smart_ptr<ObjectContext> context;
00067 smart_ptr<Instance> instance;
00068 MapDynamics * dyn;
00069 };
00070
00071
00072
00073 static obj_context_t *
00074 getContext
00075 (
00076 IN smart_ptr<PhysicsObject>& obj
00077 )
00078 {
00079 ASSERT(obj, "null");
00080 return (obj_context_t *) obj->getUserPointer();
00081 }
00082
00083
00084
00086
00087
00088
00090
00091 class Dynamic : public MapDynamics {
00092 public:
00093 ~Dynamic(void) throw();
00094
00095
00096 void initialize(IN smart_ptr<Map>& map,
00097 IN const Datahash * params);
00098
00099
00100 smart_ptr<Map> getMap(void) { return m_map; }
00101 smart_ptr<PhysicsWorld> getPhysics(void) { return m_physics; }
00102 smart_ptr<PhysicsObject> addInstance(IN smart_ptr<Instance>& instance);
00103 void removeObject(IN smart_ptr<PhysicsObject>& obj);
00104 void tickMap(IN float seconds);
00105 void iterateInstancesInZone(IN Zone * zone,
00106 IN zone_obj_iteration_fn fn,
00107 IN void * context);
00108
00109 private:
00110
00111 typedef std::vector<smart_ptr<PhysicsObject> > obj_vec_t;
00112
00113 struct zone_context_t {
00114 smart_ptr<PhysicsShape> shape;
00115 smart_ptr<PhysicsObject> ghost;
00116 obj_vec_t staticObjects;
00117 };
00118
00119 struct iter_context_t {
00120 iter_context_t(void) throw() { this->clear(); }
00121 void clear(void) throw() {
00122 fn = NULL;
00123 context = NULL;
00124 }
00125
00126
00127 zone_obj_iteration_fn fn;
00128 void * context;
00129 };
00130
00131 struct static_context_t {
00132 static_context_t(void) throw() { this->clear(); }
00133 void clear(void) throw() {
00134 pThis = NULL;
00135 zone = NULL;
00136 }
00137
00138
00139 Dynamic * pThis;
00140 Zone * zone;
00141 };
00142
00143
00144 smart_ptr<PhysicsObject> addInstanceInternal(
00145 IN smart_ptr<Instance>& instance,
00146 IN Zone * zone,
00147 IN bool isStatic);
00148 void addGhostObjectForZone(IN Zone * zone);
00149 static void addZoneInstances(IN Zone * zone,
00150 IN void * context);
00151 static void addStaticInstance(IN smart_ptr<Instance>& instance,
00152 IN void * context);
00153 static void destroyZoneContext(IN Zone * zone,
00154 IN void * context);
00155 static void objectCallback(IN smart_ptr<PhysicsObject>& obj,
00156 IN void * context);
00157
00158
00159 std::string m_timerName;
00160 smart_ptr<Map> m_map;
00161 smart_ptr<PhysicsWorld> m_physics;
00162 };
00163
00164
00165
00166 Dynamic::~Dynamic
00167 (
00168 void
00169 )
00170 throw()
00171 {
00172 if (m_map) {
00173
00174 m_map->iterateZones(destroyZoneContext, this);
00175 }
00176 }
00177
00178
00179
00181
00182
00183
00185
00186 void
00187 Dynamic::initialize
00188 (
00189 IN smart_ptr<Map>& map,
00190 IN const Datahash * params
00191 )
00192 {
00193 ASSERT(map, "null");
00194 ASSERT(params, "null");
00195
00196
00197 m_map = map;
00198
00199
00200 m_timerName = "MapDynamics::tickMap(";
00201 m_timerName += m_map->getId();
00202 m_timerName += ")";
00203
00204
00205 m_physics = PhysicsWorld::create(params);
00206 ASSERT(m_physics, "failed to create physics engine for map");
00207
00208
00209 m_map->iterateZones(addZoneInstances, this);
00210 }
00211
00212
00213
00215
00216
00217
00219
00220 smart_ptr<PhysicsObject>
00221 Dynamic::addInstance
00222 (
00223 IN smart_ptr<Instance>& instance
00224 )
00225 {
00226 ASSERT(instance, "null");
00227
00228
00229
00230 return this->addInstanceInternal(instance, NULL, false);
00231 }
00232
00233
00234
00235 void
00236 Dynamic::removeObject
00237 (
00238 IN smart_ptr<PhysicsObject>& obj
00239 )
00240 {
00241 ASSERT(obj, "null");
00242
00243 m_physics->removeObject(obj);
00244
00245 obj_context_t * oc = (obj_context_t *) obj->getUserPointer();
00246 if (oc) {
00247 obj->setUserPointer(NULL);
00248 delete oc;
00249 }
00250 }
00251
00252
00253
00254 void
00255 Dynamic::tickMap
00256 (
00257 IN float seconds
00258 )
00259 {
00260 perf::Timer timer(m_timerName.c_str());
00261 ASSERT(seconds > 0.0, "Bad seconds: %f", seconds);
00262
00263
00264
00265
00266 m_physics->tick(seconds);
00267 }
00268
00269
00270
00271 void
00272 Dynamic::iterateInstancesInZone
00273 (
00274 IN Zone * zone,
00275 IN zone_obj_iteration_fn fn,
00276 IN void * context
00277 )
00278 {
00279 ASSERT(zone, "null");
00280 ASSERT(fn, "null");
00281
00282
00283
00284 zone_context_t * zc = (zone_context_t *) zone->getUserPointer();
00285 ASSERT(zc, "null zone context");
00286
00287 for (obj_vec_t::iterator i = zc->staticObjects.begin();
00288 i != zc->staticObjects.end(); ++i) {
00289 smart_ptr<PhysicsObject>& obj = *i;
00290 ASSERT(obj, "null static object?");
00291 smart_ptr<Instance> inst = getInstanceFromPhysicsObject(obj);
00292 if (inst) {
00293
00294 fn(inst, obj, context);
00295 } else {
00296 DPRINTF("WARNING: static object with no instance?");
00297 }
00298 }
00299
00300
00301
00302 if (Zone::eType_VirtualLeaf == zone->getType()) {
00303 return;
00304 }
00305
00306
00307
00308 ASSERT(zc->shape, "null");
00309 ASSERT(zc->ghost, "null");
00310
00311
00312 m_physics->addObject(zc->ghost);
00313
00314
00315 iter_context_t ic;
00316 ic.fn = fn;
00317 ic.context = context;
00318
00319
00320
00321
00322 zc->ghost->iterateOverlappingObjects(objectCallback, &ic);
00323
00324
00325 m_physics->removeObject(zc->ghost);
00326 }
00327
00328
00329
00331
00332
00333
00335
00336 smart_ptr<PhysicsObject>
00337 Dynamic::addInstanceInternal
00338 (
00339 IN smart_ptr<Instance>& instance,
00340 IN Zone * zone,
00341 IN bool isStatic
00342 )
00343 {
00344 perf::Timer timer("MapDynamics::addInstanceInternal");
00345
00346 ASSERT(instance, "null");
00347
00348 ASSERT(zone || !isStatic, "zone is required for static objects");
00349
00350 DPRINTF("addInstanceInternal...");
00351
00352
00353
00354 physics_meta_t meta;
00355 if (!getPhysicsMetaFromInstance(instance, meta)) {
00356 DPRINTF("No physics meta?");
00357 return NULL;
00358 }
00359 ASSERT(meta.shape, "should always have a shape!");
00360
00361
00362 if (isStatic) {
00363
00364 meta.objectFlags |= PhysicsObject::eFlag_Static;
00365
00366
00367 meta.mass = 0.0;
00368 }
00369
00370
00371 smart_ptr<PhysicsObject> obj =
00372 createObject(meta, instance->getPlacement());
00373 ASSERT(obj, "null");
00374
00375
00376 smart_ptr<obj_context_t> oc = new obj_context_t;
00377 ASSERT(oc, "out of memory");
00378 oc->instance = instance;
00379 oc->dyn = this;
00380 obj->setUserPointer(oc);
00381 oc.disown();
00382
00383
00384 ASSERT(m_physics, "null");
00385 m_physics->addObject(obj);
00386
00387 DPRINTF("Successfully added object to world!");
00388 obj->dump("Just added to world");
00389
00390
00391 if (isStatic) {
00392 ASSERT(zone, "zone is required for static objects");
00393
00394 zone_context_t * zc = (zone_context_t *) zone->getUserPointer();
00395 ASSERT(zc, "null zone context");
00396
00397 zc->staticObjects.push_back(obj);
00398 }
00399
00400
00401 return obj;
00402 }
00403
00404
00405 void
00406 Dynamic::addGhostObjectForZone
00407 (
00408 IN Zone * zone
00409 )
00410 {
00411 ASSERT(zone, "null");
00412 ASSERT(m_physics, "null");
00413
00414
00415 smart_ptr<zone_context_t> szc = new zone_context_t;
00416 ASSERT(szc, "out of memory");
00417
00418 zone->setUserPointer((void *) (zone_context_t *) szc);
00419 szc.disown();
00420
00421
00422 if (Zone::eType_VirtualLeaf == zone->getType()) {
00423 return;
00424 }
00425
00426
00427 zone_context_t * zc = (zone_context_t *) zone->getUserPointer();
00428 ASSERT(zc, "just created this!");
00429
00430
00431 rect3d_t r;
00432 zone->getBoundingRect(r);
00433
00434 DPRINTF("Adding ghost object for zone '%s'", zone->getId());
00435 r.dump(" bounding box");
00436
00437
00438 point3d_t dimensions(r.x1 - r.x0, r.y1 - r.y0, r.z1 - r.z0);
00439 zc->shape = createBoxShape(dimensions);
00440 ASSERT(zc->shape, "null");
00441
00442
00443 physics_meta_t meta;
00444 meta.shape = zc->shape;
00445 meta.mass = 0;
00446 meta.objectFlags =
00447 PhysicsObject::eFlag_Ghost | PhysicsObject::eFlag_NoCollisions;
00448
00449
00450 placement_t p;
00451 p.position = point3d_t(r.x1 + r.x0, r.y1 + r.y0, r.z1 + r.z0);
00452 p.position = 0.5 * p.position;
00453
00454
00455 zc->ghost = createObject(meta, p);
00456 ASSERT(zc->ghost, "null");
00457
00458 smart_ptr<obj_context_t> oc = new obj_context_t;
00459 ASSERT(oc, "out of memory");
00460 oc->dyn = this;
00461 zc->ghost->setUserPointer(oc);
00462 oc.disown();
00463
00464
00465
00466
00467
00468
00469 }
00470
00471
00472
00473 void
00474 Dynamic::addZoneInstances
00475 (
00476 IN Zone * zone,
00477 IN void * context
00478 )
00479 {
00480 ASSERT(zone, "null");
00481 ASSERT(context, "should be this pointer");
00482 Dynamic * pThis = (Dynamic *) context;
00483
00484
00485 pThis->addGhostObjectForZone(zone);
00486
00487
00488 LeafZone * lz = dynamic_cast<LeafZone *>(zone);
00489 if (!lz) {
00490 return;
00491 }
00492
00493 static_context_t sc;
00494 sc.pThis = pThis;
00495 sc.zone = zone;
00496
00497 lz->iterateStaticInstances(addStaticInstance, &sc);
00498 }
00499
00500
00501
00502 void
00503 Dynamic::addStaticInstance
00504 (
00505 IN smart_ptr<Instance>& instance,
00506 IN void * context
00507 )
00508 {
00509 ASSERT(instance, "null");
00510 static_context_t * psc = (static_context_t *) context;
00511 ASSERT(psc, "null context");
00512 ASSERT(psc->pThis, "null");
00513 ASSERT(psc->zone, "null");
00514
00515 DPRINTF("Adding static instance!");
00516 DPRINTF(" zone: %s", psc->zone->getId());
00517 DPRINTF(" object type: %s", instance->getTypeId());
00518
00519
00520 psc->pThis->addInstanceInternal(instance, psc->zone, true);
00521 }
00522
00523
00524
00525 void
00526 Dynamic::destroyZoneContext
00527 (
00528 IN Zone * zone,
00529 IN void * context
00530 )
00531 {
00532 ASSERT(zone, "null");
00533 Dynamic * pThis = (Dynamic *) context;
00534 ASSERT(pThis, "null");
00535
00536
00537
00538
00539
00540 void * user = zone->getUserPointer();
00541 if (user) {
00542 zone->setUserPointer(NULL);
00543 zone_context_t * zc = (zone_context_t *) user;
00544
00545
00546
00547 delete zc;
00548 }
00549 }
00550
00551
00552
00553 void
00554 Dynamic::objectCallback
00555 (
00556 IN smart_ptr<PhysicsObject>& obj,
00557 IN void * context
00558 )
00559 {
00560 ASSERT(obj, "null");
00561 iter_context_t * pic = (iter_context_t *) context;
00562 ASSERT(pic, "null context");
00563
00564
00565 if (PhysicsObject::eFlag_Static & obj->getFlags()) {
00566 return;
00567 }
00568
00569
00570 obj_context_t * oc = getContext(obj);
00571 if (!oc || !oc->instance) {
00572 return;
00573 }
00574
00575
00576 placement_t& p = oc->instance->getPlacement();
00577 p.position = obj->getPosition();
00578 p.rotation = obj->getOrientation();
00579
00580
00581
00582
00583
00584 pic->fn(oc->instance, obj, pic->context);
00585 }
00586
00587
00588
00590
00591
00592
00594
00595 smart_ptr<MapDynamics>
00596 MapDynamics::create
00597 (
00598 IN smart_ptr<Map>& map,
00599 IN const Datahash * params
00600 )
00601 {
00602 ASSERT(map, "null");
00603 ASSERT(params, "null");
00604
00605 smart_ptr<Dynamic> local = new Dynamic;
00606 ASSERT(local, "out of memory");
00607
00608 local->initialize(map, params);
00609
00610 return local;
00611 }
00612
00613
00614
00615 smart_ptr<Instance>
00616 getInstanceFromPhysicsObject
00617 (
00618 IN smart_ptr<PhysicsObject>& obj
00619 )
00620 {
00621 ASSERT(obj, "null");
00622
00623 obj_context_t * oc = getContext(obj);
00624 if (!oc) {
00625 return NULL;
00626 }
00627 return oc->instance;
00628 }
00629
00630
00631
00632 MapDynamics *
00633 getMapDynamicsFromPhysicsObject
00634 (
00635 IN smart_ptr<PhysicsObject>& obj
00636 )
00637 {
00638 ASSERT(obj, "null");
00639
00640 obj_context_t * oc = getContext(obj);
00641 if (!oc)
00642 return NULL;
00643
00644 return oc->dyn;
00645 }
00646
00647
00648
00649 };
00650