khanat-opennel-code/code/nel/src/pacs/retriever_instance.cpp
2015-03-01 18:41:16 +02:00

771 lines
23 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpacs.h"
#include "nel/pacs/retriever_instance.h"
#include "nel/pacs/global_retriever.h"
using namespace std;
using namespace NLMISC;
NLPACS::CRetrieverInstance::CRetrieverInstance()
{
reset();
}
void NLPACS::CRetrieverInstance::resetLinks()
{
uint i;
// WARNING !!
// this is a HARD reset !
// only the instance i reset, no care about neighbors !!
for (i=0; i<_Neighbors.size(); ++i)
_Neighbors[i] = -1;
_BorderChainLinks.clear();
_ExteriorEdgeQuad.removeLinks();
}
void NLPACS::CRetrieverInstance::resetLinks(uint32 id)
{
vector<sint32>::iterator rit;
for (rit=_Neighbors.begin(); rit!=_Neighbors.end(); )
if (*rit == (sint32)id)
rit = _Neighbors.erase(rit);
else
++rit;
uint i;
for (i=0; i<_BorderChainLinks.size(); ++i)
if (_BorderChainLinks[i].Instance == (uint16)id)
_BorderChainLinks[i].reset();
_ExteriorEdgeQuad.removeLinks(id);
}
void NLPACS::CRetrieverInstance::reset()
{
// WARNING !!
// this is a HARD reset !
// only the instance i reset, no care about neighbors !!
_NodesInformation.clear();
_InstanceId = -1;
_RetrieverId = -1;
_Orientation = 0;
_Origin = CVector::Null;
_Type = CLocalRetriever::Landscape;
_BorderChainLinks.clear();
_ExteriorEdgeQuad.clear();
resetLinks();
}
void NLPACS::CRetrieverInstance::init(const CLocalRetriever &retriever)
{
if (!retriever.isLoaded())
return;
/*
_NodesInformation.resize(retriever.getSurfaces().size());
uint i;
// Resets _NodesInformation for later pathfinding graph annotation.
for (i=0; i<_NodesInformation.size(); ++i)
{
CVector pos = getGlobalPosition(retriever.getSurfaces()[i].getCenter());
_NodesInformation[i].Position = CVector2f(pos.x, pos.y);
}
*/
_Type = retriever.getType();
_BorderChainLinks.resize(retriever.getBorderChains().size());
}
void NLPACS::CRetrieverInstance::make(sint32 instanceId, sint32 retrieverId, const CLocalRetriever &retriever,
uint8 orientation, const CVector &origin)
{
if (_InstanceId != -1 || _RetrieverId != -1)
{
nlwarning("in call to NLPACS::CRetrieverInstance::make");
nlwarning("_InstanceId=%d _RetrieverId=%d _Orientation=%d", _InstanceId, _RetrieverId, _Orientation);
nlwarning("instanceId=%d retrieverId=%d orientation=%d", instanceId, retrieverId, orientation);
nlerror("Retriever instance %d has already been set", _InstanceId);
}
_InstanceId = instanceId;
_RetrieverId = retrieverId;
_Orientation = (orientation%4);
_Origin = origin;
_BBox = retriever.getBBox();
_BBox.setCenter(_BBox.getCenter()+_Origin);
if (_Orientation == 1 || _Orientation == 3)
{
CVector hs = _BBox.getHalfSize();
std::swap(hs.x, hs.y);
_BBox.setHalfSize(hs);
}
init(retriever);
}
//
void NLPACS::CRetrieverInstance::initEdgeQuad(NLPACS::CGlobalRetriever &gr)
{
const CLocalRetriever &lr = gr.getRetriever(_RetrieverId);
if (lr.getType() != CLocalRetriever::Interior)
{
nlerror("Attempt to init the edgequad of instance %d whereas local retriever %d is not interior", _InstanceId, _RetrieverId);
}
// build the edge quad
_ExteriorEdgeQuad.build(lr.getExteriorMesh(), gr, gr.getInternalCST(),_InstanceId);
}
void NLPACS::CRetrieverInstance::linkEdgeQuad(NLPACS::CGlobalRetriever &gr)
{
const CLocalRetriever &lr = gr.getRetriever(_RetrieverId);
const CExteriorMesh &em = lr.getExteriorMesh();
const vector<CExteriorEdgeEntry> &ee = _ExteriorEdgeQuad.getEdgeEntries();
// here we fill (partially) the _BorderChainLinks table
uint i;
for (i=0; i<ee.size(); ++i)
{
const CExteriorMesh::CEdge &edge = em.getEdge(ee[i].EdgeId);
if (edge.Link != -1)
{
const CExteriorMesh::CLink &link = em.getLink(edge.Link);
if (link.SurfaceId != 0xFFFF && link.ChainId != 0xFFFF && link.BorderChainId != 0xFFFF)
{
CRetrieverInstance::CLink &borderLink = _BorderChainLinks[link.BorderChainId];
borderLink.ChainId = 0xFFFF; // no opposite chain
borderLink.BorderChainId = 0xFFFF; // idem
if ((borderLink.Instance == 0xFFFF && borderLink.SurfaceId == 0xFFFF) ||
(borderLink.Instance == (uint16)(ee[i].Exterior.RetrieverInstanceId) &&
borderLink.SurfaceId == (uint16)(ee[i].Exterior.SurfaceId) ))
{
borderLink.Instance = (uint16)(ee[i].Exterior.RetrieverInstanceId);
borderLink.SurfaceId = (uint16)(ee[i].Exterior.SurfaceId);
}
else
{
nlwarning("Instance %d, borderLink %d: link already set to inst=%d, surf=%d, try to set to inst=%d, surf=%d",
_InstanceId, link.BorderChainId, borderLink.Instance, borderLink.SurfaceId,
(uint16)(ee[i].Exterior.RetrieverInstanceId), (uint16)(ee[i].Exterior.SurfaceId));
}
}
}
}
}
/* Links the current retriever instance to another instance
* on the given edge.
*/
void NLPACS::CRetrieverInstance::link(CRetrieverInstance &neighbor,
const vector<CLocalRetriever> &retrievers)
{
uint i, j;
for (i=0; i<_Neighbors.size(); ++i)
if (_Neighbors[i] == neighbor._InstanceId)
return;
const CLocalRetriever &retriever = retrievers[_RetrieverId];
const CLocalRetriever &nRetriever = retrievers[neighbor._RetrieverId];
const vector<CChain> &chains = retriever.getChains(),
&nChains = nRetriever.getChains();
const vector<uint16> &borderChains = retriever.getBorderChains(),
&nBorderChains = nRetriever.getBorderChains();
vector< pair<CVector,CVector> > chainTips,
nChainTips;
_BorderChainLinks.resize(borderChains.size());
neighbor._BorderChainLinks.resize(nBorderChains.size());
/*
for (i=0; i<borderChains.size(); ++i)
chainTips.push_back(make_pair(retriever.getTip(chains[borderChains[i]].getStartTip()).Point,
retriever.getTip(chains[borderChains[i]].getStopTip()).Point));
*/
for (i=0; i<borderChains.size(); ++i)
chainTips.push_back(make_pair(retriever.getStartVector(borderChains[i]),
retriever.getStopVector(borderChains[i])));
CVector translation = neighbor._Origin - _Origin;
/*
for (i=0; i<nBorderChains.size(); ++i)
nChainTips.push_back(make_pair(nRetriever.getTip(nChains[nBorderChains[i]].getStartTip()).Point+translation,
nRetriever.getTip(nChains[nBorderChains[i]].getStopTip()).Point+translation));
*/
for (i=0; i<nBorderChains.size(); ++i)
nChainTips.push_back(make_pair(nRetriever.getStartVector(nBorderChains[i])+translation,
nRetriever.getStopVector(nBorderChains[i])+translation));
for (i=0; i<borderChains.size(); ++i)
{
// if the chain is already linked, just step
if (_BorderChainLinks[i].Instance != 0xFFFF || _BorderChainLinks[i].BorderChainId != 0xFFFF ||
_BorderChainLinks[i].ChainId != 0xFFFF || _BorderChainLinks[i].SurfaceId != 0xFFFF)
continue;
float bestDist = 1.0f;
sint best = -1;
for (j=0; j<nBorderChains.size(); ++j)
{
if (neighbor._BorderChainLinks[j].Instance != 0xFFFF || neighbor._BorderChainLinks[j].BorderChainId != 0xFFFF ||
neighbor._BorderChainLinks[j].ChainId != 0xFFFF || neighbor._BorderChainLinks[j].SurfaceId != 0xFFFF)
continue;
float d = (chainTips[i].first-nChainTips[j].second).norm()+(chainTips[i].second-nChainTips[j].first).norm();
if (d < bestDist)
{
bestDist = d;
best = j;
}
}
// if no best match, just don't link
if (bestDist > 1.0e-1f || best == -1)
continue;
_BorderChainLinks[i].Instance = (uint16)neighbor._InstanceId;
_BorderChainLinks[i].BorderChainId = (uint16)best;
_BorderChainLinks[i].ChainId = nBorderChains[_BorderChainLinks[i].BorderChainId];
_BorderChainLinks[i].SurfaceId = (uint16)nChains[_BorderChainLinks[i].ChainId].getLeft();
neighbor._BorderChainLinks[best].Instance = (uint16)_InstanceId;
neighbor._BorderChainLinks[best].BorderChainId = (uint16)i;
neighbor._BorderChainLinks[best].ChainId = borderChains[neighbor._BorderChainLinks[best].BorderChainId];
neighbor._BorderChainLinks[best].SurfaceId = (uint16)chains[neighbor._BorderChainLinks[best].ChainId].getLeft();
}
_Neighbors.push_back(neighbor._InstanceId);
neighbor._Neighbors.push_back(_InstanceId);
}
void NLPACS::CRetrieverInstance::unlink(vector<CRetrieverInstance> &instances)
{
uint i;
for (i=0; i<_Neighbors.size(); ++i)
instances[_Neighbors[i]].resetLinks(_InstanceId);
resetLinks();
}
void NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVector &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst, bool sortByDistance) const
//NLPACS::CLocalRetriever::CLocalPosition NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVector &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst) const
{
/*
CVector localEstimated;
CLocalRetriever::CLocalPosition retrieved;
// get local coordinates
localEstimated = getLocalPosition(estimated);
// Yoyo: must snap vector.
CRetrieverInstance::snapVector(localEstimated);
// fills _RetrieveTable by retrievingPosition.
retriever.retrievePosition(localEstimated, cst);
uint i, surf;
sint bestSurf = -1;
sint lastSurf = -1;
float bestDistance = 1.0e10f;
float bestHeight;
bool lfound;
// for each surface in the retriever
for (i=0; i<cst.PossibleSurfaces.size(); ++i)
{
surf = cst.PossibleSurfaces[i];
cst.SurfaceLUT[surf].first = false;
// if the surface contains the estimated position.
if (cst.SurfaceLUT[surf].second != 0)
{
// at least remembers the last seen surface...
cst.SurfaceLUT[surf].second = 0;
float meanHeight;
const CQuadLeaf *leaf;
ULocalPosition lp;
lfound = false;
switch (_Type)
{
case CLocalRetriever::Landscape:
// for landscape
// search in the surface's quad tree for the actual height
leaf = retriever.getSurfaces()[surf].getQuadTree().getLeaf(localEstimated);
// if there is no acceptable leaf, just give up
if (leaf == NULL)
continue;
meanHeight = leaf->getMaxHeight();
lfound = true;
break;
case CLocalRetriever::Interior:
// for interior
// get the exact position
lp.Surface = surf;
lp.Estimation = localEstimated;
meanHeight = localEstimated.z;
retriever.snapToInteriorGround(lp, lfound);
if (lfound)
meanHeight = lp.Estimation.z;
break;
default:
// hu?
continue;
}
// if it is closer to the estimation than the previous remembered...
float distance = (float)fabs(localEstimated.z-meanHeight);
if (distance < bestDistance && lfound)
{
bestDistance = distance;
bestHeight = meanHeight;
bestSurf = surf;
}
}
}
if (bestSurf != -1)
{
// if there is a best surface, returns it
retrieved.Surface = bestSurf;
retrieved.Estimation = CVector(localEstimated.x, localEstimated.y, bestHeight);
}
else
{
// else return the last remembered...
retrieved.Surface = lastSurf;
retrieved.Estimation = localEstimated;
}
return retrieved;
*/
retrievePosition(CVectorD(estimated), retriever, cst, sortByDistance);
}
void NLPACS::CRetrieverInstance::retrievePosition(const NLMISC::CVectorD &estimated, const CLocalRetriever &retriever, CCollisionSurfaceTemp &cst, bool sortByDistance) const
{
CVector localEstimated;
// nldebug("PACS: retrievePosition in instance %d (retriever %d)", _InstanceId, _RetrieverId);
// get local coordinates
localEstimated = getLocalPosition(estimated);
// Yoyo: must snap vector.
CRetrieverInstance::snapVector(localEstimated);
// fills _RetrieveTable by retrievingPosition.
retriever.retrievePosition(localEstimated, cst);
uint i, surf;
/* sint bestSurf = -1;
sint lastSurf = -1;
float bestDistance = 1.0e10f;
float bestHeight;*/
bool found = false;
switch (_Type)
{
case CLocalRetriever::Landscape:
// for landscape
for (i=0; i<cst.PossibleSurfaces.size(); ++i)
{
surf = cst.PossibleSurfaces[i];
// nldebug("PACS: surface %d: count %d", surf, cst.SurfaceLUT[surf].Counter);
// if the surface contains the estimated position.
if (cst.SurfaceLUT[surf].Counter == 2)
{
float meanHeight;
/*
const CQuadLeaf *leaf;
// search in the surface's quad tree for the actual height
leaf = retriever.getSurfaces()[surf].getQuadTree().getLeaf(localEstimated);
// if there is no acceptable leaf, just give up
if (leaf != NULL)
{
meanHeight = leaf->getMaxHeight();
//meanHeight = retriever.getSurfaces()[surf].getQuadTree().getInterpZ(localEstimated);
// if it is closer to the estimation than the previous remembered...
found = true;
float distance = (float)fabs(localEstimated.z-meanHeight);
cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
}
*/
meanHeight = retriever.getSurface(surf).getQuantHeight()*2.0f + 1.0f;
// if it is closer to the estimation than the previous remembered...
found = true;
float distance = sortByDistance ? (float)fabs(localEstimated.z-meanHeight) : meanHeight;
cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
}
else if (cst.SurfaceLUT[surf].Counter != 0)
{
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);
}
cst.SurfaceLUT[surf].reset();
}
break;
case CLocalRetriever::Interior:
// for interior
for (i=0; i<cst.PossibleSurfaces.size(); ++i)
{
surf = cst.PossibleSurfaces[i];
// if the surface contains the estimated position.
if (cst.SurfaceLUT[surf].Counter == 2)
{
ULocalPosition lp;
bool lfound = false;
// get the exact position
lp.Surface = surf;
lp.Estimation = localEstimated;
retriever.snapToInteriorGround(lp, lfound);
if (lfound)
{
// if it is closer to the estimation than the previous remembered...
found = true;
float distance = sortByDistance ? (float)fabs(localEstimated.z-lp.Estimation.z) : lp.Estimation.z;
cst.SortedSurfaces.push_back(CCollisionSurfaceTemp::CDistanceSurface(distance, (uint16)surf, (uint16)_InstanceId, cst.SurfaceLUT[surf].FoundCloseEdge));
}
}
else if (cst.SurfaceLUT[surf].Counter != 0)
{
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);
}
cst.SurfaceLUT[surf].reset();
}
break;
default:
nlerror("Unknown instance type %d !!", _Type);
break;
}
cst.OutCounter = 0;
}
void NLPACS::CRetrieverInstance::snapToInteriorGround(NLPACS::ULocalPosition &position,
const NLPACS::CLocalRetriever &retriever) const
{
bool lfound;
retriever.snapToInteriorGround(position, lfound);
}
void NLPACS::CRetrieverInstance::snap(NLPACS::ULocalPosition &position, const NLPACS::CLocalRetriever &retriever) const
{
if (_Type == CLocalRetriever::Landscape)
{
// search in the surface's quad tree for the actual height
// position.Estimation.z = retriever.getSurfaces()[position.Surface].getQuadTree().getInterpZ(position.Estimation);
position.Estimation.z = retriever.getHeight(position);
/*
const CQuadLeaf *leaf = retriever.getSurfaces()[position.Surface].getQuadTree().getLeaf(position.Estimation);
// if there is no acceptable leaf, just give up
if (leaf != NULL)
{
position.Estimation.z = leaf->getMaxHeight();
}
else
{
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);
}
*/
}
else if (_Type == CLocalRetriever::Interior)
{
bool lfound;
retriever.snapToInteriorGround(position, lfound);
}
else
{
nlwarning("PACS: unknown instance (%d) type %d", _InstanceId, _Type);
}
}
CVector NLPACS::CRetrieverInstance::getLocalPosition(const CVector &globalPosition) const
{
switch (_Orientation)
{
default:
nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
nlerror("unexpected orientation value (%d)", _Orientation);
case 0:
return CVector(+globalPosition.x-_Origin.x, +globalPosition.y-_Origin.y, globalPosition.z-_Origin.z);
break;
case 1:
return CVector(+globalPosition.y-_Origin.y, -globalPosition.x+_Origin.x, globalPosition.z-_Origin.z);
break;
case 2:
return CVector(-globalPosition.x+_Origin.x, -globalPosition.y+_Origin.y, globalPosition.z-_Origin.z);
break;
case 3:
return CVector(-globalPosition.y+_Origin.y, +globalPosition.x-_Origin.x, globalPosition.z-_Origin.z);
break;
}
}
CVector NLPACS::CRetrieverInstance::getLocalPosition(const CVectorD &globalPosition) const
{
switch (_Orientation)
{
default:
nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
nlerror("unexpected orientation value (%d)", _Orientation);
case 0:
return CVector((float)(+globalPosition.x-_Origin.x), (float)(+globalPosition.y-_Origin.y), (float)(globalPosition.z-_Origin.z));
break;
case 1:
return CVector((float)(+globalPosition.y-_Origin.y), (float)(-globalPosition.x+_Origin.x), (float)(globalPosition.z-_Origin.z));
break;
case 2:
return CVector((float)(-globalPosition.x+_Origin.x), (float)(-globalPosition.y+_Origin.y), (float)(globalPosition.z-_Origin.z));
break;
case 3:
return CVector((float)(-globalPosition.y+_Origin.y), (float)(+globalPosition.x-_Origin.x), (float)(globalPosition.z-_Origin.z));
break;
}
}
CVector NLPACS::CRetrieverInstance::getGlobalPosition(const CVector &localPosition) const
{
switch (_Orientation)
{
default:
nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
nlerror("unexpected orientation value (%d)", _Orientation);
case 0:
return CVector(+localPosition.x+_Origin.x, +localPosition.y+_Origin.y, localPosition.z+_Origin.z );
break;
case 1:
return CVector(-localPosition.y+_Origin.x, +localPosition.x+_Origin.y, localPosition.z+_Origin.z );
break;
case 2:
return CVector(-localPosition.x+_Origin.x, -localPosition.y+_Origin.y, localPosition.z+_Origin.z );
break;
case 3:
return CVector(+localPosition.y+_Origin.x, -localPosition.x+_Origin.y, localPosition.z+_Origin.z );
break;
}
}
CVectorD NLPACS::CRetrieverInstance::getDoubleGlobalPosition(const CVector &localPosition) const
{
switch (_Orientation)
{
default:
nlwarning("in NLPACS::CRetrieverInstance::getLocalPosition()");
nlerror("unexpected orientation value (%d)", _Orientation);
case 0:
return CVectorD(+(double)localPosition.x+(double)_Origin.x, +(double)localPosition.y+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
break;
case 1:
return CVectorD(-(double)localPosition.y+(double)_Origin.x, +(double)localPosition.x+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
break;
case 2:
return CVectorD(-(double)localPosition.x+(double)_Origin.x, -(double)localPosition.y+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
break;
case 3:
return CVectorD(+(double)localPosition.y+(double)_Origin.x, -(double)localPosition.x+(double)_Origin.y, (double)localPosition.z+(double)_Origin.z );
break;
}
}
// ***************************************************************************
void NLPACS::CRetrieverInstance::testExteriorCollision(NLPACS::CCollisionSurfaceTemp &cst, const CAABBox &bboxMove, const CVector2f &transBase, const NLPACS::CLocalRetriever &retriever) const
{
sint i;
// 0. select ordered chains in the chainquad.
//=====================================
sint nEei= _ExteriorEdgeQuad.selectEdges(bboxMove, cst);
// NB: cst.OChainLUT is assured to be full of 0xFFFF after this call (if was right before).
// 1. regroup them in chains. build cst.CollisionChains
//=====================================
// NB: use cst.OChainLUT to look if a Chain has been inserted before.
uint16 *edgeLUT= cst.OChainLUT;
// bkup where we begin to add chains.
uint firstChainAdded= (uint)cst.CollisionChains.size();
// For all exterioredge entry.
for(i=0;i<nEei;i++)
{
// get the edge entry and the edge
uint16 eei = cst.ExteriorEdgeIndexes[i];
const CExteriorEdgeEntry &eee = _ExteriorEdgeQuad.getEdgeEntry(eei);
// WELL ACTUALLY DO BOTHER ABOUT DOORS !!
/*
// don't bother about doors
if (eee.Interior.RetrieverInstanceId != -1)
continue;
*/
// add/retrieve the id in cst.CollisionChains.
//=================================
uint ccId;
// if never added.
if(edgeLUT[eei]==0xFFFF)
{
// add a new CCollisionChain.
ccId= (uint)cst.CollisionChains.size();
cst.CollisionChains.push_back(CCollisionChain());
// Fill it with default.
cst.CollisionChains[ccId].Tested= false;
cst.CollisionChains[ccId].ExteriorEdge = true;
cst.CollisionChains[ccId].FirstEdgeCollide= 0xFFFFFFFF;
cst.CollisionChains[ccId].ChainId= eei;
// Fill Left right info.
cst.CollisionChains[ccId].LeftSurface = eee.Interior;
cst.CollisionChains[ccId].RightSurface = eee.Exterior;
// store this Id in the LUT of chains.
edgeLUT[eei]= uint16(ccId);
}
else
{
// get the id of this collision chain.
ccId= edgeLUT[eei];
// ACTUALLY, THIS SHOULD NEVER HAPPEN
// since ext edge are only 1 segment
}
// add edge collide to the list.
//=================================
CCollisionChain &colChain= cst.CollisionChains[ccId];
CVector2f p0 = CVector2f(retriever._ExteriorMesh.getEdge(eee.EdgeId).Start);
CVector2f p1 = CVector2f(retriever._ExteriorMesh.getEdge(eee.EdgeId+1).Start);
// alloc a new edgeCollide.
uint32 ecnId= cst.allocEdgeCollideNode();
CEdgeCollideNode &ecn= cst.getEdgeCollideNode(ecnId);
// append to the front of the list.
ecn.Next= colChain.FirstEdgeCollide;
colChain.FirstEdgeCollide= ecnId;
// build this edge.
p0+= transBase;
p1+= transBase;
ecn.make(p0, p1);
}
// 2. Reset LUT to 0xFFFF.
//=====================================
// for all collisions chains inserted (starting from firstChainAdded), reset LUT.
for(i=firstChainAdded; i<(sint)cst.CollisionChains.size(); i++)
{
uint ccId= cst.CollisionChains[i].ChainId;
edgeLUT[ccId]= 0xFFFF;
cst.CollisionChains[i].ChainId = _ExteriorEdgeQuad.getEdgeEntry(ccId).EdgeId;
}
}
void NLPACS::CRetrieverInstance::serial(NLMISC::IStream &f)
{
/*
Version 0:
- base version.
Version 1:
- added type and _EdgeQuad
*/
sint ver= f.serialVersion(1);
f.serial(_InstanceId, _RetrieverId, _Orientation, _Origin);
f.serialCont(_Neighbors);
f.serialCont(_BorderChainLinks);
f.serial(_BBox);
// serialises the number of nodes
uint16 totalNodes = uint16(_NodesInformation.size());
f.serial(totalNodes);
if (f.isReading())
{
// if the stream is reading, reinits the temps table...
_NodesInformation.resize(totalNodes);
}
if (ver >= 1)
{
f.serialEnum(_Type);
f.serial(_ExteriorEdgeQuad);
// a fix for old versions (with wrong _Type value)
if (_Type != CLocalRetriever::Interior) _Type = CLocalRetriever::Landscape;
}
}
void NLPACS::CRetrieverInstance::resetBorderChainLinks(const vector<uint> &links)
{
uint i;
for (i=0; i<links.size(); ++i)
{
if (links[i] >= _BorderChainLinks.size())
_BorderChainLinks.resize(links[i]+1);
_BorderChainLinks[links[i]].reset();
}
}