khanat-code-old/code/nel/tools/pacs/build_rbank/build_rbank.cpp
2012-04-23 20:30:57 +03:00

1101 lines
29 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 "nel/misc/types_nl.h"
#include "nel/misc/debug.h"
#include "nel/misc/path.h"
#include "nel/misc/common.h"
#include "nel/misc/file.h"
#include "nel/misc/time_nl.h"
#include "nel/misc/polygon.h"
#include "nel/misc/smart_ptr.h"
#include "nel/3d/scene_group.h"
#include "nel/3d/transform_shape.h"
#include "nel/3d/water_model.h"
#include "nel/3d/water_shape.h"
#include "nel/3d/quad_grid.h"
#include "build_rbank.h"
#include "build_surf.h"
#include "surface_splitter.h"
#include "nel/../../src/pacs/global_retriever.h"
#include "nel/../../src/pacs/retriever_bank.h"
#include "nel/../../src/pacs/surface_quad.h"
#include "nel/../../src/pacs/local_retriever.h"
#include "nel/../../src/pacs/retriever_instance.h"
#include "nel/../../src/pacs/chain.h"
#include "nel/../../src/pacs/collision_mesh_build.h"
#include <string>
#include <deque>
#include <map>
using namespace std;
using namespace NLMISC;
using namespace NL3D;
class CIGBox
{
public:
CIGBox() {}
CIGBox(const string &name, const CAABBox &bbox) : Name(name), BBox(bbox) {}
string Name;
CAABBox BBox;
void serial(NLMISC::IStream &f) { f.serial(Name, BBox); }
};
/*
string getZoneNameById(uint16 id)
{
uint x = id%256;
uint y = id/256;
char ych[32];
sprintf(ych,"%d_%c%c", y+1, 'A'+x/26, 'A'+x%26);
return string(ych);
}
*/
string getZoneNameByCoord(float x, float y)
{
const float zoneDim = 160.0f;
float xcount = x/zoneDim;
float ycount = -y/zoneDim + 1;
char ych[32];
sprintf(ych,"%d_%c%c",(sint)ycount, 'A'+(sint)xcount/26, 'A'+(sint)xcount%26);
return string(ych);
}
CVector getZoneCenterById(uint16 id)
{
CAABBox bbox;
uint x, y;
const float zdim = 160.0f;
x = id%256;
y = id/256;
return CVector(zdim*((float)x+0.5f), -zdim*((float)y+0.5f), 0.0f);
}
uint32 getIdByCoord(uint x, uint y)
{
return y*256+x;
}
string changeExt(string name, const string &ext)
{
string::iterator it, last;
last = name.end();
for (it=name.begin(); it!=name.end(); ++it)
if (*it == '.')
last = it;
name.erase(last, name.end());
name.append(".");
name.append(ext);
return name;
}
void processAllPasses(string &zoneName)
{
uint /*i,*/ j;
NLPACS::CZoneTessellation tessellation;
vector<NLPACS::COrderedChain3f> fullChains;
string name;
string filename;
try
{
uint16 zid = getZoneIdByName(zoneName);
CAABBox box = getZoneBBoxById(zid);
CVector translation = -box.getCenter();
if (tessellation.setup(zid, 4, translation))
{
tessellation.build();
CAABBox tbox = tessellation.computeBBox();
tessellation.compile();
tessellation.generateBorders(1.0);
NLPACS::CLocalRetriever retriever;
CAABBox rbbox = tessellation.BestFittingBBox;
CVector hs = rbbox.getHalfSize();
hs.z = 10000.0f;
rbbox.setHalfSize(hs);
retriever.setBBox(rbbox);
retriever.setType(NLPACS::CLocalRetriever::Landscape);
for (j=0; j<tessellation.Surfaces.size(); ++j)
{
retriever.addSurface(0,
0,
0,
0,
0,
tessellation.Surfaces[j].IsUnderWater,
tessellation.Surfaces[j].WaterHeight,
tessellation.Surfaces[j].ClusterHint,
tessellation.Surfaces[j].Center,
tessellation.Surfaces[j].HeightQuad,
tessellation.Surfaces[j].QuantHeight);
if (Verbose)
{
nlinfo("Added surface %d: water=%d", j, (tessellation.Surfaces[j].IsUnderWater ? 1 : 0));
}
}
for (j=0; j<tessellation.Borders.size(); ++j)
{
if (tessellation.Borders[j].Right < -1)
{
retriever.addChain(tessellation.Borders[j].Vertices,
tessellation.Borders[j].Left,
NLPACS::CChain::getDummyBorderChainId());
}
else
{
retriever.addChain(tessellation.Borders[j].Vertices,
tessellation.Borders[j].Left,
tessellation.Borders[j].Right);
}
}
retriever.computeLoopsAndTips();
retriever.findBorderChains();
retriever.updateChainIds();
retriever.computeTopologies();
retriever.computeCollisionChainQuad();
retriever.setType(NLPACS::CLocalRetriever::Landscape);
// and save it...
if (!retriever.checkSurfacesIntegrity(translation))
{
nlwarning("retriever '%s' has a surface issue (self covering surface...)", zoneName.c_str());
}
COFile outputRetriever;
name = changeExt(zoneName, string("lr"));
filename = OutputPath+name;
if (Verbose)
nlinfo("save file %s", filename.c_str());
outputRetriever.open(filename);
retriever.serial(outputRetriever);
}
}
catch(const Exception &e)
{
printf("%s\n", e.what ());
}
}
//
//
//
//
//
//
/*
void tessellateAndMoulineZone(string &zoneName)
{
uint i, j;
NLPACS::CZoneTessellation tessellation;
vector<NLPACS::COrderedChain3f> fullChains;
string name;
string filename;
try
{
uint16 zid = getZoneIdByName(zoneName);
CAABBox box = getZoneBBoxById(zid);
CVector translation = -box.getCenter();
if (tessellation.setup(zid, 4, translation))
{
tessellation.build();
CAABBox tbox = tessellation.computeBBox();
vector<CIGBox> boxes;
try
{
if (CFile::fileExists (IGBoxes))
{
CIFile binput(IGBoxes);
binput.serialCont(boxes);
}
else
{
nlinfo("WARNING: IG list no found");
}
}
catch (const Exception &) { nlinfo("WARNING: IG list no found"); }
for (i=0; i<boxes.size(); ++i)
{
if (tbox.intersect(boxes[i].BBox))
{
try
{
// load ig associated to the zone
string igname = boxes[i].Name;
CIFile monStream(CPath::lookup(igname));
CInstanceGroup ig;
monStream.serial(ig);
// search in group for water instance
for (j=0; j<ig._InstancesInfos.size(); ++j)
{
string shapeName = ig._InstancesInfos[j].Name;
if (CFile::getExtension (shapeName) == "")
shapeName += ".shape";
string shapeNameLookup = CPath::lookup (shapeName, false, false);
if (!shapeNameLookup.empty())
{
CIFile f;
if (f.open (shapeNameLookup))
{
CShapeStream shape;
shape.serial(f);
CWaterShape *wshape = dynamic_cast<CWaterShape *>(shape.getShapePointer());
if (wshape == NULL)
continue;
CMatrix matrix;
ig.getInstanceMatrix(j, matrix);
CPolygon wpoly;
wshape->getShapeInWorldSpace(wpoly);
uint k;
for (k=0; k<wpoly.Vertices.size(); ++k)
{
//wpoly.Vertices[k].z = 0.0f;
wpoly.Vertices[k] = matrix * wpoly.Vertices[k];
}
tessellation.addWaterShape(wpoly);
}
else
{
nlwarning ("Can't load shape %s", shapeNameLookup.c_str());
}
}
}
}
catch (const Exception &e)
{
nlwarning("%s", e.what());
}
}
}
tessellation.compile();
tessellation.generateBorders(1.0);
NLPACS::CLocalRetriever retriever;
CAABBox rbbox = tessellation.BestFittingBBox;
CVector hs = rbbox.getHalfSize();
hs.z = 10000.0f;
rbbox.setHalfSize(hs);
retriever.setBBox(rbbox);
retriever.setType(NLPACS::CLocalRetriever::Landscape);
for (j=0; j<(sint)tessellation.Surfaces.size(); ++j)
{
retriever.addSurface(0,
0,
0,
0,
0,
tessellation.Surfaces[j].IsUnderWater,
tessellation.Surfaces[j].WaterHeight,
tessellation.Surfaces[j].ClusterHint,
tessellation.Surfaces[j].Center,
tessellation.Surfaces[j].HeightQuad,
tessellation.Surfaces[j].QuantHeight);
}
for (j=0; j<(sint)tessellation.Borders.size(); ++j)
{
if (tessellation.Borders[j].Right < -1)
{
retriever.addChain(tessellation.Borders[j].Vertices,
tessellation.Borders[j].Left,
NLPACS::CChain::getDummyBorderChainId());
}
else
{
retriever.addChain(tessellation.Borders[j].Vertices,
tessellation.Borders[j].Left,
tessellation.Borders[j].Right);
}
}
fullChains = retriever.getFullOrderedChains();
// save raw retriever
COFile outputRetriever;
name = changeExt(zoneName, string("lr"));
filename = OutputPath+PreprocessDirectory+name;
if (Verbose)
nlinfo("save file %s", filename.c_str());
outputRetriever.open(filename);
retriever.serial(outputRetriever);
// save raw chains
COFile outputChains;
name = changeExt(zoneName, string("ochain"));
filename = OutputPath+name;
if (Verbose)
nlinfo("save file %s", filename.c_str());
outputChains.open(filename);
outputChains.serialCont(fullChains);
}
}
catch(const Exception &e)
{
printf(e.what ());
}
}
void processRetriever(string &zoneName)
{
string name;
string filename;
try
{
uint16 zid = getZoneIdByName(zoneName);
CAABBox box = getZoneBBoxById(zid);
NLPACS::CLocalRetriever retriever;
// load raw retriever
CIFile inputRetriever;
name = changeExt(zoneName, string("lr"));
filename = OutputPath+PreprocessDirectory+name;
if (Verbose)
nlinfo("load file %s", filename.c_str());
if (CFile::fileExists(filename))
{
inputRetriever.open(filename);
retriever.serial(inputRetriever);
// compute the retriever
retriever.computeLoopsAndTips();
retriever.findBorderChains();
retriever.updateChainIds();
retriever.computeTopologies();
retriever.computeCollisionChainQuad();
retriever.setType(NLPACS::CLocalRetriever::Landscape);
//
CSurfaceSplitter splitter;
//splitter.build(retriever);
// and save it...
COFile outputRetriever;
name = changeExt(zoneName, string("lr"));
filename = OutputPath+name;
if (Verbose)
nlinfo("save file %s", filename.c_str());
outputRetriever.open(filename);
retriever.serial(outputRetriever);
}
}
catch(const Exception &e)
{
printf(e.what ());
}
}
*/
//
class CFaultyChain
{
public:
uint Chain;
CVectorD Start, End;
sint PreviousChain, NextChain;
};
class CReconstructed
{
public:
CReconstructed() : FrontInstance(-1), FrontChain(-1) {}
vector<uint> Chains;
CVectorD Start, End;
sint FrontInstance, FrontChain;
};
class CFaultyInstance
{
public:
uint Instance;
vector<CFaultyChain> Chains;
vector<CReconstructed> Reconstructed;
};
class CChainRef
{
public:
uint Chain, Previous;
uint FrontChain;
uint BorderId;
uint From, To;
};
class CFullChain
{
public:
uint Instance;
vector<CVector> Vertices;
vector<CChainRef> Chains;
};
void fixFaultyLinks(map<uint, CFaultyInstance> &faultyInstances,
const vector<NLPACS::CRetrieverInstance> &instances,
const vector<NLPACS::CLocalRetriever> &retrievers)
{
map<uint, CFaultyInstance>::iterator ifi;
uint i, j, k, l;
// first
// rebuild full chains
// -- join all chains that are missing a link
for (ifi=faultyInstances.begin(); ifi!=faultyInstances.end(); ++ifi)
{
CFaultyInstance &inst = (*ifi).second;
// for each chain, find best matching ending chain
for (k=0; k<inst.Chains.size(); ++k)
{
sint best = -1;
double bestDist = 1.0e10;
for (l=0; l<inst.Chains.size(); ++l)
{
if (l == k || (best != -1 && inst.Chains[best].PreviousChain != -1))
continue;
CVectorD diff = inst.Chains[k].End - inst.Chains[l].Start;
double dist = diff.norm();
if (dist < 0.1 && dist < bestDist)
{
best = l;
bestDist = dist;
}
}
if (best != -1)
{
inst.Chains[best].PreviousChain = k;
inst.Chains[k].NextChain = best;
}
}
//
for (k=0; k<inst.Chains.size(); ++k)
{
if (inst.Chains[k].PreviousChain == -1)
{
l = k;
inst.Reconstructed.push_back(CReconstructed());
do
{
inst.Reconstructed.back().Chains.push_back(l);
}
while ((sint)(l=inst.Chains[l].NextChain) != -1);
inst.Reconstructed.back().Start = inst.Chains[inst.Reconstructed.back().Chains.front()].Start;
inst.Reconstructed.back().End = inst.Chains[inst.Reconstructed.back().Chains.back()].End;
}
}
}
// second
// match reconstructed chains
// -- for each reconstructed chain in an instance, find best matching reconstructed chain in neighbour instances
for (ifi=faultyInstances.begin(); ifi!=faultyInstances.end(); ++ifi)
{
CFaultyInstance &inst = (*ifi).second;
const NLPACS::CRetrieverInstance &instance = instances[inst.Instance];
const NLPACS::CLocalRetriever &retriever = retrievers[instance.getRetrieverId()];
vector<sint32> neighbs = instance.getNeighbors();
for (i=0; i<neighbs.size(); ++i)
{
map<uint, CFaultyInstance>::iterator ifn = faultyInstances.find(neighbs[i]);
if (ifn == faultyInstances.end())
continue;
CFaultyInstance &neighb = (*ifn).second;
for (j=0; j<inst.Reconstructed.size(); ++j)
{
if (inst.Reconstructed[j].FrontInstance != -1)
continue;
CVectorD &astart = inst.Reconstructed[j].Start,
&aend = inst.Reconstructed[j].End;
const NLPACS::CRetrieverInstance &ninstance = instances[neighb.Instance];
const NLPACS::CLocalRetriever &nretriever = retrievers[ninstance.getRetrieverId()];
for (k=0; k<neighb.Reconstructed.size(); ++k)
{
if (neighb.Reconstructed[k].FrontInstance != -1)
continue;
CVectorD &bstart = neighb.Reconstructed[j].Start,
&bend = neighb.Reconstructed[j].End;
if ((astart-bend).norm() < 0.1 && (aend-bstart).norm() < 0.1)
{
// ok, found missing match !
inst.Reconstructed[j].FrontInstance = neighb.Instance;
inst.Reconstructed[j].FrontChain = k;
neighb.Reconstructed[k].FrontInstance = inst.Instance;
neighb.Reconstructed[k].FrontChain = j;
CFullChain fci, fcn;
uint m;
CVector ori = instance.getOrigin(),
orn = ninstance.getOrigin();
fci.Instance = inst.Instance;
fcn.Instance = neighb.Instance;
// build full chains
for (l=0; l<inst.Reconstructed[j].Chains.size(); ++l)
{
uint chain = inst.Chains[inst.Reconstructed[j].Chains[l]].Chain;
NLPACS::CLocalRetriever::CIterator it(&retriever, chain);
CChainRef cr;
cr.Chain = chain;
cr.Previous = chain;
cr.From = (uint)fci.Vertices.size();
cr.BorderId = NLPACS::CChain::convertBorderChainId(retriever.getChain(chain).getRight());
while (!it.end())
{
fci.Vertices.push_back(it.get3d()+ori);
++it;
}
cr.To = (uint)fci.Vertices.size()-1;
if (l < inst.Reconstructed[j].Chains.size()-1)
fci.Vertices.pop_back();
fci.Chains.push_back(cr);
}
for (l=0; l<neighb.Reconstructed[k].Chains.size(); ++l)
{
uint chain = neighb.Chains[neighb.Reconstructed[k].Chains[l]].Chain;
NLPACS::CLocalRetriever::CIterator it(&nretriever, chain);
CChainRef cr;
cr.Chain = chain;
cr.Previous = chain;
cr.From = (uint)fcn.Vertices.size();
cr.BorderId = NLPACS::CChain::convertBorderChainId(nretriever.getChain(chain).getRight());
while (!it.end())
{
fcn.Vertices.push_back(it.get3d()+orn);
++it;
}
cr.To = (uint)fcn.Vertices.size()-1;
if (l < neighb.Reconstructed[k].Chains.size()-1)
fcn.Vertices.pop_back();
fcn.Chains.push_back(cr);
}
if (fcn.Vertices.size() != fci.Vertices.size())
{
nlwarning("Couldn't reconstruct link between %d and %d, mismatching number of vertices", inst.Instance, neighb.Instance);
break;
}
for (l=0; l<fci.Vertices.size(); ++l)
{
if ((fci.Vertices[l] - fcn.Vertices[fci.Vertices.size()-1-l]).norm() > 0.2f)
{
nlwarning("Couldn't reconstruct link between %d and %d, some vertices don't match", inst.Instance, neighb.Instance);
break;
}
fci.Vertices[l] -= ori;
fcn.Vertices[fci.Vertices.size()-1-l] -= orn;
}
if (l<fci.Vertices.size())
break;
uint newChaini = (uint)retriever.getChains().size(),
newChainn = (uint)nretriever.getChains().size();
// save free border ids in order to renumerate them after splits
vector<uint> ifreeBorderIds, nfreeBorderIds;
uint inextBorderId, nnextBorderId;
for (l=0; l<fci.Chains.size(); ++l)
ifreeBorderIds.push_back(fci.Chains[l].BorderId);
inextBorderId = (uint)retriever.getBorderChains().size();
for (l=0; l<fcn.Chains.size(); ++l)
nfreeBorderIds.push_back(fcn.Chains[l].BorderId);
nnextBorderId = (uint)nretriever.getBorderChains().size();
// generate splits from first chain on second chain
for (l=0; l<fci.Chains.size()-1; ++l)
{
uint splitAt = (uint)fci.Vertices.size()-1 - fci.Chains[l].To;
for (m=(uint)fcn.Chains.size()-1; (sint)m>=0 && fcn.Chains[m].From>splitAt; --m)
;
// no split ?
if ((sint)m < 0 || fcn.Chains[m].From == splitAt)
continue;
// insert split in second chain
fcn.Chains.insert(fcn.Chains.begin()+m+1, fcn.Chains[m]);
fcn.Chains[m].To = splitAt;
fcn.Chains[m+1].From = splitAt;
fcn.Chains[m+1].Chain = newChainn++;
}
// generate splits from second chain on first chain
for (l=0; l<fcn.Chains.size()-1; ++l)
{
uint splitAt = (uint)fcn.Vertices.size()-1 - fcn.Chains[l].To;
for (m=(uint)fci.Chains.size()-1; (sint)m>=0 && fci.Chains[m].From>splitAt; --m)
;
// no split ?
if ((sint)m < 0 || fci.Chains[m].From == splitAt)
continue;
// insert split in first chain
fci.Chains.insert(fci.Chains.begin()+m+1, fci.Chains[m]);
fci.Chains[m].To = splitAt;
fci.Chains[m+1].From = splitAt;
fci.Chains[m+1].Chain = newChaini++;
}
if (fci.Chains.size() != fcn.Chains.size())
{
nlwarning("Couldn't reconstruct link between %d and %d, chain splitting failed", inst.Instance, neighb.Instance);
break;
}
// renumerate border ids after splits
for (l=0; l<fci.Chains.size(); ++l)
{
if (!ifreeBorderIds.empty())
{
fci.Chains[l].BorderId = ifreeBorderIds.back();
ifreeBorderIds.pop_back();
}
else
{
fci.Chains[l].BorderId = inextBorderId++;
}
(const_cast<NLPACS::CLocalRetriever&>(retriever)).forceBorderChainId(fci.Chains[l].Chain, fci.Chains[l].BorderId);
}
for (l=0; l<fcn.Chains.size(); ++l)
{
if (!nfreeBorderIds.empty())
{
fcn.Chains[l].BorderId = nfreeBorderIds.back();
nfreeBorderIds.pop_back();
}
else
{
fcn.Chains[l].BorderId = nnextBorderId++;
}
(const_cast<NLPACS::CLocalRetriever&>(nretriever)).forceBorderChainId(fcn.Chains[l].Chain, fcn.Chains[l].BorderId);
}
// insert/replace new chains in instances
vector<NLPACS::CLocalRetriever::CChainReplacement> replacement;
vector<uint> newIds;
l=0;
while (l<fci.Chains.size())
{
sint previous=-1;
newIds.clear();
replacement.clear();
for (; l<fci.Chains.size(); ++l)
{
if (previous != -1 && previous != (sint)fci.Chains[l].Previous)
break;
previous = fci.Chains[l].Previous;
NLPACS::CLocalRetriever::CChainReplacement cr;
cr.Chain = fci.Chains[l].Chain;
cr.Left = retriever.getChain(previous).getLeft();
cr.Right = NLPACS::CChain::convertBorderChainId(fci.Chains[l].BorderId);
cr.Vertices.clear();
cr.Vertices.insert(cr.Vertices.begin(),
fci.Vertices.begin()+fci.Chains[l].From,
fci.Vertices.begin()+fci.Chains[l].To+1);
replacement.push_back(cr);
newIds.push_back(fci.Chains[l].BorderId);
}
if (replacement.size() >= 2)
{
(const_cast<NLPACS::CLocalRetriever&>(retriever)).replaceChain(previous, replacement);
(const_cast<NLPACS::CRetrieverInstance&>(instance)).resetBorderChainLinks(newIds);
}
}
l=0;
while (l<fcn.Chains.size())
{
sint previous=-1;
newIds.clear();
replacement.clear();
for (; l<fcn.Chains.size(); ++l)
{
if (previous != -1 && previous != (sint)fcn.Chains[l].Previous)
break;
previous = fcn.Chains[l].Previous;
NLPACS::CLocalRetriever::CChainReplacement cr;
cr.Chain = fcn.Chains[l].Chain;
cr.Left = nretriever.getChain(previous).getLeft();
cr.Right = NLPACS::CChain::convertBorderChainId(fcn.Chains[l].BorderId);
cr.Vertices.clear();
cr.Vertices.insert(cr.Vertices.begin(),
fcn.Vertices.begin()+fcn.Chains[l].From,
fcn.Vertices.begin()+fcn.Chains[l].To+1);
replacement.push_back(cr);
newIds.push_back(fcn.Chains[l].BorderId);
}
if (replacement.size() >= 2)
{
(const_cast<NLPACS::CLocalRetriever&>(nretriever)).replaceChain(previous, replacement);
(const_cast<NLPACS::CRetrieverInstance&>(ninstance)).resetBorderChainLinks(newIds);
}
}
// force links between instances (border chain links)
for (l=0; l<fci.Chains.size(); ++l)
{
m = (uint)fci.Chains.size()-1-l;
(const_cast<NLPACS::CRetrieverInstance&>(instance)).forceBorderChainLink(fci.Chains[l].BorderId,
neighb.Instance,
fcn.Chains[m].BorderId,
fcn.Chains[m].Chain,
nretriever.getChain(fcn.Chains[m].Chain).getLeft());
(const_cast<NLPACS::CRetrieverInstance&>(ninstance)).forceBorderChainLink(fcn.Chains[m].BorderId,
inst.Instance,
fci.Chains[l].BorderId,
fci.Chains[l].Chain,
retriever.getChain(fci.Chains[l].Chain).getLeft());
if (Verbose)
nlinfo("Fixed: link between %d/%d and %d/%d => %d/%d - %d/%d", fci.Instance, fci.Chains[l].Previous, fcn.Instance, fcn.Chains[m].Previous, fci.Instance, fci.Chains[l].Chain, fcn.Instance, fcn.Chains[m].Chain);
}
break;
}
}
}
}
(const_cast<NLPACS::CLocalRetriever&>(retriever)).computeCollisionChainQuad();
}
}
void processGlobalRetriever()
{
NLPACS::CRetrieverBank retrieverBank;
NLPACS::CGlobalRetriever globalRetriever;
uint ULid = getZoneIdByName(GlobalUL),
DRid = getZoneIdByName(GlobalDR);
CAABBox ULbbox = getZoneBBoxById(ULid);
CAABBox DRbbox = getZoneBBoxById(DRid);
CAABBox bbox;
CVector vmin, vmax;
vmin.minof(ULbbox.getMin(), DRbbox.getMin());
vmax.maxof(ULbbox.getMax(), DRbbox.getMax());
bbox.setMinMax(vmin, vmax);
uint x0 = ULid%256,
y0 = ULid/256,
x1 = DRid%256,
y1 = DRid/256;
globalRetriever.setRetrieverBank(&retrieverBank);
globalRetriever.init();
uint x, y;
if (Verbose)
nlinfo("make all instances");
for (y=y0; y<=y1; ++y)
{
for (x=x0; x<=x1; ++x)
{
try
{
string filename = OutputPath+getZoneNameById(x+y*256)+".lr";
if (CFile::fileExists (filename))
{
uint retrieverId = retrieverBank.addRetriever(filename);
globalRetriever.makeInstance(retrieverId, 0, getZoneCenterById((uint16)getIdByCoord(x, y)));
}
}
catch (const Exception &e)
{
printf("%s\n", e.what ());
}
}
}
if (Verbose)
nlinfo("make all links");
globalRetriever.makeAllLinks();
// if (Verbose)
// nlinfo("clean retriever bank up");
// retrieverBank.clean();
map<uint, CFaultyInstance> faultyInstances;
const vector<NLPACS::CRetrieverInstance> &instances = globalRetriever.getInstances();
const vector<NLPACS::CLocalRetriever> &retrievers = retrieverBank.getRetrievers();
uint i, j;
uint totalUnlinked = 0, totalLink = 0;
for (i=0; i<instances.size(); ++i)
{
const vector<NLPACS::CRetrieverInstance::CLink> &links = instances[i].getBorderChainLinks();
CVector pos = instances[i].getBBox().getCenter();
string unlinkstr = "instance "+toString(i)+":"+getZoneNameById(getZoneIdByPos(pos))+":";
bool unlinkerr = false;
const NLPACS::CLocalRetriever &retriever = retrievers[instances[i].getRetrieverId()];
CFaultyInstance fi;
fi.Instance = i;
for (j=0; j<links.size(); ++j)
{
++totalLink;
if (links[j].Instance == 0xffff)
{
unlinkstr += (string(" ")+toString(j));
++totalUnlinked;
unlinkerr = true;
CFaultyChain fc;
fc.Chain = retriever.getBorderChain(j);
fc.Start = retriever.getStartVector(fc.Chain) + instances[i].getOrigin();
fc.End = retriever.getStopVector(fc.Chain) + instances[i].getOrigin();
fc.PreviousChain = -1;
fc.NextChain = -1;
fi.Chains.push_back(fc);
}
}
if (unlinkerr)
{
if (Verbose)
nlinfo("unlink: %s", unlinkstr.c_str());
faultyInstances.insert(make_pair<uint, CFaultyInstance>(i, fi));
}
}
if (Verbose)
nlinfo("%d are still unlinked (%d links total)", totalUnlinked, totalLink);
// rebuild full chains
if (totalUnlinked > 0)
{
if (Verbose)
nlinfo("Fixing faulty links...");
fixFaultyLinks(faultyInstances, instances, retrievers);
// recheck
const vector<NLPACS::CRetrieverInstance> &instances = globalRetriever.getInstances();
const vector<NLPACS::CLocalRetriever> &retrievers = retrieverBank.getRetrievers();
uint i, j;
uint totalUnlinked = 0, totalLink = 0;
for (i=0; i<instances.size(); ++i)
{
const vector<NLPACS::CRetrieverInstance::CLink> &links = instances[i].getBorderChainLinks();
CVector pos = instances[i].getBBox().getCenter();
string unlinkstr = "instance "+toString(i)+":"+getZoneNameById(getZoneIdByPos(pos))+":";
bool unlinkerr = false;
const NLPACS::CLocalRetriever &retriever = retrievers[instances[i].getRetrieverId()];
CFaultyInstance fi;
fi.Instance = i;
for (j=0; j<links.size(); ++j)
{
++totalLink;
if (links[j].Instance == 0xffff)
{
unlinkstr += (string(" ")+toString(j));
++totalUnlinked;
unlinkerr = true;
CFaultyChain fc;
fc.Chain = retriever.getBorderChain(j);
fc.Start = retriever.getStartVector(fc.Chain) + instances[i].getOrigin();
fc.End = retriever.getStopVector(fc.Chain) + instances[i].getOrigin();
fc.PreviousChain = -1;
fc.NextChain = -1;
fi.Chains.push_back(fc);
}
}
if (unlinkerr)
{
if (Verbose)
nlinfo("after fix: unlink: %s", unlinkstr.c_str());
faultyInstances.insert(make_pair<uint, CFaultyInstance>(i, fi));
}
}
}
if (Verbose)
nlinfo("init the quad grid");
globalRetriever.initQuadGrid();
string filename;
COFile outputRetriever;
filename = OutputPath+GlobalRetriever;
if (Verbose)
nlinfo("save file %s", filename.c_str());
outputRetriever.open(filename);
globalRetriever.serial(outputRetriever);
COFile outputBank;
filename = OutputPath+RetrieverBank;
if (Verbose)
nlinfo("save file %s", filename.c_str());
outputBank.open(filename);
retrieverBank.serial(outputBank);
retrieverBank.saveRetrievers(OutputPath, CFile::getFilenameWithoutExtension(RetrieverBank));
}
///
void updateRetrieverBank()
{
NLPACS::CRetrieverBank retrieverBank;
string filename;
filename = OutputPath+RetrieverBank;
CIFile inputBank;
if (Verbose)
nlinfo("load file %s", filename.c_str());
inputBank.open(filename);
retrieverBank.serial(inputBank);
inputBank.close();
COFile outputBank;
if (Verbose)
nlinfo("save file %s", filename.c_str());
outputBank.open(filename);
retrieverBank.serial(outputBank);
outputBank.close();
}