2017-03-15 19:29:34 +00:00
// 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/pacs/global_retriever.h"
# include "nel/pacs/retriever_bank.h"
# include "nel/pacs/surface_quad.h"
# include "nel/pacs/local_retriever.h"
# include "nel/pacs/retriever_instance.h"
# include "nel/pacs/chain.h"
# include "nel/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 ( std : : 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 ( std : : 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 ( ) ;
}