From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/local__retriever_8cpp-source.html | 1704 ++++++++++++++++++++ 1 file changed, 1704 insertions(+) create mode 100644 docs/doxygen/nel/local__retriever_8cpp-source.html (limited to 'docs/doxygen/nel/local__retriever_8cpp-source.html') diff --git a/docs/doxygen/nel/local__retriever_8cpp-source.html b/docs/doxygen/nel/local__retriever_8cpp-source.html new file mode 100644 index 00000000..eb2cb470 --- /dev/null +++ b/docs/doxygen/nel/local__retriever_8cpp-source.html @@ -0,0 +1,1704 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# 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  
+

local_retriever.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 "nel/misc/plane.h"
+00029 
+00030 #include "pacs/local_retriever.h"
+00031 #include "pacs/collision_desc.h"
+00032 #include "pacs/retriever_instance.h"
+00033 
+00034 #include "nel/misc/hierarchical_timer.h"
+00035 
+00036 using namespace std;
+00037 using namespace NLMISC;
+00038 
+00040 const float     NLPACS::CLocalRetriever::_TipThreshold = 0.1f;
+00041 const float     NLPACS::CLocalRetriever::_EdgeTipThreshold = 0.1f;
+00042 
+00044 const float     InsurePositionThreshold = 2.0e-2f;
+00045 
+00046 //static float  hybrid2dNorm(const CVector &v)
+00047 //{
+00048 //      return (float)(sqrt(sqr(v.x)+sqr(v.y))+fabs(v.z)*0.1);
+00049 //}
+00050 
+00051 
+00052 
+00053 
+00054 
+00055 NLPACS::CLocalRetriever::CLocalRetriever()
+00056 {
+00057         _Type = Landscape;
+00058         _FaceGrid.clear();
+00059 }
+00060 
+00061 
+00062 
+00063 const CVector   &NLPACS::CLocalRetriever::getStartVector(uint32 chain) const
+00064 {
+00065         const COrderedChain3f   &ochain = _FullOrderedChains[_Chains[chain].getSubChains().front()];
+00066         return (ochain.isForward()) ? ochain.getVertices().front() : ochain.getVertices().back();
+00067 }
+00068 
+00069 const CVector   &NLPACS::CLocalRetriever::getStopVector(uint32 chain) const
+00070 {
+00071         const COrderedChain3f   &ochain = _FullOrderedChains[_Chains[chain].getSubChains().back()];
+00072         return (ochain.isForward()) ? ochain.getVertices().back() : ochain.getVertices().front();
+00073 }
+00074 
+00075 
+00076 
+00077 
+00078 const CVector   &NLPACS::CLocalRetriever::getStartVector(uint32 chain, sint32 surface) const
+00079 {
+00080         bool                                    onLeft = _Chains[chain].getLeft() == surface;
+00081         const COrderedChain3f   &ochain = onLeft ? _FullOrderedChains[_Chains[chain].getSubChains().front()] :
+00082                                                                                            _FullOrderedChains[_Chains[chain].getSubChains().back()];
+00083 
+00084         if (ochain.isForward() && onLeft || !ochain.isForward() && !onLeft)
+00085                 return ochain.getVertices().front();
+00086         else
+00087                 return ochain.getVertices().back();
+00088 }
+00089 
+00090 const CVector   &NLPACS::CLocalRetriever::getStopVector(uint32 chain, sint32 surface) const
+00091 {
+00092         bool                                    onLeft = _Chains[chain].getLeft() == surface;
+00093         const COrderedChain3f   &ochain = onLeft ? _FullOrderedChains[_Chains[chain].getSubChains().back()] :
+00094                                                                                            _FullOrderedChains[_Chains[chain].getSubChains().front()];
+00095 
+00096         if (ochain.isForward() && onLeft || !ochain.isForward() && !onLeft)
+00097                 return ochain.getVertices().back();
+00098         else
+00099                 return ochain.getVertices().front();
+00100 }
+00101 
+00102 
+00103 
+00104 
+00105 uint16                  NLPACS::CLocalRetriever::getStartTip(uint32 chain, sint32 surface) const
+00106 {
+00107         return (_Chains[chain].getLeft() == surface) ? _Chains[chain].getStartTip() : _Chains[chain].getStopTip();
+00108 }
+00109 
+00110 uint16                  NLPACS::CLocalRetriever::getStopTip(uint32 chain, sint32 surface) const
+00111 {
+00112         return (_Chains[chain].getLeft() == surface) ? _Chains[chain].getStopTip() : _Chains[chain].getStartTip();
+00113 }
+00114 
+00115 
+00116 
+00117 
+00118 
+00119 void                    NLPACS::CLocalRetriever::setStartTip(uint32 chain, sint32 surface, uint16 startTip)
+00120 {
+00121         if (_Chains[chain].getLeft() == surface)
+00122                 _Chains[chain]._StartTip = startTip;
+00123         else
+00124                 _Chains[chain]._StopTip = startTip;
+00125 }
+00126 
+00127 void                    NLPACS::CLocalRetriever::setStopTip(uint32 chain, sint32 surface, uint16 stopTip)
+00128 {
+00129         if (_Chains[chain].getLeft() == surface)
+00130                 _Chains[chain]._StopTip = stopTip;
+00131         else
+00132                 _Chains[chain]._StartTip = stopTip;
+00133 }
+00134 
+00135 
+00136 
+00137 
+00138 uint32                  NLPACS::CLocalRetriever::getPreviousChain(uint32 chain, sint32 surface) const
+00139 {
+00140         uint                                                            loop;
+00141         uint                                                            loopIndex;
+00142 
+00143         if (_Chains[chain].getLeft() == surface)
+00144         {
+00145                 loop = _Chains[chain]._LeftLoop;
+00146                 loopIndex = _Chains[chain]._LeftLoopIndex;
+00147         }
+00148         else
+00149         {
+00150                 loop = _Chains[chain]._RightLoop;
+00151                 loopIndex = _Chains[chain]._RightLoopIndex;
+00152         }
+00153 
+00154         const CRetrievableSurface                       &surf = _Surfaces[surface];
+00155         const CRetrievableSurface::TLoop        &sLoop = surf._Loops[loop];
+00156         return surf._Chains[sLoop[(loopIndex+sLoop.size()-1)%sLoop.size()]].Chain;
+00157 }
+00158 
+00159 uint32                  NLPACS::CLocalRetriever::getNextChain(uint32 chain, sint32 surface) const
+00160 {
+00161         uint                                                            loop;
+00162         uint                                                            loopIndex;
+00163 
+00164         if (_Chains[chain].getLeft() == surface)
+00165         {
+00166                 loop = _Chains[chain]._LeftLoop;
+00167                 loopIndex = _Chains[chain]._LeftLoopIndex;
+00168         }
+00169         else
+00170         {
+00171                 loop = _Chains[chain]._RightLoop;
+00172                 loopIndex = _Chains[chain]._RightLoopIndex;
+00173         }
+00174 
+00175         const CRetrievableSurface                       &surf = _Surfaces[surface];
+00176         const CRetrievableSurface::TLoop        &sLoop = surf._Loops[loop];
+00177         return surf._Chains[sLoop[(loopIndex+1)%sLoop.size()]].Chain;
+00178 }
+00179 
+00180 
+00181 
+00182 
+00183 void    NLPACS::CLocalRetriever::unify()
+00184 {
+00185         uint    i, j;
+00186 
+00187         for (i=0; i<_Chains.size(); ++i)
+00188                 _Chains[i].unify(_OrderedChains);
+00189 
+00190         for (i=0; i<_Tips.size(); ++i)
+00191         {
+00192                 NLPACS::CLocalRetriever::CTip   &tip = _Tips[i];
+00193                 CVector2s ptip = tip.Point;
+00194 
+00195                 for (j=0; j<tip.Chains.size(); ++j)
+00196                 {
+00197                         if (tip.Chains[j].Start)
+00198                         {
+00199                                 if (_Chains[tip.Chains[j].Chain].getStartVector(_OrderedChains) != ptip)
+00200                                         nlwarning("chain %d is not stuck to tip %d", tip.Chains[j].Chain, i);
+00201                                 _Chains[tip.Chains[j].Chain].setStartVector(ptip, _OrderedChains);
+00202                         }
+00203                         else
+00204                         {
+00205                                 if (_Chains[tip.Chains[j].Chain].getStopVector(_OrderedChains) != ptip)
+00206                                         nlwarning("chain %d is not stuck to tip %d", tip.Chains[j].Chain, i);
+00207                                 _Chains[tip.Chains[j].Chain].setStopVector(ptip, _OrderedChains);
+00208                         }
+00209                 }
+00210         }
+00211 
+00212         _FullOrderedChains.resize(_OrderedChains.size());
+00213         for (i=0; i<_OrderedChains.size(); ++i)
+00214                 _FullOrderedChains[i].unpack(_OrderedChains[i]);
+00215 }
+00216 
+00217 
+00218 
+00219 
+00220 
+00221 
+00222 
+00223 void    NLPACS::CLocalRetriever::dumpSurface(uint surf, const CVector &vect) const
+00224 {
+00225         const CRetrievableSurface       &surface = _Surfaces[surf];
+00226 
+00227         nlinfo("dump surf %d", surf);
+00228         nlinfo("%d chains, %d loops", surface._Chains.size(), surface._Loops.size());
+00229         
+00230         uint    i, j, k;
+00231 
+00232         for (i=0; i<surface._Chains.size(); ++i)
+00233         {
+00234                 uint                    chainId = surface._Chains[i].Chain;
+00235                 const CChain    &chain = _Chains[chainId];
+00236                 nlinfo("-- chain %d[%d]: %d sub left=%d right=%d start=%d stop=%d", i, chainId, chain.getSubChains().size(), chain.getLeft(), chain.getRight(), chain.getStartTip(), chain.getStopTip());
+00237 
+00238                 for (j=0; j<chain.getSubChains().size(); ++j)
+00239                 {
+00240                         const COrderedChain3f   &ochain = _FullOrderedChains[chain.getSubChain(j)];
+00241                         const COrderedChain             &ochains = _OrderedChains[chain.getSubChain(j)];
+00242                         nlinfo("     subchain %d[%d]: fwd=%d parent=%d idx=%d", j, chain.getSubChain(j), ochain.isForward(), ochain.getParentId(), ochain.getIndexInParent());
+00243                         for (k=0; k<ochain.getVertices().size(); ++k)
+00244                                 nlinfo("       v[%d]=(%.3f,%.3f,%.3f) (%d,%d)", k, ochain.getVertices()[k].x+vect.x, ochain.getVertices()[k].y+vect.y, ochain.getVertices()[k].z+vect.z, ochains.getVertices()[k].x, ochains.getVertices()[k].y);
+00245                 }
+00246 
+00247         }
+00248 
+00249         for (i=0; i<surface._Loops.size(); ++i)
+00250         {
+00251                 const CRetrievableSurface::TLoop        &loop = surface._Loops[i];
+00252                 nlinfo("-- loop %d: %d chains length=%.2f", i, loop.size(), loop.Length);
+00253                 static char     wbuffer[256];
+00254                 static char     buffer[10240];
+00255                 sprintf(buffer, "    chains:");
+00256                 for (j=0; j<loop.size(); ++j)
+00257                 {
+00258                         sprintf(wbuffer, " %d[%d]", loop[j], surface._Chains[loop[j]].Chain);
+00259                         strcat(buffer, wbuffer);
+00260                 }
+00261                 nlinfo("%s", buffer);
+00262         }
+00263 }
+00264 
+00265 
+00266 float   NLPACS::CLocalRetriever::distanceToBorder(const ULocalPosition &pos) const
+00267 {
+00268         const CRetrievableSurface       &surf = _Surfaces[pos.Surface];
+00269         uint                                            i, j;
+00270         float                                           minDist = 1.0e10f, dist;
+00271 
+00272         for (i=0; i<surf._Chains.size(); ++i)
+00273         {
+00274                 const CChain    &chain = _Chains[surf._Chains[i].Chain];
+00275                 for (j=0; j<chain.getSubChains().size(); ++j)
+00276                 {
+00277                         dist = _OrderedChains[chain.getSubChain(j)].distance(pos.Estimation);
+00278                         if (dist < minDist)
+00279                         {
+00280                                 minDist = dist;
+00281                         }
+00282                 }
+00283         }
+00284 
+00285         return minDist;
+00286 }
+00287 
+00288 
+00289 
+00290 
+00291 
+00292 sint32  NLPACS::CLocalRetriever::addSurface(uint8 normalq, uint8 orientationq,
+00293                                                                                         uint8 mat, uint8 charact, uint8 level,
+00294                                                                                         bool isUnderWater, float waterHeight,
+00295                                                                                         const CVector &center,
+00296                                                                                         const NLPACS::CSurfaceQuadTree &quad)
+00297 {
+00298         // creates a new surface...
+00299         sint32  newId = _Surfaces.size();
+00300         _Surfaces.resize(newId+1);
+00301         CRetrievableSurface     &surf = _Surfaces.back();
+00302 
+00303         // ... and fills it
+00304         surf._NormalQuanta = normalq;
+00305         surf._OrientationQuanta = orientationq;
+00306         surf._Material = mat;
+00307         surf._Character = charact;
+00308         surf._Level = level;
+00309         surf._Quad = quad;
+00310         surf._Center = center;
+00311 
+00312         // WARNING!! MODIFY THESE IF QUANTAS VALUES CHANGE !!
+00313         surf._IsFloor = (surf._NormalQuanta <= 1);
+00314         surf._IsCeiling = (surf._NormalQuanta >= 3);
+00315 
+00316         surf._Flags = 0;
+00317         surf._Flags |= (surf._IsFloor) ? (1<<CRetrievableSurface::IsFloorBit) : 0;
+00318         surf._Flags |= (surf._IsCeiling) ? (1<<CRetrievableSurface::IsCeilingBit) : 0;
+00319         surf._Flags |= (!surf._IsFloor && !surf._IsCeiling) ? (1<<CRetrievableSurface::IsSlantBit) : 0;
+00320 
+00321         surf._Flags |= (isUnderWater) ? (1<<CRetrievableSurface::IsUnderWaterBit) : 0;
+00322         surf._WaterHeight = waterHeight;
+00323 
+00324         surf._Flags |= ((0xffffffff<<(CRetrievableSurface::NormalQuantasStartBit)) & CRetrievableSurface::NormalQuantasBitMask);
+00325 
+00326         return newId;
+00327 }
+00328 
+00329 sint32  NLPACS::CLocalRetriever::addChain(const vector<CVector> &verts,
+00330                                                                                   sint32 left, sint32 right)
+00331 {
+00332         vector<CVector> vertices = verts;
+00333         uint            i;
+00334 
+00335         if (vertices.size() < 2)
+00336         {
+00337                 nlwarning("in NLPACS::CLocalRetriever::addChain()");
+00338                 nlwarning("The chain has less than 2 vertices");
+00339                 return -1;
+00340         }
+00341 
+00342         // Remove doubled vertices due to CVector2s snapping
+00343         vector<CVector2s>       converts;
+00344 
+00345         for (i=0; i<vertices.size(); ++i)
+00346                 converts.push_back(CVector2s(vertices[i]));
+00347 
+00348         vector<CVector2s>::iterator     next2s = converts.begin(), it2s, prev2s;
+00349         prev2s = next2s; ++next2s;
+00350         it2s = next2s; ++next2s;
+00351 
+00352         vector<CVector>::iterator       it3f = vertices.begin();
+00353         CVector                                         prev3f = *it3f;
+00354         ++it3f;
+00355 
+00356 
+00357         for (; it2s != converts.end() && next2s != converts.end(); )
+00358         {
+00359                 // if the next point is equal to the previous
+00360                 if (*it2s == *prev2s || *it2s == *next2s)
+00361                 {
+00362                         // then remove the next point
+00363                         it2s = converts.erase(it2s);
+00364                         it3f = vertices.erase(it3f);
+00365 
+00366                         prev2s = it2s;
+00367                         --prev2s;
+00368                         next2s = it2s;
+00369                         ++next2s;
+00370                 }
+00371                 else
+00372                 {
+00373                         // else remember the next point, and step to the next...
+00374                         ++prev2s;
+00375                         ++it2s;
+00376                         ++next2s;
+00377                         ++it3f;
+00378                         prev3f = *it3f;
+00379                 }
+00380         }
+00381         
+00382         if (vertices.size() < 2)
+00383         {
+00384                 nlwarning("in NLPACS::CLocalRetriever::addChain()");
+00385                 nlwarning("The chain was snapped to a single point");
+00386                 return -1;
+00387         }
+00388 
+00389         sint32          newId = _Chains.size();
+00390         _Chains.resize(newId+1);
+00391         CChain          &chain = _Chains.back();
+00392 
+00393         if (left>(sint)_Surfaces.size())
+00394                 nlerror ("left surface id MUST be id<%d (id=%d)", _Surfaces.size(), left);
+00395         if (right>(sint)_Surfaces.size())
+00396                 nlerror ("right surface id MUST be id<%d (id=%d)", _Surfaces.size(), right);
+00397 
+00398         // checks if we can build the chain.
+00399         if (newId > 65535)
+00400                 nlerror("in NLPACS::CLocalRetriever::addChain(): reached the maximum number of chains");
+00401 
+00402         CRetrievableSurface     *leftSurface = (left>=0) ? &(_Surfaces[left]) : NULL;
+00403         CRetrievableSurface     *rightSurface = (right>=0) ? &(_Surfaces[right]) : NULL;
+00404 
+00405         // adds the chain and the link to the surface links vector.
+00406         if (leftSurface != NULL)
+00407                 leftSurface->_Chains.push_back(CRetrievableSurface::CSurfaceLink(newId, right));
+00408         if (rightSurface != NULL)
+00409                 rightSurface->_Chains.push_back(CRetrievableSurface::CSurfaceLink(newId, left));
+00410 
+00411         chain._StartTip = 0xffff;
+00412         chain._StopTip = 0xffff;
+00413 
+00414         // make the chain and its subchains.
+00415         chain.make(vertices, left, right, _OrderedChains, (uint16)newId, _FullOrderedChains);
+00416 
+00417         return newId;
+00418 }
+00419 
+00420 
+00421 
+00422 
+00423 void    NLPACS::CLocalRetriever::computeLoopsAndTips()
+00424 {
+00425         // for each surface,
+00426         // examine each chain tip to match another tip inside the surface tips
+00427         // if there is no matching tip, then creates a new one
+00428 
+00429         uint    i, j;
+00430 
+00431         for (i=0; i<_Surfaces.size(); ++i)
+00432         {
+00433                 CRetrievableSurface     &surface = _Surfaces[i];
+00434 
+00435                 vector<bool>            chainFlags;
+00436                 chainFlags.resize(surface._Chains.size());
+00437                 for (j=0; j<chainFlags.size(); ++j)
+00438                         chainFlags[j] = false;
+00439 
+00440                 uint    totalAdded = 0;
+00441 
+00442                 while (true)
+00443                 {
+00444                         for (j=0; j<chainFlags.size() && chainFlags[j]; ++j)
+00445                                 ;
+00446 
+00447                         if (j == chainFlags.size())
+00448                                 break;
+00449 
+00450                         uint32                                          loopId = surface._Loops.size();
+00451                         surface._Loops.push_back(CRetrievableSurface::TLoop());
+00452                         CRetrievableSurface::TLoop      &loop = surface._Loops.back();
+00453 
+00454                         CVector loopStart = getStartVector(surface._Chains[j].Chain, i);
+00455                         CVector currentEnd = getStopVector(surface._Chains[j].Chain, i);
+00456                         _Chains[surface._Chains[j].Chain].setLoopIndexes(i, loopId, loop.size());
+00457                         loop.push_back(j);
+00458                         chainFlags[j] = true;
+00459 
+00460                         float   loopCloseDistance;
+00461 
+00462                         while (true)
+00463                         {
+00464 //                              loopCloseDistance = hybrid2dNorm(loopStart-currentEnd);
+00465                                 loopCloseDistance = (loopStart-currentEnd).norm();
+00466 
+00467                                 // choose the best matching start vector
+00468                                 sint    bestChain = -1;
+00469                                 float   best = 1.0e10f;
+00470                                 CVector thisStart;
+00471                                 for (j=0; j<chainFlags.size(); ++j)
+00472                                 {
+00473                                         if (chainFlags[j])
+00474                                                 continue;
+00475                                         thisStart = getStartVector(surface._Chains[j].Chain, i);
+00476 //                                      float   d = hybrid2dNorm(thisStart-currentEnd);
+00477                                         float   d = (thisStart-currentEnd).norm();
+00478                                         if (d < best)
+00479                                         {
+00480                                                 best = d;
+00481                                                 bestChain = j;
+00482                                         }
+00483                                 }
+00484 
+00485                                 if ((bestChain == -1 || best > 3.0e-2f)&& loopCloseDistance > 3.0e-2f)
+00486                                 {
+00487                                         nlwarning("in NLPACS::CLocalRetriever::computeTips()");
+00488 
+00489                                         dumpSurface(i);
+00490 
+00491                                         for (j=0; j<surface._Chains.size(); ++j)
+00492                                         {
+00493                                                 CVector start = getStartVector(surface._Chains[j].Chain, i);
+00494                                                 CVector end = getStopVector(surface._Chains[j].Chain, i);
+00495                                                 nlinfo("surf=%d chain=%d", i, surface._Chains[j].Chain);
+00496                                                 nlinfo("start=(%f,%f,%f)", start.x, start.y, start.z);
+00497                                                 nlinfo("end=(%f,%f,%f)", end.x, end.y, end.z);
+00498                                         }
+00499                                         
+00500                                         nlwarning("bestChain=%d best=%f", bestChain, best);
+00501                                         nlwarning("loopCloseDistance=%f", loopCloseDistance);
+00502                                         nlerror("Couldn't close loop on surface=%d", i);
+00503                                 }
+00504                                 else if (best > 1.0e0f && loopCloseDistance < 3.0e-2f ||
+00505                                                  loopCloseDistance < 1.0e-3f)
+00506                                 {
+00507                                         break;
+00508                                 }
+00509 
+00510                                 currentEnd = getStopVector(surface._Chains[bestChain].Chain, i);
+00511                                 _Chains[surface._Chains[bestChain].Chain].setLoopIndexes(i, loopId, loop.size());
+00512                                 loop.push_back(bestChain);
+00513                                 chainFlags[bestChain] = true;
+00514                                 ++totalAdded;
+00515                         }
+00516                 }
+00517         }
+00518 
+00519         for (i=0; i<_Chains.size(); ++i)
+00520         {
+00521 /*              if (i == 431)
+00522                         nlstop;
+00523 */
+00524                 uint    whichTip;
+00525                 // for both tips (start and stop)
+00526                 for (whichTip=0; whichTip<=1; ++whichTip)
+00527                 {
+00528                         // get the tip id
+00529                         uint    thisTip = (whichTip) ? _Chains[i].getStopTip() : _Chains[i].getStartTip();
+00530 
+00531                         if (thisTip != 0xffff && thisTip >= _Tips.size())
+00532                         {
+00533                                 nlwarning("in NLPACS::CLocalRetriever::computeLoopsAndTips()");
+00534                                 nlerror("checked a tip that doesn't exist on chain %d (tipId=%d)", i, thisTip);
+00535                         }
+00536 
+00537                         // if it is unaffected yet creates an new tip and affect it to the common chains
+00538                         if (thisTip == 0xffff)
+00539                         {
+00540                                 uint    turn;
+00541                                 uint    tipId = _Tips.size();
+00542 /*
+00543                                 if (tipId == 310)
+00544                                         nlstop;
+00545 */
+00546                                 _Tips.resize(tipId+1);
+00547                                 CTip    &tip = _Tips[tipId];
+00548                                 tip.Point = (whichTip) ? getStopVector(i) : getStartVector(i);
+00549 
+00550                                 for (turn=0; turn<=1; ++turn)
+00551                                 {
+00552                                         uint    chain = i;
+00553 
+00554                                         //
+00555                                         if (whichTip)
+00556                                                 _Chains[chain]._StopTip = tipId;
+00557                                         else
+00558                                                 _Chains[chain]._StartTip = tipId;
+00559 
+00560                                         sint32  surf = (!turn && !whichTip || turn && whichTip) ? _Chains[chain].getLeft() : _Chains[chain].getRight();
+00561 
+00562                                         while (surf >= 0)
+00563                                         {
+00564 
+00565                                                 CChain  &nextChain = (turn) ? _Chains[chain = getNextChain(chain, surf)] : _Chains[chain = getPreviousChain(chain, surf)];
+00566                                                 bool    isForward = (nextChain.getLeft() == surf);      // tells if the left surf is the current surf
+00567                                                 bool    selectTip = isForward && !turn || !isForward && turn;
+00568                                                 uint16  &tipRef = selectTip ? nextChain._StopTip : nextChain._StartTip;
+00569                                                 surf = (isForward) ? nextChain.getRight() : nextChain.getLeft();
+00570 
+00571                                                 if (tipRef != 0xffff && tipRef != tipId)
+00572                                                 {
+00573                                                         nlwarning("in NLPACS::CLocalRetriever::computeLoopsAndTips()");
+00574                                                         nlerror("Trying to setup a already created tip (tipId=%d, previous=%d)", tipId, tipRef);
+00575                                                 }
+00576                                                 else if (tipRef != 0xffff)
+00577                                                 {
+00578                                                         break;
+00579                                                 }
+00580 
+00581                                                 tipRef = tipId;
+00582                                         }
+00583                                 }
+00584                         }
+00585                 }
+00586         }
+00587 
+00588         for (i=0; i<_Chains.size(); ++i)
+00589         {
+00590                 uint    startTip = _Chains[i].getStartTip(),
+00591                                 stopTip = _Chains[i].getStopTip();
+00592 
+00593 /*
+00594                 if (_Chains[i].getEdge() >= 0 && startTip == stopTip)
+00595                 {
+00596                         nlwarning("NLPACS::CLocalRetriever::computeLoopsAndTips(): chain %d on edge %d has same StartTip and StopTip", i, _Chains[i].getEdge(), startTip, stopTip);
+00597                 }
+00598 */
+00599 
+00600                 _Tips[startTip].Chains.push_back(CTip::CChainTip(i, true));
+00601                 _Tips[stopTip].Chains.push_back(CTip::CChainTip(i, false));
+00602         }
+00603 
+00604         for (i=0; i<_Surfaces.size(); ++i)
+00605         {
+00606                 for (j=0; j<_Surfaces[i]._Loops.size(); ++j)
+00607                 {
+00608                         _Surfaces[i]._Loops[j].Length = 0.0f;
+00609                         uint    k;
+00610 
+00611                         for (k=0; k<_Surfaces[i]._Loops[j].size(); ++k)
+00612                                 _Surfaces[i]._Loops[j].Length += _Chains[_Surfaces[i]._Chains[_Surfaces[i]._Loops[j][k]].Chain].getLength();
+00613                 }
+00614         }
+00615 }
+00616 
+00617 
+00618 //
+00619 void    NLPACS::CLocalRetriever::buildSurfacePolygons(uint32 surface, list<CPolygon> &polygons) const
+00620 {
+00621         const CRetrievableSurface       &surf = _Surfaces[surface];
+00622 
+00623         uint    i, j, k, l;
+00624 
+00625         for (i=0; i<surf._Loops.size(); ++i)
+00626         {
+00627                 polygons.push_back();
+00628                 CPolygon        &poly = polygons.back();
+00629 
+00630                 for (j=0; j<surf._Loops[i].size(); ++j)
+00631                 {
+00632                         const CChain    &chain = _Chains[surf._Loops[i][j]];
+00633                         bool                    chainforward = ((uint32)chain._Left == surface);
+00634 
+00635                         if (chainforward)
+00636                         {
+00637                                 for (k=0; k<chain._SubChains.size(); ++k)
+00638                                 {
+00639                                         const COrderedChain             &ochain = _OrderedChains[chain._SubChains[k]];
+00640                                         bool                                    ochainforward = ochain.isForward();
+00641 
+00642                                         if (ochainforward)
+00643                                         {
+00644                                                 for (l=0; l<ochain.getVertices().size()-1; ++l)
+00645                                                         poly.Vertices.push_back(ochain[l].unpack3f());
+00646                                         }
+00647                                         else
+00648                                         {
+00649                                                 for (l=ochain.getVertices().size()-1; l>0; --l)
+00650                                                         poly.Vertices.push_back(ochain[l].unpack3f());
+00651                                         }
+00652                                 }
+00653                         }
+00654                         else
+00655                         {
+00656                                 for (k=chain._SubChains.size(); (sint)k>0; --k)
+00657                                 {
+00658                                         const COrderedChain             &ochain = _OrderedChains[chain._SubChains[k]];
+00659                                         bool                                    ochainforward = ochain.isForward();
+00660 
+00661                                         if (ochainforward)
+00662                                         {
+00663                                                 for (l=ochain.getVertices().size()-1; (sint)l>0; --l)
+00664                                                         poly.Vertices.push_back(ochain[l].unpack3f());
+00665                                         }
+00666                                         else
+00667                                         {
+00668                                                 for (l=0; l<ochain.getVertices().size()-1; ++l)
+00669                                                         poly.Vertices.push_back(ochain[l].unpack3f());
+00670                                         }
+00671                                 }
+00672                         }
+00673                 }
+00674         }
+00675 }
+00676 
+00677 
+00678 // not implemented...
+00679 void    NLPACS::CLocalRetriever::sortTips()
+00680 {
+00681 }
+00682 
+00683 
+00684 
+00685 
+00686 void    NLPACS::CLocalRetriever::findBorderChains()
+00687 {
+00688         uint    chain;
+00689 
+00690         // for each chain, if it belongs to an edge of the
+00691         // local retriever, then adds it to the _BorderChains.
+00692         for (chain=0; chain<_Chains.size(); ++chain)
+00693                 if (_Chains[chain].isBorderChain())
+00694                 {
+00695                         sint32  index = _BorderChains.size();
+00696                         _BorderChains.push_back(chain);
+00697                         _Chains[chain].setBorderChainIndex(index);
+00698                 }
+00699 }
+00700 
+00701 void    NLPACS::CLocalRetriever::updateChainIds()
+00702 {
+00703         uint    surf, link;
+00704 
+00705         for (surf=0; surf<_Surfaces.size(); ++surf)
+00706         {
+00707                 CRetrievableSurface     &surface = _Surfaces[surf];
+00708 
+00709                 for (link=0; link<surface._Chains.size(); ++link)
+00710                 {
+00711                         sint32  chain = surface._Chains[link].Chain;
+00712 
+00713                         if (_Chains[chain]._Left == (sint32)surf)
+00714                                 surface._Chains[link].Surface = _Chains[chain]._Right;
+00715                         else if (_Chains[chain]._Right == (sint32)surf)
+00716                                 surface._Chains[link].Surface = _Chains[chain]._Left;
+00717                         else
+00718                         {
+00719                                 nlwarning("in NLPACS::CLocalRetriever::updateEdgesOnSurfaces()");
+00720                                 nlerror("Can't find back point to surface %d on chain %d", surf, chain);
+00721                         }
+00722                 }
+00723         }
+00724 }
+00725 
+00726 void    NLPACS::CLocalRetriever::computeTopologies()
+00727 {
+00728         nlinfo("compute topologies");
+00729 
+00730         // Find topologies out...
+00731         uint            character;
+00732         for (character=0; character<NumCreatureModels; ++character)
+00733         {
+00734                 // for each type of creature, flood fill surfaces...
+00735                 sint32  surface;
+00736                 uint    topology = 0;
+00737 
+00738                 for (surface=0; surface<(sint)_Surfaces.size(); ++surface)
+00739                 {
+00740                         if (_Surfaces[surface]._Topologies[character] == -1 &&
+00741                                 _Surfaces[surface]._Character == character)
+00742                         {
+00743                                 vector<sint32>  surfacesStack;
+00744                                 surfacesStack.push_back(surface);
+00745 
+00746                                 while (!surfacesStack.empty())
+00747                                 {
+00748                                         CRetrievableSurface     &current = _Surfaces[surfacesStack.back()];
+00749                                         surfacesStack.pop_back();
+00750                                         current._Topologies[character] = topology;
+00751 
+00752                                         uint    i;
+00753                                         for (i=0; i<current._Chains.size(); ++i)
+00754                                         {
+00755                                                 CChain  &chain = _Chains[current._Chains[i].Chain];
+00756                                                 sint32  link = (chain.getLeft() == surface) ? chain.getRight() : chain.getLeft();
+00757                                                 if (link>=0 && link<(sint)_Surfaces.size() &&
+00758                                                         _Surfaces[link]._Topologies[character] == -1 &&
+00759                                                         _Surfaces[link]._Character >= character)
+00760                                                 {
+00761                                                         surfacesStack.push_back(link);
+00762                                                         _Surfaces[link]._Topologies[character] = topology;
+00763                                                 }
+00764                                         }
+00765                                 }
+00766 
+00767                                 ++topology;
+00768                         }
+00769                 }
+00770 
+00771                 _Topologies[character].resize(topology);
+00772                 nlinfo("generated %d topologies for character %d", topology, character);
+00773         }
+00774 
+00775         uint            surface;
+00776         for (surface=0; surface<_Surfaces.size(); ++surface)
+00777         {
+00778                 CRetrievableSurface     &current = _Surfaces[surface];
+00779 
+00780                 for (character=0; character<NumCreatureModels; ++character)
+00781                         if (current._Topologies[character] >= 0)
+00782                                 _Topologies[character][current._Topologies[character]].push_back(surface);
+00783         }
+00784 }
+00785 
+00786 void    NLPACS::CLocalRetriever::translate(const NLMISC::CVector &translation)
+00787 {
+00788         uint    i;
+00789         for (i=0; i<_OrderedChains.size(); ++i)
+00790                 _OrderedChains[i].translate(translation);
+00791         for (i=0; i<_Surfaces.size(); ++i)
+00792                 _Surfaces[i].translate(translation);
+00793         for (i=0; i<_Tips.size(); ++i)
+00794                 _Tips[i].translate(translation);
+00795 }
+00796 
+00797 void    NLPACS::CLocalRetriever::serial(NLMISC::IStream &f)
+00798 {
+00799         /*
+00800         Version 0:
+00801                 - base version (with collision info).
+00802         Version 1:
+00803                 - interior vertices and faces, for interior ground snapping
+00804         Version 2:
+00805                 - face grid added.
+00806         Version 3:
+00807                 - identifier added.
+00808         */
+00809         sint    ver= f.serialVersion(3);
+00810 
+00811         uint    i;
+00812         f.serialCont(_Chains);
+00813         f.serialCont(_OrderedChains);
+00814         f.serialCont(_FullOrderedChains);
+00815         f.serialCont(_Surfaces);
+00816         f.serialCont(_Tips);
+00817         f.serialCont(_BorderChains);
+00818         for (i=0; i<NumCreatureModels; ++i)
+00819                 f.serialCont(_Topologies[i]);
+00820         f.serial(_ChainQuad);
+00821         f.serial(_BBox);
+00822         f.serialEnum(_Type);
+00823         f.serial(_ExteriorMesh);
+00824 
+00825         // a fix for old versions (with wrong _Type value)
+00826         if (_Type != CLocalRetriever::Interior) _Type = CLocalRetriever::Landscape;
+00827 
+00828         if (ver >= 1)
+00829         {
+00830                 f.serialCont(_InteriorVertices);
+00831                 f.serialCont(_InteriorFaces);
+00832 
+00833         }
+00834         if (ver >= 2)
+00835         {
+00836                 f.serial(_FaceGrid);
+00837         }
+00838         if (ver >= 3)
+00839         {
+00840                 f.serial(_Id);
+00841         }
+00842 }
+00843 
+00844 
+00845 
+00846 
+00847 
+00848 
+00849 
+00850 
+00851 bool    NLPACS::CLocalRetriever::insurePosition(NLPACS::ULocalPosition &local) const
+00852 {
+00853         if (local.Surface < 0 || local.Surface >= (sint)_Surfaces.size())
+00854         {
+00855                 nlwarning("PACS: can't insure position to inexistant surface %d", local.Surface);
+00856                 return false;
+00857         }
+00858 
+00859         // the surface
+00860         const NLPACS::CRetrievableSurface       &surface = _Surfaces[local.Surface];
+00861 
+00862         uint            i, j, k;
+00863         CVector2f       M = CVector2f(local.Estimation);
+00864         bool            moved = false;
+00865 
+00866         // for each chain and each subchain of the surface,
+00867         // check if point is located on the good side of the border (and far enough to avoid accuracy issues)
+00868         for (i=0; i<surface.getChains().size(); ++i)
+00869         {
+00870                 uint                                    ichain = surface.getChain(i).Chain;
+00871                 const NLPACS::CChain    &chain = _Chains[ichain];
+00872 
+00873                 for (j=0; j<chain.getSubChains().size(); ++j)
+00874                 {
+00875                         uint                                            iochain = chain.getSubChain(j);
+00876                         const NLPACS::COrderedChain     &ochain = _OrderedChains[iochain];
+00877 
+00878                         uint                                            isAtLeft = ((chain.getLeft() == local.Surface) ? 1 : 0);
+00879                         uint                                            isForward = (ochain.isForward() ? 1 : 0);
+00880                         bool                                            shouldBeUpper = !((isAtLeft ^ isForward) != 0); // shouldBeAtLeft for vertical segment
+00881 
+00882                         for (k=0; (sint)k<(sint)(ochain.getVertices().size()-1); ++k)
+00883                         {
+00884                                 CVector2f       A = ochain[k].unpack();
+00885                                 CVector2f       B = ochain[k+1].unpack();
+00886                                 CVector2f       AB = B-A;
+00887 
+00888                                 float           lambda = ((M-A)*AB)/AB.sqrnorm();
+00889 
+00890                                 if (lambda<0.0f || lambda>1.0f)
+00891                                         continue;
+00892 
+00893                                 CVector2f       n = (shouldBeUpper ? CVector2f(-AB.y, AB.x) : CVector2f(AB.y, -AB.x)).normed();
+00894                                 float           d = (M-A)*n;
+00895 
+00896                                 // if point is too close of the border or on the wrong side
+00897                                 // move it far enough
+00898                                 if (d < InsurePositionThreshold && d > -InsurePositionThreshold)
+00899                                 {
+00900                                         M += (InsurePositionThreshold*1.1f-d)*n;
+00901                                         moved = true;
+00902                                 }
+00903                         }
+00904                 }
+00905         }
+00906 
+00907         NLPACS::CRetrieverInstance::snapVector(M);
+00908 
+00909         local.Estimation.x = M.x;
+00910         local.Estimation.y = M.y;
+00911 
+00912         {
+00913                 float   fx1024 = local.Estimation.x * 1024.0f;
+00914                 float   fy1024 = local.Estimation.x * 1024.0f;
+00915                 sint32  ix1024 = (sint32)floor(fx1024);
+00916                 sint32  iy1024 = (sint32)floor(fy1024);
+00917 
+00918                 nlassert ((float)ix1024 == fx1024);
+00919                 nlassert ((float)iy1024 == fy1024);
+00920         }
+00921 
+00922         return moved;
+00923 }
+00924 
+00925 
+00926 void    NLPACS::CLocalRetriever::retrievePosition(CVector estimated, /*std::vector<uint8> &retrieveTable,*/ CCollisionSurfaceTemp &cst) const
+00927 {
+00928         CAABBox                 box;
+00929         const double    BorderThreshold = 2.0e-2f;
+00930         box.setMinMax(CVector(estimated.x-(float)BorderThreshold, _BBox.getMin().y, 0.0f), CVector(estimated.x+(float)BorderThreshold, _BBox.getMax().y, 0.0f));
+00931         uint                    numEdges = _ChainQuad.selectEdges(box, cst);
+00932 
+00933         uint                    ochain, i;
+00934         CVector2s               estim = CVector2s(estimated);
+00935 
+00936         cst.PossibleSurfaces.clear();
+00937 
+00938         // WARNING!!
+00939         // cst.SurfaceLUT is assumed to be 0 filled !!
+00940 
+00941 //      nldebug("estim=(%d,%d)", estim.x, estim.y);
+00942 
+00943         // for each ordered chain, checks if the estimated position is between the min and max.
+00944         for (i=0; i<numEdges; ++i)
+00945         {
+00946                 ochain = cst.EdgeChainEntries[i].OChainId;
+00947 
+00948                 const COrderedChain     &sub = _OrderedChains[ochain];
+00949                 const CVector2s &min = sub.getMin(),
+00950                                                 &max = sub.getMax();
+00951 
+00952                 // checks the position against the min and max of the chain
+00953                 if (estim.x < min.x || estim.x > max.x)
+00954                         continue;
+00955 
+00956                 bool    isUpper;
+00957                 bool    isOnBorder = false;
+00958 
+00959                 sint32  left = _Chains[sub.getParentId()].getLeft(),
+00960                                 right = _Chains[sub.getParentId()].getRight();
+00961 
+00962                 if (estim.y < min.y)
+00963                 {
+00964                         if (estim.x == max.x)
+00965                                 continue;
+00966                         isUpper = false;
+00967 //                      nlinfo("Box: min(%d,%d) max(%d,%d) forward=%d left=%d right=%d upper=false", min.x, min.y, max.x, max.y, sub.isForward(), left, right);
+00968                 }
+00969                 else if (estim.y > max.y)
+00970                 {
+00971                         if (estim.x == max.x)
+00972                                 continue;
+00973                         isUpper = true;
+00974 //                      nlinfo("Box: min(%d,%d) max(%d,%d) forward=%d left=%d right=%d upper=true", min.x, min.y, max.x, max.y, sub.isForward(), left, right);
+00975                 }
+00976                 else
+00977                 {
+00978                         const vector<CVector2s> &vertices = sub.getVertices();
+00979                         uint                                    start = 0, stop = vertices.size()-1;
+00980 
+00982 
+00983                         // then finds the smallest segment of the chain that includes the estimated position.
+00984                         while (stop-start > 1)
+00985                         {
+00986                                 uint    mid = (start+stop)/2;
+00987 
+00988                                 if (vertices[mid].x > estim.x)
+00989                                         stop = mid;
+00990                                 else
+00991                                         start = mid;
+00992                         }
+00993 
+00994                         // if a vertical edge
+00995                         if (vertices[start].x == vertices[stop].x)
+00996                         {
+00997                                 // look for maximal bounds
+00998                                 while (start > 0 && vertices[start].x == vertices[start-1].x)
+00999                                         --start;
+01000 
+01001                                 while (stop < vertices.size()-1 && vertices[stop].x == vertices[stop+1].x)
+01002                                         ++stop;
+01003 
+01004                                 // if upper or lower the bounds, do nothing
+01005                                 if (estim.y > vertices[start].y && estim.y > vertices[stop].y ||
+01006                                         estim.y < vertices[start].y && estim.y < vertices[stop].y)
+01007                                         continue;
+01008 
+01009                                 isOnBorder = true;
+01010                                 cst.incSurface(left);
+01011                                 cst.incSurface(right);
+01012                                 if (left >= 0)  cst.SurfaceLUT[left].FoundCloseEdge = true;
+01013                                 if (right >= 0) cst.SurfaceLUT[right].FoundCloseEdge = true;
+01014                                 continue;
+01015 //                              nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d border=true", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right);
+01016                         }
+01017                         else if (vertices[stop].x == estim.x)
+01018                         {
+01019                                 // if 
+01020                                 continue;
+01021                         }
+01022 
+01023                         // and then checks if the estimated position is up or down the chain.
+01024 
+01025                         // first trivial case (up both tips)
+01026                         if (estim.y > vertices[start].y && estim.y > vertices[stop].y)
+01027                         {
+01028                                 isUpper = true;
+01029 //                              nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d upper=true", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right);
+01030                         }
+01031                         // second trivial case (down both tips)
+01032                         else if (estim.y < vertices[start].y && estim.y < vertices[stop].y)
+01033                         {
+01034                                 isUpper = false;
+01035 //                              nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d upper=false", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right);
+01036                         }
+01037                         // full test...
+01038                         else
+01039                         {
+01040                                 const CVector2s &vstart = vertices[start],
+01041                                                                 &vstop = vertices[stop];
+01042 
+01043                                 sint16                  intersect = vstart.y + (vstop.y-vstart.y)*(estim.x-vstart.x)/(vstop.x-vstart.x);
+01044 
+01045                                 isUpper = estim.y > intersect;
+01046                                 isOnBorder = (fabs(estim.y - intersect)<BorderThreshold*Vector2sAccuracy);
+01047 //                              nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d upper=%s border=%s", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right, isUpper ? "true":"false", isOnBorder ? "true":"false");
+01048                         }
+01049                 }
+01050 
+01051                 if (isOnBorder)
+01052                 {
+01053                         cst.incSurface(left);
+01054                         cst.incSurface(right);
+01055                         if (left >= 0)  cst.SurfaceLUT[left].FoundCloseEdge = true;
+01056                         if (right >= 0) cst.SurfaceLUT[right].FoundCloseEdge = true;
+01057                         continue;
+01058                 }
+01059 
+01060                 // Depending on the chain is forward, up the position, increase/decrease the surface table...
+01061                 if (sub.isForward())
+01062                 {
+01063                         if (isUpper)
+01064                         {
+01065                                 cst.incSurface(left);
+01066                                 cst.decSurface(right);
+01067                         }
+01068                         else
+01069                         {
+01070                                 cst.decSurface(left);
+01071                                 cst.incSurface(right);
+01072                         }
+01073                 }
+01074                 else
+01075                 {
+01076                         if (isUpper)
+01077                         {
+01078                                 cst.decSurface(left);
+01079                                 cst.incSurface(right);
+01080                         }
+01081                         else
+01082                         {
+01083                                 cst.incSurface(left);
+01084                                 cst.decSurface(right);
+01085                         }
+01086                 }
+01087         }
+01088 }
+01089 
+01090 
+01091 void    NLPACS::CLocalRetriever::initFaceGrid()
+01092 {
+01093         CFaceGrid::CFaceGridBuild       fgb;
+01094         fgb.init(64, 4.0f);
+01095 
+01096         uint    i;
+01097         for (i=0; i<_InteriorFaces.size(); ++i)
+01098         {
+01099                 CAABBox                 box;
+01100                 CInteriorFace   &f = _InteriorFaces[i];
+01101                 box.setCenter(_InteriorVertices[f.Verts[0]]);
+01102                 box.extend(_InteriorVertices[f.Verts[1]]);
+01103                 box.extend(_InteriorVertices[f.Verts[2]]);
+01104 
+01105                 fgb.insert(box.getMin(), box.getMax(), i);
+01106         }
+01107 
+01108         _FaceGrid.create(fgb);
+01109 }
+01110 
+01111 void    NLPACS::CLocalRetriever::snapToInteriorGround(NLPACS::ULocalPosition &position, bool &snapped) const
+01112 {
+01113         // first preselect faces around the (x, y) position (CQuadGrid ?)
+01114         vector<uint32>  selection;
+01115         _FaceGrid.select(position.Estimation, selection);
+01116 
+01117         // from the preselect faces, look for the only face that belongs to the surface
+01118         // and that contains the position
+01119         CVector                                         pos = position.Estimation;
+01120         CVector                                         posh = pos+CVector(0.0f, 0.0f, 1.0f);
+01121         CVector2f                                       pos2d = position.Estimation;
+01122         float                                           bestDist = 1.0e10f;
+01123         CVector                                         best;
+01124         vector<uint32>::iterator        it;
+01125         snapped = false;
+01126         for (it=selection.begin(); it!=selection.end(); ++it)
+01127         {
+01128                 const CInteriorFace     &f = _InteriorFaces[*it];
+01129                 if (f.Surface == (uint32)position.Surface)
+01130                 {
+01131                         CVector v[3];
+01132                         v[0] = _InteriorVertices[f.Verts[0]];
+01133                         v[1] = _InteriorVertices[f.Verts[1]];
+01134                         v[2] = _InteriorVertices[f.Verts[2]];
+01135 
+01136                         CVector2f       n;
+01137                         float           c;                      // 2D cartesian coefficients of line in plane X/Y.
+01138                         // Line p0-p1.
+01139                         n = CVector2f(-(v[1].y-v[0].y), (v[1].x-v[0].x)).normed();
+01140                         c = -(v[0].x*n.x + v[0].y*n.y);
+01141                         if (n*pos2d + c < -1.0f/Vector2sAccuracy)       continue;
+01142                         // Line p1-p2.
+01143                         n = CVector2f(-(v[2].y-v[1].y), (v[2].x-v[1].x)).normed();
+01144                         c = -(v[1].x*n.x + v[1].y*n.y);
+01145                         if (n*pos2d + c < -1.0f/Vector2sAccuracy)       continue;
+01146                         //  Line p2-p0.
+01147                         n = CVector2f(-(v[0].y-v[2].y), (v[0].x-v[2].x)).normed();
+01148                         c = -(v[2].x*n.x + v[2].y*n.y);
+01149                         if (n*pos2d + c < -1.0f/Vector2sAccuracy)       continue;
+01150 
+01151                         CPlane  p;
+01152                         p.make(v[0], v[1], v[2]);
+01153 
+01154                         CVector i = p.intersect(pos, posh);
+01155 
+01156                         float   d = (float)fabs(pos.z-i.z);
+01157 
+01158                         if (d < bestDist)
+01159                         {
+01160                                 bestDist = d;
+01161                                 best = i;
+01162                         }
+01163                 }
+01164         }
+01165 
+01166         // and computes the real position on this face
+01167         if (bestDist < 50.0f)
+01168         {
+01169                 snapped = true;
+01170                 position.Estimation = best;
+01171         }
+01172 }
+01173 
+01174 float   NLPACS::CLocalRetriever::getHeight(const NLPACS::ULocalPosition &position) const
+01175 {
+01176         if (_Type == Interior)
+01177         {
+01178                 // first preselect faces around the (x, y) position (CQuadGrid ?)
+01179                 vector<uint32>  selection;
+01180                 _FaceGrid.select(position.Estimation, selection);
+01181 
+01182                 // from the preselect faces, look for the only face that belongs to the surface
+01183                 // and that contains the position
+01184                 CVector pos = position.Estimation;
+01185                 CVector posh = pos+CVector(0.0f, 0.0f, 1.0f);
+01186                 float   bestDist = 1.0e10f;
+01187                 CVector best;
+01188                 vector<uint32>::iterator        it;
+01189                 for (it=selection.begin(); it!=selection.end(); ++it)
+01190                 {
+01191                         const CInteriorFace     &f = _InteriorFaces[*it];
+01192                         if (f.Surface == (uint32)position.Surface)
+01193                         {
+01194                                 CVector v[3];
+01195                                 v[0] = _InteriorVertices[f.Verts[0]];
+01196                                 v[1] = _InteriorVertices[f.Verts[1]];
+01197                                 v[2] = _InteriorVertices[f.Verts[2]];
+01198 
+01199                                 float           a,b,c;          // 2D cartesian coefficients of line in plane X/Y.
+01200                                 // Line p0-p1.
+01201                                 a = -(v[1].y-v[0].y);
+01202                                 b =  (v[1].x-v[0].x);
+01203                                 c = -(v[0].x*a + v[0].y*b);
+01204                                 if (a*pos.x + b*pos.y + c < 0)  continue;
+01205                                 // Line p1-p2.
+01206                                 a = -(v[2].y-v[1].y);
+01207                                 b =  (v[2].x-v[1].x);
+01208                                 c = -(v[1].x*a + v[1].y*b);
+01209                                 if (a*pos.x + b*pos.y + c < 0)  continue;
+01210                                 //  Line p2-p0.
+01211                                 a = -(v[0].y-v[2].y);
+01212                                 b =  (v[0].x-v[2].x);
+01213                                 c = -(v[2].x*a + v[2].y*b);
+01214                                 if (a*pos.x + b*pos.y + c < 0)  continue;
+01215 
+01216                                 CPlane  p;
+01217                                 p.make(v[0], v[1], v[2]);
+01218 
+01219                                 CVector i = p.intersect(pos, posh);
+01220 
+01221                                 float   d = (float)fabs(pos.z-i.z);
+01222 
+01223                                 if (d < bestDist)
+01224                                 {
+01225                                         bestDist = d;
+01226                                         best = i;
+01227                                 }
+01228                         }
+01229                 }
+01230 
+01231                 // and computes the real position on this face
+01232                 return (bestDist < 50.0f) ?     best.z : position.Estimation.z;
+01233         }
+01234         else
+01235         {
+01236 
+01237                 // find quad leaf.
+01238                 const CQuadLeaf *leaf = _Surfaces[position.Surface].getQuadTree().getLeaf(position.Estimation);
+01239 
+01240                 // if there is no acceptable leaf, just give up
+01241                 if (leaf == NULL)
+01242                 {
+01243                         //nlinfo("COL: quadtree: don't find the quadLeaf!");
+01244                         return position.Estimation.z;
+01245                 }
+01246                 else
+01247                 {
+01248                         // else return mean height.
+01249                         float   meanHeight = (leaf->getMinHeight()+leaf->getMaxHeight())*0.5f;
+01250                         return meanHeight;
+01251                 }
+01252 
+01253 //              return _Surfaces[position.Surface].getQuadTree().getInterpZ(position.Estimation);
+01254         }
+01255 }
+01256 
+01257 
+01258 
+01259 #ifdef NL_OS_WINDOWS
+01260 #pragma optimize( "", off )
+01261 #endif // NL_OS_WINDOWS
+01262 
+01263 void    NLPACS::CLocalRetriever::findPath(const NLPACS::CLocalRetriever::CLocalPosition &A, 
+01264                                                                                   const NLPACS::CLocalRetriever::CLocalPosition &B, 
+01265                                                                                   std::vector<NLPACS::CVector2s> &path, 
+01266                                                                                   NLPACS::CCollisionSurfaceTemp &cst) const
+01267 {
+01268         if (A.Surface != B.Surface)
+01269         {
+01270                 nlwarning("in NLPACS::CLocalRetriever::findPath()");
+01271                 nlerror("Try to find a path between 2 points that are not in the same surface (A=%d, B=%d)", A.Surface, B.Surface);
+01272         }
+01273 
+01274         CVector         a = A.Estimation,
+01275                                 b = B.Estimation,
+01276                                 n = CVector(a.y-b.y, b.x-a.x, 0.0f);
+01277 
+01278         _ChainQuad.selectEdges(a, b, cst);
+01279 
+01281         vector<CIntersectionMarker>     intersections;
+01282 
+01283         uint    i, j;
+01284         sint32  surfaceId = A.Surface;
+01285         const CRetrievableSurface       &surface = _Surfaces[surfaceId];
+01286 
+01287         for (i=0; i<cst.EdgeChainEntries.size(); ++i)
+01288         {
+01289                 CEdgeChainEntry         &entry = cst.EdgeChainEntries[i];
+01290                 const COrderedChain     &chain = _OrderedChains[entry.OChainId];
+01291 
+01292                 if (_Chains[chain.getParentId()].getLeft() != surfaceId &&
+01293                         _Chains[chain.getParentId()].getRight() != surfaceId)
+01294                         continue;
+01295 
+01296                 for (j=entry.EdgeStart; j<entry.EdgeEnd; ++j)
+01297                 {
+01298                         // here the edge collision test
+01299 
+01300                         CVector p0 = chain[j].unpack3f(),
+01301                                         p1 = chain[j+1].unpack3f();
+01302 
+01303                         float   vp0 = (p0-a)*n,
+01304                                         vp1 = (p1-a)*n;
+01305 
+01306                         if (vp0*vp1 <= 0.0f)
+01307                         {
+01308                                 CVector np = CVector(p0.y-p1.y, p1.x-p0.x, 0.0f);
+01309 
+01310                                 float   va = (a-p0)*np,
+01311                                                 vb = (b-p0)*np;
+01312 
+01313                                 // here we have an intersection
+01314                                 if (va*vb <= 0.0f)
+01315                                 {
+01316                                         const CChain    &parent = _Chains[chain.getParentId()];
+01317                                         bool                    isIn = (va-vb < 0.0f) ^ (parent.getLeft() == surfaceId) ^ chain.isForward();
+01318 
+01319                                         intersections.push_back(CIntersectionMarker(va/(va-vb), entry.OChainId, j, isIn));
+01320                                 }
+01321                         }
+01322                 }
+01323         }
+01324 
+01325         sort(intersections.begin(), intersections.end());
+01326 
+01327         uint    intersStart = 0;
+01328         uint    intersEnd = intersections.size();
+01329 
+01330         if (intersEnd > 0)
+01331         {
+01332                 while (intersStart < intersections.size() &&
+01333                            intersections[intersStart].In && intersections[intersStart].Position < 1.0e-4f)
+01334                         ++intersStart;
+01335 
+01336                 while (intersStart < intersEnd &&
+01337                            !intersections[intersEnd-1].In && intersections[intersEnd-1].Position > 1.0f-1.0e-4f)
+01338                         --intersEnd;
+01339 
+01340                 // Check intersections have a valid order
+01341                 if ((intersEnd-intersStart) & 1)
+01342                 {
+01343                         nlwarning("in NLPACS::CLocalRetriever::findPath()");
+01344                         nlerror("Found an odd (%d) number of intersections", intersections.size());
+01345                 }
+01346                 
+01347                 for (i=intersStart; i<intersEnd; )
+01348                 {
+01349                         uint    exitLoop, enterLoop;
+01350 
+01351                         const CChain    &exitChain = _Chains[_OrderedChains[intersections[i].OChain].getParentId()];
+01352                         exitLoop = (exitChain.getLeft() == surfaceId) ? exitChain.getLeftLoop() : exitChain.getRightLoop();
+01353 
+01354                         if (intersections[i++].In)
+01355                         {
+01356                                 nlwarning("in NLPACS::CLocalRetriever::findPath()");
+01357                                 nlerror("Entered the surface before exited", intersections.size());
+01358                         }
+01359 
+01360                         const CChain    &enterChain = _Chains[_OrderedChains[intersections[i].OChain].getParentId()];
+01361                         enterLoop = (enterChain.getLeft() == surfaceId) ? enterChain.getLeftLoop() : enterChain.getRightLoop();
+01362 
+01363                         if (!intersections[i++].In)
+01364                         {
+01365                                 nlwarning("in NLPACS::CLocalRetriever::findPath()");
+01366                                 nlerror("Exited twice the surface", intersections.size());
+01367                         }
+01368 
+01369                         if (exitLoop != enterLoop)
+01370                         {
+01371                                 nlwarning("in NLPACS::CLocalRetriever::findPath()");
+01372                                 nlerror("Exited and rentered by a different loop");
+01373                         }
+01374                 }
+01375         }
+01376 
+01377 //      dumpSurface(surfaceId);
+01378 
+01379         path.push_back(CVector2s(A.Estimation));
+01380 
+01381         for (i=intersStart; i<intersEnd; )
+01382         {
+01383                 uint                                                            exitChainId = _OrderedChains[intersections[i].OChain].getParentId(),
+01384                                                                                         enterChainId = _OrderedChains[intersections[i+1].OChain].getParentId();
+01385                 const CChain                                            &exitChain = _Chains[exitChainId],
+01386                                                                                         &enterChain = _Chains[enterChainId];
+01387                 uint                                                            loopId, exitLoopIndex, enterLoopIndex;
+01388 
+01389                 if (exitChain.getLeft() == surfaceId)
+01390                 {
+01391                         loopId = exitChain.getLeftLoop();
+01392                         exitLoopIndex = exitChain.getLeftLoopIndex();
+01393                 }
+01394                 else
+01395                 {
+01396                         loopId = exitChain.getRightLoop();
+01397                         exitLoopIndex = exitChain.getRightLoopIndex();
+01398                 }
+01399 
+01400                 const CRetrievableSurface::TLoop        &loop = surface._Loops[loopId];
+01401 
+01402                 if (enterChain.getLeft() == surfaceId)
+01403                         enterLoopIndex = enterChain.getLeftLoopIndex();
+01404                 else
+01405                         enterLoopIndex = enterChain.getRightLoopIndex();
+01406 
+01407                 float                   forwardLength = (exitChain.getLength()+enterChain.getLength())*0.5f;
+01408 
+01409                 sint    loopIndex = exitLoopIndex;
+01410                 uint    thisChainId = exitChainId;
+01411                 bool    thisChainForward = (enterChain.getLeft() == surfaceId);
+01412                 uint    thisOChainId = intersections[i].OChain;
+01413                 sint    thisOChainIndex = _OrderedChains[thisOChainId].getIndexInParent();
+01414                 bool    forward;
+01415 
+01416                 if (exitChainId != enterChainId)
+01417                 {
+01418                         for (j=(exitLoopIndex+1)%loop.size(); j!=enterLoopIndex; j=(j+1)%loop.size())
+01419                                 forwardLength += _Chains[surface._Chains[loop[j]].Chain].getLength();
+01420                         forward = (forwardLength <= loop.Length-forwardLength);
+01421                 }
+01422                 else
+01423                 {
+01424                         forward = !thisChainForward ^ (_OrderedChains[intersections[i].OChain].getIndexInParent() < _OrderedChains[intersections[i+1].OChain].getIndexInParent());
+01425                 }
+01426 
+01427                 path.push_back(CVector2s(A.Estimation+intersections[i].Position*(B.Estimation-A.Estimation)));
+01428 
+01429                 while (true)
+01430                 {
+01431                         sint    from = (thisOChainId == intersections[i].OChain) ? intersections[i].Edge : -1,
+01432                                         to = (thisOChainId == intersections[i+1].OChain) ? intersections[i+1].Edge : -1;
+01433                         bool    oforward = thisChainForward ^ forward ^ _OrderedChains[thisOChainId].isForward();
+01434 
+01435                         if (from != -1 && to != -1)
+01436                                 oforward = (intersections[i].Edge < intersections[i+1].Edge);
+01437 
+01438                         _OrderedChains[thisOChainId].traverse(from, to, oforward, path);
+01439 
+01440                         if (thisOChainId == intersections[i+1].OChain)
+01441                                 break;
+01442 
+01443                         thisOChainIndex = (thisChainForward ^ forward) ? thisOChainIndex-1 : thisOChainIndex+1;
+01444 
+01445                         if (thisOChainIndex < 0 || thisOChainIndex >= (sint)_Chains[thisChainId]._SubChains.size())
+01446                         {
+01447                                 if (forward)
+01448                                 {
+01449                                         loopIndex++;
+01450                                         if (loopIndex == (sint)loop.size())
+01451                                                 loopIndex = 0;
+01452                                 }
+01453                                 else
+01454                                 {
+01455                                         loopIndex--;
+01456                                         if (loopIndex < 0)
+01457                                                 loopIndex = loop.size()-1;
+01458                                 }
+01459 
+01460                                 thisChainId = surface._Chains[loop[loopIndex]].Chain;
+01461                                 thisChainForward = (_Chains[thisChainId].getLeft() == surfaceId);
+01462                                 thisOChainIndex = (thisChainForward && forward || !thisChainForward && !forward) ? 
+01463                                         0 : _Chains[thisChainId]._SubChains.size()-1;
+01464                         }
+01465 
+01466                         thisOChainId = _Chains[thisChainId]._SubChains[thisOChainIndex];
+01467                 }
+01468 
+01469                 path.push_back(CVector2s(A.Estimation+intersections[i+1].Position*(B.Estimation-A.Estimation)));
+01470                 i += 2;
+01471         }
+01472 
+01473         path.push_back(CVector2s(B.Estimation));
+01474 }
+01475 #ifdef NL_OS_WINDOWS
+01476 #pragma optimize( "", on ) 
+01477 #endif // NL_OS_WINDOWS
+01478 
+01479 // ***************************************************************************
+01480 // ***************************************************************************
+01481 // Collisions part.
+01482 // ***************************************************************************
+01483 // ***************************************************************************
+01484 
+01485 
+01486 // ***************************************************************************
+01487 void    NLPACS::CLocalRetriever::computeCollisionChainQuad()
+01488 {
+01489         _ChainQuad.build(_OrderedChains);
+01490 }
+01491 
+01492 
+01493 // ***************************************************************************
+01494 void    NLPACS::CLocalRetriever::testCollision(CCollisionSurfaceTemp &cst, const CAABBox &bboxMove, const CVector2f &transBase) const
+01495 {
+01496 //      H_AUTO(PACS_LR_testCollision);
+01497 
+01498         sint    i;
+01499 
+01500         // 0. select ordered chains in the chainquad.
+01501         //=====================================
+01502 //      H_BEFORE(PACS_LR_testCol_selEdges);
+01503         sint    nEce= _ChainQuad.selectEdges(bboxMove, cst);
+01504 //      H_AFTER(PACS_LR_testCol_selEdges);
+01505         // NB: cst.OChainLUT is assured to be full of 0xFFFF after this call (if was right before).
+01506 
+01507 
+01508         // 1. regroup them in chains. build cst.CollisionChains
+01509         //=====================================
+01510         // NB: use cst.OChainLUT to look if a Chain has been inserted before.
+01511         uint16  *chainLUT= cst.OChainLUT;
+01512 
+01513         // bkup where we begin to add chains.
+01514         uint    firstChainAdded= cst.CollisionChains.size();
+01515 
+01516         // For all edgechain entry.
+01517         for(i=0;i<nEce;i++)
+01518         {
+01519                 CEdgeChainEntry         &ece= cst.EdgeChainEntries[i];
+01520                 // this is the ordered chain in the retriever.
+01521                 const   COrderedChain   &oChain= this->getOrderedChains()[ece.OChainId];
+01522                 // this is the id of the chain is the local retriever.
+01523                 uint16                          chainId= oChain.getParentId();
+01524 
+01525 
+01526                 // add/retrieve the id in cst.CollisionChains.
+01527                 //=================================
+01528                 uint                            ccId;
+01529                 // if never added.
+01530                 if(chainLUT[chainId]==0xFFFF)
+01531                 {
+01532 //                      H_AUTO(PACS_LR_testCol_addToLUT);
+01533                         // add a new CCollisionChain.
+01534                         ccId= cst.CollisionChains.size();
+01535                         cst.CollisionChains.push_back(CCollisionChain());
+01536                         // Fill it with default.
+01537                         cst.CollisionChains[ccId].Tested= false;
+01538                         cst.CollisionChains[ccId].ExteriorEdge = false;
+01539                         cst.CollisionChains[ccId].FirstEdgeCollide= 0xFFFFFFFF;
+01540                         cst.CollisionChains[ccId].ChainId= chainId;
+01541                         // Fill Left right info.
+01542                         cst.CollisionChains[ccId].LeftSurface.SurfaceId= this->getChains()[chainId].getLeft();
+01543                         cst.CollisionChains[ccId].RightSurface.SurfaceId= this->getChains()[chainId].getRight();
+01544                         // NB: cst.CollisionChains[ccId].*Surface.RetrieverInstanceId is not filled here because we don't have
+01545                         // this info at this level.
+01546 
+01547                         // store this Id in the LUT of chains.
+01548                         chainLUT[chainId]= ccId;
+01549                 }
+01550                 else
+01551                 {
+01552                         // get the id of this collision chain.
+01553                         ccId= chainLUT[chainId];
+01554                 }
+01555 
+01556                 // add edge collide to the list.
+01557                 //=================================
+01558 //              H_BEFORE(PACS_LR_testCol_addToList);
+01559                 CCollisionChain                 &colChain= cst.CollisionChains[ccId];
+01560                 const std::vector<CVector2s>    &oChainVertices= oChain.getVertices();
+01561                 for(sint edge=ece.EdgeStart; edge<ece.EdgeEnd; edge++)
+01562                 {
+01563                         CVector2f       p0= oChainVertices[edge].unpack();
+01564                         CVector2f       p1= oChainVertices[edge+1].unpack();
+01565 
+01566                         // alloc a new edgeCollide.
+01567                         uint32  ecnId= cst.allocEdgeCollideNode();
+01568                         CEdgeCollideNode        &ecn= cst.getEdgeCollideNode(ecnId);
+01569 
+01570                         // append to the front of the list.
+01571                         ecn.Next= colChain.FirstEdgeCollide;
+01572                         colChain.FirstEdgeCollide= ecnId;
+01573 
+01574                         // build this edge.
+01575                         p0+= transBase;
+01576                         p1+= transBase;
+01577                         ecn.make(p0, p1);
+01578                 }
+01579 //              H_AFTER(PACS_LR_testCol_addToList);
+01580         }
+01581 
+01582 
+01583 
+01584         // 2. Reset LUT to 0xFFFF.
+01585         //=====================================
+01586 
+01587 //      H_BEFORE(PACS_LR_testCol_resetLUT);
+01588         // for all collisions chains inserted (starting from firstChainAdded), reset LUT.
+01589         for(i=firstChainAdded; i<(sint)cst.CollisionChains.size(); i++)
+01590         {
+01591                 uint    ccId= cst.CollisionChains[i].ChainId;
+01592                 chainLUT[ccId]= 0xFFFF;
+01593         }
+01594 //      H_AFTER(PACS_LR_testCol_resetLUT);
+01595 }
+01596 
+01597 
+01598 // ***************************************************************************
+01599 // ***************************************************************************
+01600 // ***************************************************************************
+01601 // ***************************************************************************
+01602 
+01603 
+01604 // ***************************************************************************
+01605 void    NLPACS::CLocalRetriever::buildInteriorSurfaceBBoxes(std::vector<NLMISC::CAABBox>        &surfaceBBoxes) const
+01606 {
+01607         // resize dest, and init.
+01608         vector<bool>    firstTriangle;
+01609         surfaceBBoxes.clear();
+01610         surfaceBBoxes.resize(_Surfaces.size());
+01611         firstTriangle.resize(_Surfaces.size(), true);
+01612 
+01613         // For all _InteriorFaces.
+01614         for(uint iIntFace=0; iIntFace<_InteriorFaces.size(); iIntFace++)
+01615         {
+01616                 const CInteriorFace     &intFace= _InteriorFaces[iIntFace];
+01617 
+01618                 // Extend the surface of this face with her 3 points.
+01619 
+01620                 // check good id.
+01621                 if(intFace.Surface==(uint)-1)
+01622                         continue;
+01623                 nlassert(intFace.Surface<_Surfaces.size());
+01624 
+01625                 // If first time we extend the bbox of this surface
+01626                 if(firstTriangle[intFace.Surface])
+01627                 {
+01628                         surfaceBBoxes[intFace.Surface].setCenter(_InteriorVertices[intFace.Verts[0]] );
+01629                         firstTriangle[intFace.Surface]= false;
+01630                 }
+01631                 else
+01632                         surfaceBBoxes[intFace.Surface].extend(_InteriorVertices[intFace.Verts[0]] );
+01633 
+01634                 // extend with other 2 points
+01635                 surfaceBBoxes[intFace.Surface].extend(_InteriorVertices[intFace.Verts[1]] );
+01636                 surfaceBBoxes[intFace.Surface].extend(_InteriorVertices[intFace.Verts[2]] );
+01637         }
+01638 
+01639 }
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1