# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

retriever_instance.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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         // WARNING !!
00046         // this is a HARD reset !
00047         // only the instance i reset, no care about neighbors !!
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         // WARNING !!
00075         // this is a HARD reset !
00076         // only the instance i reset, no care about neighbors !!
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         // Resets _NodesInformation for later pathfinding graph annotation.
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         // build the edge quad
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         // here we fill (partially) the _BorderChainLinks table
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;            // no opposite chain
00168                                 borderLink.BorderChainId = 0xFFFF;      // idem
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 /* Links the current retriever instance to another instance
00188  * on the given edge.
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                 // if the chain is already linked, just step
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                 // if no best match, just don't link
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 //NLPACS::CLocalRetriever::CLocalPosition       NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVector &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst) const
00283 {
00284 /*
00285         CVector                                                 localEstimated;
00286         CLocalRetriever::CLocalPosition retrieved;
00287 
00288         // get local coordinates
00289         localEstimated = getLocalPosition(estimated);
00290         // Yoyo: must snap vector.
00291         CRetrieverInstance::snapVector(localEstimated);
00292 
00293         // fills _RetrieveTable by retrievingPosition.
00294         retriever.retrievePosition(localEstimated, cst);
00295 
00296         uint    i, surf;
00297         sint    bestSurf = -1;
00298         sint    lastSurf = -1;
00299         float   bestDistance = 1.0e10f;
00300         float   bestHeight;
00301         bool    lfound;
00302 
00303         // for each surface in the retriever
00304         for (i=0; i<cst.PossibleSurfaces.size(); ++i)
00305         {
00306                 surf = cst.PossibleSurfaces[i];
00307                 cst.SurfaceLUT[surf].first = false;
00308                 // if the surface contains the estimated position.
00309                 if (cst.SurfaceLUT[surf].second != 0)
00310                 {
00311                         // at least remembers the last seen surface...
00312                         cst.SurfaceLUT[surf].second = 0;
00313                         float                   meanHeight;
00314                         const CQuadLeaf *leaf;
00315                         ULocalPosition  lp;
00316                         lfound = false;
00317 
00318                         switch (_Type)
00319                         {
00320                         case CLocalRetriever::Landscape:
00321                                 // for landscape
00322                                 // search in the surface's quad tree for the actual height
00323                                 leaf = retriever.getSurfaces()[surf].getQuadTree().getLeaf(localEstimated);
00324                                 // if there is no acceptable leaf, just give up
00325                                 if (leaf == NULL)
00326                                         continue;
00327                                 meanHeight = leaf->getMaxHeight();
00328                                 lfound = true;
00329                                 break;
00330                         case CLocalRetriever::Interior:
00331                                 // for interior
00332                                 // get the exact position
00333                                 lp.Surface = surf;
00334                                 lp.Estimation = localEstimated;
00335                                 meanHeight = localEstimated.z;
00336                                 retriever.snapToInteriorGround(lp, lfound);
00337                                 if (lfound)
00338                                         meanHeight = lp.Estimation.z;
00339                                 break;
00340                         default:
00341                                 // hu?
00342                                 continue;
00343                         }
00344 
00345                         // if it is closer to the estimation than the previous remembered...
00346                         float   distance = (float)fabs(localEstimated.z-meanHeight);
00347                         if (distance < bestDistance && lfound)
00348                         {
00349                                 bestDistance = distance;
00350                                 bestHeight = meanHeight;
00351                                 bestSurf = surf;
00352                         }
00353                 }
00354         }
00355 
00356         if (bestSurf != -1)
00357         {
00358                 // if there is a best surface, returns it
00359                 retrieved.Surface = bestSurf;
00360                 retrieved.Estimation = CVector(localEstimated.x, localEstimated.y, bestHeight);
00361         }
00362         else
00363         {
00364                 // else return the last remembered...
00365                 retrieved.Surface = lastSurf;
00366                 retrieved.Estimation = localEstimated;
00367         }
00368 
00369         return retrieved;
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 //      nldebug("PACS: retrievePosition in instance %d (retriever %d)", _InstanceId, _RetrieverId);
00379 
00380         // get local coordinates
00381         localEstimated = getLocalPosition(estimated);
00382         // Yoyo: must snap vector.
00383         CRetrieverInstance::snapVector(localEstimated);
00384 
00385         // fills _RetrieveTable by retrievingPosition.
00386         retriever.retrievePosition(localEstimated, cst);
00387 
00388         uint    i, surf;
00389 /*      sint    bestSurf = -1;
00390         sint    lastSurf = -1;
00391         float   bestDistance = 1.0e10f;
00392         float   bestHeight;*/
00393         bool    found = false;
00394 
00395         switch (_Type)
00396         {
00397         case CLocalRetriever::Landscape:
00398                 // for landscape
00399                 for (i=0; i<cst.PossibleSurfaces.size(); ++i)
00400                 {
00401                         surf = cst.PossibleSurfaces[i];
00402 
00403 //                      nldebug("PACS: surface %d: count %d", surf, cst.SurfaceLUT[surf].Counter);
00404 
00405                         // if the surface contains the estimated position.
00406                         if (cst.SurfaceLUT[surf].Counter == 2)
00407                         {
00408                                 float                   meanHeight;
00409                                 const CQuadLeaf *leaf;
00410 
00411                                 // search in the surface's quad tree for the actual height
00412                                 leaf = retriever.getSurfaces()[surf].getQuadTree().getLeaf(localEstimated);
00413                                 // if there is no acceptable leaf, just give up
00414                                 if (leaf != NULL)
00415                                 {
00416                                         meanHeight = leaf->getMaxHeight();
00417                                         //meanHeight = retriever.getSurfaces()[surf].getQuadTree().getInterpZ(localEstimated);
00418 
00419                                         // if it is closer to the estimation than the previous remembered...
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                 // for interior
00437                 for (i=0; i<cst.PossibleSurfaces.size(); ++i)
00438                 {
00439                         surf = cst.PossibleSurfaces[i];
00440                         // if the surface contains the estimated position.
00441                         if (cst.SurfaceLUT[surf].Counter == 2)
00442                         {
00443                                 ULocalPosition  lp;
00444                                 bool                    lfound = false;
00445 
00446                                 // get the exact position
00447                                 lp.Surface = surf;
00448                                 lp.Estimation = localEstimated;
00449                                 retriever.snapToInteriorGround(lp, lfound);
00450                                 if (lfound)
00451                                 {
00452                                         // if it is closer to the estimation than the previous remembered...
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                 // search in the surface's quad tree for the actual height
00489 //              position.Estimation.z = retriever.getSurfaces()[position.Surface].getQuadTree().getInterpZ(position.Estimation);
00490 
00491                 const CQuadLeaf *leaf = retriever.getSurfaces()[position.Surface].getQuadTree().getLeaf(position.Estimation);
00492                 // if there is no acceptable leaf, just give up
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         // 0. select ordered chains in the chainquad.
00614         //=====================================
00615         sint    nEei= _ExteriorEdgeQuad.selectEdges(bboxMove, cst);
00616         // NB: cst.OChainLUT is assured to be full of 0xFFFF after this call (if was right before).
00617 
00618 
00619         // 1. regroup them in chains. build cst.CollisionChains
00620         //=====================================
00621         // NB: use cst.OChainLUT to look if a Chain has been inserted before.
00622         uint16  *edgeLUT= cst.OChainLUT;
00623 
00624         // bkup where we begin to add chains.
00625         uint    firstChainAdded= cst.CollisionChains.size();
00626 
00627         // For all exterioredge entry.
00628         for(i=0;i<nEei;i++)
00629         {
00630                 // get the edge entry and the edge
00631                 uint16                                          eei = cst.ExteriorEdgeIndexes[i];
00632                 const CExteriorEdgeEntry        &eee = _ExteriorEdgeQuad.getEdgeEntry(eei);
00633 
00634                 // don't bother about doors
00635                 if (eee.Interior.RetrieverInstanceId != -1)
00636                         continue;
00637 
00638                 // add/retrieve the id in cst.CollisionChains.
00639                 //=================================
00640                 uint                            ccId;
00641                 // if never added.
00642                 if(edgeLUT[eei]==0xFFFF)
00643                 {
00644                         // add a new CCollisionChain.
00645                         ccId= cst.CollisionChains.size();
00646                         cst.CollisionChains.push_back(CCollisionChain());
00647                         // Fill it with default.
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                         // Fill Left right info.
00653                         cst.CollisionChains[ccId].LeftSurface = eee.Interior;
00654                         cst.CollisionChains[ccId].RightSurface = eee.Exterior;
00655 
00656                         // store this Id in the LUT of chains.
00657                         edgeLUT[eei]= ccId;
00658                 }
00659                 else
00660                 {
00661                         // get the id of this collision chain.
00662                         ccId= edgeLUT[eei];
00663                 }
00664 
00665                 // add edge collide to the list.
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                 // alloc a new edgeCollide.
00673                 uint32  ecnId= cst.allocEdgeCollideNode();
00674                 CEdgeCollideNode        &ecn= cst.getEdgeCollideNode(ecnId);
00675 
00676                 // append to the front of the list.
00677                 ecn.Next= colChain.FirstEdgeCollide;
00678                 colChain.FirstEdgeCollide= ecnId;
00679 
00680                 // build this edge.
00681                 p0+= transBase;
00682                 p1+= transBase;
00683                 ecn.make(p0, p1);
00684         }
00685 
00686 
00687 
00688         // 2. Reset LUT to 0xFFFF.
00689         //=====================================
00690 
00691         // for all collisions chains inserted (starting from firstChainAdded), reset LUT.
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         Version 0:
00707                 - base version.
00708         Version 1:
00709                 - added type and _EdgeQuad
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         // serialises the number of nodes
00719         uint16  totalNodes = _NodesInformation.size();
00720         f.serial(totalNodes);
00721         if (f.isReading())
00722         {
00723                 // if the stream is reading, reinits the temps table...
00724                 _NodesInformation.resize(totalNodes);
00725         }
00726 
00727         if (ver >= 1)
00728         {
00729                 f.serialEnum(_Type);
00730                 f.serial(_ExteriorEdgeQuad);
00731 
00732                 // a fix for old versions (with wrong _Type value)
00733                 if (_Type != CLocalRetriever::Interior) _Type = CLocalRetriever::Landscape;
00734         }
00735 }