Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / src / pacs / retriever_instance.cpp
blobd5d96510cf996458c4df2cf142ffe964597f1639
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpacs.h"
19 #include "nel/pacs/retriever_instance.h"
20 #include "nel/pacs/global_retriever.h"
22 using namespace std;
23 using namespace NLMISC;
27 NLPACS::CRetrieverInstance::CRetrieverInstance()
29 reset();
33 void NLPACS::CRetrieverInstance::resetLinks()
35 uint i;
36 // WARNING !!
37 // this is a HARD reset !
38 // only the instance i reset, no care about neighbors !!
39 for (i=0; i<_Neighbors.size(); ++i)
40 _Neighbors[i] = -1;
41 _BorderChainLinks.clear();
43 _ExteriorEdgeQuad.removeLinks();
46 void NLPACS::CRetrieverInstance::resetLinks(uint32 id)
48 vector<sint32>::iterator rit;
49 for (rit=_Neighbors.begin(); rit!=_Neighbors.end(); )
50 if (*rit == (sint32)id)
51 rit = _Neighbors.erase(rit);
52 else
53 ++rit;
55 uint i;
56 for (i=0; i<_BorderChainLinks.size(); ++i)
57 if (_BorderChainLinks[i].Instance == (uint16)id)
58 _BorderChainLinks[i].reset();
60 _ExteriorEdgeQuad.removeLinks(id);
63 void NLPACS::CRetrieverInstance::reset()
65 // WARNING !!
66 // this is a HARD reset !
67 // only the instance i reset, no care about neighbors !!
68 _NodesInformation.clear();
69 _InstanceId = -1;
70 _RetrieverId = -1;
71 _Orientation = 0;
72 _Origin = CVector::Null;
73 _Type = CLocalRetriever::Landscape;
74 _BorderChainLinks.clear();
75 _ExteriorEdgeQuad.clear();
77 resetLinks();
80 void NLPACS::CRetrieverInstance::init(const CLocalRetriever &retriever)
82 if (!retriever.isLoaded())
83 return;
85 _NodesInformation.resize(retriever.getSurfaces().size());
86 uint i;
88 // Resets _NodesInformation for later pathfinding graph annotation.
89 for (i=0; i<_NodesInformation.size(); ++i)
91 CVector pos = getGlobalPosition(retriever.getSurfaces()[i].getCenter());
92 _NodesInformation[i].Position = CVector2f(pos.x, pos.y);
96 _Type = retriever.getType();
97 _BorderChainLinks.resize(retriever.getBorderChains().size());
100 void NLPACS::CRetrieverInstance::make(sint32 instanceId, sint32 retrieverId, const CLocalRetriever &retriever,
101 uint8 orientation, const CVector &origin)
103 if (_InstanceId != -1 || _RetrieverId != -1)
105 nlwarning("in call to NLPACS::CRetrieverInstance::make");
106 nlwarning("_InstanceId=%d _RetrieverId=%d _Orientation=%d", _InstanceId, _RetrieverId, _Orientation);
107 nlwarning("instanceId=%d retrieverId=%d orientation=%d", instanceId, retrieverId, orientation);
108 nlerror("Retriever instance %d has already been set", _InstanceId);
111 _InstanceId = instanceId;
112 _RetrieverId = retrieverId;
113 _Orientation = (orientation%4);
114 _Origin = origin;
116 _BBox = retriever.getBBox();
117 _BBox.setCenter(_BBox.getCenter()+_Origin);
119 if (_Orientation == 1 || _Orientation == 3)
121 CVector hs = _BBox.getHalfSize();
122 std::swap(hs.x, hs.y);
123 _BBox.setHalfSize(hs);
126 init(retriever);
130 void NLPACS::CRetrieverInstance::initEdgeQuad(NLPACS::CGlobalRetriever &gr)
132 const CLocalRetriever &lr = gr.getRetriever(_RetrieverId);
134 if (lr.getType() != CLocalRetriever::Interior)
136 nlerror("Attempt to init the edgequad of instance %d whereas local retriever %d is not interior", _InstanceId, _RetrieverId);
139 // build the edge quad
140 _ExteriorEdgeQuad.build(lr.getExteriorMesh(), gr, gr.getInternalCST(),_InstanceId);
143 void NLPACS::CRetrieverInstance::linkEdgeQuad(NLPACS::CGlobalRetriever &gr)
145 const CLocalRetriever &lr = gr.getRetriever(_RetrieverId);
146 const CExteriorMesh &em = lr.getExteriorMesh();
148 const vector<CExteriorEdgeEntry> &ee = _ExteriorEdgeQuad.getEdgeEntries();
150 // here we fill (partially) the _BorderChainLinks table
151 uint i;
152 for (i=0; i<ee.size(); ++i)
154 const CExteriorMesh::CEdge &edge = em.getEdge(ee[i].EdgeId);
155 if (edge.Link != -1)
157 const CExteriorMesh::CLink &link = em.getLink(edge.Link);
159 if (link.SurfaceId != 0xFFFF && link.ChainId != 0xFFFF && link.BorderChainId != 0xFFFF)
161 CRetrieverInstance::CLink &borderLink = _BorderChainLinks[link.BorderChainId];
162 borderLink.ChainId = 0xFFFF; // no opposite chain
163 borderLink.BorderChainId = 0xFFFF; // idem
164 if ((borderLink.Instance == 0xFFFF && borderLink.SurfaceId == 0xFFFF) ||
165 (borderLink.Instance == (uint16)(ee[i].Exterior.RetrieverInstanceId) &&
166 borderLink.SurfaceId == (uint16)(ee[i].Exterior.SurfaceId) ))
168 borderLink.Instance = (uint16)(ee[i].Exterior.RetrieverInstanceId);
169 borderLink.SurfaceId = (uint16)(ee[i].Exterior.SurfaceId);
171 else
173 nlwarning("Instance %d, borderLink %d: link already set to inst=%d, surf=%d, try to set to inst=%d, surf=%d",
174 _InstanceId, link.BorderChainId, borderLink.Instance, borderLink.SurfaceId,
175 (uint16)(ee[i].Exterior.RetrieverInstanceId), (uint16)(ee[i].Exterior.SurfaceId));
182 /* Links the current retriever instance to another instance
183 * on the given edge.
185 void NLPACS::CRetrieverInstance::link(CRetrieverInstance &neighbor,
186 const vector<CLocalRetriever> &retrievers)
188 uint i, j;
189 for (i=0; i<_Neighbors.size(); ++i)
190 if (_Neighbors[i] == neighbor._InstanceId)
191 return;
193 const CLocalRetriever &retriever = retrievers[_RetrieverId];
194 const CLocalRetriever &nRetriever = retrievers[neighbor._RetrieverId];
196 const vector<CChain> &chains = retriever.getChains(),
197 &nChains = nRetriever.getChains();
198 const vector<uint16> &borderChains = retriever.getBorderChains(),
199 &nBorderChains = nRetriever.getBorderChains();
201 vector< pair<CVector,CVector> > chainTips,
202 nChainTips;
204 _BorderChainLinks.resize(borderChains.size());
205 neighbor._BorderChainLinks.resize(nBorderChains.size());
208 for (i=0; i<borderChains.size(); ++i)
209 chainTips.push_back(make_pair(retriever.getTip(chains[borderChains[i]].getStartTip()).Point,
210 retriever.getTip(chains[borderChains[i]].getStopTip()).Point));
212 for (i=0; i<borderChains.size(); ++i)
213 chainTips.push_back(make_pair(retriever.getStartVector(borderChains[i]),
214 retriever.getStopVector(borderChains[i])));
216 CVector translation = neighbor._Origin - _Origin;
218 for (i=0; i<nBorderChains.size(); ++i)
219 nChainTips.push_back(make_pair(nRetriever.getTip(nChains[nBorderChains[i]].getStartTip()).Point+translation,
220 nRetriever.getTip(nChains[nBorderChains[i]].getStopTip()).Point+translation));
222 for (i=0; i<nBorderChains.size(); ++i)
223 nChainTips.push_back(make_pair(nRetriever.getStartVector(nBorderChains[i])+translation,
224 nRetriever.getStopVector(nBorderChains[i])+translation));
226 for (i=0; i<borderChains.size(); ++i)
228 // if the chain is already linked, just step
229 if (_BorderChainLinks[i].Instance != 0xFFFF || _BorderChainLinks[i].BorderChainId != 0xFFFF ||
230 _BorderChainLinks[i].ChainId != 0xFFFF || _BorderChainLinks[i].SurfaceId != 0xFFFF)
231 continue;
233 float bestDist = 1.0f;
234 sint best = -1;
236 for (j=0; j<nBorderChains.size(); ++j)
238 if (neighbor._BorderChainLinks[j].Instance != 0xFFFF || neighbor._BorderChainLinks[j].BorderChainId != 0xFFFF ||
239 neighbor._BorderChainLinks[j].ChainId != 0xFFFF || neighbor._BorderChainLinks[j].SurfaceId != 0xFFFF)
240 continue;
242 float d = (chainTips[i].first-nChainTips[j].second).norm()+(chainTips[i].second-nChainTips[j].first).norm();
243 if (d < bestDist)
245 bestDist = d;
246 best = j;
250 // if no best match, just don't link
251 if (bestDist > 1.0e-1f || best == -1)
252 continue;
254 _BorderChainLinks[i].Instance = (uint16)neighbor._InstanceId;
255 _BorderChainLinks[i].BorderChainId = (uint16)best;
256 _BorderChainLinks[i].ChainId = nBorderChains[_BorderChainLinks[i].BorderChainId];
257 _BorderChainLinks[i].SurfaceId = (uint16)nChains[_BorderChainLinks[i].ChainId].getLeft();
259 neighbor._BorderChainLinks[best].Instance = (uint16)_InstanceId;
260 neighbor._BorderChainLinks[best].BorderChainId = (uint16)i;
261 neighbor._BorderChainLinks[best].ChainId = borderChains[neighbor._BorderChainLinks[best].BorderChainId];
262 neighbor._BorderChainLinks[best].SurfaceId = (uint16)chains[neighbor._BorderChainLinks[best].ChainId].getLeft();
265 _Neighbors.push_back(neighbor._InstanceId);
266 neighbor._Neighbors.push_back(_InstanceId);
270 void NLPACS::CRetrieverInstance::unlink(vector<CRetrieverInstance> &instances)
272 uint i;
274 for (i=0; i<_Neighbors.size(); ++i)
275 instances[_Neighbors[i]].resetLinks(_InstanceId);
277 resetLinks();
283 void NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVector &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst, bool sortByDistance) const
284 //NLPACS::CLocalRetriever::CLocalPosition NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVector &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst) const
287 CVector localEstimated;
288 CLocalRetriever::CLocalPosition retrieved;
290 // get local coordinates
291 localEstimated = getLocalPosition(estimated);
292 // Yoyo: must snap vector.
293 CRetrieverInstance::snapVector(localEstimated);
295 // fills _RetrieveTable by retrievingPosition.
296 retriever.retrievePosition(localEstimated, cst);
298 uint i, surf;
299 sint bestSurf = -1;
300 sint lastSurf = -1;
301 float bestDistance = 1.0e10f;
302 float bestHeight;
303 bool lfound;
305 // for each surface in the retriever
306 for (i=0; i<cst.PossibleSurfaces.size(); ++i)
308 surf = cst.PossibleSurfaces[i];
309 cst.SurfaceLUT[surf].first = false;
310 // if the surface contains the estimated position.
311 if (cst.SurfaceLUT[surf].second != 0)
313 // at least remembers the last seen surface...
314 cst.SurfaceLUT[surf].second = 0;
315 float meanHeight;
316 const CQuadLeaf *leaf;
317 ULocalPosition lp;
318 lfound = false;
320 switch (_Type)
322 case CLocalRetriever::Landscape:
323 // for landscape
324 // search in the surface's quad tree for the actual height
325 leaf = retriever.getSurfaces()[surf].getQuadTree().getLeaf(localEstimated);
326 // if there is no acceptable leaf, just give up
327 if (leaf == NULL)
328 continue;
329 meanHeight = leaf->getMaxHeight();
330 lfound = true;
331 break;
332 case CLocalRetriever::Interior:
333 // for interior
334 // get the exact position
335 lp.Surface = surf;
336 lp.Estimation = localEstimated;
337 meanHeight = localEstimated.z;
338 retriever.snapToInteriorGround(lp, lfound);
339 if (lfound)
340 meanHeight = lp.Estimation.z;
341 break;
342 default:
343 // hu?
344 continue;
347 // if it is closer to the estimation than the previous remembered...
348 float distance = (float)fabs(localEstimated.z-meanHeight);
349 if (distance < bestDistance && lfound)
351 bestDistance = distance;
352 bestHeight = meanHeight;
353 bestSurf = surf;
358 if (bestSurf != -1)
360 // if there is a best surface, returns it
361 retrieved.Surface = bestSurf;
362 retrieved.Estimation = CVector(localEstimated.x, localEstimated.y, bestHeight);
364 else
366 // else return the last remembered...
367 retrieved.Surface = lastSurf;
368 retrieved.Estimation = localEstimated;
371 return retrieved;
373 retrievePosition(CVectorD(estimated), retriever, cst, sortByDistance);
376 void NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVectorD &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst, bool sortByDistance) const
378 CVector localEstimated;
380 // nldebug("PACS: retrievePosition in instance %d (retriever %d)", _InstanceId, _RetrieverId);
382 // get local coordinates
383 localEstimated = getLocalPosition(estimated);
384 // Yoyo: must snap vector.
385 CRetrieverInstance::snapVector(localEstimated);
387 // fills _RetrieveTable by retrievingPosition.
388 retriever.retrievePosition(localEstimated, cst);
390 uint i, surf;
391 /* sint bestSurf = -1;
392 sint lastSurf = -1;
393 float bestDistance = 1.0e10f;
394 float bestHeight;*/
395 bool found = false;
397 switch (_Type)
399 case CLocalRetriever::Landscape:
400 // for landscape
401 for (i=0; i<cst.PossibleSurfaces.size(); ++i)
403 surf = cst.PossibleSurfaces[i];
405 // nldebug("PACS: surface %d: count %d", surf, cst.SurfaceLUT[surf].Counter);
407 // if the surface contains the estimated position.
408 if (cst.SurfaceLUT[surf].Counter == 2)
410 float meanHeight;
412 const CQuadLeaf *leaf;
414 // search in the surface's quad tree for the actual height
415 leaf = retriever.getSurfaces()[surf].getQuadTree().getLeaf(localEstimated);
416 // if there is no acceptable leaf, just give up
417 if (leaf != NULL)
419 meanHeight = leaf->getMaxHeight();
420 //meanHeight = retriever.getSurfaces()[surf].getQuadTree().getInterpZ(localEstimated);
422 // if it is closer to the estimation than the previous remembered...
423 found = true;
424 float distance = (float)fabs(localEstimated.z-meanHeight);
425 cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
429 meanHeight = retriever.getSurface(surf).getQuantHeight()*2.0f + 1.0f;
431 // if it is closer to the estimation than the previous remembered...
432 found = true;
433 float distance = sortByDistance ? (float)fabs(localEstimated.z-meanHeight) : meanHeight;
434 cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
437 else if (cst.SurfaceLUT[surf].Counter != 0)
439 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);
442 cst.SurfaceLUT[surf].reset();
445 break;
447 case CLocalRetriever::Interior:
448 // for interior
449 for (i=0; i<cst.PossibleSurfaces.size(); ++i)
451 surf = cst.PossibleSurfaces[i];
452 // if the surface contains the estimated position.
453 if (cst.SurfaceLUT[surf].Counter == 2)
455 ULocalPosition lp;
456 bool lfound = false;
458 // get the exact position
459 lp.Surface = surf;
460 lp.Estimation = localEstimated;
461 retriever.snapToInteriorGround(lp, lfound);
462 if (lfound)
464 // if it is closer to the estimation than the previous remembered...
465 found = true;
466 float distance = sortByDistance ? (float)fabs(localEstimated.z-lp.Estimation.z) : lp.Estimation.z;
467 cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
470 else if (cst.SurfaceLUT[surf].Counter != 0)
472 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);
475 cst.SurfaceLUT[surf].reset();
477 break;
479 default:
480 nlerror("Unknown instance type %d !!", _Type);
481 break;
484 cst.OutCounter = 0;
489 void NLPACS::CRetrieverInstance::snapToInteriorGround(NLPACS::ULocalPosition &position,
490 const NLPACS::CLocalRetriever &retriever) const
492 bool lfound;
493 retriever.snapToInteriorGround(position, lfound);
496 void NLPACS::CRetrieverInstance::snap(NLPACS::ULocalPosition &position, const NLPACS::CLocalRetriever &retriever) const
498 if (_Type == CLocalRetriever::Landscape)
500 // search in the surface's quad tree for the actual height
501 // position.Estimation.z = retriever.getSurfaces()[position.Surface].getQuadTree().getInterpZ(position.Estimation);
503 position.Estimation.z = retriever.getHeight(position);
506 const CQuadLeaf *leaf = retriever.getSurfaces()[position.Surface].getQuadTree().getLeaf(position.Estimation);
507 // if there is no acceptable leaf, just give up
508 if (leaf != NULL)
510 position.Estimation.z = leaf->getMaxHeight();
512 else
514 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);
518 else if (_Type == CLocalRetriever::Interior)
520 bool lfound;
521 retriever.snapToInteriorGround(position, lfound);
523 else
525 nlwarning("PACS: unknown instance (%d) type %d", _InstanceId, _Type);
533 CVector NLPACS::CRetrieverInstance::getLocalPosition(const CVector &globalPosition) const
535 switch (_Orientation)
537 default:
538 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
539 nlerror("unexpected orientation value (%d)", _Orientation);
540 case 0:
541 return CVector(+globalPosition.x-_Origin.x, +globalPosition.y-_Origin.y, globalPosition.z-_Origin.z);
542 break;
543 case 1:
544 return CVector(+globalPosition.y-_Origin.y, -globalPosition.x+_Origin.x, globalPosition.z-_Origin.z);
545 break;
546 case 2:
547 return CVector(-globalPosition.x+_Origin.x, -globalPosition.y+_Origin.y, globalPosition.z-_Origin.z);
548 break;
549 case 3:
550 return CVector(-globalPosition.y+_Origin.y, +globalPosition.x-_Origin.x, globalPosition.z-_Origin.z);
551 break;
555 CVector NLPACS::CRetrieverInstance::getLocalPosition(const CVectorD &globalPosition) const
557 switch (_Orientation)
559 default:
560 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
561 nlerror("unexpected orientation value (%d)", _Orientation);
562 case 0:
563 return CVector((float)(+globalPosition.x-_Origin.x), (float)(+globalPosition.y-_Origin.y), (float)(globalPosition.z-_Origin.z));
564 break;
565 case 1:
566 return CVector((float)(+globalPosition.y-_Origin.y), (float)(-globalPosition.x+_Origin.x), (float)(globalPosition.z-_Origin.z));
567 break;
568 case 2:
569 return CVector((float)(-globalPosition.x+_Origin.x), (float)(-globalPosition.y+_Origin.y), (float)(globalPosition.z-_Origin.z));
570 break;
571 case 3:
572 return CVector((float)(-globalPosition.y+_Origin.y), (float)(+globalPosition.x-_Origin.x), (float)(globalPosition.z-_Origin.z));
573 break;
577 CVector NLPACS::CRetrieverInstance::getGlobalPosition(const CVector &localPosition) const
579 switch (_Orientation)
581 default:
582 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
583 nlerror("unexpected orientation value (%d)", _Orientation);
584 case 0:
585 return CVector(+localPosition.x+_Origin.x, +localPosition.y+_Origin.y, localPosition.z+_Origin.z );
586 break;
587 case 1:
588 return CVector(-localPosition.y+_Origin.x, +localPosition.x+_Origin.y, localPosition.z+_Origin.z );
589 break;
590 case 2:
591 return CVector(-localPosition.x+_Origin.x, -localPosition.y+_Origin.y, localPosition.z+_Origin.z );
592 break;
593 case 3:
594 return CVector(+localPosition.y+_Origin.x, -localPosition.x+_Origin.y, localPosition.z+_Origin.z );
595 break;
599 CVectorD NLPACS::CRetrieverInstance::getDoubleGlobalPosition(const CVector &localPosition) const
601 switch (_Orientation)
603 default:
604 nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
605 nlerror("unexpected orientation value (%d)", _Orientation);
606 case 0:
607 return CVectorD(+(double)localPosition.x+(double)_Origin.x, +(double)localPosition.y+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
608 break;
609 case 1:
610 return CVectorD(-(double)localPosition.y+(double)_Origin.x, +(double)localPosition.x+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
611 break;
612 case 2:
613 return CVectorD(-(double)localPosition.x+(double)_Origin.x, -(double)localPosition.y+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
614 break;
615 case 3:
616 return CVectorD(+(double)localPosition.y+(double)_Origin.x, -(double)localPosition.x+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
617 break;
623 // ***************************************************************************
624 void NLPACS::CRetrieverInstance::testExteriorCollision(NLPACS::CCollisionSurfaceTemp &cst, const CAABBox &bboxMove, const CVector2f &transBase, const NLPACS::CLocalRetriever &retriever) const
626 sint i;
628 // 0. select ordered chains in the chainquad.
629 //=====================================
630 sint nEei= _ExteriorEdgeQuad.selectEdges(bboxMove, cst);
631 // NB: cst.OChainLUT is assured to be full of 0xFFFF after this call (if was right before).
634 // 1. regroup them in chains. build cst.CollisionChains
635 //=====================================
636 // NB: use cst.OChainLUT to look if a Chain has been inserted before.
637 uint16 *edgeLUT= cst.OChainLUT;
639 // bkup where we begin to add chains.
640 uint firstChainAdded= (uint)cst.CollisionChains.size();
642 // For all exterioredge entry.
643 for(i=0;i<nEei;i++)
645 // get the edge entry and the edge
646 uint16 eei = cst.ExteriorEdgeIndexes[i];
647 const CExteriorEdgeEntry &eee = _ExteriorEdgeQuad.getEdgeEntry(eei);
649 // WELL ACTUALLY DO BOTHER ABOUT DOORS !!
651 // don't bother about doors
652 if (eee.Interior.RetrieverInstanceId != -1)
653 continue;
656 // add/retrieve the id in cst.CollisionChains.
657 //=================================
658 uint ccId;
659 // if never added.
660 if(edgeLUT[eei]==0xFFFF)
662 // add a new CCollisionChain.
663 ccId= (uint)cst.CollisionChains.size();
664 cst.CollisionChains.push_back(CCollisionChain());
665 // Fill it with default.
666 cst.CollisionChains[ccId].Tested= false;
667 cst.CollisionChains[ccId].ExteriorEdge = true;
668 cst.CollisionChains[ccId].FirstEdgeCollide= 0xFFFFFFFF;
669 cst.CollisionChains[ccId].ChainId= eei;
670 // Fill Left right info.
671 cst.CollisionChains[ccId].LeftSurface = eee.Interior;
672 cst.CollisionChains[ccId].RightSurface = eee.Exterior;
674 // store this Id in the LUT of chains.
675 edgeLUT[eei]= uint16(ccId);
677 else
679 // get the id of this collision chain.
680 ccId= edgeLUT[eei];
682 // ACTUALLY, THIS SHOULD NEVER HAPPEN
683 // since ext edge are only 1 segment
686 // add edge collide to the list.
687 //=================================
688 CCollisionChain &colChain= cst.CollisionChains[ccId];
690 CVector2f p0 = CVector2f(retriever._ExteriorMesh.getEdge(eee.EdgeId).Start);
691 CVector2f p1 = CVector2f(retriever._ExteriorMesh.getEdge(eee.EdgeId+1).Start);
693 // alloc a new edgeCollide.
694 uint32 ecnId= cst.allocEdgeCollideNode();
695 CEdgeCollideNode &ecn= cst.getEdgeCollideNode(ecnId);
697 // append to the front of the list.
698 ecn.Next= colChain.FirstEdgeCollide;
699 colChain.FirstEdgeCollide= ecnId;
701 // build this edge.
702 p0+= transBase;
703 p1+= transBase;
704 ecn.make(p0, p1);
709 // 2. Reset LUT to 0xFFFF.
710 //=====================================
712 // for all collisions chains inserted (starting from firstChainAdded), reset LUT.
713 for(i=firstChainAdded; i<(sint)cst.CollisionChains.size(); i++)
715 uint ccId= cst.CollisionChains[i].ChainId;
716 edgeLUT[ccId]= 0xFFFF;
717 cst.CollisionChains[i].ChainId = _ExteriorEdgeQuad.getEdgeEntry(ccId).EdgeId;
725 void NLPACS::CRetrieverInstance::serial(NLMISC::IStream &f)
728 Version 0:
729 - base version.
730 Version 1:
731 - added type and _EdgeQuad
733 sint ver= f.serialVersion(1);
735 f.serial(_InstanceId, _RetrieverId, _Orientation, _Origin);
736 f.serialCont(_Neighbors);
737 f.serialCont(_BorderChainLinks);
738 f.serial(_BBox);
740 // serialises the number of nodes
741 uint16 totalNodes = uint16(_NodesInformation.size());
742 f.serial(totalNodes);
743 if (f.isReading())
745 // if the stream is reading, reinits the temps table...
746 _NodesInformation.resize(totalNodes);
749 if (ver >= 1)
751 f.serialEnum(_Type);
752 f.serial(_ExteriorEdgeQuad);
754 // a fix for old versions (with wrong _Type value)
755 if (_Type != CLocalRetriever::Interior) _Type = CLocalRetriever::Landscape;
761 void NLPACS::CRetrieverInstance::resetBorderChainLinks(const vector<uint> &links)
763 uint i;
764 for (i=0; i<links.size(); ++i)
766 if (links[i] >= _BorderChainLinks.size())
767 _BorderChainLinks.resize(links[i]+1);
769 _BorderChainLinks[links[i]].reset();