Added new mechanism for handling Seams.
This commit is contained in:
@@ -8,8 +8,10 @@
|
||||
|
||||
#include "ReaderWriterTXP.h"
|
||||
#include "TXPNode.h"
|
||||
#include "TXPTileNode.h"
|
||||
#include "TXPArchive.h"
|
||||
#include "TXPPagedLOD.h"
|
||||
#include "TXPSeamLOD.h"
|
||||
#include "TileMapper.h"
|
||||
|
||||
#define ReaderWriterTXPERROR(s) osg::notify(osg::NOTICE) << "txp::ReaderWriterTXP::" << (s) << " error: "
|
||||
|
||||
@@ -59,17 +61,40 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fil
|
||||
sscanf(name.c_str(),"tile%d_%dx%d_%d",&lod,&x,&y,&id);
|
||||
TXPArchive* archive = getArchive(id,osgDB::getFilePath(fileName));
|
||||
|
||||
osg::ref_ptr<TXPTileNode> txpTileNode = new TXPTileNode;
|
||||
txpTileNode->setArchive(archive);
|
||||
|
||||
if (txpTileNode->loadTile(x,y,lod))
|
||||
{
|
||||
//osg::notify(osg::NOTICE) << "Tile " << x << " " << y << " " << lod << " lodaded" << std::endl;
|
||||
TXPArchive::TileInfo info;
|
||||
if (!archive->getTileInfo(x,y,lod,info))
|
||||
return ReadResult::ERROR_IN_READING_FILE;
|
||||
|
||||
return txpTileNode.get();
|
||||
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,x,y,lod,archive);
|
||||
|
||||
int numLods = archive->getNumLODs();
|
||||
if (lod < (numLods-1))
|
||||
{
|
||||
char pagedLODfile[1024];
|
||||
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp",
|
||||
archive->getDir(),
|
||||
lod,
|
||||
x,
|
||||
y,
|
||||
archive->getId()
|
||||
);
|
||||
|
||||
osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
|
||||
// not use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
|
||||
pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
|
||||
pagedLOD->setFileName(1,pagedLODfile);
|
||||
pagedLOD->setRange(1,0,info.minRange);
|
||||
pagedLOD->setCenter(info.center);
|
||||
pagedLOD->setRadius(info.radius);
|
||||
pagedLOD->setPriorityOffset(0,numLods-lod);
|
||||
pagedLOD->setPriorityScale(0,1.0f);
|
||||
pagedLOD->setNumChildrenThatCannotBeExpired(1);
|
||||
pagedLOD->setTileId(x,y,lod);
|
||||
|
||||
return pagedLOD.get();
|
||||
}
|
||||
else
|
||||
return ReadResult::ERROR_IN_READING_FILE;
|
||||
return tileContent.get();
|
||||
}
|
||||
|
||||
// We load subtilesLOD_XxY_ID.txp
|
||||
@@ -82,6 +107,10 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fil
|
||||
|
||||
osg::ref_ptr<osg::Group> subtiles = new osg::Group;
|
||||
|
||||
int numLods = archive->getNumLODs();
|
||||
int sizeX, sizeY;
|
||||
archive->getLODSize(lod+1,sizeX,sizeY);
|
||||
|
||||
for (int ix = 0; ix < 2; ix++)
|
||||
for (int iy = 0; iy < 2; iy++)
|
||||
{
|
||||
@@ -89,12 +118,41 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fil
|
||||
int tileY = y*2+iy;
|
||||
int tileLOD = lod+1;
|
||||
|
||||
TXPTileNode* txpTileNode = new TXPTileNode;
|
||||
txpTileNode->setArchive(archive);
|
||||
|
||||
if (txpTileNode->loadTile(tileX,tileY,tileLOD))
|
||||
TXPArchive::TileInfo info;
|
||||
if (!archive->getTileInfo(tileX,tileY,tileLOD,info))
|
||||
continue;
|
||||
|
||||
osg::ref_ptr<osg::Node> tileContent = getTileContent(info,tileX,tileY,tileLOD,archive);
|
||||
|
||||
if (tileLOD < (numLods-1))
|
||||
{
|
||||
subtiles->addChild(txpTileNode);
|
||||
char pagedLODfile[1024];
|
||||
sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp",
|
||||
archive->getDir(),
|
||||
tileLOD,
|
||||
tileX,
|
||||
tileY,
|
||||
archive->getId()
|
||||
);
|
||||
|
||||
osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
|
||||
// not use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
|
||||
pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
|
||||
pagedLOD->setFileName(1,pagedLODfile);
|
||||
pagedLOD->setRange(1,0,info.minRange);
|
||||
pagedLOD->setCenter(info.center);
|
||||
pagedLOD->setRadius(info.radius);
|
||||
pagedLOD->setPriorityOffset(0,numLods-lod);
|
||||
pagedLOD->setPriorityScale(0,1.0f);
|
||||
pagedLOD->setNumChildrenThatCannotBeExpired(1);
|
||||
pagedLOD->setTileId(tileX,tileY,tileLOD);
|
||||
|
||||
subtiles->addChild(pagedLOD.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
subtiles->setUserData(new TileIdentifier(tileX,tileY,tileLOD));
|
||||
subtiles->addChild(tileContent.get());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -162,5 +220,167 @@ TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir)
|
||||
return archive;
|
||||
}
|
||||
|
||||
class SeamFinder: public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
SeamFinder(int x, int y, int lod, TXPArchive::TileInfo& info, TXPArchive *archive ):
|
||||
NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_x(x), _y(y), _lod(lod), _info(info), _archive(archive)
|
||||
{};
|
||||
|
||||
virtual void apply(osg::Group& group)
|
||||
{
|
||||
for (unsigned int i = 0; i < group.getNumChildren(); i++)
|
||||
{
|
||||
osg::Node* child = group.getChild(i);
|
||||
osg::Node* seam = seamReplacement(child);
|
||||
if (child != seam)
|
||||
{
|
||||
group.replaceChild(child,seam);
|
||||
}
|
||||
else
|
||||
{
|
||||
child->accept(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
osg::Node* seamReplacement(osg::Node* node);
|
||||
|
||||
int _x, _y, _lod;
|
||||
TXPArchive::TileInfo& _info;
|
||||
TXPArchive *_archive;
|
||||
};
|
||||
|
||||
osg::Node* SeamFinder::seamReplacement(osg::Node* node)
|
||||
{
|
||||
osg::Group* group = node->asGroup();
|
||||
if (group == 0) return node;
|
||||
|
||||
std::vector<osg::Node*> nonSeamChildren;
|
||||
osg::LOD* hiRes = 0;
|
||||
osg::LOD* loRes = 0;
|
||||
|
||||
for (unsigned int i = 0; i < group->getNumChildren(); i++)
|
||||
{
|
||||
osg::LOD* lod = dynamic_cast<osg::LOD*>(group->getChild(i));
|
||||
if (lod == 0)
|
||||
{
|
||||
nonSeamChildren.push_back(group->getChild(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
bool nonSeamChild = true;
|
||||
|
||||
// seam center is outside the bounding box of the tile
|
||||
if (!_info.bbox.contains(lod->getCenter()))
|
||||
{
|
||||
// seams have center as the neighbour tile
|
||||
osg::Vec3 d = _info.center - lod->getCenter();
|
||||
if (((fabs(d.x())-_info.size.x()) > 0.0001) && ((fabs(d.y())-_info.size.y()) > 0.0001))
|
||||
{
|
||||
nonSeamChildren.push_back(lod);
|
||||
continue;
|
||||
}
|
||||
|
||||
// low res seam has min/max ranges of lod+1 range/lod 0 range
|
||||
if ((fabs(_info.minRange-lod->getMinRange(0))<0.001)&&(fabs(_info.lod0Range-lod->getMaxRange(0))<0.001))
|
||||
{
|
||||
|
||||
if (loRes==0)
|
||||
{
|
||||
loRes = lod;
|
||||
nonSeamChild = false;
|
||||
}
|
||||
}
|
||||
|
||||
// hi res seam has min/max ranges of 0 range/lod+1 range
|
||||
if ((lod->getMinRange(0)==0.0f)&&(fabs(_info.minRange-lod->getMaxRange(0))<0.001))
|
||||
{
|
||||
if (hiRes==0)
|
||||
{
|
||||
hiRes = lod;
|
||||
nonSeamChild = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nonSeamChild)
|
||||
{
|
||||
nonSeamChildren.push_back(lod);
|
||||
}
|
||||
}
|
||||
|
||||
if (loRes)
|
||||
{
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
int lod = _lod;
|
||||
osg::Vec3 delta = loRes->getCenter()-_info.center;
|
||||
if (fabs(delta.x())>fabs(delta.y()))
|
||||
{
|
||||
if (delta.x()<0.0) --dx; // west
|
||||
else dx++; // east
|
||||
}
|
||||
else
|
||||
{
|
||||
if (delta.y()<0.0) --dy; // south
|
||||
else ++dy; // north
|
||||
}
|
||||
TXPSeamLOD* seam = new TXPSeamLOD(
|
||||
_x,
|
||||
_y,
|
||||
lod,
|
||||
dx,
|
||||
dy
|
||||
);
|
||||
seam->addChild(loRes->getChild(0)); // low res
|
||||
if (hiRes)
|
||||
{
|
||||
seam->addChild(hiRes->getChild(0)); // high res
|
||||
}
|
||||
|
||||
if (nonSeamChildren.size())
|
||||
{
|
||||
std::cout<<"Alert *** need to place in a seperate osg::Group NOT the TXPSeamLOD"<<std::endl;
|
||||
for (unsigned int i = 0; i < nonSeamChildren.size(); i++)
|
||||
seam->addChild(nonSeamChildren[i]);
|
||||
}
|
||||
return seam;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
osg::Node* ReaderWriterTXP::getTileContent(TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive)
|
||||
{
|
||||
if (archive == 0) return false;
|
||||
|
||||
int numLods = archive->getNumLODs();
|
||||
|
||||
double realMinRange = info.minRange;
|
||||
double realMaxRange = info.maxRange;
|
||||
double usedMaxRange = osg::maximum(info.maxRange,1e7);
|
||||
osg::Vec3 tileCenter;
|
||||
osg::Group* tileGroup = archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter);
|
||||
|
||||
// if group has only one child, then simply use its child.
|
||||
#if 1
|
||||
while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())
|
||||
{
|
||||
tileGroup = tileGroup->getChild(0)->asGroup();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Handle seams
|
||||
if (lod < (numLods-1))
|
||||
{
|
||||
SeamFinder sfv(x,y,lod,info,archive);
|
||||
tileGroup->accept(sfv);
|
||||
}
|
||||
|
||||
return tileGroup;
|
||||
}
|
||||
|
||||
osgDB::RegisterReaderWriterProxy<ReaderWriterTXP> g_txpReaderWriterProxy;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user