00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdpacs.h"
00027
00028 #include "pacs/retriever_instance.h"
00029 #include "pacs/global_retriever.h"
00030
00031 using namespace std;
00032 using namespace NLMISC;
00033
00034
00035
00036 NLPACS::CRetrieverInstance::CRetrieverInstance()
00037 {
00038 reset();
00039 }
00040
00041
00042 void NLPACS::CRetrieverInstance::resetLinks()
00043 {
00044 uint i;
00045
00046
00047
00048 for (i=0; i<_Neighbors.size(); ++i)
00049 _Neighbors[i] = -1;
00050 _BorderChainLinks.clear();
00051
00052 _ExteriorEdgeQuad.removeLinks();
00053 }
00054
00055 void NLPACS::CRetrieverInstance::resetLinks(uint32 id)
00056 {
00057 vector<sint32>::iterator rit;
00058 for (rit=_Neighbors.begin(); rit!=_Neighbors.end(); )
00059 if (*rit == (sint32)id)
00060 rit = _Neighbors.erase(rit);
00061 else
00062 ++rit;
00063
00064 uint i;
00065 for (i=0; i<_BorderChainLinks.size(); ++i)
00066 if (_BorderChainLinks[i].Instance == (uint16)id)
00067 _BorderChainLinks[i].reset();
00068
00069 _ExteriorEdgeQuad.removeLinks(id);
00070 }
00071
00072 void NLPACS::CRetrieverInstance::reset()
00073 {
00074
00075
00076
00077 _NodesInformation.clear();
00078 _InstanceId = -1;
00079 _RetrieverId = -1;
00080 _Orientation = 0;
00081 _Origin = CVector::Null;
00082 _Type = CLocalRetriever::Landscape;
00083 _BorderChainLinks.clear();
00084 _ExteriorEdgeQuad.clear();
00085
00086 resetLinks();
00087 }
00088
00089 void NLPACS::CRetrieverInstance::init(const CLocalRetriever &retriever)
00090 {
00091 _NodesInformation.resize(retriever.getSurfaces().size());
00092 uint i;
00093
00094
00095 for (i=0; i<_NodesInformation.size(); ++i)
00096 {
00097 CVector pos = getGlobalPosition(retriever.getSurfaces()[i].getCenter());
00098 _NodesInformation[i].Position = CVector2f(pos.x, pos.y);
00099 }
00100
00101 _Type = retriever.getType();
00102 _BorderChainLinks.resize(retriever.getBorderChains().size());
00103 }
00104
00105 void NLPACS::CRetrieverInstance::make(sint32 instanceId, sint32 retrieverId, const CLocalRetriever &retriever,
00106 uint8 orientation, const CVector &origin)
00107 {
00108 if (_InstanceId != -1 || _RetrieverId != -1)
00109 {
00110 nlwarning("in call to NLPACS::CRetrieverInstance::make");
00111 nlwarning("_InstanceId=%d _RetrieverId=%d _Orientation=%d", _InstanceId, _RetrieverId, _Orientation);
00112 nlwarning("instanceId=%d retrieverId=%d orientation=%d", instanceId, retrieverId, orientation);
00113 nlerror("Retriever instance %d has already been set", _InstanceId);
00114 }
00115
00116 _InstanceId = instanceId;
00117 _RetrieverId = retrieverId;
00118 _Orientation = (orientation%4);
00119 _Origin = origin;
00120
00121 _BBox = retriever.getBBox();
00122 _BBox.setCenter(_BBox.getCenter()+_Origin);
00123
00124 if (_Orientation == 1 || _Orientation == 3)
00125 {
00126 CVector hs = _BBox.getHalfSize();
00127 std::swap(hs.x, hs.y);
00128 _BBox.setHalfSize(hs);
00129 }
00130
00131 init(retriever);
00132 }
00133
00134
00135 void NLPACS::CRetrieverInstance::initEdgeQuad(NLPACS::CGlobalRetriever &gr)
00136 {
00137 const CLocalRetriever &lr = gr.getRetriever(_RetrieverId);
00138
00139 if (lr.getType() != CLocalRetriever::Interior)
00140 {
00141 nlerror("Attempt to init the edgequad of instance %d whereas local retriever %d is not interior", _InstanceId, _RetrieverId);
00142 }
00143
00144
00145 _ExteriorEdgeQuad.build(lr.getExteriorMesh(), gr, gr.getInternalCST(),_InstanceId);
00146 }
00147
00148 void NLPACS::CRetrieverInstance::linkEdgeQuad(NLPACS::CGlobalRetriever &gr)
00149 {
00150 const CLocalRetriever &lr = gr.getRetriever(_RetrieverId);
00151 const CExteriorMesh &em = lr.getExteriorMesh();
00152
00153 const vector<CExteriorEdgeEntry> &ee = _ExteriorEdgeQuad.getEdgeEntries();
00154
00155
00156 uint i;
00157 for (i=0; i<ee.size(); ++i)
00158 {
00159 const CExteriorMesh::CEdge &edge = em.getEdge(ee[i].EdgeId);
00160 if (edge.Link != -1)
00161 {
00162 const CExteriorMesh::CLink &link = em.getLink(edge.Link);
00163
00164 if (link.SurfaceId != 0xFFFF && link.ChainId != 0xFFFF && link.BorderChainId != 0xFFFF)
00165 {
00166 CRetrieverInstance::CLink &borderLink = _BorderChainLinks[link.BorderChainId];
00167 borderLink.ChainId = 0xFFFF;
00168 borderLink.BorderChainId = 0xFFFF;
00169 if ((borderLink.Instance == 0xFFFF && borderLink.SurfaceId == 0xFFFF) ||
00170 (borderLink.Instance == (uint16)(ee[i].Exterior.RetrieverInstanceId) &&
00171 borderLink.SurfaceId == (uint16)(ee[i].Exterior.SurfaceId) ))
00172 {
00173 borderLink.Instance = (uint16)(ee[i].Exterior.RetrieverInstanceId);
00174 borderLink.SurfaceId = (uint16)(ee[i].Exterior.SurfaceId);
00175 }
00176 else
00177 {
00178 nlwarning("Instance %d, borderLink %d: link already set to inst=%d, surf=%d, try to set to inst=%d, surf=%d",
00179 _InstanceId, link.BorderChainId, borderLink.Instance, borderLink.SurfaceId,
00180 (uint16)(ee[i].Exterior.RetrieverInstanceId), (uint16)(ee[i].Exterior.SurfaceId));
00181 }
00182 }
00183 }
00184 }
00185 }
00186
00187
00188
00189
00190 void NLPACS::CRetrieverInstance::link(CRetrieverInstance &neighbor,
00191 const vector<CLocalRetriever> &retrievers)
00192 {
00193 uint i, j;
00194 for (i=0; i<_Neighbors.size(); ++i)
00195 if (_Neighbors[i] == neighbor._InstanceId)
00196 return;
00197
00198 const CLocalRetriever &retriever = retrievers[_RetrieverId];
00199 const CLocalRetriever &nRetriever = retrievers[neighbor._RetrieverId];
00200
00201 const vector<CChain> &chains = retriever.getChains(),
00202 &nChains = nRetriever.getChains();
00203 const vector<uint16> &borderChains = retriever.getBorderChains(),
00204 &nBorderChains = nRetriever.getBorderChains();
00205
00206 vector< pair<CVector,CVector> > chainTips,
00207 nChainTips;
00208
00209 _BorderChainLinks.resize(borderChains.size());
00210 neighbor._BorderChainLinks.resize(nBorderChains.size());
00211
00212 for (i=0; i<borderChains.size(); ++i)
00213 chainTips.push_back(make_pair(retriever.getTip(chains[borderChains[i]].getStartTip()).Point,
00214 retriever.getTip(chains[borderChains[i]].getStopTip()).Point));
00215
00217
00218 CVector translation = neighbor._Origin - _Origin;
00219
00220 for (i=0; i<nBorderChains.size(); ++i)
00221 nChainTips.push_back(make_pair(nRetriever.getTip(nChains[nBorderChains[i]].getStartTip()).Point+translation,
00222 nRetriever.getTip(nChains[nBorderChains[i]].getStopTip()).Point+translation));
00223
00224 for (i=0; i<borderChains.size(); ++i)
00225 {
00226
00227 if (_BorderChainLinks[i].Instance != 0xFFFF || _BorderChainLinks[i].BorderChainId != 0xFFFF ||
00228 _BorderChainLinks[i].ChainId != 0xFFFF || _BorderChainLinks[i].SurfaceId != 0xFFFF)
00229 continue;
00230
00231 float bestDist = 1.0f;
00232 sint best = -1;
00233
00234 for (j=0; j<nBorderChains.size(); ++j)
00235 {
00236 if (neighbor._BorderChainLinks[j].Instance != 0xFFFF || neighbor._BorderChainLinks[j].BorderChainId != 0xFFFF ||
00237 neighbor._BorderChainLinks[j].ChainId != 0xFFFF || neighbor._BorderChainLinks[j].SurfaceId != 0xFFFF)
00238 continue;
00239
00240 float d = (chainTips[i].first-nChainTips[j].second).norm()+(chainTips[i].second-nChainTips[j].first).norm();
00241 if (d < bestDist)
00242 {
00243 bestDist = d;
00244 best = j;
00245 }
00246 }
00247
00248
00249 if (bestDist > 1.0e-1f || best == -1)
00250 continue;
00251
00252 _BorderChainLinks[i].Instance = (uint16)neighbor._InstanceId;
00253 _BorderChainLinks[i].BorderChainId = (uint16)best;
00254 _BorderChainLinks[i].ChainId = nBorderChains[_BorderChainLinks[i].BorderChainId];
00255 _BorderChainLinks[i].SurfaceId = (uint16)nChains[_BorderChainLinks[i].ChainId].getLeft();
00256
00257 neighbor._BorderChainLinks[best].Instance = (uint16)_InstanceId;
00258 neighbor._BorderChainLinks[best].BorderChainId = (uint16)i;
00259 neighbor._BorderChainLinks[best].ChainId = borderChains[neighbor._BorderChainLinks[best].BorderChainId];
00260 neighbor._BorderChainLinks[best].SurfaceId = (uint16)chains[neighbor._BorderChainLinks[best].ChainId].getLeft();
00261 }
00262
00263 _Neighbors.push_back(neighbor._InstanceId);
00264 neighbor._Neighbors.push_back(_InstanceId);
00265 }
00266
00267
00268 void NLPACS::CRetrieverInstance::unlink(vector<CRetrieverInstance> &instances)
00269 {
00270 uint i;
00271
00272 for (i=0; i<_Neighbors.size(); ++i)
00273 instances[_Neighbors[i]].resetLinks(_InstanceId);
00274
00275 resetLinks();
00276 }
00277
00278
00279
00280
00281 void NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVector &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst) const
00282
00283 {
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 retrievePosition(CVectorD(estimated), retriever, cst);
00372 }
00373
00374 void NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVectorD &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst) const
00375 {
00376 CVector localEstimated;
00377
00378
00379
00380
00381 localEstimated = getLocalPosition(estimated);
00382
00383 CRetrieverInstance::snapVector(localEstimated);
00384
00385
00386 retriever.retrievePosition(localEstimated, cst);
00387
00388 uint i, surf;
00389
00390
00391
00392
00393 bool found = false;
00394
00395 switch (_Type)
00396 {
00397 case CLocalRetriever::Landscape:
00398
00399 for (i=0; i<cst.PossibleSurfaces.size(); ++i)
00400 {
00401 surf = cst.PossibleSurfaces[i];
00402
00403
00404
00405
00406 if (cst.SurfaceLUT[surf].Counter == 2)
00407 {
00408 float meanHeight;
00409 const CQuadLeaf *leaf;
00410
00411
00412 leaf = retriever.getSurfaces()[surf].getQuadTree().getLeaf(localEstimated);
00413
00414 if (leaf != NULL)
00415 {
00416 meanHeight = leaf->getMaxHeight();
00417
00418
00419
00420 found = true;
00421 float distance = (float)fabs(localEstimated.z-meanHeight);
00422 cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
00423 }
00424 }
00425 else if (cst.SurfaceLUT[surf].Counter != 0)
00426 {
00427 nlwarning("PACS: unexpected surface (%d) count (%d) at instance %d (pos=(%f,%f,%f))", surf, cst.SurfaceLUT[surf].Counter, _InstanceId, estimated.x, estimated.y, estimated.z);
00428 }
00429
00430 cst.SurfaceLUT[surf].reset();
00431 }
00432
00433 break;
00434
00435 case CLocalRetriever::Interior:
00436
00437 for (i=0; i<cst.PossibleSurfaces.size(); ++i)
00438 {
00439 surf = cst.PossibleSurfaces[i];
00440
00441 if (cst.SurfaceLUT[surf].Counter == 2)
00442 {
00443 ULocalPosition lp;
00444 bool lfound = false;
00445
00446
00447 lp.Surface = surf;
00448 lp.Estimation = localEstimated;
00449 retriever.snapToInteriorGround(lp, lfound);
00450 if (lfound)
00451 {
00452
00453 found = true;
00454 float distance = (float)fabs(localEstimated.z-lp.Estimation.z);
00455 cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
00456 }
00457 }
00458 else if (cst.SurfaceLUT[surf].Counter != 0)
00459 {
00460 nlwarning("PACS: unexpected surface (%d) count (%d) at instance %d (pos=(%f,%f,%f))", surf, cst.SurfaceLUT[surf].Counter, _InstanceId, estimated.x, estimated.y, estimated.z);
00461 }
00462
00463 cst.SurfaceLUT[surf].reset();
00464 }
00465 break;
00466
00467 default:
00468 nlerror("Unknown instance type %d !!", _Type);
00469 break;
00470 }
00471
00472 cst.OutCounter = 0;
00473 }
00474
00475
00476
00477 void NLPACS::CRetrieverInstance::snapToInteriorGround(NLPACS::ULocalPosition &position,
00478 const NLPACS::CLocalRetriever &retriever) const
00479 {
00480 bool lfound;
00481 retriever.snapToInteriorGround(position, lfound);
00482 }
00483
00484 void NLPACS::CRetrieverInstance::snap(NLPACS::ULocalPosition &position, const NLPACS::CLocalRetriever &retriever) const
00485 {
00486 if (_Type == CLocalRetriever::Landscape)
00487 {
00488
00489
00490
00491 const CQuadLeaf *leaf = retriever.getSurfaces()[position.Surface].getQuadTree().getLeaf(position.Estimation);
00492
00493 if (leaf != NULL)
00494 {
00495 position.Estimation.z = leaf->getMaxHeight();
00496 }
00497 else
00498 {
00499 nlwarning("PACS: couldn't snap position (%f,%f,%f) on surface %d instance %d", position.Estimation.x, position.Estimation.y, position.Estimation.z, position.Surface, _InstanceId);
00500 }
00501
00502 }
00503 else if (_Type == CLocalRetriever::Interior)
00504 {
00505 bool lfound;
00506 retriever.snapToInteriorGround(position, lfound);
00507 }
00508 else
00509 {
00510 nlwarning("PACS: unknown instance (%d) type %d", _InstanceId, _Type);
00511 }
00512 }
00513
00514
00515
00516
00517
00518 CVector NLPACS::CRetrieverInstance::getLocalPosition(const CVector &globalPosition) const
00519 {
00520 switch (_Orientation)
00521 {
00522 default:
00523 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
00524 nlerror("unexpected orientation value (%d)", _Orientation);
00525 case 0:
00526 return CVector(+globalPosition.x-_Origin.x, +globalPosition.y-_Origin.y, globalPosition.z-_Origin.z);
00527 break;
00528 case 1:
00529 return CVector(+globalPosition.y-_Origin.y, -globalPosition.x+_Origin.x, globalPosition.z-_Origin.z);
00530 break;
00531 case 2:
00532 return CVector(-globalPosition.x+_Origin.x, -globalPosition.y+_Origin.y, globalPosition.z-_Origin.z);
00533 break;
00534 case 3:
00535 return CVector(-globalPosition.y+_Origin.y, +globalPosition.x-_Origin.x, globalPosition.z-_Origin.z);
00536 break;
00537 }
00538 }
00539
00540 CVector NLPACS::CRetrieverInstance::getLocalPosition(const CVectorD &globalPosition) const
00541 {
00542 switch (_Orientation)
00543 {
00544 default:
00545 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
00546 nlerror("unexpected orientation value (%d)", _Orientation);
00547 case 0:
00548 return CVector((float)(+globalPosition.x-_Origin.x), (float)(+globalPosition.y-_Origin.y), (float)(globalPosition.z-_Origin.z));
00549 break;
00550 case 1:
00551 return CVector((float)(+globalPosition.y-_Origin.y), (float)(-globalPosition.x+_Origin.x), (float)(globalPosition.z-_Origin.z));
00552 break;
00553 case 2:
00554 return CVector((float)(-globalPosition.x+_Origin.x), (float)(-globalPosition.y+_Origin.y), (float)(globalPosition.z-_Origin.z));
00555 break;
00556 case 3:
00557 return CVector((float)(-globalPosition.y+_Origin.y), (float)(+globalPosition.x-_Origin.x), (float)(globalPosition.z-_Origin.z));
00558 break;
00559 }
00560 }
00561
00562 CVector NLPACS::CRetrieverInstance::getGlobalPosition(const CVector &localPosition) const
00563 {
00564 switch (_Orientation)
00565 {
00566 default:
00567 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
00568 nlerror("unexpected orientation value (%d)", _Orientation);
00569 case 0:
00570 return CVector(+localPosition.x+_Origin.x, +localPosition.y+_Origin.y, localPosition.z+_Origin.z );
00571 break;
00572 case 1:
00573 return CVector(-localPosition.y+_Origin.x, +localPosition.x+_Origin.y, localPosition.z+_Origin.z );
00574 break;
00575 case 2:
00576 return CVector(-localPosition.x+_Origin.x, -localPosition.y+_Origin.y, localPosition.z+_Origin.z );
00577 break;
00578 case 3:
00579 return CVector(+localPosition.y+_Origin.x, -localPosition.x+_Origin.y, localPosition.z+_Origin.z );
00580 break;
00581 }
00582 }
00583
00584 CVectorD NLPACS::CRetrieverInstance::getDoubleGlobalPosition(const CVector &localPosition) const
00585 {
00586 switch (_Orientation)
00587 {
00588 default:
00589 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
00590 nlerror("unexpected orientation value (%d)", _Orientation);
00591 case 0:
00592 return CVectorD(+(double)localPosition.x+(double)_Origin.x, +(double)localPosition.y+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
00593 break;
00594 case 1:
00595 return CVectorD(-(double)localPosition.y+(double)_Origin.x, +(double)localPosition.x+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
00596 break;
00597 case 2:
00598 return CVectorD(-(double)localPosition.x+(double)_Origin.x, -(double)localPosition.y+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
00599 break;
00600 case 3:
00601 return CVectorD(+(double)localPosition.y+(double)_Origin.x, -(double)localPosition.x+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
00602 break;
00603 }
00604 }
00605
00606
00607
00608
00609 void NLPACS::CRetrieverInstance::testExteriorCollision(NLPACS::CCollisionSurfaceTemp &cst, const CAABBox &bboxMove, const CVector2f &transBase, const NLPACS::CLocalRetriever &retriever) const
00610 {
00611 sint i;
00612
00613
00614
00615 sint nEei= _ExteriorEdgeQuad.selectEdges(bboxMove, cst);
00616
00617
00618
00619
00620
00621
00622 uint16 *edgeLUT= cst.OChainLUT;
00623
00624
00625 uint firstChainAdded= cst.CollisionChains.size();
00626
00627
00628 for(i=0;i<nEei;i++)
00629 {
00630
00631 uint16 eei = cst.ExteriorEdgeIndexes[i];
00632 const CExteriorEdgeEntry &eee = _ExteriorEdgeQuad.getEdgeEntry(eei);
00633
00634
00635 if (eee.Interior.RetrieverInstanceId != -1)
00636 continue;
00637
00638
00639
00640 uint ccId;
00641
00642 if(edgeLUT[eei]==0xFFFF)
00643 {
00644
00645 ccId= cst.CollisionChains.size();
00646 cst.CollisionChains.push_back(CCollisionChain());
00647
00648 cst.CollisionChains[ccId].Tested= false;
00649 cst.CollisionChains[ccId].ExteriorEdge = true;
00650 cst.CollisionChains[ccId].FirstEdgeCollide= 0xFFFFFFFF;
00651 cst.CollisionChains[ccId].ChainId= eei;
00652
00653 cst.CollisionChains[ccId].LeftSurface = eee.Interior;
00654 cst.CollisionChains[ccId].RightSurface = eee.Exterior;
00655
00656
00657 edgeLUT[eei]= ccId;
00658 }
00659 else
00660 {
00661
00662 ccId= edgeLUT[eei];
00663 }
00664
00665
00666
00667 CCollisionChain &colChain= cst.CollisionChains[ccId];
00668
00669 CVector2f p0 = CVector2f(retriever._ExteriorMesh.getEdge(eee.EdgeId).Start);
00670 CVector2f p1 = CVector2f(retriever._ExteriorMesh.getEdge(eee.EdgeId+1).Start);
00671
00672
00673 uint32 ecnId= cst.allocEdgeCollideNode();
00674 CEdgeCollideNode &ecn= cst.getEdgeCollideNode(ecnId);
00675
00676
00677 ecn.Next= colChain.FirstEdgeCollide;
00678 colChain.FirstEdgeCollide= ecnId;
00679
00680
00681 p0+= transBase;
00682 p1+= transBase;
00683 ecn.make(p0, p1);
00684 }
00685
00686
00687
00688
00689
00690
00691
00692 for(i=firstChainAdded; i<(sint)cst.CollisionChains.size(); i++)
00693 {
00694 uint ccId= cst.CollisionChains[i].ChainId;
00695 edgeLUT[ccId]= 0xFFFF;
00696 }
00697
00698 }
00699
00700
00701
00702
00703 void NLPACS::CRetrieverInstance::serial(NLMISC::IStream &f)
00704 {
00705
00706
00707
00708
00709
00710
00711 sint ver= f.serialVersion(1);
00712
00713 f.serial(_InstanceId, _RetrieverId, _Orientation, _Origin);
00714 f.serialCont(_Neighbors);
00715 f.serialCont(_BorderChainLinks);
00716 f.serial(_BBox);
00717
00718
00719 uint16 totalNodes = _NodesInformation.size();
00720 f.serial(totalNodes);
00721 if (f.isReading())
00722 {
00723
00724 _NodesInformation.resize(totalNodes);
00725 }
00726
00727 if (ver >= 1)
00728 {
00729 f.serialEnum(_Type);
00730 f.serial(_ExteriorEdgeQuad);
00731
00732
00733 if (_Type != CLocalRetriever::Interior) _Type = CLocalRetriever::Landscape;
00734 }
00735 }