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 #include "mapzone.h"
00036
00037 #include "common/wave_ex.h"
00038 #include "typeinst/typeinst.h"
00039 #include "geometry/geometry_3d.h"
00040 #include "perf/perf.h"
00041 #include "util/token_stream.h"
00042
00043
00044 namespace mapzone {
00045
00046
00047
00049
00050
00051
00053
00054 class ZoneImpl : public aesop::LeafZone {
00055 public:
00056
00057 ZoneImpl(void) throw();
00058 ~ZoneImpl(void) throw() { }
00059
00060
00061 void initialize(IN std::istream& stream,
00062 IN eType type);
00063 void resolveIds(IN zone_map_t& map);
00064 void calcBoundaries(void);
00065 static ZoneImpl * getZoneImpl(IN aesop::Zone * z);
00066
00067
00068 const char * getId(void) const throw() { return m_id.c_str(); }
00069 aesop::Zone::eType getType(void) const throw() { return m_type; }
00070 void getBoundingRect(OUT rect3d_t& r) const { r = m_bounds; }
00071 bool containsPoint(IN const point3d_t& p) const throw();
00072 aesop::LeafZone * getLeafZone(IN const point3d_t& p) throw();
00073 const aesop::LeafZone * getLeafZone(IN const point3d_t& p) const throw();
00074 void * getUserPointer(void) const throw() { return m_user; }
00075 void setUserPointer(void * p) throw() { m_user = p; }
00076
00077
00078 void iterateVisibleZones(IN aesop::leafzone_iteration_fn callback,
00079 IN void * context);
00080 bool isLeafVisible(IN LeafZone * lz) throw();
00081 void iterateStaticInstances(IN aesop::instance_iteration_fn callback,
00082 IN void * context);
00083
00084 private:
00085
00086
00087
00088
00089 typedef std::set<ZoneImpl * > zone_set_t;
00090
00091
00092 void loadParentZone(IN std::istream& stream);
00093 void loadLeafZone(IN std::istream& stream);
00094 void loadVirtualLeafZone(IN std::istream& stream);
00095
00096
00097 std::string m_id;
00098 eType m_type;
00099 rect3d_t m_bounds;
00100 VecString m_zoneIds;
00101 aesop::vec_instance_t m_static;
00102 zone_set_t m_zones;
00103 void * m_user;
00104 bool m_haveBounds;
00105 };
00106
00107
00108
00109 ZoneImpl::ZoneImpl
00110 (
00111 void
00112 )
00113 throw()
00114 {
00115 m_user = NULL;
00116 }
00117
00118
00119
00121
00122
00123
00125
00126 void
00127 ZoneImpl::initialize
00128 (
00129 IN std::istream& stream,
00130 IN eType type
00131 )
00132 {
00133 perf::Timer timer("mapzone::Zone::initialize");
00134 ASSERT(stream.good(), "bad?");
00135 ASSERT(!m_zones.size(), "Already have zones?");
00136 ASSERT(!m_zoneIds.size(), "Already have zone IDs?");
00137
00138 m_haveBounds = false;
00139
00140
00141 ASSERT(eType_Leaf == type || eType_Parent == type
00142 || eType_VirtualLeaf == type,
00143 "Bad zone type: %d", type);
00144 m_type = type;
00145
00146
00147 expectToken(stream, "{");
00148
00149
00150 expectToken(stream, "id");
00151 getNextToken(stream, m_id);
00152
00153
00154
00155 if (eType_Leaf == this->getType()) {
00156 this->loadLeafZone(stream);
00157 } else if (eType_Parent == this->getType()) {
00158 this->loadParentZone(stream);
00159 } else if (eType_VirtualLeaf == this->getType()) {
00160 this->loadVirtualLeafZone(stream);
00161 } else {
00162 ASSERT(false, "should never get here (invalid zone type)");
00163 }
00164
00165
00166
00167 }
00168
00169
00170
00171 void
00172 ZoneImpl::resolveIds
00173 (
00174 IN zone_map_t& map
00175 )
00176 {
00177
00178 ASSERT(!m_zones.size(), "Already have zones?");
00179 for (VecString::const_iterator i = m_zoneIds.begin();
00180 i != m_zoneIds.end(); ++i) {
00181 const char * id = i->c_str();
00182
00183 zone_map_t::iterator j = map.find(id);
00184 if (map.end() == j) {
00185 const char * selfId = this->getId();
00186 WAVE_EX(wex);
00187 wex << "Zone id not found: '" << id << "'. Used by ";
00188 wex << "zone '" << selfId << "'";
00189 }
00190
00191 Zone * z = j->second;
00192 ASSERT(z, "null zone in map?");
00193
00194 ZoneImpl * zi = ZoneImpl::getZoneImpl(z);
00195 ASSERT(zi, "null");
00196
00197
00198 m_zones.insert(zi);
00199 }
00200
00201
00202 m_zoneIds.clear();
00203 }
00204
00205
00206
00207 void
00208 ZoneImpl::calcBoundaries
00209 (
00210 void
00211 )
00212 {
00213 if (m_haveBounds)
00214 return;
00215
00216 ASSERT(eType_Parent == this->getType(),
00217 "Only parent zones should need to calculate boundaries");
00218
00219
00220 bool first = true;
00221 for (zone_set_t::iterator i = m_zones.begin(); i != m_zones.end();
00222 ++i) {
00223 ZoneImpl * zi = *i;
00224 ASSERT(zi, "null zone in m_zones");
00225
00226
00227 if (eType_VirtualLeaf == zi->getType()) {
00228 continue;
00229 }
00230
00231 zi->calcBoundaries();
00232
00233 if (first) {
00234
00235 zi->getBoundingRect(m_bounds);
00236 first = false;
00237 } else {
00238
00239 rect3d_t r;
00240 zi->getBoundingRect(r);
00241 m_bounds.expand(r);
00242 }
00243 }
00244
00245
00246 ASSERT_THROW(!first, "Parent zone '" << this->getId() <<
00247 "' has no non-virtual children?");
00248
00249
00250 m_haveBounds = true;
00251 }
00252
00253
00254
00255 ZoneImpl *
00256 ZoneImpl::getZoneImpl
00257 (
00258 IN aesop::Zone * z
00259 )
00260 {
00261 ASSERT(z, "null");
00262
00263 ZoneImpl * zi = dynamic_cast<ZoneImpl *>(z);
00264 if (!zi) {
00265 WAVE_EX(wex);
00266 wex << "Zone object is not implemented by mapzone library";
00267 }
00268 return zi;
00269 }
00270
00271
00272
00274
00275
00276
00278
00279 bool
00280 ZoneImpl::containsPoint
00281 (
00282 IN const point3d_t& p
00283 )
00284 const
00285 throw()
00286 {
00287 return m_bounds.containsPoint(p);
00288 }
00289
00290
00291
00292 aesop::LeafZone *
00293 ZoneImpl::getLeafZone
00294 (
00295 IN const point3d_t& p
00296 )
00297 throw()
00298 {
00299 const Zone * cz = (const Zone *) this;
00300 const LeafZone * clz = cz->getLeafZone(p);
00301 return (LeafZone *)(clz);
00302 }
00303
00304
00305
00306 const aesop::LeafZone *
00307 ZoneImpl::getLeafZone
00308 (
00309 IN const point3d_t& p
00310 )
00311 const
00312 throw()
00313 {
00314 if (eType_VirtualLeaf == this->getType()) {
00315 return NULL;
00316 } else if (eType_Leaf == this->getType()) {
00317 if (this->containsPoint(p)) {
00318 return this;
00319 }
00320 } else {
00321
00322
00323 for (zone_set_t::const_iterator i = m_zones.begin();
00324 i != m_zones.end(); ++i) {
00325 const ZoneImpl * zi = *i;
00326 ASSERT(zi, "empty in child array");
00327
00328 const LeafZone * lz = zi->getLeafZone(p);
00329 if (lz) {
00330 return lz;
00331 }
00332 }
00333 }
00334
00335
00336 return NULL;
00337 }
00338
00339
00340
00342
00343
00344
00346
00347 void
00348 ZoneImpl::iterateVisibleZones
00349 (
00350 IN aesop::leafzone_iteration_fn callback,
00351 IN void * context
00352 )
00353 {
00354 ASSERT(callback, "null");
00355
00356
00357
00358 callback(this, context);
00359
00360
00361 for (zone_set_t::iterator i = m_zones.begin(); i != m_zones.end();
00362 ++i) {
00363 ZoneImpl * zi = *i;
00364 ASSERT(zi, "null zone in vector");
00365
00366
00367 callback(zi, context);
00368 }
00369 }
00370
00371
00372
00373 bool
00374 ZoneImpl::isLeafVisible
00375 (
00376 IN LeafZone * lz
00377 )
00378 throw()
00379 {
00380 ASSERT(lz, "null");
00381
00382 ZoneImpl * zi = dynamic_cast<ZoneImpl *>(lz);
00383 ASSERT(zi, "can't downcast from leaf zone?");
00384
00385
00386 if (zi == this)
00387 return true;
00388
00389
00390 return (m_zones.end() != m_zones.find(zi));
00391 }
00392
00393
00394
00395 void
00396 ZoneImpl::iterateStaticInstances
00397 (
00398 IN aesop::instance_iteration_fn callback,
00399 IN void * context
00400 )
00401 {
00402 ASSERT(callback, "null");
00403
00404
00405
00406 for (aesop::vec_instance_t::iterator i = m_static.begin();
00407 i != m_static.end(); ++i) {
00408
00409
00410 callback(*i, context);
00411 }
00412 }
00413
00414
00415
00417
00418
00419
00421
00422 void
00423 ZoneImpl::loadParentZone
00424 (
00425 IN std::istream& stream
00426 )
00427 {
00428 ASSERT(stream.good(), "bad?");
00429
00430
00431 std::string token;
00432 while (true) {
00433 getNextToken(stream, token);
00434
00435 if ("}" == token) {
00436 break;
00437 }
00438
00439 if ("child" != token) {
00440 WAVE_EX(wex);
00441 wex << "parent zone should contain only 'child' ";
00442 wex << "entries. Found this instead: " << token;
00443 }
00444
00445 getNextToken(stream, token);
00446 DPRINTF(" Parent zone '%s' has child zone '%s'",
00447 m_id.c_str(), token.c_str());
00448
00449
00450 m_zoneIds.push_back(token);
00451 }
00452 }
00453
00454
00455
00456 void
00457 ZoneImpl::loadLeafZone
00458 (
00459 IN std::istream& stream
00460 )
00461 {
00462 ASSERT(stream.good(), "bad?");
00463
00464
00465 expectToken(stream, "boundary");
00466 parseRect3d(stream, m_bounds);
00467 m_bounds.dump("bounding rect");
00468 if (!m_bounds.isValid()) {
00469 WAVE_EX(wex);
00470 wex << "Leaf zone '" << m_id << "' has invalid bounding rect.";
00471 }
00472 m_haveBounds = true;
00473
00474
00475 expectToken(stream, "visible");
00476 expectToken(stream, "{");
00477 while (true) {
00478 std::string token;
00479 getNextToken(stream, token);
00480
00481 if ("}" == token) {
00482 break;
00483 }
00484 if ("zone" != token) {
00485 WAVE_EX(wex);
00486 wex << "visible list should contain only 'zone' ";
00487 wex << "entries. Found this instead:" << token;
00488 }
00489
00490 getNextToken(stream, token);
00491 DPRINTF(" Leaf zone '%s' is visible from '%s'",
00492 token.c_str(), m_id.c_str());
00493 m_zoneIds.push_back(token);
00494 }
00495
00496
00497 expectToken(stream, "staticInstances");
00498 expectToken(stream, "{");
00499 loadInstances(stream, m_static);
00500
00501
00502 expectToken(stream, "}");
00503 }
00504
00505
00506
00507 void
00508 ZoneImpl::loadVirtualLeafZone
00509 (
00510 IN std::istream& stream
00511 )
00512 {
00513 ASSERT(stream.good(), "bad?");
00514
00515
00516 expectToken(stream, "boundary");
00517 parseRect3d(stream, m_bounds);
00518 m_bounds.dump("bounding rect");
00519 if (!m_bounds.isValid()) {
00520 WAVE_EX(wex);
00521 wex << "Virtual leaf zone '" << m_id << "' has invalid bounding rect.";
00522 }
00523 m_haveBounds = true;
00524
00525
00526 expectToken(stream, "staticInstances");
00527 expectToken(stream, "{");
00528 loadInstances(stream, m_static);
00529
00530
00531 expectToken(stream, "}");
00532 }
00533
00534
00535
00537
00538
00539
00541
00542 smart_ptr<aesop::Zone>
00543 loadZone
00544 (
00545 IN std::istream& stream,
00546 IN aesop::Zone::eType type
00547 )
00548 {
00549 ASSERT(stream.good(), "not good?");
00550 ASSERT(aesop::Zone::eType_Invalid != type, "Bad type: %d", type);
00551 smart_ptr<ZoneImpl> local = new ZoneImpl;
00552 ASSERT(local, "out of memory");
00553
00554 local->initialize(stream, type);
00555
00556 return local;
00557 }
00558
00559
00560
00561 void
00562 resolveZoneIds
00563 (
00564 IN aesop::Zone * zone,
00565 IN zone_map_t& map
00566 )
00567 {
00568 ASSERT(zone, "null");
00569
00570 ZoneImpl * zi = ZoneImpl::getZoneImpl(zone);
00571 ASSERT(zi, "null");
00572 zi->resolveIds(map);
00573 }
00574
00575
00576
00577 void
00578 calcBoundaries
00579 (
00580 IN aesop::Zone * zone
00581 )
00582 {
00583 ASSERT(zone, "null");
00584
00585 ZoneImpl * zi = ZoneImpl::getZoneImpl(zone);
00586 ASSERT(zi, "null");
00587 zi->calcBoundaries();
00588 }
00589
00590
00591
00592 };
00593