00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "stdpacs.h"
00025
00026 #include "nel/misc/path.h"
00027 #include "nel/misc/line.h"
00028 #include "nel/misc/async_file_manager.h"
00029 #include "nel/misc/common.h"
00030 #include "nel/misc/variable.h"
00031
00032 #include "nel/misc/hierarchical_timer.h"
00033
00034 #include "global_retriever.h"
00035 #include "retriever_bank.h"
00036
00037 #include <set>
00038
00039
00040 #include "nel/misc/time_nl.h"
00041 NLMISC::TTicks AStarTicks;
00042 NLMISC::TTicks PathTicks;
00043 NLMISC::TTicks ChainTicks;
00044 NLMISC::TTicks SurfTicks;
00045 NLMISC::TTicks ThisAStarTicks;
00046 NLMISC::TTicks ThisPathTicks;
00047 NLMISC::TTicks ThisChainTicks;
00048 NLMISC::TTicks ThisSurfTicks;
00049
00050 uint PacsRetrieveVerbose = 0;
00051
00052 using namespace std;
00053 using namespace NLMISC;
00054
00055 const float InsureSurfaceThreshold = 0.5f;
00056
00057 H_AUTO_DECL ( NLPACS_Refresh_LR_Around )
00058 H_AUTO_DECL ( NLPACS_Retrieve_Position )
00059
00060 #define NLPACS_HAUTO_REFRESH_LR_AROUND H_AUTO_USE ( NLPACS_Refresh_LR_Around )
00061 #define NLPACS_HAUTO_RETRIEVE_POSITION H_AUTO_USE ( NLPACS_Retrieve_Position )
00062
00063
00064
00065 NLPACS::CGlobalRetriever::~CGlobalRetriever()
00066 {
00067
00068 waitEndOfAsyncLoading();
00069 }
00070
00071
00072 void NLPACS::CGlobalRetriever::init()
00073 {
00074 _BBox.setCenter(CVector::Null);
00075 _BBox.setHalfSize(CVector::Null);
00076
00077 _InstanceGrid.create(128, 160.0f);
00078 }
00079
00080 void NLPACS::CGlobalRetriever::initQuadGrid()
00081 {
00082 _InstanceGrid.clear();
00083 _InstanceGrid.create(128, 160.0f);
00084
00085 uint i;
00086 for (i=0; i<_Instances.size(); ++i)
00087 _InstanceGrid.insert(_Instances[i].getBBox().getMin(), _Instances[i].getBBox().getMax(), i);
00088 }
00089
00090 void NLPACS::CGlobalRetriever::initRetrieveTable()
00091 {
00092 uint i;
00093 uint size = 0;
00094
00095 for (i=0; i<_Instances.size(); ++i)
00096 {
00097 if (_Instances[i].getInstanceId() != -1 && _Instances[i].getRetrieverId() != -1)
00098 {
00099 const CLocalRetriever &retriever = getRetriever(_Instances[i].getRetrieverId());
00100 size = std::max((uint)retriever.getSurfaces().size(), size);
00101 }
00102 }
00103
00104 _RetrieveTable.resize(size);
00105 for (i=0; i<size; ++i)
00106 _RetrieveTable[i] = 0;
00107 }
00108
00109
00110
00111 bool NLPACS::CGlobalRetriever::selectInstances(const NLMISC::CAABBox &bbox, CCollisionSurfaceTemp &cst, UGlobalPosition::TType type) const
00112 {
00113 _InstanceGrid.select(bbox.getMin(), bbox.getMax());
00114 cst.CollisionInstances.clear();
00115
00116 bool allLoaded = true;
00117
00118 NLPACS::CQuadGrid<uint32>::CIterator it;
00119 for (it=_InstanceGrid.begin(); it!=_InstanceGrid.end(); ++it)
00120 {
00121 if ((type == UGlobalPosition::Landscape && _Instances[*it].getType() == CLocalRetriever::Interior) ||
00122 (type == UGlobalPosition::Interior && _Instances[*it].getType() == CLocalRetriever::Landscape))
00123 continue;
00124
00125 if (_Instances[*it].getBBox().intersect(bbox))
00126 {
00127 if (!_RetrieverBank->isLoaded(_Instances[*it].getRetrieverId()))
00128 allLoaded = false;
00129 cst.CollisionInstances.push_back(*it);
00130 }
00131 }
00132
00133 return allLoaded;
00134 }
00135
00136
00137
00138 void NLPACS::CGlobalRetriever::serial(NLMISC::IStream &f)
00139 {
00140
00141
00142
00143
00144 (void)f.serialVersion(0);
00145
00146 f.serialCont(_Instances);
00147 f.serial(_BBox);
00148
00149 if (f.isReading())
00150 initAll(false);
00151 }
00152
00153
00154
00155 void NLPACS::CGlobalRetriever::check() const
00156 {
00157 uint i, j, k;
00158
00159 for (i=0; i<_Instances.size(); ++i)
00160 {
00161 if (_Instances[i].getInstanceId() == -1)
00162 {
00163 nlwarning("Uninitialized instance %d", i);
00164 continue;
00165 }
00166
00167 if (_Instances[i].getInstanceId() != (sint)i)
00168 nlwarning("InstanceId for instance %d is not correctly initialized", i);
00169
00170 if (_Instances[i].getRetrieverId() == -1)
00171 {
00172 nlwarning("No retriever at instance %d", i);
00173 continue;
00174 }
00175
00176 const CRetrieverInstance &instance = _Instances[i];
00177
00178 if (instance.getRetrieverId()<0 || instance.getRetrieverId()>=(sint)_RetrieverBank->getRetrievers().size())
00179 {
00180 nlwarning("Instance %d has wrong retriever reference", i);
00181 continue;
00182 }
00183
00184 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(instance.getRetrieverId());
00185
00186 for (j=0; j<retriever.getChains().size(); ++j)
00187 {
00188 const CChain &chain = retriever.getChain(j);
00189 for (k=0; k<chain.getSubChains().size(); ++k)
00190 {
00191 if (chain.getSubChain(k) >= retriever.getOrderedChains().size())
00192 {
00193 nlwarning("retriever %d, chain %d: subchain %d reference is not valid", instance.getRetrieverId(), j, k);
00194 continue;
00195 }
00196
00197 if (retriever.getOrderedChain(chain.getSubChain(k)).getParentId() != j)
00198 {
00199 nlwarning("retriever %d, ochain %d: reference on parent is not valid", instance.getRetrieverId(), chain.getSubChain(k));
00200 continue;
00201 }
00202
00203 if (retriever.getOrderedChain(chain.getSubChain(k)).getIndexInParent() != k)
00204 {
00205 nlwarning("retriever %d, ochain %d: index on parent is not valid", instance.getRetrieverId(), chain.getSubChain(k));
00206 continue;
00207 }
00208 }
00209
00210 if (chain.getLeft()<0 || chain.getLeft()>=(sint)retriever.getSurfaces().size())
00211 {
00212 nlwarning("retriever %d, chain %d: reference on left surface is not valid", instance.getRetrieverId(), j);
00213 }
00214
00215 if (chain.getRight()>=(sint)retriever.getSurfaces().size() ||
00216 chain.getRight()<=CChain::getDummyBorderChainId() && !CChain::isBorderChainId(chain.getRight()))
00217 {
00218 nlwarning("retriever %d, chain %d: reference on right surface is not valid", instance.getRetrieverId(), j);
00219 }
00220
00221 if (CChain::isBorderChainId(chain.getRight()))
00222 {
00223 sint link = chain.getBorderChainIndex();
00224
00225 if (link<0 || link>=(sint)instance.getBorderChainLinks().size())
00226 {
00227 nlwarning("retriever %d, instance %d, chain %d: reference on right link is not valid", instance.getRetrieverId(), instance.getInstanceId(), j);
00228 }
00229 else
00230 {
00231 CRetrieverInstance::CLink lnk = instance.getBorderChainLink(link);
00232
00233 if (lnk.Instance != 0xFFFF || lnk.SurfaceId != 0xFFFF ||
00234 lnk.ChainId != 0xFFFF || lnk.BorderChainId != 0xFFFF)
00235 {
00236 if (lnk.Instance >= _Instances.size() ||
00237 _Instances[lnk.Instance].getRetrieverId()<0 ||
00238 _Instances[lnk.Instance].getRetrieverId()>(sint)_RetrieverBank->getRetrievers().size() ||
00239 lnk.SurfaceId >= getRetriever(_Instances[lnk.Instance].getRetrieverId()).getSurfaces().size() ||
00240 ((lnk.ChainId >= getRetriever(_Instances[lnk.Instance].getRetrieverId()).getChains().size() ||
00241 lnk.BorderChainId >= getRetriever(_Instances[lnk.Instance].getRetrieverId()).getBorderChains().size()) && instance.getType() != CLocalRetriever::Interior ))
00242 {
00243 nlwarning("retriever %d, instance %d, link %d: reference on instance may be not valid [Inst=%d, Surf=%d, Chain=%d, BorderChain=%d]", instance.getRetrieverId(), instance.getInstanceId(), link, lnk.Instance, lnk.SurfaceId, lnk.ChainId, lnk.BorderChainId);
00244 }
00245 }
00246 }
00247 }
00248 }
00249 }
00250 }
00251
00252
00253
00254 float NLPACS::CGlobalRetriever::distanceToBorder(const UGlobalPosition &pos) const
00255 {
00256 if (pos.InstanceId < 0 || pos.InstanceId > (sint)_Instances.size())
00257 return 0.0f;
00258
00259 return getRetriever(_Instances[pos.InstanceId].getRetrieverId()).distanceToBorder(pos.LocalPosition);
00260 }
00261
00262 void NLPACS::CGlobalRetriever::getBorders(const UGlobalPosition &pos, std::vector<std::pair<NLMISC::CLine, uint8> > &edges)
00263 {
00264 edges.clear();
00265
00266 if (pos.InstanceId < 0)
00267 return;
00268
00269 CVectorD gpos = getDoubleGlobalPosition(pos);
00270 CAABBox sbox;
00271 sbox.setCenter(gpos);
00272 sbox.setHalfSize(CVector(50.0f, 50.0f, 100.0f));
00273
00274 getBorders(sbox, edges);
00275 }
00276
00277 void NLPACS::CGlobalRetriever::getBorders(const CAABBox &sbox, std::vector<std::pair<NLMISC::CLine, uint8> > &edges)
00278 {
00279 edges.clear();
00280
00281 selectInstances(sbox, _InternalCST);
00282
00283 uint inst;
00284 for (inst=0; inst<_InternalCST.CollisionInstances.size(); ++inst)
00285 {
00286 CRetrieverInstance &instance = _Instances[_InternalCST.CollisionInstances[inst]];
00287 CLocalRetriever &retriever = const_cast<CLocalRetriever &>(getRetriever(instance.getRetrieverId()));
00288 if (!retriever.isLoaded())
00289 continue;
00290
00291 CChainQuad &chainquad = retriever.getChainQuad();
00292
00293 CAABBox box;
00294 CVector origin = instance.getOrigin();
00295 box.setCenter(sbox.getCenter()-origin);
00296 box.setHalfSize(sbox.getHalfSize());
00297 chainquad.selectEdges(box, _InternalCST);
00298
00299 uint ece;
00300
00301 CVector dz(0.0f, 0.0f, 0.5f);
00302 float zp = (float)sbox.getCenter().z;
00303 for (ece=0; ece<_InternalCST.EdgeChainEntries.size(); ++ece)
00304 {
00305 CEdgeChainEntry &entry = _InternalCST.EdgeChainEntries[ece];
00306
00307
00308 const CChain &fchain = retriever.getChain(retriever.getOrderedChain(entry.OChainId).getParentId());
00309 uint8 chainType = (fchain.getRight() >= 0 ? 1 : (fchain.isBorderChain() ? 2 : 0));
00310
00311
00312 if (chainType == 1)
00313 {
00314 uint left = fchain.getLeft();
00315 uint right = fchain.getRight();
00316
00317 const CRetrievableSurface &lsurface = retriever.getSurface(left);
00318 const CRetrievableSurface &rsurface = retriever.getSurface(right);
00319
00320 bool luw = (lsurface.getFlags() & (1 << CRetrievableSurface::IsUnderWaterBit)) != 0;
00321 bool ruw = (rsurface.getFlags() & (1 << CRetrievableSurface::IsUnderWaterBit)) != 0;
00322
00323 if (luw && !ruw || !luw && ruw)
00324 chainType = 3;
00325 }
00326
00327 if (retriever.getFullOrderedChains().size() > 0)
00328 {
00329 const COrderedChain3f &ochain = retriever.getFullOrderedChain(entry.OChainId);
00330
00331 uint edge;
00332 for (edge=entry.EdgeStart; edge<entry.EdgeEnd; ++edge)
00333 {
00334 edges.push_back(make_pair(CLine(), chainType));
00335 edges.back().first.V0 = ochain[edge] + origin;
00336 edges.back().first.V1 = ochain[edge+1] + origin;
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 }
00347 }
00348 else
00349 {
00350 const COrderedChain &ochain = retriever.getOrderedChain(entry.OChainId);
00351
00352 uint edge;
00353 for (edge=entry.EdgeStart; edge<entry.EdgeEnd; ++edge)
00354 {
00355 edges.push_back(make_pair(CLine(), chainType));
00356 edges.back().first.V0 = ochain[edge].unpack3f() + origin;
00357 edges.back().first.V0.z = zp;
00358 edges.back().first.V1 = ochain[edge+1].unpack3f() + origin;
00359 edges.back().first.V1.z = zp;
00360 }
00361 }
00362 }
00363
00364 const CExteriorMesh &em = retriever.getExteriorMesh();
00365 const CExteriorMesh::CEdge *previousEdge = NULL;
00366 for(uint k = 0; k < em.getEdges().size(); ++k)
00367 {
00368 if (previousEdge)
00369 {
00370 edges.push_back(make_pair(CLine(), previousEdge->Link < 0 ? 4 : 5));
00371 edges.back().first.V0 = previousEdge->Start + origin;
00372 edges.back().first.V1 = em.getEdges()[k].Start + origin;
00373 }
00374 previousEdge = em.getEdges()[k].Link != -2 ? &em.getEdges()[k] : NULL;
00375 }
00376 }
00377 }
00378
00379
00380
00381
00382 void NLPACS::CGlobalRetriever::makeLinks(uint n)
00383 {
00384 CRetrieverInstance &instance = _Instances[n];
00385
00386 selectInstances(instance.getBBox(), _InternalCST);
00387
00388 uint i;
00389 for (i=0; i<_InternalCST.CollisionInstances.size(); ++i)
00390 {
00391 CRetrieverInstance &neighbor = _Instances[_InternalCST.CollisionInstances[i]];
00392
00393 if (neighbor.getInstanceId() == instance.getInstanceId())
00394 continue;
00395
00396 try
00397 {
00398 instance.link(neighbor, _RetrieverBank->getRetrievers());
00399 neighbor.link(instance, _RetrieverBank->getRetrievers());
00400 }
00401 catch (Exception &e)
00402 {
00403 nlwarning("in NLPACS::CGlobalRetriever::makeLinks()");
00404 nlwarning("caught an exception during linkage of %d and %d: %s", instance.getInstanceId(), neighbor.getInstanceId(), e.what());
00405 }
00406 }
00407
00408 if (getRetriever(instance.getRetrieverId()).getType() == CLocalRetriever::Interior)
00409 instance.linkEdgeQuad(*this);
00410 }
00411
00412 void NLPACS::CGlobalRetriever::resetAllLinks()
00413 {
00414 uint n;
00415 for (n=0; n<_Instances.size(); ++n)
00416 _Instances[n].unlink(_Instances);
00417 }
00418
00419
00420 void NLPACS::CGlobalRetriever::makeAllLinks()
00421 {
00422 resetAllLinks();
00423
00424 uint n;
00425 for (n=0; n<_Instances.size(); ++n)
00426 makeLinks(n);
00427 }
00428
00429 void NLPACS::CGlobalRetriever::initAll(bool initInstances)
00430 {
00431 if (initInstances)
00432 {
00433 uint n;
00434 for (n=0; n<_Instances.size(); ++n)
00435 if (_Instances[n].getInstanceId() != -1 && _Instances[n].getRetrieverId() != -1)
00436 _Instances[n].init(_RetrieverBank->getRetriever(_Instances[n].getRetrieverId()));
00437 }
00438
00439 initQuadGrid();
00440 initRetrieveTable();
00441 }
00442
00443
00444
00445 const NLPACS::CRetrieverInstance &NLPACS::CGlobalRetriever::makeInstance(uint32 retrieverId, uint8 orientation, const CVector &origin)
00446 {
00447 uint id;
00448 for (id=0; id<_Instances.size() && _Instances[id].getInstanceId()!=-1; ++id)
00449 ;
00450
00451 if (id == _Instances.size())
00452 _Instances.resize(id+1);
00453
00454 CRetrieverInstance &instance = _Instances[id];
00455 const CLocalRetriever &retriever = getRetriever(retrieverId);
00456
00457 if (_RetrieveTable.size() < retriever.getSurfaces().size())
00458 _RetrieveTable.resize(retriever.getSurfaces().size(), 0);
00459
00460 instance.make(id, retrieverId, retriever, orientation, origin);
00461
00462 CVector hsize = instance.getBBox().getHalfSize();
00463 hsize.z = 0.0f;
00464 if (hsize != CVector::Null)
00465 {
00466 if (_BBox.getHalfSize() == CVector::Null)
00467 {
00468 _BBox = instance.getBBox();
00469 }
00470 else
00471 {
00472 _BBox.extend(instance.getBBox().getMin());
00473 _BBox.extend(instance.getBBox().getMax());
00474 }
00475
00476 if (getRetriever(instance.getRetrieverId()).getType() == CLocalRetriever::Interior)
00477 instance.initEdgeQuad(*this);
00478
00479 _InstanceGrid.insert(instance.getBBox().getMin(), instance.getBBox().getMax(), instance.getInstanceId());
00480 }
00481
00482 return instance;
00483 }
00484
00485
00486
00487 NLPACS::UGlobalPosition NLPACS::CGlobalRetriever::retrievePosition(const CVector &estimated, float threshold) const
00488 {
00489 return retrievePosition(CVectorD(estimated), (double)threshold, UGlobalPosition::Unspecified);
00490 }
00491
00492 NLPACS::UGlobalPosition NLPACS::CGlobalRetriever::retrievePosition(const CVectorD &estimated, double threshold) const
00493 {
00494 return retrievePosition(estimated, threshold, UGlobalPosition::Unspecified);
00495 }
00496
00497 NLPACS::UGlobalPosition NLPACS::CGlobalRetriever::retrievePosition(const CVector &estimated) const
00498 {
00499 return retrievePosition(estimated, 1.0e10f, UGlobalPosition::Unspecified);
00500 }
00501
00502 NLPACS::UGlobalPosition NLPACS::CGlobalRetriever::retrievePosition(const CVectorD &estimated) const
00503 {
00504 return retrievePosition(estimated, 1.0e10, UGlobalPosition::Unspecified);
00505 }
00506
00507
00508 NLPACS::UGlobalPosition NLPACS::CGlobalRetriever::retrievePosition(const CVectorD &estimated, double , NLPACS::UGlobalPosition::TType retrieveSpec) const
00509 {
00510 NLPACS_HAUTO_RETRIEVE_POSITION
00511
00512
00513 CGlobalPosition result = CGlobalPosition(-1, CLocalRetriever::CLocalPosition(-1, estimated));
00514
00515 if (!_BBox.include(CVector((float)estimated.x, (float)estimated.y, (float)estimated.z)))
00516 {
00517 _ForbiddenInstances.clear();
00518 return result;
00519 }
00520
00521
00522
00523 CAABBox bbpos;
00524 bbpos.setCenter(estimated);
00525 bbpos.setHalfSize(CVector(0.5f, 0.5f, 0.5f));
00526 if (!selectInstances(bbpos, _InternalCST, retrieveSpec))
00527 {
00528 return result;
00529 }
00530
00531 uint i;
00532
00533 _InternalCST.SortedSurfaces.clear();
00534
00535
00536 for (i=0; i<_InternalCST.CollisionInstances.size(); ++i)
00537 {
00538 uint32 id = _InternalCST.CollisionInstances[i];
00539 const CRetrieverInstance &instance = _Instances[id];
00540 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(instance.getRetrieverId());
00541
00542 uint j;
00543 for (j=0; j<_ForbiddenInstances.size(); ++j)
00544 if (_ForbiddenInstances[j] == (sint32)id)
00545 break;
00546
00547 if (j<_ForbiddenInstances.size() || !retriever.isLoaded())
00548 continue;
00549
00550 instance.retrievePosition(estimated, retriever, _InternalCST);
00551 }
00552
00553 _ForbiddenInstances.clear();
00554
00555 if (!_InternalCST.SortedSurfaces.empty())
00556 {
00557
00558 std::sort(_InternalCST.SortedSurfaces.begin(), _InternalCST.SortedSurfaces.end(), CCollisionSurfaceTemp::CDistanceSurface());
00559
00560 uint selInstance;
00561 float bestDist = 1.0e10f;
00562 for (selInstance=0; selInstance<_InternalCST.SortedSurfaces.size(); ++selInstance)
00563 {
00564 uint32 id = _InternalCST.SortedSurfaces[selInstance].Instance;
00565 const CRetrieverInstance &instance = _Instances[id];
00566
00567 if (instance.getType() == CLocalRetriever::Interior && _InternalCST.SortedSurfaces[selInstance].Distance < bestDist+6.0f)
00568 break;
00569
00570 if (selInstance == 0)
00571 bestDist = _InternalCST.SortedSurfaces[0].Distance;
00572 }
00573
00574 if (selInstance >= _InternalCST.SortedSurfaces.size())
00575 selInstance = 0;
00576
00577 uint32 id = _InternalCST.SortedSurfaces[selInstance].Instance;
00578 const CRetrieverInstance &instance = _Instances[id];
00579 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(instance.getRetrieverId());
00580
00581
00582 result.InstanceId = id;
00583 result.LocalPosition.Surface = _InternalCST.SortedSurfaces[selInstance].Surface;
00584 result.LocalPosition.Estimation = instance.getLocalPosition(estimated);
00585
00586 CRetrieverInstance::snapVector(result.LocalPosition.Estimation);
00587
00588
00589
00590
00591 if (_InternalCST.SortedSurfaces[selInstance].FoundCloseEdge)
00592 {
00593 bool moved;
00594 uint numMove = 0;
00595 do
00596 {
00597 moved = retriever.insurePosition(result.LocalPosition);
00598 ++numMove;
00599 }
00600 while (moved && numMove < 100);
00601
00602
00603 if (numMove > 1)
00604 {
00605 nldebug("PACS: insured position inside surface (%d,%d)-(%f,%f,%f), %d moves needed", result.InstanceId, result.LocalPosition.Surface, estimated.x, estimated.y, estimated.z, numMove-1);
00606 }
00607
00608 if (moved)
00609 {
00610 nlwarning ("PACS: couldn't insure position (%.f,%.f) within the surface (surf=%d,inst=%d) after 100 retries", result.LocalPosition.Estimation.x, result.LocalPosition.Estimation.y, result.LocalPosition.Surface, result.InstanceId);
00611 }
00612 }
00613
00614
00615 instance.snap(result.LocalPosition, retriever);
00616
00617
00618 if (PacsRetrieveVerbose)
00619 nlinfo("retrievePosition(%f,%f,%f) -> %d/%d/(%f,%f,%f) - %s/%s",
00620 estimated.x, estimated.y, estimated.z,
00621 result.InstanceId, result.LocalPosition.Surface,
00622 result.LocalPosition.Estimation.x, result.LocalPosition.Estimation.y, result.LocalPosition.Estimation.z,
00623 retriever.getIdentifier().c_str(),
00624 retriever.getType() == CLocalRetriever::Interior ? "Interior" : "Landscape");
00625 }
00626 else
00627 {
00628 if (PacsRetrieveVerbose)
00629 nlwarning("PACS: unable to retrieve correct position (%f,%f,%f)", estimated.x, estimated.y, estimated.z);
00630
00631 }
00632
00633 return result;
00634 }
00635
00636
00637
00638
00639 NLPACS::UGlobalPosition NLPACS::CGlobalRetriever::retrievePosition(const CVectorD &estimated, uint h, sint &res) const
00640 {
00641
00642 CGlobalPosition result = CGlobalPosition(-1, CLocalRetriever::CLocalPosition(-1, estimated));
00643
00644 if (!_BBox.include(CVector((float)estimated.x, (float)estimated.y, (float)estimated.z)))
00645 {
00646 _ForbiddenInstances.clear();
00647 res = Failed;
00648 return result;
00649 }
00650
00651
00652
00653 CAABBox bbpos;
00654 bbpos.setCenter(estimated);
00655 bbpos.setHalfSize(CVector(0.5f, 0.5f, 0.5f));
00656 bool canGet = selectInstances(bbpos, _InternalCST);
00657
00658 if (!canGet)
00659 {
00660 res = MissingLr;
00661 return result;
00662 }
00663
00664 uint i;
00665
00666 _InternalCST.SortedSurfaces.clear();
00667
00668
00669 for (i=0; i<_InternalCST.CollisionInstances.size(); ++i)
00670 {
00671 uint32 id = _InternalCST.CollisionInstances[i];
00672 const CRetrieverInstance &instance = _Instances[id];
00673 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(instance.getRetrieverId());
00674
00675 uint j;
00676 for (j=0; j<_ForbiddenInstances.size(); ++j)
00677 if (_ForbiddenInstances[j] == (sint32)id)
00678 break;
00679
00680 if (j<_ForbiddenInstances.size() || !retriever.isLoaded())
00681 continue;
00682
00683 instance.retrievePosition(estimated, retriever, _InternalCST, false);
00684 }
00685
00686 _ForbiddenInstances.clear();
00687
00688 if (!_InternalCST.SortedSurfaces.empty())
00689 {
00690
00691 std::sort(_InternalCST.SortedSurfaces.begin(), _InternalCST.SortedSurfaces.end(), CCollisionSurfaceTemp::CDistanceSurface());
00692
00693 if (h >= _InternalCST.SortedSurfaces.size())
00694 {
00695
00696 res = Failed;
00697 return result;
00698 }
00699
00700 uint32 id = _InternalCST.SortedSurfaces[h].Instance;
00701 const CRetrieverInstance &instance = _Instances[id];
00702 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(instance.getRetrieverId());
00703
00704
00705 result.InstanceId = id;
00706 result.LocalPosition.Surface = _InternalCST.SortedSurfaces[h].Surface;
00707 result.LocalPosition.Estimation = instance.getLocalPosition(estimated);
00708
00709 CRetrieverInstance::snapVector(result.LocalPosition.Estimation);
00710
00711
00712
00713
00714 if (_InternalCST.SortedSurfaces[h].FoundCloseEdge)
00715 {
00716 bool moved;
00717 uint numMove = 0;
00718 do
00719 {
00720 moved = retriever.insurePosition(result.LocalPosition);
00721 ++numMove;
00722 }
00723 while (moved && numMove < 100);
00724
00725
00726 if (numMove > 1)
00727 {
00728 nldebug("PACS: insured position inside surface (%d,%d)-(%f,%f,%f), %d moves needed", result.InstanceId, result.LocalPosition.Surface, estimated.x, estimated.y, estimated.z, numMove-1);
00729 }
00730
00731 if (moved)
00732 {
00733 nlwarning ("PACS: couldn't insure position (%.f,%.f) within the surface (surf=%d,inst=%d) after 100 retries", result.LocalPosition.Estimation.x, result.LocalPosition.Estimation.y, result.LocalPosition.Surface, result.InstanceId);
00734 }
00735 }
00736
00737
00738 instance.snap(result.LocalPosition, retriever);
00739 }
00740 else
00741 {
00742 res = Failed;
00743
00744
00745 }
00746
00747 res = Success;
00748 return result;
00749 }
00750
00751
00752
00753
00754 sint32 NLPACS::CGlobalRetriever::getIdentifier(const string &id) const
00755 {
00756 sint32 i;
00757 for (i=0; i<(sint32)(_RetrieverBank->getRetrievers().size()); ++i)
00758 if (getRetriever(i).getIdentifier() == id)
00759 return i;
00760
00761 return -1;
00762 }
00763
00764 const string &NLPACS::CGlobalRetriever::getIdentifier(const NLPACS::UGlobalPosition &position) const
00765 {
00766 static const string nullString = string("");
00767
00768 if (position.InstanceId == -1)
00769 return nullString;
00770
00771 return getRetriever(_Instances[position.InstanceId].getRetrieverId()).getIdentifier();
00772 }
00773
00774 sint32 NLPACS::CGlobalRetriever::getLocalRetrieverId(const NLPACS::UGlobalPosition &position) const
00775 {
00776 if (position.InstanceId == -1)
00777 return -1;
00778
00779 return _Instances[position.InstanceId].getRetrieverId();
00780 }
00781
00782
00783
00784 bool NLPACS::CGlobalRetriever::buildInstance(const string &id, const NLMISC::CVectorD &position, sint32 &instanceId)
00785 {
00786
00787 sint32 retrieverId = getIdentifier(id);
00788
00789 instanceId = -1;
00790
00791
00792 if (retrieverId < 0)
00793 return false;
00794
00795 const CRetrieverInstance &instance = makeInstance(retrieverId, 0, CVector(position));
00796
00797
00798 if (&instance == NULL || instance.getInstanceId() == -1 || instance.getRetrieverId() != retrieverId)
00799 return false;
00800
00801
00802 makeLinks(instance.getInstanceId());
00803
00804 instanceId = instance.getInstanceId();
00805
00806 return true;
00807 }
00808
00809
00810
00811 void NLPACS::CGlobalRetriever::removeInstance(sint32 instanceId)
00812 {
00813 if (instanceId < 0 || instanceId >= (sint32)_Instances.size() || _Instances[instanceId].getInstanceId() < 0)
00814 {
00815 nlwarning("CGlobalRetriever::removeInstance(): Can't unlink instance %d, doesn't exist", instanceId);
00816 return;
00817 }
00818
00819
00820 CRetrieverInstance &instance = _Instances[instanceId];
00821
00822
00823 instance.unlink(_Instances);
00824
00825
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 CVector NLPACS::CGlobalRetriever::getGlobalPosition(const UGlobalPosition &global) const
00845 {
00846 if (global.InstanceId >= 0)
00847 {
00848 return _Instances[global.InstanceId].getGlobalPosition(global.LocalPosition.Estimation);
00849 }
00850 else
00851 {
00852
00853 return global.LocalPosition.Estimation;
00854 }
00855 }
00856
00857 CVectorD NLPACS::CGlobalRetriever::getDoubleGlobalPosition(const NLPACS::UGlobalPosition &global) const
00858 {
00859 if (global.InstanceId >= 0)
00860 {
00861 return _Instances[global.InstanceId].getDoubleGlobalPosition(global.LocalPosition.Estimation);
00862 }
00863 else
00864 {
00865
00866 return CVectorD(global.LocalPosition.Estimation);
00867 }
00868 }
00869
00870
00871
00872 void NLPACS::CGlobalRetriever::findAStarPath(const NLPACS::UGlobalPosition &begin,
00873 const NLPACS::UGlobalPosition &end,
00874 vector<NLPACS::CRetrieverInstance::CAStarNodeAccess> &path,
00875 uint32 forbidFlags) const
00876 {
00877 TTicks astarStart;
00878 ThisAStarTicks = 0;
00879 astarStart = CTime::getPerformanceTime();
00880
00881
00882
00883
00884 multimap<float, CRetrieverInstance::CAStarNodeAccess> open;
00885
00886 vector<CRetrieverInstance::CAStarNodeAccess> close;
00887
00888
00889 CRetrieverInstance::CAStarNodeAccess beginNode;
00890 beginNode.InstanceId = begin.InstanceId;
00891 beginNode.NodeId = (uint16)begin.LocalPosition.Surface;
00892 CRetrieverInstance::CAStarNodeInfo &beginInfo = getNode(beginNode);
00893
00894
00895 CRetrieverInstance::CAStarNodeAccess endNode;
00896 endNode.InstanceId = end.InstanceId;
00897 endNode.NodeId = (uint16)end.LocalPosition.Surface;
00898 CRetrieverInstance::CAStarNodeInfo &endInfo = getNode(endNode);
00899
00900
00901 CRetrieverInstance::CAStarNodeAccess node = beginNode;
00902 beginInfo.Parent.InstanceId = -1;
00903 beginInfo.Parent.NodeId = 0;
00904 beginInfo.Parent.ThroughChain = 0;
00905 beginInfo.Cost = 0;
00906 beginInfo.F = (endInfo.Position-beginInfo.Position).norm();
00907
00908
00909 open.insert(make_pair(beginInfo.F, node));
00910
00911
00912 CVector2f endPosition = CVector2f(getGlobalPosition(end));
00913
00914 uint i;
00915
00916 path.clear();
00917
00918 for(;;)
00919 {
00920 if (open.empty())
00921 {
00922
00923 return;
00924 }
00925
00926 multimap<float, CRetrieverInstance::CAStarNodeAccess>::iterator it;
00927
00928 it = open.begin();
00929 node = it->second;
00930 open.erase(it);
00931
00932 if (node == endNode)
00933 {
00934
00935 CRetrieverInstance::CAStarNodeAccess pathNode = node;
00936 uint numNodes = 0;
00937 while (pathNode.InstanceId != -1)
00938 {
00939 ++numNodes;
00940 CRetrieverInstance &instance = _Instances[pathNode.InstanceId];
00941 CRetrieverInstance::CAStarNodeInfo &pathInfo = instance._NodesInformation[pathNode.NodeId];
00942 pathNode = pathInfo.Parent;
00943 }
00944
00945 path.resize(numNodes);
00946 pathNode = node;
00947 while (pathNode.InstanceId != -1)
00948 {
00949 path[--numNodes] = pathNode;
00950 CRetrieverInstance &instance = _Instances[pathNode.InstanceId];
00951 CRetrieverInstance::CAStarNodeInfo &pathInfo = instance._NodesInformation[pathNode.NodeId];
00952 pathNode = pathInfo.Parent;
00953 }
00954
00955 ThisAStarTicks += (CTime::getPerformanceTime()-astarStart);
00956
00957 nlinfo("found a path");
00958 for (i=0; i<path.size(); ++i)
00959 {
00960 CRetrieverInstance &instance = _Instances[path[i].InstanceId];
00961 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(instance.getRetrieverId());
00962 nlinfo("pathNode %d = (Inst=%d, Node=%d, Through=%d)", i, path[i].InstanceId, path[i].NodeId, path[i].ThroughChain);
00963 if (path[i].ThroughChain != 0xffff)
00964 {
00965 const CChain &chain = retriever.getChain(path[i].ThroughChain);
00966 nlinfo(" chain: left=%d right=%d", chain.getLeft(), chain.getRight());
00967 if (CChain::isBorderChainId(chain.getRight()))
00968 {
00969 CRetrieverInstance::CLink lnk = instance.getBorderChainLink(CChain::convertBorderChainId(chain.getRight()));
00970 sint instanceid = lnk.Instance;
00971 sint id = lnk.SurfaceId;
00972 nlinfo(" right: instance=%d surf=%d", instanceid, id);
00973 }
00974 }
00975 }
00976 nlinfo("open.size()=%d", open.size());
00977 nlinfo("close.size()=%d", close.size());
00978
00979 return;
00980 }
00981
00982
00983 CRetrieverInstance &inst = _Instances[node.InstanceId];
00984 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(inst.getRetrieverId());
00985 const CRetrievableSurface &surf = retriever.getSurface(node.NodeId);
00986 const vector<CRetrievableSurface::CSurfaceLink> &chains = surf.getChains();
00987
00988 CRetrieverInstance *nextInstance;
00989 const CLocalRetriever *nextRetriever;
00990 const CRetrievableSurface *nextSurface;
00991
00992 nlinfo("examine node (instance=%d,surf=%d,cost=%g)", node.InstanceId, node.NodeId, inst._NodesInformation[node.NodeId].Cost);
00993
00994 for (i=0; i<chains.size(); ++i)
00995 {
00996 sint32 nextNodeId = chains[i].Surface;
00997 CRetrieverInstance::CAStarNodeAccess nextNode;
00998
00999 if (CChain::isBorderChainId(nextNodeId))
01000 {
01001
01002
01003
01004 CRetrieverInstance::CLink lnk = inst.getBorderChainLink(CChain::convertBorderChainId(nextNodeId));
01005 nextNode.InstanceId = lnk.Instance;
01006
01007 if (nextNode.InstanceId < 0)
01008 continue;
01009
01010 nextInstance = &_Instances[nextNode.InstanceId];
01011 nextRetriever = &(_RetrieverBank->getRetriever(nextInstance->getRetrieverId()));
01012
01013 sint nodeId = lnk.SurfaceId;
01014 nlassert(nodeId >= 0);
01015 nextNode.NodeId = (uint16)nodeId;
01016 }
01017 else if (nextNodeId >= 0)
01018 {
01019
01020 nextNode.InstanceId = node.InstanceId;
01021 nextNode.NodeId = (uint16) nextNodeId;
01022 nextInstance = &inst;
01023 nextRetriever = &retriever;
01024 }
01025 else
01026 {
01027
01028 continue;
01029 }
01030
01031 nextSurface = &(nextRetriever->getSurface(nextNode.NodeId));
01032
01033 if (nextSurface->getFlags() & forbidFlags)
01034 continue;
01035
01036
01037
01038 CRetrieverInstance::CAStarNodeInfo &nextInfo = nextInstance->_NodesInformation[nextNode.NodeId];
01039 float stepCost = (nextInfo.Position-inst._NodesInformation[node.NodeId].Position).norm();
01040 float nextCost = inst._NodesInformation[node.NodeId].Cost+stepCost;
01041 float nextHeuristic = (nextInfo.Position-endPosition).norm();
01042 float nextF = nextCost+nextHeuristic;
01043
01044 vector<CRetrieverInstance::CAStarNodeAccess>::iterator closeIt;
01045 for (closeIt=close.begin(); closeIt!=close.end() && *closeIt!=nextNode; ++closeIt)
01046 ;
01047
01048 if (closeIt != close.end() && nextInfo.F < nextF)
01049 continue;
01050
01051 multimap<float, CRetrieverInstance::CAStarNodeAccess>::iterator openIt;
01052 for (openIt=open.begin(); openIt!=open.end() && openIt->second!=nextNode; ++openIt)
01053 ;
01054
01055 if (openIt != open.end() && nextInfo.F < nextF)
01056 continue;
01057
01058 if (openIt != open.end())
01059 open.erase(openIt);
01060
01061 if (closeIt != close.end())
01062 close.erase(closeIt);
01063
01064 nextInfo.Parent = node;
01065 nextInfo.Parent.ThroughChain = (uint16)(chains[i].Chain);
01066 nextInfo.Cost = nextCost;
01067 nextInfo.F = nextF;
01068
01069 nlinfo(" adding node (instance=%d,surf=%d) f=%g, through=%d", nextNode.InstanceId, nextNode.NodeId, nextInfo.F, i);
01070
01071 open.insert(make_pair(nextInfo.F, nextNode));
01072 }
01073 close.push_back(node);
01074 }
01075 }
01076
01077
01078
01079 void NLPACS::CGlobalRetriever::findPath(const NLPACS::UGlobalPosition &begin,
01080 const NLPACS::UGlobalPosition &end,
01081 NLPACS::CGlobalRetriever::CGlobalPath &path,
01082 uint32 forbidFlags) const
01083 {
01084
01085 vector<CRetrieverInstance::CAStarNodeAccess> astarPath;
01086 findAStarPath(begin, end, astarPath, forbidFlags);
01087
01088 TTicks surfStart;
01089 TTicks chainStart;
01090
01091 ThisChainTicks = 0;
01092 ThisSurfTicks = 0;
01093 ThisPathTicks = 0;
01094
01095 path.clear();
01096 path.resize(astarPath.size());
01097
01098 uint i, j;
01099 for (i=0; i<astarPath.size(); ++i)
01100 {
01101 chainStart = CTime::getPerformanceTime();
01102 CLocalPath &surf = path[i];
01103 surf.InstanceId = astarPath[i].InstanceId;
01104 const CLocalRetriever &retriever = _RetrieverBank->getRetriever(_Instances[surf.InstanceId].getRetrieverId());
01105
01106
01107 if (i == 0)
01108 {
01109
01110 surf.Start.ULocalPosition::operator= (begin.LocalPosition);
01111 }
01112 else
01113 {
01114
01115
01116 CVector prev = _Instances[path[i-1].InstanceId].getGlobalPosition(path[i-1].End.Estimation);
01117 CVector current = _Instances[surf.InstanceId].getLocalPosition(prev);
01118 surf.Start.Surface = astarPath[i].NodeId;
01119 surf.Start.Estimation = current;
01120 }
01121
01122
01123 if (i == astarPath.size()-1)
01124 {
01125 surf.End.ULocalPosition::operator= (end.LocalPosition);
01126 }
01127 else
01128 {
01129
01130
01131 const CChain &chain = retriever.getChain(astarPath[i].ThroughChain);
01132 float cumulLength = 0.0f, midLength=chain.getLength()*0.5f;
01133 for (j=0; j<chain.getSubChains().size() && cumulLength<=midLength; ++j)
01134 cumulLength += retriever.getOrderedChain(chain.getSubChain(j)).getLength();
01135 --j;
01136 const COrderedChain &ochain = retriever.getOrderedChain(chain.getSubChain(j));
01137 surf.End.Surface = astarPath[i].NodeId;
01138 {
01139 if (ochain.getVertices().size() & 1)
01140 {
01141 surf.End.Estimation = ochain[ochain.getVertices().size()/2].unpack3f();
01142 }
01143 else
01144 {
01145 surf.End.Estimation = (ochain[ochain.getVertices().size()/2].unpack3f()+
01146 ochain[ochain.getVertices().size()/2-1].unpack3f())*0.5f;
01147 }
01148 }
01149 }
01150 ThisChainTicks += (CTime::getPerformanceTime()-chainStart);
01151
01152 surfStart = CTime::getPerformanceTime();
01153 retriever.findPath(surf.Start, surf.End, surf.Path, _InternalCST);
01154 ThisSurfTicks += (CTime::getPerformanceTime()-surfStart);
01155 }
01156
01157 ThisPathTicks = ThisAStarTicks+ThisChainTicks+ThisSurfTicks;
01158 PathTicks += ThisPathTicks;
01159 SurfTicks += ThisSurfTicks;
01160 AStarTicks += ThisAStarTicks;
01161 ChainTicks += ThisChainTicks;
01162 }
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 const NLPACS::CRetrievableSurface *NLPACS::CGlobalRetriever::getSurfaceById(const NLPACS::CSurfaceIdent &surfId) const
01177 {
01178 if(surfId.RetrieverInstanceId>=0 && surfId.SurfaceId>=0)
01179 {
01180 sint32 locRetId= this->getInstance(surfId.RetrieverInstanceId).getRetrieverId();
01181 const CLocalRetriever &retr = _RetrieverBank->getRetriever(locRetId);
01182 if (!retr.isLoaded() || surfId.SurfaceId >= (sint)retr.getSurfaces().size())
01183 return NULL;
01184 const CRetrievableSurface &surf= retr.getSurface(surfId.SurfaceId);
01185 return &surf;
01186 }
01187 else
01188 return NULL;
01189 }
01190
01191
01192
01193
01194 void NLPACS::CGlobalRetriever::findCollisionChains(CCollisionSurfaceTemp &cst, const NLMISC::CAABBox &bboxMove, const NLMISC::CVector &origin) const
01195 {
01196
01197
01198 sint i,j;
01199
01200
01201
01202
01203
01204 cst.CollisionChains.clear();
01205 cst.resetEdgeCollideNodes();
01206
01207
01208
01209
01210
01211 CAABBox bboxMoveGlobal= bboxMove;
01212 bboxMoveGlobal.setCenter(bboxMoveGlobal.getCenter()+origin);
01213 selectInstances(bboxMoveGlobal, cst);
01214
01215
01216
01217
01218
01219 for(i=0 ; i<(sint)cst.CollisionInstances.size(); i++)
01220 {
01221
01222
01223 sint32 curInstance= cst.CollisionInstances[i];
01224 const CRetrieverInstance &retrieverInstance= getInstance(curInstance);
01225
01226
01227 sint32 localRetrieverId= retrieverInstance.getRetrieverId();
01228
01229 if(localRetrieverId<0)
01230 continue;
01231 const CLocalRetriever &localRetriever= _RetrieverBank->getRetriever(localRetrieverId);
01232
01233 if (!localRetriever.isLoaded())
01234 {
01235 nlwarning("local retriever %d in %s not loaded, findCollisionChains in this retriever aborted", localRetrieverId, _RetrieverBank->getNamePrefix().c_str());
01236 continue;
01237 }
01238
01239
01240 CVector deltaOrigin;
01241 deltaOrigin= origin - retrieverInstance.getOrigin();
01242
01243
01244 CAABBox bboxMoveLocal= bboxMove;
01245 bboxMoveLocal.setCenter(bboxMoveLocal.getCenter()+deltaOrigin);
01246
01247
01248
01249 sint firstCollisionChain= cst.CollisionChains.size();
01250 CVector2f transBase(-deltaOrigin.x, -deltaOrigin.y);
01251
01252
01253
01254
01255 localRetriever.testCollision(cst, bboxMoveLocal, transBase);
01256
01257 if (retrieverInstance.getType() == CLocalRetriever::Interior)
01258 retrieverInstance.testExteriorCollision(cst, bboxMoveLocal, transBase, localRetriever);
01259
01260
01261 sint nCollisionChain= cst.CollisionChains.size();
01262
01263
01264
01265
01266
01267
01268 for(j=firstCollisionChain; j<nCollisionChain; j++)
01269 {
01270 CCollisionChain &cc= cst.CollisionChains[j];
01271
01272
01273 if (cc.ExteriorEdge)
01274 continue;
01275
01276
01277 cc.LeftSurface.RetrieverInstanceId= curInstance;
01278
01279
01280 const CChain &originalChain= localRetriever.getChain(cc.ChainId);
01281 if( !originalChain.isBorderChainId(cc.RightSurface.SurfaceId) )
01282 {
01283 cc.RightSurface.RetrieverInstanceId= curInstance;
01284 }
01285 else
01286 {
01287
01288
01289 CRetrieverInstance::CLink link;
01290
01291 link = retrieverInstance.getBorderChainLink(CChain::convertBorderChainId(cc.RightSurface.SurfaceId));
01292
01293
01294 sint neighborInstanceId= (sint16)link.Instance;
01295
01296 cc.RightSurface.RetrieverInstanceId= neighborInstanceId;
01297
01298
01299 if(neighborInstanceId<0)
01300 {
01301
01302 cc.RightSurface.SurfaceId= -1;
01303 }
01304 else
01305 {
01306
01307 cc.RightSurface.SurfaceId= (sint16)link.SurfaceId;
01308 }
01309 }
01310
01311 nlassert(cc.LeftSurface.RetrieverInstanceId < (sint)_Instances.size());
01312 nlassert(cc.RightSurface.RetrieverInstanceId < (sint)_Instances.size());
01313 }
01314
01315
01316
01317
01318
01319
01320 for(j=firstCollisionChain; j<nCollisionChain; j++)
01321 {
01322 const CCollisionChain &cj = cst.CollisionChains[j];
01323
01324 if (cj.ExteriorEdge && cj.LeftSurface.RetrieverInstanceId!=-1)
01325 continue;
01326
01327
01328 for(sint k=0; k<firstCollisionChain; k++)
01329 {
01330 const CCollisionChain &ck = cst.CollisionChains[k];
01331
01332 if (cj.LeftSurface.RetrieverInstanceId != cj.RightSurface.RetrieverInstanceId &&
01333 cj.LeftSurface == ck.RightSurface && cj.RightSurface == ck.LeftSurface)
01334 {
01335 const CRetrieverInstance &instj = getInstance(cj.LeftSurface.RetrieverInstanceId),
01336 &instk = getInstance(ck.LeftSurface.RetrieverInstanceId);
01337 const CLocalRetriever &retrj = getRetriever(instj.getRetrieverId()),
01338 &retrk = getRetriever(instk.getRetrieverId());
01339
01340 if (!retrj.isLoaded() || !retrk.isLoaded())
01341 {
01342 nlwarning("using not loaded retriever %d or %d in bank '%s', aborted", instj.getRetrieverId(), instk.getRetrieverId(), _RetrieverBank->getNamePrefix().c_str());
01343 continue;
01344 }
01345
01346 nlassert(retrj.getChain(cj.ChainId).isBorderChain() && retrk.getChain(ck.ChainId).isBorderChain());
01347
01348 if (instj.getBorderChainLink(retrj.getChain(cj.ChainId).getBorderChainIndex()).ChainId != ck.ChainId ||
01349 instk.getBorderChainLink(retrk.getChain(ck.ChainId).getBorderChainIndex()).ChainId != cj.ChainId)
01350 {
01351 continue;
01352 }
01353
01354
01355
01356 if(j<nCollisionChain-1)
01357 {
01358 swap(cst.CollisionChains[j], cst.CollisionChains[nCollisionChain-1]);
01359
01360
01361 }
01362
01363
01364 nCollisionChain--;
01365 cst.CollisionChains.resize(nCollisionChain);
01366
01367
01368 j--;
01369 break;
01370 }
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 }
01394
01395 }
01396
01397 }
01398
01399 }
01400
01401
01402
01403 void NLPACS::CGlobalRetriever::testCollisionWithCollisionChains(CCollisionSurfaceTemp &cst, const CVector2f &startCol, const CVector2f &deltaCol,
01404 CSurfaceIdent startSurface, float radius, const CVector2f bboxStart[4], TCollisionType colType) const
01405 {
01406
01407
01408
01409 CSurfaceIdent currentSurface= startSurface;
01410 uint nextCollisionSurfaceTested=0;
01411 sint i;
01412
01413
01414 cst.CollisionDescs.clear();
01415
01416 for(i=0; i<(sint)cst.CollisionChains.size(); i++)
01417 {
01418 CCollisionChain &colChain= cst.CollisionChains[i];
01419 colChain.Tested= false;
01420 }
01421
01422 vector<pair<sint32, bool> > checkedExtEdges;
01423
01424
01425
01426
01427
01428
01429 for(;;)
01430 {
01431
01432
01433 for(i=0; i<(sint)cst.CollisionChains.size(); i++)
01434 {
01435 CCollisionChain &colChain= cst.CollisionChains[i];
01436
01438 nlassert(colChain.LeftSurface.RetrieverInstanceId < (sint)_Instances.size());
01439 nlassert(colChain.RightSurface.RetrieverInstanceId < (sint)_Instances.size());
01440
01441
01442 if(colChain.hasSurface(currentSurface) && !colChain.Tested)
01443 {
01444
01445 colChain.Tested= true;
01446
01447
01448 if (colChain.ExteriorEdge && colChain.LeftSurface.RetrieverInstanceId != -1)
01449 {
01450 bool enterInterior = (currentSurface.RetrieverInstanceId == colChain.RightSurface.RetrieverInstanceId);
01451
01452 uint j;
01453 sint32 cmp = (colChain.LeftSurface.RetrieverInstanceId<<16) + colChain.ChainId;
01454 for (j=0; j<checkedExtEdges.size() && (checkedExtEdges[j].first != cmp); ++j)
01455 ;
01456
01457
01458 if (j < checkedExtEdges.size())
01459 {
01460 if (checkedExtEdges[j].second != enterInterior)
01461 continue;
01462 }
01463 else
01464 checkedExtEdges.push_back(make_pair(cmp, enterInterior));
01465 }
01466
01467
01468
01469
01470 float t=0.0, tMin=1;
01471 CVector2f normal, normalMin;
01472
01473 sint32 curEdge= colChain.FirstEdgeCollide;
01474 while(curEdge!=(sint32)0xFFFFFFFF)
01475 {
01476
01477 CEdgeCollideNode &colEdge= cst.getEdgeCollideNode(curEdge);
01478
01479
01480 if(colType==CGlobalRetriever::Circle)
01481 t= colEdge.testCircleMove(startCol, deltaCol, radius, normal);
01482 else if(colType==CGlobalRetriever::BBox)
01483 t= colEdge.testBBoxMove(startCol, deltaCol, bboxStart, normal);
01484
01485
01486 if(t<tMin)
01487 {
01488 tMin= t;
01489 normalMin= normal;
01490 }
01491
01492
01493 curEdge= colEdge.Next;
01494 }
01495
01496
01497
01498
01499 if(tMin<1)
01500 {
01501 CSurfaceIdent collidedSurface= colChain.getOtherSurface(currentSurface);
01502
01503
01504 if (colChain.ExteriorEdge && currentSurface == colChain.LeftSurface)
01505 {
01506
01507 CVector2f p = startCol + deltaCol*tMin;
01508
01509 CVector ori = getInstance(startSurface.RetrieverInstanceId).getOrigin();
01510 ori.z = 0.0f;
01511
01512
01513 UGlobalPosition rp;
01514 rp.InstanceId = currentSurface.RetrieverInstanceId;
01515 rp.LocalPosition.Surface = currentSurface.SurfaceId;
01516 rp.LocalPosition.Estimation = p;
01517
01518 float estimatedZ= getMeanHeight(rp);
01519
01520
01521 CVectorD zp = CVectorD(p.x, p.y, estimatedZ) + CVectorD(ori);
01522
01523 _ForbiddenInstances.clear();
01524 _ForbiddenInstances.push_back(currentSurface.RetrieverInstanceId);
01525 UGlobalPosition gp = retrievePosition(zp);
01526
01527 collidedSurface.RetrieverInstanceId = gp.InstanceId;
01528 collidedSurface.SurfaceId = gp.LocalPosition.Surface;
01529 }
01530
01532 nlassert(collidedSurface.RetrieverInstanceId < (sint)_Instances.size());
01533
01534
01535
01536 sint indexInsert= cst.CollisionDescs.size();
01537 sint colFound= -1;
01538
01539
01540 for(sint j= nextCollisionSurfaceTested; j<(sint)cst.CollisionDescs.size(); j++)
01541 {
01542
01543 if(tMin < cst.CollisionDescs[j].ContactTime)
01544 {
01545 indexInsert= min(j, indexInsert);
01546 }
01547
01548 if(cst.CollisionDescs[j].ContactSurface==collidedSurface)
01549 {
01550 colFound= j;
01551
01552 break;
01553 }
01554 }
01555
01556
01557 if(colFound==-1 || indexInsert<=colFound)
01558 {
01559 CCollisionSurfaceDesc newCol;
01560 newCol.ContactSurface= collidedSurface;
01561 newCol.ContactTime= tMin;
01562 newCol.ContactNormal.set(normalMin.x, normalMin.y, 0);
01563
01564
01565 if(colFound==indexInsert)
01566 {
01567 cst.CollisionDescs[indexInsert]= newCol;
01568 }
01569 else
01570 {
01571
01572 if(colFound!=-1)
01573 cst.CollisionDescs.erase(cst.CollisionDescs.begin() + colFound);
01574
01575
01576 cst.CollisionDescs.insert(cst.CollisionDescs.begin() + indexInsert, newCol);
01577 }
01578 }
01579 }
01580 }
01581 }
01582
01583
01584
01585
01586 if(nextCollisionSurfaceTested>=cst.CollisionDescs.size())
01587 break;
01588
01589 else
01590 {
01591
01592
01593 currentSurface= cst.CollisionDescs[nextCollisionSurfaceTested].ContactSurface;
01594
01595
01596 bool isWall;
01597 if(currentSurface.SurfaceId<0)
01598 isWall= true;
01599 else
01600 {
01601
01602 sint32 locRetId= this->getInstance(currentSurface.RetrieverInstanceId).getRetrieverId();
01603
01604 if (!_RetrieverBank->getRetriever(locRetId).isLoaded())
01605 {
01606 nextCollisionSurfaceTested++;
01607 continue;
01608 }
01609
01610 const CLocalRetriever &retr = _RetrieverBank->getRetriever(locRetId);
01611 if (currentSurface.SurfaceId < (sint)retr.getSurfaces().size())
01612 {
01613 const CRetrievableSurface &surf= _RetrieverBank->getRetriever(locRetId).getSurface(currentSurface.SurfaceId);
01614 isWall= !(surf.isFloor() || surf.isCeiling());
01615 }
01616 else
01617 {
01618 isWall = true;
01619 }
01620 }
01621
01622
01623 if(isWall)
01624 {
01625
01626 cst.CollisionDescs.resize(nextCollisionSurfaceTested+1);
01627 break;
01628 }
01629 else
01630 {
01631
01632
01633 nextCollisionSurfaceTested++;
01634 }
01635 }
01636 }
01637
01638 }
01639
01640
01641
01642 bool NLPACS::CGlobalRetriever::verticalChain(const CCollisionChain &colChain) const
01643 {
01644
01645 const CRetrievableSurface *left= getSurfaceById(colChain.LeftSurface);
01646 const CRetrievableSurface *right= getSurfaceById(colChain.RightSurface);
01647
01648
01649 bool leftWall;
01650 if(!left)
01651 leftWall= true;
01652 else
01653 leftWall= !(left->isFloor() || left->isCeiling());
01654
01655
01656 bool rightWall;
01657 if(!right)
01658 rightWall= true;
01659 else
01660 rightWall= !(right->isFloor() || right->isCeiling());
01661
01662
01663 return leftWall && rightWall;
01664 }
01665
01666
01667
01668 NLPACS::CSurfaceIdent NLPACS::CGlobalRetriever::testMovementWithCollisionChains(CCollisionSurfaceTemp &cst, const CVector2f &startCol, const CVector2f &endCol,
01669 CSurfaceIdent startSurface, UGlobalPosition &restart) const
01670 {
01671
01672
01673
01674 CSurfaceIdent currentSurface= startSurface;
01675 sint i;
01676
01677
01678 cst.MoveDescs.clear();
01679
01680
01681 static vector<pair<sint32, bool> > checkedExtEdges;
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696 for(i=0; i<(sint)cst.CollisionChains.size(); i++)
01697 {
01698 CCollisionChain &colChain= cst.CollisionChains[i];
01699
01700 if (colChain.ExteriorEdge)
01701 {
01702 sint32 cmp = (colChain.LeftSurface.RetrieverInstanceId<<16) + colChain.ChainId;
01703
01704 uint j;
01705 for (j=0; j<checkedExtEdges.size() && (checkedExtEdges[j].first != cmp); ++j)
01706 ;
01707
01708
01709 if (j < checkedExtEdges.size())
01710 continue;
01711 }
01712
01713
01714
01715 CRational64 t;
01716
01717 sint32 curEdge= colChain.FirstEdgeCollide;
01718 while(curEdge!=(sint32)0xFFFFFFFF)
01719 {
01720
01721 CEdgeCollideNode &colEdge= cst.getEdgeCollideNode(curEdge);
01722
01723
01724 CEdgeCollide::TPointMoveProblem pmpb;
01725 t= colEdge.testPointMove(startCol, endCol, pmpb);
01726
01727 if(t== -1)
01728 {
01729 static const string errs[CEdgeCollide::PointMoveProblemCount]= {
01730 "ParallelEdges", "StartOnEdge", "StopOnEdge", "TraverseEndPoint", "EdgeNull"};
01731
01732
01733 if(pmpb==CEdgeCollide::StartOnEdge)
01734 {
01735 nlinfo("COL: Precision Problem: %s", errs[pmpb].c_str());
01736 checkedExtEdges.clear();
01737 return CSurfaceIdent(-1, -1);
01738 }
01739 else if(pmpb==CEdgeCollide::EdgeNull)
01740 {
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757 t= 1;
01758 }
01759 else
01760 return CSurfaceIdent(-2, -2);
01761 }
01762
01763
01764 if(t<1)
01765 {
01766
01767 cst.MoveDescs.push_back(CMoveSurfaceDesc(t, colChain.LeftSurface, colChain.RightSurface));
01768 cst.MoveDescs.back().ExteriorEdge = colChain.ExteriorEdge;
01769 cst.MoveDescs.back().ChainId = (uint16)colChain.ChainId;
01770 cst.MoveDescs.back().MovementSens= colEdge.Norm*(endCol-startCol)>=0;
01771 }
01772
01773
01774 curEdge= colEdge.Next;
01775 }
01776 }
01777
01778
01779
01780
01781
01782 sort(cst.MoveDescs.begin(), cst.MoveDescs.end());
01783
01784
01785
01786
01787 for(i=0;i<(sint)cst.MoveDescs.size();i++)
01788 {
01789 CMoveSurfaceDesc &msd = cst.MoveDescs[i];
01790
01791
01792 if(msd.hasSurface(currentSurface))
01793 {
01794
01795 if (msd.ExteriorEdge && msd.LeftSurface.RetrieverInstanceId != -1)
01796 {
01797 bool enterInterior = (currentSurface.RetrieverInstanceId == msd.RightSurface.RetrieverInstanceId);
01798
01799
01800
01801 if(enterInterior == msd.MovementSens)
01802 continue;
01803
01804 uint j;
01805 sint32 cmp = (msd.LeftSurface.RetrieverInstanceId<<16) + msd.ChainId;
01806 for (j=0; j<checkedExtEdges.size() && (checkedExtEdges[j].first != cmp); ++j)
01807 ;
01808
01809
01810 if (j < checkedExtEdges.size())
01811 {
01812 if (checkedExtEdges[j].second != enterInterior)
01813 continue;
01814 }
01815 else
01816 checkedExtEdges.push_back(make_pair(cmp, enterInterior));
01817
01818
01819 if (!enterInterior)
01820 {
01821
01822 float ctime = (float)((double)(msd.ContactTime.Numerator)/(double)(msd.ContactTime.Denominator));
01823 CVector2f p = startCol*(1.0f-ctime) + endCol*ctime;
01824
01825 CVector ori = getInstance(startSurface.RetrieverInstanceId).getOrigin();
01826 ori.z = 0.0f;
01827
01828
01829 UGlobalPosition rp;
01830 rp.InstanceId = currentSurface.RetrieverInstanceId;
01831 rp.LocalPosition.Surface = currentSurface.SurfaceId;
01832 rp.LocalPosition.Estimation = p;
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845 float estimatedZ = getInteriorHeightAround(rp, 0.1f);
01846
01847
01848 CVectorD zp = CVectorD(p.x, p.y, estimatedZ) + CVectorD(ori);
01849
01850 _ForbiddenInstances.clear();
01851 _ForbiddenInstances.push_back(currentSurface.RetrieverInstanceId);
01852 restart = retrievePosition(zp);
01853
01854 return CSurfaceIdent(-3, -3);
01855 }
01856 else
01857 {
01858 currentSurface= msd.getOtherSurface(currentSurface);
01859 }
01860 }
01861 else
01862 {
01863 currentSurface= msd.getOtherSurface(currentSurface);
01864 }
01865
01866
01867 bool isWall;
01868 if(currentSurface.SurfaceId<0)
01869 isWall= true;
01870 else
01871 {
01872
01873 sint32 locRetId= this->getInstance(currentSurface.RetrieverInstanceId).getRetrieverId();
01874
01875 if (!_RetrieverBank->getRetriever(locRetId).isLoaded())
01876 continue;
01877
01878 const CRetrievableSurface &surf= _RetrieverBank->getRetriever(locRetId).getSurface(currentSurface.SurfaceId);
01879 isWall= !(surf.isFloor() || surf.isCeiling());
01880 }
01881
01882
01883 if(isWall)
01884 {
01885
01886 checkedExtEdges.clear();
01887 return CSurfaceIdent(-1, -1);
01888 }
01889 }
01890 }
01891
01892 checkedExtEdges.clear();
01893 return currentSurface;
01894 }
01895
01896
01897
01898
01899 const NLPACS::TCollisionSurfaceDescVector
01900 *NLPACS::CGlobalRetriever::testCylinderMove(const UGlobalPosition &startPos, const NLMISC::CVector &delta, float radius, CCollisionSurfaceTemp &cst) const
01901 {
01902
01903
01904 CSurfaceIdent startSurface(startPos.InstanceId, startPos.LocalPosition.Surface);
01905
01906
01907
01908
01909 cst.CollisionDescs.clear();
01910
01911
01912 if (startPos.InstanceId==-1)
01913 {
01914
01915
01916
01917
01918 return NULL;
01919 }
01920
01921 cst.PrecStartSurface= startSurface;
01922 cst.PrecStartPos= startPos.LocalPosition.Estimation;
01923 cst.PrecDeltaPos= delta;
01924 cst.PrecValid= true;
01925
01926
01927
01928
01929 if (delta.isNull())
01930 return &cst.CollisionDescs;
01931
01932
01933
01934
01935 CVector origin;
01936 origin= getInstance(startPos.InstanceId).getOrigin();
01937
01938
01939
01940
01941 CAABBox bboxMove;
01942
01943
01944 CVector start= startPos.LocalPosition.Estimation;
01945 CVector end= start+delta;
01946
01947 bboxMove.setCenter(start-CVector(radius, radius, 0));
01948 bboxMove.extend(start+CVector(radius, radius, 0));
01949 bboxMove.extend(end-CVector(radius, radius, 0));
01950 bboxMove.extend(end+CVector(radius, radius, 0));
01951
01952
01953
01954
01955 findCollisionChains(cst, bboxMove, origin);
01956
01957
01958
01959
01960
01961 CVector2f startCol(start.x, start.y);
01962 CVector2f deltaCol(delta.x, delta.y);
01963 CVector2f obbDummy[4];
01964 testCollisionWithCollisionChains(cst, startCol, deltaCol, startSurface, radius, obbDummy, CGlobalRetriever::Circle);
01965
01966
01967 return &cst.CollisionDescs;
01968 }
01969
01970
01971
01972 const NLPACS::TCollisionSurfaceDescVector
01973 *NLPACS::CGlobalRetriever::testBBoxMove(const UGlobalPosition &startPos, const NLMISC::CVector &delta,
01974 const NLMISC::CVector &locI, const NLMISC::CVector &locJ, CCollisionSurfaceTemp &cst) const
01975 {
01976
01977
01978 CSurfaceIdent startSurface(startPos.InstanceId, startPos.LocalPosition.Surface);
01979
01980
01981
01982
01983 cst.CollisionDescs.clear();
01984
01985
01986 if (startPos.InstanceId==-1)
01987 {
01988
01989
01990
01991
01992 return NULL;
01993 }
01994
01995
01996 cst.PrecStartSurface= startSurface;
01997 cst.PrecStartPos= startPos.LocalPosition.Estimation;
01998 cst.PrecDeltaPos= delta;
01999 cst.PrecValid= true;
02000
02001
02002
02003
02004 if (delta.isNull())
02005 return &cst.CollisionDescs;
02006
02007
02008
02009
02010 CVector origin;
02011 origin= getInstance(startPos.InstanceId).getOrigin();
02012
02013
02014
02015
02016 CVector2f obbStart[4];
02017
02018 CVector start= startPos.LocalPosition.Estimation;
02019 CVector2f obbCenter(start.x, start.y);
02020 CVector2f locI2d(locI.x, locI.y);
02021 CVector2f locJ2d(locJ.x, locJ.y);
02022
02023
02024 obbStart[0]= obbCenter - locI2d - locJ2d;
02025 obbStart[1]= obbCenter + locI2d - locJ2d;
02026 obbStart[2]= obbCenter + locI2d + locJ2d;
02027 obbStart[3]= obbCenter - locI2d + locJ2d;
02028
02029
02030
02031 CAABBox bboxMove;
02032
02033 bboxMove.setCenter(CVector(obbStart[0].x, obbStart[0].y, 0));
02034 bboxMove.extend(CVector(obbStart[1].x, obbStart[1].y, 0));
02035 bboxMove.extend(CVector(obbStart[2].x, obbStart[2].y, 0));
02036 bboxMove.extend(CVector(obbStart[3].x, obbStart[3].y, 0));
02037 bboxMove.extend(CVector(obbStart[0].x, obbStart[0].y, 0) + delta);
02038 bboxMove.extend(CVector(obbStart[1].x, obbStart[1].y, 0) + delta);
02039 bboxMove.extend(CVector(obbStart[2].x, obbStart[2].y, 0) + delta);
02040 bboxMove.extend(CVector(obbStart[3].x, obbStart[3].y, 0) + delta);
02041
02042
02043
02044
02045
02046 findCollisionChains(cst, bboxMove, origin);
02047
02048
02049
02050
02051
02052 CVector2f startCol(start.x, start.y);
02053 CVector2f deltaCol(delta.x, delta.y);
02054 testCollisionWithCollisionChains(cst, startCol, deltaCol, startSurface, 0, obbStart, CGlobalRetriever::BBox);
02055
02056
02057 return &cst.CollisionDescs;
02058 }
02059
02060
02061
02062
02063 NLPACS::UGlobalPosition
02064 NLPACS::CGlobalRetriever::doMove(const NLPACS::UGlobalPosition &startPos, const NLMISC::CVector &delta, float t, NLPACS::CCollisionSurfaceTemp &cst, bool rebuildChains) const
02065 {
02066
02067
02068 CSurfaceIdent startSurface(startPos.InstanceId, startPos.LocalPosition.Surface);
02069
02070
02071 clamp(t, 0.0f, 1.0f);
02072
02073
02074
02075
02076 cst.CollisionDescs.clear();
02077
02078
02079 if (startPos.InstanceId==-1)
02080 {
02081
02082
02083
02084
02085 return startPos;
02086 }
02087
02088 if(!rebuildChains)
02089 {
02090
02091 if( cst.PrecStartSurface != startSurface ||
02092 cst.PrecStartPos!=startPos.LocalPosition.Estimation ||
02093 cst.PrecDeltaPos!=delta ||
02094 !cst.PrecValid)
02095 {
02096
02097
02098
02099 return startPos;
02100 }
02101
02102 }
02103 else
02104 {
02105
02106
02107 cst.PrecValid= false;
02108 }
02109
02110
02111
02112
02113
02114
02115
02116 CVector origin;
02117 origin= getInstance(startPos.InstanceId).getOrigin();
02118
02119
02120
02121
02122 CVector start= startPos.LocalPosition.Estimation;
02123
02124 CVector end= start + delta*t;
02125
02126
02127 if(rebuildChains)
02128 {
02129
02130
02131
02132 CAABBox bboxMove;
02133
02134
02135 float radius= 4.0f/Vector2sAccuracy;
02136 bboxMove.setCenter(start-CVector(radius, radius, 0));
02137 bboxMove.extend(start+CVector(radius, radius, 0));
02138 bboxMove.extend(end-CVector(radius, radius, 0));
02139 bboxMove.extend(end+CVector(radius, radius, 0));
02140
02141
02142 findCollisionChains(cst, bboxMove, origin);
02143 }
02144
02145
02146
02147 CSurfaceIdent endSurface;
02148 CVector endRequest= end;
02149 const sint maxPbPrec= 32;
02150 sint pbPrecNum= 0;
02151
02152
02153 CRetrieverInstance::snapVector(endRequest);
02154 end= endRequest;
02155
02156
02157 {
02158 CVector startTest= start;
02159 CRetrieverInstance::snapVector(startTest);
02160 nlassert( start == startTest );
02161 }
02162
02163
02164
02165 for(;;)
02166 {
02167
02168 CRetrieverInstance::snapVector(end);
02169
02170 CVector2f startCol(start.x, start.y);
02171 CVector2f endCol(end.x, end.y);
02172
02173
02174 if(endCol==startCol)
02175 {
02176 UGlobalPosition res;
02177 res= startPos;
02178
02179 res.LocalPosition.Estimation.z= end.z;
02180 return res;
02181 }
02182
02183
02184 UGlobalPosition restart;
02185 endSurface= testMovementWithCollisionChains(cst, startCol, endCol, startSurface, restart);
02186
02187
02188 if (endSurface.SurfaceId >= -1)
02189 {
02190 break;
02191 }
02192
02193 else if (endSurface.SurfaceId == -3)
02194 {
02195 start = getDoubleGlobalPosition(restart) - origin;
02196 startSurface.RetrieverInstanceId = restart.InstanceId;
02197 startSurface.SurfaceId = restart.LocalPosition.Surface;
02198
02199 CVector startTest= start;
02200 CRetrieverInstance::snapVector(startTest);
02201 nlassert( start == startTest );
02202 }
02203
02204
02205
02206
02207
02208
02209 else if (endSurface.SurfaceId == -2)
02210 {
02211
02212 if(pbPrecNum<maxPbPrec)
02213 {
02214 static struct {sint x,y;} dirs[8]= { {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0}, {-1,-1}, {0,-1}, {1,-1}};
02215 sint dir= pbPrecNum%8;
02216 sint dist= pbPrecNum/8+1;
02217 CVector dta;
02218
02219
02220 dta.x= dirs[dir].x * dist * 1.0f/SnapPrecision;
02221 dta.y= dirs[dir].y * dist * 1.0f/SnapPrecision;
02222 dta.z= 0;
02223
02224
02225 end= endRequest + dta;
02226
02227 pbPrecNum++;
02228 }
02229 else
02230 {
02231
02232 endSurface= CSurfaceIdent(-1,-1);
02233 break;
02234 }
02235 }
02236 }
02237
02238
02239
02240
02241 if(endSurface.SurfaceId==-1)
02242 return startPos;
02243 else
02244 {
02245
02246 CGlobalPosition res;
02247
02248 res.InstanceId= endSurface.RetrieverInstanceId;
02249 res.LocalPosition.Surface= endSurface.SurfaceId;
02250
02251
02252
02253
02254 CVector deltaOrigin;
02255 deltaOrigin= origin - getInstance(res.InstanceId).getOrigin();
02256
02257
02258
02259
02260
02261 res.LocalPosition.Estimation= end + deltaOrigin;
02262
02263
02264
02265 return res;
02266 }
02267
02268 }
02269
02270
02271
02272 const NLPACS::TCollisionSurfaceDescVector &NLPACS::CGlobalRetriever::testBBoxRot(const CGlobalPosition &startPos,
02273 const NLMISC::CVector &locI, const NLMISC::CVector &locJ, CCollisionSurfaceTemp &cst) const
02274 {
02275
02276
02277 CSurfaceIdent startSurface(startPos.InstanceId, startPos.LocalPosition.Surface);
02278
02279
02280
02281
02282 cst.CollisionDescs.clear();
02283
02284
02285 cst.PrecValid= false;
02286
02287
02288
02289
02290
02291 CVector origin;
02292 origin= getInstance(startPos.InstanceId).getOrigin();
02293
02294
02295
02296
02297 CVector2f obbStart[4];
02298
02299 CVector start= startPos.LocalPosition.Estimation;
02300 CVector2f obbCenter(start.x, start.y);
02301 CVector2f locI2d(locI.x, locI.y);
02302 CVector2f locJ2d(locJ.x, locJ.y);
02303
02304
02305 obbStart[0]= obbCenter - locI2d - locJ2d;
02306 obbStart[1]= obbCenter + locI2d - locJ2d;
02307 obbStart[2]= obbCenter + locI2d + locJ2d;
02308 obbStart[3]= obbCenter - locI2d + locJ2d;
02309
02310
02311
02312 CAABBox bboxMove;
02313
02314 bboxMove.setCenter(CVector(obbStart[0].x, obbStart[0].y, 0));
02315 bboxMove.extend(CVector(obbStart[1].x, obbStart[1].y, 0));
02316 bboxMove.extend(CVector(obbStart[2].x, obbStart[2].y, 0));
02317 bboxMove.extend(CVector(obbStart[3].x, obbStart[3].y, 0));
02318
02319
02320
02321
02322
02323 findCollisionChains(cst, bboxMove, origin);
02324
02325
02326
02327
02328
02329 CVector2f startCol(start.x, start.y);
02330 testRotCollisionWithCollisionChains(cst, startCol, startSurface, obbStart);
02331
02332
02333
02334 return cst.CollisionDescs;
02335 }
02336
02337
02338
02339 void NLPACS::CGlobalRetriever::testRotCollisionWithCollisionChains(CCollisionSurfaceTemp &cst, const CVector2f &, CSurfaceIdent startSurface, const CVector2f bbox[4]) const
02340 {
02341
02342
02343
02344 CSurfaceIdent currentSurface= startSurface;
02345 sint i;
02346
02347
02348 cst.RotDescs.clear();
02349 cst.CollisionDescs.clear();
02350
02351
02352
02353
02354
02355
02356
02357 for(i=0; i<(sint)cst.CollisionChains.size(); i++)
02358 {
02359 CCollisionChain &colChain= cst.CollisionChains[i];
02360
02361
02362
02363
02364
02365 sint32 curEdge= colChain.FirstEdgeCollide;
02366 while(curEdge!=(sint32)0xFFFFFFFF)
02367 {
02368
02369 CEdgeCollideNode &colEdge= cst.getEdgeCollideNode(curEdge);
02370
02371
02372 if(colEdge.testBBoxCollide(bbox))
02373 {
02374
02375 cst.RotDescs.push_back(CRotSurfaceDesc(colChain.LeftSurface, colChain.RightSurface));
02376 break;
02377 }
02378
02379
02380 curEdge= colEdge.Next;
02381 }
02382 }
02383
02384
02385
02386
02387 sint indexCD=0;
02388 for(;;)
02389 {
02390
02391 for(i=0;i<(sint)cst.RotDescs.size();i++)
02392 {
02393
02394 if(cst.RotDescs[i].hasSurface(currentSurface) && !cst.RotDescs[i].Tested)
02395 {
02396 cst.RotDescs[i].Tested= true;
02397
02398
02399 CCollisionSurfaceDesc col;
02400 col.ContactTime= 0;
02401 col.ContactNormal= CVector::Null;
02402 col.ContactSurface= cst.RotDescs[i].getOtherSurface(currentSurface);
02403 cst.CollisionDescs.push_back(col);
02404 }
02405 }
02406
02407
02408 if(indexCD<(sint)cst.CollisionDescs.size())
02409 currentSurface= cst.CollisionDescs[indexCD++].ContactSurface;
02410 else
02411 break;
02412 }
02413
02414 }
02415
02416
02417
02418 NLPACS::UGlobalRetriever *NLPACS::UGlobalRetriever::createGlobalRetriever (const char *globalRetriever, const NLPACS::URetrieverBank *retrieverBank)
02419 {
02420
02421
02422
02423 const NLPACS::CRetrieverBank* bank=static_cast<const NLPACS::CRetrieverBank*>(retrieverBank);
02424
02425 CIFile file;
02426 if (file.open(CPath::lookup(globalRetriever)))
02427 {
02428 CGlobalRetriever *retriever = new CGlobalRetriever();
02429
02430
02431 retriever->setRetrieverBank(bank);
02432
02433 file.serial(*retriever);
02434 retriever->initAll(false);
02435
02436 return static_cast<UGlobalRetriever *>(retriever);
02437 }
02438 else
02439 return NULL;
02440 }
02441
02442
02443
02444 void NLPACS::UGlobalRetriever::deleteGlobalRetriever (UGlobalRetriever *retriever)
02445 {
02446
02447 nlassert (dynamic_cast<NLPACS::CGlobalRetriever*>(retriever));
02448 NLPACS::CGlobalRetriever* r=static_cast<NLPACS::CGlobalRetriever*>(retriever);
02449
02450
02451 delete r;
02452 }
02453
02454
02455
02456 float NLPACS::CGlobalRetriever::getMeanHeight(const UGlobalPosition &pos) const
02457 {
02458
02459 if ((pos.InstanceId==-1)||(pos.LocalPosition.Surface==-1))
02460 return pos.LocalPosition.Estimation.z;
02461
02462
02463 const CRetrieverInstance &instance = getInstance(pos.InstanceId);
02464 const CLocalRetriever &retriever= _RetrieverBank->getRetriever(instance.getRetrieverId());
02465
02466 if (!retriever.isLoaded())
02467 return pos.LocalPosition.Estimation.z;
02468
02469
02470 return retriever.getHeight(pos.LocalPosition);
02471 }
02472
02473
02474 float NLPACS::CGlobalRetriever::getInteriorHeightAround(const UGlobalPosition &pos, float outsideTolerance) const
02475 {
02476
02477 if ((pos.InstanceId==-1)||(pos.LocalPosition.Surface==-1))
02478 return pos.LocalPosition.Estimation.z;
02479
02480
02481 const CRetrieverInstance &instance = getInstance(pos.InstanceId);
02482 const CLocalRetriever &retriever= _RetrieverBank->getRetriever(instance.getRetrieverId());
02483
02484 if (!retriever.isLoaded())
02485 return pos.LocalPosition.Estimation.z;
02486
02487
02488 return retriever.getInteriorHeightAround(pos.LocalPosition, outsideTolerance);
02489 }
02490
02491
02492
02493 bool NLPACS::CGlobalRetriever::testRaytrace (const CVectorD &, const CVectorD &)
02494 {
02495
02496 return false;
02497 }
02498
02499
02500
02501 void NLPACS::CGlobalRetriever::refreshLrAround(const CVector &position, float radius)
02502 {
02503 NLPACS_HAUTO_REFRESH_LR_AROUND
02504
02505
02506 if (_RetrieverBank->allLoaded())
02507 return;
02508
02509 std::list<CLrLoader>::iterator ite = _LrLoaderList.begin();
02510 while (ite != _LrLoaderList.end())
02511 {
02512
02513 if (ite->Finished && ite->Successful)
02514 {
02515 if (!ite->_Buffer.isReading())
02516 ite->_Buffer.invert();
02517
02518 ite->_Buffer.resetBufPos();
02519
02520
02521
02522 const_cast<CRetrieverBank*>(_RetrieverBank)->loadRetriever(ite->LrId, ite->_Buffer);
02523
02524
02525
02526 ite->_Buffer.clear();
02527
02528
02529
02530 nlinfo("Lr '%s' loading task complete", ite->LoadFile.c_str());
02531
02532
02533 _LrLoaderList.erase (ite);
02534
02535 break;
02536 }
02537
02538
02539 ite++;
02540 }
02541
02542 CAABBox box;
02543 box.setCenter(position);
02544 box.setHalfSize(CVector(radius, radius, 1000.0f));
02545
02546 selectInstances(box, _InternalCST);
02547
02548 set<uint> newlr, in, out;
02549 map<uint, CVector> lrPosition;
02550
02551 uint i;
02552 for (i=0; i<_InternalCST.CollisionInstances.size(); ++i)
02553 {
02554 uint lrId = (uint)(_Instances[_InternalCST.CollisionInstances[i]].getRetrieverId());
02555 newlr.insert(lrId);
02556 lrPosition.insert (map<uint, CVector>::value_type(lrId, _Instances[_InternalCST.CollisionInstances[i]].getBBox().getCenter()));
02557 }
02558
02559 const_cast<CRetrieverBank*>(_RetrieverBank)->diff(newlr, in, out);
02560
02561 set<uint>::iterator it;
02562
02563
02564 for (it=out.begin(); it!=out.end(); ++it)
02565 {
02566 const_cast<CRetrieverBank*>(_RetrieverBank)->unloadRetriever(*it);
02567 nlinfo("Freed Lr '%s'", (_RetrieverBank->getNamePrefix() + "_" + toString(*it) + ".lr").c_str());
02568 }
02569
02570
02571 set<uint>::iterator iteIn = in.begin();
02572 while (iteIn != in.end())
02573 {
02574
02575 ite = _LrLoaderList.begin();
02576 while (ite != _LrLoaderList.end())
02577 {
02578 if (ite->LrId == *iteIn)
02579 break;
02580
02581 ite++;
02582 }
02583
02584
02585 if (ite == _LrLoaderList.end())
02586 {
02587
02588 map<uint, CVector>::iterator iteLR = lrPosition.find(*iteIn);
02589 nlassert (iteLR != lrPosition.end());
02590
02591 _LrLoaderList.push_back (CLrLoader (iteLR->second));
02592 CLrLoader &loader = _LrLoaderList.back();
02593 loader.Finished = false;
02594 loader.LrId = *iteIn;
02595 loader.LoadFile = _RetrieverBank->getNamePrefix() + "_" + toString(loader.LrId) + ".lr";
02596
02597 CAsyncFileManager::getInstance().addLoadTask(&loader);
02598
02599 nlinfo("Lr '%s' added to load", loader.LoadFile.c_str());
02600 }
02601
02602
02603 iteIn++;
02604 }
02605 }
02606
02607
02608 void NLPACS::CGlobalRetriever::waitEndOfAsyncLoading()
02609 {
02610 while (!_LrLoaderList.empty ())
02611 {
02612 std::list<CLrLoader>::iterator ite = _LrLoaderList.begin();
02613 while (ite != _LrLoaderList.end())
02614 {
02615
02616 if (ite->Finished)
02617 {
02618 if (!ite->_Buffer.isReading())
02619 ite->_Buffer.invert();
02620
02621 const_cast<CRetrieverBank*>(_RetrieverBank)->loadRetriever(ite->LrId, ite->_Buffer);
02622
02623 ite->_Buffer.clear();
02624
02625
02626 _LrLoaderList.erase(ite);
02627
02628 break;
02629 }
02630
02631
02632 ite++;
02633 }
02634
02635 if (!_LrLoaderList.empty())
02636 nlSleep(0);
02637 }
02638
02639 }
02640
02641
02642 void NLPACS::CGlobalRetriever::refreshLrAroundNow(const CVector &position, float radius)
02643 {
02644
02645 if (_RetrieverBank->allLoaded())
02646 return;
02647
02648
02649 waitEndOfAsyncLoading();
02650
02651
02652 CAABBox box;
02653 box.setCenter(position);
02654 box.setHalfSize(CVector(radius, radius, 1000.0f));
02655
02656 selectInstances(box, _InternalCST);
02657
02658 set<uint> newlr, in, out;
02659 uint i;
02660 for (i=0; i<_InternalCST.CollisionInstances.size(); ++i)
02661 newlr.insert((uint)(_Instances[_InternalCST.CollisionInstances[i]].getRetrieverId()));
02662
02663 const_cast<CRetrieverBank*>(_RetrieverBank)->diff(newlr, in, out);
02664
02665 set<uint>::iterator it;
02666
02667
02668 for (it=out.begin(); it!=out.end(); ++it)
02669 const_cast<CRetrieverBank*>(_RetrieverBank)->unloadRetriever(*it);
02670
02671
02672 for (it=in.begin(); it!=in.end(); ++it)
02673 {
02674 string fname = _RetrieverBank->getNamePrefix() + "_" + toString(*it) + ".lr";
02675 CIFile f;
02676 if (!f.open(CPath::lookup(fname, false)))
02677 {
02678 nlwarning("Couldn't find file '%s' to load, retriever loading aborted", fname.c_str());
02679 continue;
02680 }
02681
02682 const_cast<CRetrieverBank*>(_RetrieverBank)->loadRetriever(*it, f);
02683 }
02684 }
02685
02686 void NLPACS::CGlobalRetriever::CLrLoader::run()
02687 {
02688 CIFile f;
02689
02690
02691 f.setAsyncLoading(true);
02692 f.setCacheFileOnOpen(true);
02693
02694 Successful = false;
02695
02696 if (!f.open(CPath::lookup(LoadFile, false)))
02697 {
02698 nlwarning("Couldn't find file '%s' to load, retriever loading aborted", LoadFile.c_str());
02699 _Buffer.clear();
02700 Finished = true;
02701 return;
02702 }
02703
02704 if (!_Buffer.isReading())
02705 _Buffer.invert();
02706
02707 uint8 *buffer = _Buffer.bufferToFill(f.getFileSize());
02708 f.serialBuffer(buffer, f.getFileSize());
02709
02710 Successful = true;
02711 Finished = true;
02712 }
02713
02714
02715 void NLPACS::CGlobalRetriever::CLrLoader::getName (std::string &result) const
02716 {
02717 result = "LoadLR(" + LoadFile + ")";
02718 }
02719
02720
02721
02722 NLMISC_CATEGORISED_VARIABLE(nel, uint, PacsRetrieveVerbose, "Allow retrieve position to dump info");
02723
02724