Added new mechanism for handling Seams.
This commit is contained in:
@@ -126,10 +126,6 @@ SOURCE=..\..\..\src\osgPlugins\txp\TXPSeamLOD.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TXPTileNode.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TileMapper.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -254,10 +250,6 @@ SOURCE=..\..\..\src\osgPlugins\txp\TXPSeamLOD.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TXPTileNode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\osgPlugins\txp\TileMapper.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -7,7 +7,6 @@ CXXFILES =\
|
||||
TXPIO.cpp\
|
||||
TXPNode.cpp\
|
||||
TXPPageManager.cpp\
|
||||
TXPTileNode.cpp\
|
||||
TXPParser.cpp\
|
||||
TXPSeamLOD.cpp\
|
||||
TXPPagedLOD.cpp\
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -43,9 +43,10 @@
|
||||
#include <osg/Referenced>
|
||||
#include <map>
|
||||
|
||||
#include "TXPArchive.h"
|
||||
|
||||
namespace txp
|
||||
{
|
||||
class TXPArchive;
|
||||
class ReaderWriterTXP : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
@@ -64,6 +65,8 @@ public:
|
||||
protected:
|
||||
TXPArchive *getArchive(int id, const std::string&);
|
||||
std::map< int,osg::ref_ptr<TXPArchive> > _archives;
|
||||
|
||||
osg::Node* getTileContent(TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive);
|
||||
|
||||
static int _archiveId;
|
||||
};
|
||||
|
||||
@@ -224,7 +224,7 @@ bool TXPArchive::loadMaterials()
|
||||
osg_material->setShininess(osg::Material::FRONT_AND_BACK , (float)shinines);
|
||||
|
||||
osg_material->setAlpha(osg::Material::FRONT_AND_BACK ,(float)alpha);
|
||||
osg_state_set->setAttributeAndModes(osg_material, osg::StateAttribute::ON);
|
||||
//osg_state_set->setAttributeAndModes(osg_material, osg::StateAttribute::ON);
|
||||
|
||||
if( alpha < 1.0f )
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <osg/Notify>
|
||||
#include <osg/BoundingBox>
|
||||
#include <osg/PagedLOD>
|
||||
#include <osg/Timer>
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
@@ -9,6 +11,9 @@
|
||||
#include "TileMapper.h"
|
||||
#include "TXPNode.h"
|
||||
#include "TXPPagedLOD.h"
|
||||
|
||||
|
||||
|
||||
using namespace txp;
|
||||
|
||||
|
||||
@@ -46,8 +51,40 @@ void TXPNode::traverse(osg::NodeVisitor& nv)
|
||||
switch(nv.getVisitorType())
|
||||
{
|
||||
case osg::NodeVisitor::CULL_VISITOR:
|
||||
{
|
||||
|
||||
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
|
||||
if (cv)
|
||||
{
|
||||
//const osg::Timer& timer = *osg::Timer::instance();
|
||||
//osg::Timer_t start = timer.tick();
|
||||
//std::cout<<"Doing visible tile search"<<std::endl;
|
||||
|
||||
osg::ref_ptr<TileMapper> tileMapper = new TileMapper;
|
||||
tileMapper->pushViewport(cv->getViewport());
|
||||
tileMapper->pushProjectionMatrix(&(cv->getProjectionMatrix()));
|
||||
tileMapper->pushModelViewMatrix(&(cv->getModelViewMatrix()));
|
||||
|
||||
// traverse the scene graph to search for valid tiles
|
||||
accept(*tileMapper);
|
||||
|
||||
tileMapper->popModelViewMatrix();
|
||||
tileMapper->popProjectionMatrix();
|
||||
tileMapper->popViewport();
|
||||
|
||||
//std::cout<<" found " << tileMapper._tileMap.size() << std::endl;
|
||||
|
||||
tileMapper->checkValidityOfAllVisibleTiles();
|
||||
|
||||
cv->setUserData(tileMapper.get());
|
||||
|
||||
//std::cout<<"Completed visible tile search in "<<timer.delta_m(start,timer.tick())<<std::endl;
|
||||
|
||||
}
|
||||
|
||||
updateEye(nv);
|
||||
break;
|
||||
}
|
||||
case osg::NodeVisitor::UPDATE_VISITOR:
|
||||
updateSceneGraph();
|
||||
break;
|
||||
@@ -188,30 +225,17 @@ osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod)
|
||||
TXPArchive::TileInfo info;
|
||||
_archive->getTileInfo(x,y,lod,info);
|
||||
|
||||
TXPPagedLOD* pagedLOD = new TXPPagedLOD;
|
||||
osg::PagedLOD* pagedLOD = new osg::PagedLOD;
|
||||
pagedLOD->setFileName(0,pagedLODfile);
|
||||
//pagedLOD->setPriorityOffset(0,1.0f);
|
||||
pagedLOD->setPriorityOffset(0,_archive->getNumLODs());
|
||||
pagedLOD->setPriorityScale(0,1.0f);
|
||||
pagedLOD->setRange(0,0.0,info.maxRange);
|
||||
pagedLOD->setCenter(info.center);
|
||||
pagedLOD->setRadius(info.radius);
|
||||
pagedLOD->setNumChildrenThatCannotBeExpired(1);
|
||||
pagedLOD->setTileId(x,y,lod);
|
||||
|
||||
int sizeX, sizeY;
|
||||
if (_archive->getLODSize(lod,sizeX,sizeY))
|
||||
{
|
||||
if ((x-1) > -1) pagedLOD->addNeighbour(x-1,y);
|
||||
if ((x+1) < sizeX) pagedLOD->addNeighbour(x+1,y);
|
||||
if ((y-1) > -1) pagedLOD->addNeighbour(x,y-1);
|
||||
if ((y+1) < sizeY) pagedLOD->addNeighbour(x,y+1);
|
||||
}
|
||||
|
||||
_nodesToAdd.push_back(pagedLOD);
|
||||
|
||||
TileMapper::instance()->insertPagedLOD(x,y,lod,pagedLOD);
|
||||
|
||||
return pagedLOD;
|
||||
}
|
||||
|
||||
@@ -234,10 +258,7 @@ void TXPNode::updateSceneGraph()
|
||||
}
|
||||
_nodesToAdd.clear();
|
||||
|
||||
}
|
||||
|
||||
TileMapper::instance()->prunePagedLOD();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,78 +3,55 @@
|
||||
using namespace txp;
|
||||
|
||||
TXPPagedLOD::TXPPagedLOD():
|
||||
PagedLOD(),
|
||||
_tileX(-1),
|
||||
_tileY(-1),
|
||||
_tileLOD(-1),
|
||||
_lastChildTraversed(-1)
|
||||
PagedLOD()
|
||||
{
|
||||
}
|
||||
|
||||
TXPPagedLOD::TXPPagedLOD(const TXPPagedLOD& plod,const osg::CopyOp& copyop):
|
||||
PagedLOD(plod,copyop),
|
||||
_tileX(plod._tileX),
|
||||
_tileY(plod._tileY),
|
||||
_tileLOD(plod._tileLOD),
|
||||
_lastChildTraversed(plod._lastChildTraversed)
|
||||
PagedLOD(plod,copyop),
|
||||
_tileIdentifier(plod._tileIdentifier)
|
||||
{
|
||||
}
|
||||
|
||||
TXPPagedLOD::~TXPPagedLOD()
|
||||
{
|
||||
TileMapper::instance()->removePagedLOD(_tileX,_tileY,_tileLOD);
|
||||
}
|
||||
|
||||
void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
|
||||
// PagedLOD::traverse(nv);
|
||||
//
|
||||
// return;
|
||||
TileMapper* tileMapper = dynamic_cast<TileMapper*>(nv.getUserData());
|
||||
bool forceUseOfFirstChild = tileMapper ? (tileMapper->isNodeBlackListed(this)) : false;
|
||||
|
||||
double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
|
||||
bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
|
||||
|
||||
switch(nv.getTraversalMode())
|
||||
{
|
||||
case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN):
|
||||
case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN):
|
||||
std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv));
|
||||
break;
|
||||
case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
|
||||
case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
|
||||
{
|
||||
float distance = nv.getDistanceToEyePoint(getCenter(),true);
|
||||
|
||||
_lastChildTraversed = -1;
|
||||
int lastChildTraversed = -1;
|
||||
bool needToLoadChild = false;
|
||||
bool rollBack = false;
|
||||
for(unsigned int i=0;i<_rangeList.size();++i)
|
||||
|
||||
unsigned maxRangeSize = _rangeList.size();
|
||||
if (maxRangeSize!=0 && forceUseOfFirstChild) maxRangeSize=1;
|
||||
|
||||
for(unsigned int i=0;i<maxRangeSize;++i)
|
||||
{
|
||||
if (_rangeList[i].first<=distance && distance<_rangeList[i].second)
|
||||
if (forceUseOfFirstChild || _rangeList[i].first<=distance && distance<_rangeList[i].second)
|
||||
{
|
||||
if (i<_children.size())
|
||||
{
|
||||
bool acceptThisChild = true;
|
||||
if (updateTimeStamp) _perRangeDataList[i]._timeStamp=timeStamp;
|
||||
|
||||
if (i)
|
||||
{
|
||||
for (unsigned int ni = 0; ni < _neighbours.size(); ni++)
|
||||
{
|
||||
Neighbour& n = _neighbours[ni];
|
||||
if (TileMapper::instance()->getPagedLOD(n._x, n._y, _tileLOD)== 0)
|
||||
{
|
||||
rollBack = true;
|
||||
acceptThisChild = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptThisChild)
|
||||
{
|
||||
if (updateTimeStamp) _perRangeDataList[i]._timeStamp=timeStamp;
|
||||
_children[i]->accept(nv);
|
||||
_lastChildTraversed = (int)i;
|
||||
}
|
||||
//std::cout<<"PagedLOD::traverse() - Selecting child "<<i<<std::endl;
|
||||
_children[i]->accept(nv);
|
||||
lastChildTraversed = (int)i;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -82,14 +59,6 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rollBack)
|
||||
{
|
||||
if (updateTimeStamp) _perRangeDataList[0]._timeStamp=timeStamp;
|
||||
_children[0]->accept(nv);
|
||||
_lastChildTraversed = 0;
|
||||
//std::cout << "Rolling back" << std::endl;
|
||||
}
|
||||
|
||||
if (needToLoadChild)
|
||||
{
|
||||
@@ -97,12 +66,11 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
|
||||
|
||||
//std::cout<<"PagedLOD::traverse() - falling back "<<std::endl;
|
||||
// select the last valid child.
|
||||
if (numChildren>0 && ((int)numChildren-1)!=_lastChildTraversed)
|
||||
if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
|
||||
{
|
||||
//std::cout<<" to child "<<numChildren-1<<std::endl;
|
||||
if (updateTimeStamp) _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
|
||||
_children[numChildren-1]->accept(nv);
|
||||
_lastChildTraversed = numChildren-1;
|
||||
}
|
||||
|
||||
// now request the loading of the next unload child.
|
||||
@@ -128,3 +96,4 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#define __TXPPAGEDLOD_H_
|
||||
|
||||
#include <osg/PagedLOD>
|
||||
#include "TileMapper.h"
|
||||
|
||||
namespace txp
|
||||
{
|
||||
@@ -52,33 +53,15 @@ namespace txp
|
||||
|
||||
inline void setTileId(int x, int y, int lod)
|
||||
{
|
||||
_tileX = x; _tileY = y; _tileLOD = lod;
|
||||
_tileIdentifier.set(x,y,lod);
|
||||
}
|
||||
|
||||
inline void addNeighbour(int x,int y)
|
||||
{
|
||||
Neighbour n;
|
||||
n._x = x;
|
||||
n._y = y;
|
||||
_neighbours.push_back(n);
|
||||
}
|
||||
TileIdentifier _tileIdentifier;
|
||||
|
||||
int _tileX;
|
||||
int _tileY;
|
||||
int _tileLOD;
|
||||
|
||||
inline const int getLastTraversedChild() const { return _lastChildTraversed; }
|
||||
|
||||
protected:
|
||||
virtual ~TXPPagedLOD();
|
||||
|
||||
int _lastChildTraversed;
|
||||
|
||||
struct Neighbour
|
||||
{
|
||||
int _x, _y;
|
||||
};
|
||||
std::vector<Neighbour> _neighbours;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -412,7 +412,7 @@ void TXPParser::loadLocalMaterials()
|
||||
osg_material->setShininess(osg::Material::FRONT_AND_BACK , (float)shinines);
|
||||
|
||||
osg_material->setAlpha(osg::Material::FRONT_AND_BACK ,(float)alpha);
|
||||
osg_state_set->setAttributeAndModes(osg_material, osg::StateAttribute::ON);
|
||||
//osg_state_set->setAttributeAndModes(osg_material, osg::StateAttribute::ON);
|
||||
|
||||
if( alpha < 1.0f )
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "TXPSeamLOD.h"
|
||||
#include "TXPArchive.h"
|
||||
#include "TXPTileNode.h"
|
||||
#include "TXPPagedLOD.h"
|
||||
#include "TileMapper.h"
|
||||
|
||||
@@ -9,90 +8,43 @@ using namespace txp;
|
||||
TXPSeamLOD::TXPSeamLOD() :
|
||||
Group()
|
||||
{
|
||||
_neighbourTileX =
|
||||
_neighbourTileY =
|
||||
_neighbourTileLOD = -1;
|
||||
_tileRef = 0;
|
||||
_txpNode = 0;
|
||||
_archive = 0;
|
||||
_hiResPresent = false;
|
||||
_nonSeamChildrenIndex = -1;
|
||||
_dx = 0;
|
||||
_dy = 0;
|
||||
}
|
||||
|
||||
TXPSeamLOD::TXPSeamLOD(int x, int y, int lod, const osg::Vec3& center, float dmin, float dmid, float dmax) :
|
||||
TXPSeamLOD::TXPSeamLOD(int x, int y, int lod, int dx, int dy) :
|
||||
Group()
|
||||
{
|
||||
_neighbourTileX = x;
|
||||
_neighbourTileY = y;
|
||||
_neighbourTileLOD = lod;
|
||||
_center = center;
|
||||
_min = dmin;
|
||||
_mid = dmid;
|
||||
_max = dmax;
|
||||
_txpNode = 0;
|
||||
_tileRef = 0;
|
||||
_archive = 0;
|
||||
_hiResPresent = false;
|
||||
_nonSeamChildrenIndex = -1;
|
||||
_tid.x = x;
|
||||
_tid.y = y;
|
||||
_tid.lod = lod;
|
||||
_dx = dx;
|
||||
_dy = dy;
|
||||
}
|
||||
|
||||
TXPSeamLOD::TXPSeamLOD(const TXPSeamLOD& ttg,const osg::CopyOp& copyop) :
|
||||
Group(ttg,copyop)
|
||||
{
|
||||
_neighbourTileX = ttg._neighbourTileX;
|
||||
_neighbourTileY = ttg._neighbourTileY;
|
||||
_neighbourTileLOD = ttg._neighbourTileLOD;
|
||||
_tileRef = ttg._tileRef;
|
||||
_archive = ttg._archive;
|
||||
_hiResPresent = ttg._hiResPresent;
|
||||
_nonSeamChildrenIndex = ttg._nonSeamChildrenIndex;
|
||||
_tid = ttg._tid;
|
||||
_dx = ttg._dx;
|
||||
_dy = ttg._dy;
|
||||
}
|
||||
|
||||
void TXPSeamLOD::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR && _children.size()==2)
|
||||
if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR && getNumChildren()==2)
|
||||
{
|
||||
|
||||
//osg::PagedLOD* pagedLOD = TileMapper::instance()->getPagedLOD(_neighbourTileX,_neighbourTileY, _neighbourTileLOD);
|
||||
TXPPagedLOD* pagedLOD = dynamic_cast<TXPPagedLOD*>(TileMapper::instance()->getPagedLOD(_neighbourTileX,_neighbourTileY, _neighbourTileLOD));
|
||||
#if 1
|
||||
if (pagedLOD && pagedLOD->getLastTraversedChild()>0)
|
||||
|
||||
TileMapper* tileMapper = dynamic_cast<TileMapper*>(nv.getUserData());
|
||||
if (tileMapper && !tileMapper->isTileNeighbourALowerLODLevel(_tid,_dx,_dy))
|
||||
{
|
||||
getChild(1)->accept(nv);
|
||||
}
|
||||
else
|
||||
{
|
||||
getChild(0)->accept(nv);
|
||||
#else
|
||||
bool acceptLoRes = true;
|
||||
if (pagedLOD)
|
||||
{
|
||||
|
||||
float distance = nv.getDistanceToEyePoint(_center,true);
|
||||
distance = nv.getDistanceToEyePoint(pagedLOD->getCenter(),true);
|
||||
|
||||
//std::cout<<"distance to eye from center = "<<distance<<" min = "<< _min<<" mid = "<< _mid << " max = "<<_max<<std::endl;
|
||||
//std::cout<<" TXPSeam::_center "<<_center<<" PageLOD::_center "<<pagedLOD->getCenter()<<std::endl;
|
||||
int numChildren = osg::minimum(getNumChildren(),pagedLOD->getNumChildren());
|
||||
for(int i=numChildren-1;i>=0;--i)
|
||||
{
|
||||
//std::cout<<" child "<<i<<" range = min "<<pagedLOD->getMinRange(i)<<" max = "<<pagedLOD->getMaxRange(i)<<std::endl;
|
||||
if (distance<=pagedLOD->getMaxRange(i))
|
||||
{
|
||||
getChild(i)->accept(nv);
|
||||
acceptLoRes = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (acceptLoRes)
|
||||
{
|
||||
getChild(0)->accept(nv); // pick low res
|
||||
}
|
||||
|
||||
if (_nonSeamChildrenIndex > -1)
|
||||
{
|
||||
for (int i = _nonSeamChildrenIndex; i < (int)getNumChildren(); i++ )
|
||||
getChild(i)->accept(nv);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "TXPTileNode.h"
|
||||
#include "TXPArchive.h"
|
||||
#include "TileMapper.h"
|
||||
|
||||
namespace txp
|
||||
{
|
||||
@@ -50,8 +49,7 @@ public:
|
||||
|
||||
TXPSeamLOD();
|
||||
|
||||
TXPSeamLOD(int x, int y, int lod, const osg::Vec3& center, float dmin,
|
||||
float dmid, float dmax);
|
||||
TXPSeamLOD(int x, int y, int lod, int dx, int dy);
|
||||
|
||||
TXPSeamLOD(const TXPSeamLOD&,
|
||||
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
@@ -60,49 +58,12 @@ public:
|
||||
|
||||
virtual void traverse(osg::NodeVisitor& nv);
|
||||
|
||||
void setTileRef(bool* b)
|
||||
{
|
||||
_tileRef = b;
|
||||
}
|
||||
|
||||
void setTxpNode(TXPTileNode* txpNode)
|
||||
{
|
||||
_txpNode = txpNode;
|
||||
}
|
||||
|
||||
TXPTileNode* getTxpNode() const
|
||||
{
|
||||
return _txpNode;
|
||||
}
|
||||
|
||||
void setArchive(TXPArchive* ar)
|
||||
{
|
||||
_archive = ar;
|
||||
}
|
||||
|
||||
inline void setHiResPresent(bool p) { _hiResPresent = p; }
|
||||
inline void setNonSeamChildrenIndex(int ix) { _nonSeamChildrenIndex = ix; }
|
||||
|
||||
protected:
|
||||
|
||||
bool _hiResPresent;
|
||||
TileIdentifier _tid;
|
||||
|
||||
int _nonSeamChildrenIndex;
|
||||
|
||||
int _neighbourTileX;
|
||||
int _neighbourTileY;
|
||||
int _neighbourTileLOD;
|
||||
|
||||
osg::Vec3 _center;
|
||||
|
||||
float _min;
|
||||
float _mid;
|
||||
float _max;
|
||||
|
||||
bool* _tileRef;
|
||||
|
||||
TXPTileNode* _txpNode;
|
||||
TXPArchive* _archive;
|
||||
int _dx;
|
||||
int _dy;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
#include <osg/PagedLOD>
|
||||
|
||||
#include "TileMapper.h"
|
||||
#include "TXPTileNode.h"
|
||||
#include "TXPArchive.h"
|
||||
#include "TXPSeamLOD.h"
|
||||
#include "TXPPagedLOD.h"
|
||||
using namespace txp;
|
||||
|
||||
class PrintVisitor : public osg::NodeVisitor
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
PrintVisitor():NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
_indent = 0;
|
||||
_step = 4;
|
||||
}
|
||||
|
||||
inline void moveIn() { _indent += _step; }
|
||||
inline void moveOut() { _indent -= _step; }
|
||||
inline void writeIndent()
|
||||
{
|
||||
for(int i=0;i<_indent;++i) std::cout << " ";
|
||||
}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
moveIn();
|
||||
writeIndent(); std::cout << node.className() <<std::endl;
|
||||
traverse(node);
|
||||
moveOut();
|
||||
}
|
||||
|
||||
virtual void apply(osg::Geode& node) { apply((osg::Node&)node); }
|
||||
virtual void apply(osg::Billboard& node) { apply((osg::Geode&)node); }
|
||||
virtual void apply(osg::LightSource& node) { apply((osg::Group&)node); }
|
||||
virtual void apply(osg::ClipNode& node) { apply((osg::Group&)node); }
|
||||
|
||||
virtual void apply(osg::Group& node) { apply((osg::Node&)node); }
|
||||
virtual void apply(osg::Transform& node) { apply((osg::Group&)node); }
|
||||
virtual void apply(osg::Projection& node) { apply((osg::Group&)node); }
|
||||
virtual void apply(osg::Switch& node) { apply((osg::Group&)node); }
|
||||
virtual void apply(osg::LOD& lod)
|
||||
{
|
||||
moveIn();
|
||||
writeIndent(); std::cout << lod.className() <<std::endl;
|
||||
if (lod.className()=="TXPPagedLOD")
|
||||
{
|
||||
TXPPagedLOD *plod = (TXPPagedLOD*)&lod;
|
||||
writeIndent(); std::cout << "X="<<plod->_tileX<<" Y="<<plod->_tileY<<" LOD="<<plod->_tileLOD<< std::endl;
|
||||
}
|
||||
//writeIndent(); std::cout << "center="<<lod.getCenter()<<std::endl;
|
||||
for(unsigned int i=0;i<lod.getNumChildren();++i)
|
||||
{
|
||||
//writeIndent(); std::cout << "child min="<<lod.getMinRange(i)<<" max="<<lod.getMaxRange(i)<<std::endl;
|
||||
lod.getChild(i)->accept(*this);
|
||||
}
|
||||
moveOut();
|
||||
}
|
||||
virtual void apply(osg::Impostor& node) { apply((osg::LOD&)node); }
|
||||
|
||||
protected:
|
||||
|
||||
int _indent;
|
||||
int _step;
|
||||
};
|
||||
|
||||
TXPTileNode::TXPTileNode():
|
||||
osg::Group(),
|
||||
_archive(0)
|
||||
{
|
||||
}
|
||||
|
||||
TXPTileNode::TXPTileNode(const TXPTileNode& tn,const osg::CopyOp& copyop):
|
||||
osg::Group(tn,copyop),
|
||||
_archive(tn._archive)
|
||||
{
|
||||
}
|
||||
|
||||
TXPTileNode::~TXPTileNode()
|
||||
{
|
||||
}
|
||||
|
||||
void TXPTileNode::setArchive(TXPArchive* archive)
|
||||
{
|
||||
_archive = 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 x = _x;
|
||||
int y = _y;
|
||||
int lod = _lod;
|
||||
osg::Vec3 delta = loRes->getCenter()-_info.center;
|
||||
if (fabs(delta.x())>fabs(delta.y()))
|
||||
{
|
||||
if (delta.x()<0.0) --x; // west
|
||||
else x++; // east
|
||||
}
|
||||
else
|
||||
{
|
||||
if (delta.y()<0.0) --y; // south
|
||||
else ++y; // north
|
||||
}
|
||||
TXPSeamLOD* seam = new TXPSeamLOD(
|
||||
x,
|
||||
y,
|
||||
lod,
|
||||
loRes->getCenter(),
|
||||
0.f,
|
||||
_info.minRange,
|
||||
_info.maxRange
|
||||
);
|
||||
seam->setArchive(_archive);
|
||||
seam->addChild(loRes->getChild(0)); // low res
|
||||
if (hiRes)
|
||||
{
|
||||
seam->addChild(hiRes->getChild(0)); // high res
|
||||
seam->setHiResPresent(true);
|
||||
}
|
||||
if (nonSeamChildren.size())
|
||||
{
|
||||
seam->setNonSeamChildrenIndex(seam->getNumChildren());
|
||||
for (unsigned int i = 0; i < nonSeamChildren.size(); i++)
|
||||
seam->addChild(nonSeamChildren[i]);
|
||||
}
|
||||
return seam;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
bool TXPTileNode::loadTile(int x, int y, int lod)
|
||||
{
|
||||
if (_archive == 0) return false;
|
||||
|
||||
TXPArchive::TileInfo info;
|
||||
|
||||
bool validTile = _archive->getTileInfo(x,y,lod,info);
|
||||
int numLods = _archive->getNumLODs();
|
||||
|
||||
if (validTile)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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(tileGroup,info.minRange,osg::maximum(info.maxRange,1e7));
|
||||
pagedLOD->setFileName(1,pagedLODfile);
|
||||
pagedLOD->setRange(1,0,info.minRange);
|
||||
pagedLOD->setCenter(info.center);
|
||||
//pagedLOD->setCenter(tileCenter);
|
||||
pagedLOD->setRadius(info.radius);
|
||||
pagedLOD->setPriorityOffset(0,numLods-lod);
|
||||
pagedLOD->setPriorityScale(0,1.0f);
|
||||
pagedLOD->setNumChildrenThatCannotBeExpired(1);
|
||||
pagedLOD->setTileId(x,y,lod);
|
||||
|
||||
int sizeX, sizeY;
|
||||
if (_archive->getLODSize(lod,sizeX,sizeY))
|
||||
{
|
||||
if ((x-1) > -1) pagedLOD->addNeighbour(x-1,y);
|
||||
if ((x+1) < sizeX) pagedLOD->addNeighbour(x+1,y);
|
||||
if ((y-1) > -1) pagedLOD->addNeighbour(x,y-1);
|
||||
if ((y+1) < sizeY) pagedLOD->addNeighbour(x,y+1);
|
||||
}
|
||||
|
||||
TileMapper::instance()->insertPagedLOD(x,y,lod,pagedLOD.get());
|
||||
|
||||
addChild(pagedLOD.get());
|
||||
|
||||
//PrintVisitor pv;
|
||||
//accept(pv);
|
||||
}
|
||||
else
|
||||
{
|
||||
addChild(tileGroup);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/***************************************************************************
|
||||
* December 2003
|
||||
*
|
||||
* This TerraPage loader was re-written in a fashion to use PagedLOD
|
||||
* to manage paging entirely, also includes a version of Terrex's smart mesh
|
||||
* adapted to work with PagedLOD. The essential code by Boris Bralo is still present,
|
||||
* slight modified.
|
||||
* nick at terrex dot com
|
||||
*
|
||||
* Ported to PagedLOD technology by Trajce Nikolov (Nick) & Robert Osfield
|
||||
*****************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* OpenSceneGraph loader for Terrapage format database
|
||||
* by Boris Bralo 2002
|
||||
*
|
||||
* based on/modifed sgl (Scene Graph Library) loader by Bryan Walsh
|
||||
*
|
||||
* This loader is based on/modified from Terrain Experts Performer Loader,
|
||||
* and was ported to SGL by Bryan Walsh / bryanw at earthlink dot net
|
||||
*
|
||||
* That loader is redistributed under the terms listed on Terrain Experts
|
||||
* website (www.terrex.com/www/pages/technology/technologypage.htm)
|
||||
*
|
||||
* "TerraPage is provided as an Open Source format for use by anyone...
|
||||
* We supply the TerraPage C++ source code free of charge. Anyone
|
||||
* can use it and redistribute it as needed (including our competitors).
|
||||
* We do, however, ask that you keep the TERREX copyrights intact."
|
||||
*
|
||||
* Copyright Terrain Experts Inc. 1999.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __TXPTILENODE_H_
|
||||
#define __TXPTILENODE_H_
|
||||
|
||||
#include <osg/Group>
|
||||
#include "TXPArchive.h"
|
||||
|
||||
namespace txp
|
||||
{
|
||||
class TXPArchive;
|
||||
class TXPTileNode : public osg::Group
|
||||
{
|
||||
public:
|
||||
TXPTileNode();
|
||||
|
||||
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
||||
TXPTileNode(const TXPTileNode&,
|
||||
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Node(txp, TXPTileNode);
|
||||
|
||||
void setArchive(TXPArchive* archive);
|
||||
bool loadTile(int x, int y, int lod);
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~TXPTileNode();
|
||||
|
||||
TXPArchive* _archive;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
#endif // __TXPTILENODE_H_
|
||||
@@ -1,48 +1,437 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library 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
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include "TileMapper.h"
|
||||
#include <OpenThreads/ScopedLock>
|
||||
//#include "TXPTileNode.h"
|
||||
#include "TXPPagedLOD.h"
|
||||
|
||||
#include <osg/Material>
|
||||
|
||||
using namespace txp;
|
||||
|
||||
TileMapper* TileMapper::instance()
|
||||
float TileMapper::getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const
|
||||
{
|
||||
static osg::ref_ptr<TileMapper> s_tilemapper = new TileMapper;
|
||||
return s_tilemapper.get();
|
||||
if (withLODScale) return (pos-getEyeLocal()).length()*getLODScale();
|
||||
else return (pos-getEyeLocal()).length();
|
||||
}
|
||||
|
||||
osg::PagedLOD* TileMapper::getPagedLOD(int x, int y, int lod)
|
||||
inline TileMapper::value_type distance(const osg::Vec3& coord,const osg::Matrix& matrix)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
TileMap::iterator itr = _tileMap.find(TileTriple(x,y,lod));
|
||||
if (itr!=_tileMap.end()) return itr->second;
|
||||
else return 0;
|
||||
|
||||
//std::cout << "distance("<<coord<<", "<<matrix<<")"<<std::endl;
|
||||
|
||||
return -((TileMapper::value_type)coord[0]*(TileMapper::value_type)matrix(0,2)+(TileMapper::value_type)coord[1]*(TileMapper::value_type)matrix(1,2)+(TileMapper::value_type)coord[2]*(TileMapper::value_type)matrix(2,2)+matrix(3,2));
|
||||
}
|
||||
|
||||
void TileMapper::insertPagedLOD(int x, int y, int lod, osg::PagedLOD* pagedLod)
|
||||
float TileMapper::getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODScale) const
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
_tileMap[TileTriple(x,y,lod)]=pagedLod;
|
||||
const osg::Matrix& matrix = *_modelviewStack.back();
|
||||
float dist = distance(pos,matrix);
|
||||
|
||||
if (withLODScale) return dist*getLODScale();
|
||||
else return dist;
|
||||
}
|
||||
|
||||
void TileMapper::removePagedLOD(int x, int y, int lod)
|
||||
void TileMapper::apply(osg::Node& node)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
TileMap::iterator itr = _tileMap.find(TileTriple(x,y,lod));
|
||||
if (itr!=_tileMap.end()) _tileMap.erase(itr);
|
||||
if (isCulled(node)) return;
|
||||
|
||||
// push the culling mode.
|
||||
pushCurrentMask();
|
||||
|
||||
traverse(node);
|
||||
|
||||
// pop the culling mode.
|
||||
popCurrentMask();
|
||||
}
|
||||
|
||||
void TileMapper::prunePagedLOD()
|
||||
void TileMapper::apply(osg::Group& node)
|
||||
{
|
||||
// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||
// for(TileMap::iterator itr = _tileMap.begin();
|
||||
// itr!=_tileMap.end();
|
||||
// ++itr)
|
||||
// {
|
||||
// if (itr->second.valid() && itr->second->referenceCount()==1)
|
||||
// {
|
||||
// TileMap::iterator eitr = itr;
|
||||
// --itr;
|
||||
// _tileMap.erase(eitr);
|
||||
// }
|
||||
// }
|
||||
//std::cout<<"_tileMap.size()="<<_tileMap.size()<<std::endl;
|
||||
if (isCulled(node)) return;
|
||||
|
||||
// push the culling mode.
|
||||
pushCurrentMask();
|
||||
|
||||
TileIdentifier* tid = dynamic_cast<TileIdentifier*>(node.getUserData());
|
||||
|
||||
if (tid)
|
||||
{
|
||||
_tileStack.push_back(TileStack::value_type(*tid,&node));
|
||||
|
||||
_containsGeode = false;
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
|
||||
if (tid)
|
||||
{
|
||||
if (_containsGeode)
|
||||
{
|
||||
insertTile(*tid);
|
||||
|
||||
_containsGeode = false;
|
||||
|
||||
#if 0
|
||||
std::cout<<"found Group="<<tid->lod
|
||||
<<" X="<<tid->x
|
||||
<<" Y="<<tid->y
|
||||
<<" ptr="<<&node<<std::endl;
|
||||
|
||||
std::cout<<" inheritance list "<<_tileStack.size()<<std::endl;
|
||||
for(TileStack::iterator itr=_tileStack.begin();
|
||||
itr!=_tileStack.end();
|
||||
++itr)
|
||||
{
|
||||
std::cout<<" LOD="<<itr->first.lod
|
||||
<<" X="<<itr->first.x
|
||||
<<" Y="<<itr->first.y
|
||||
<<" className="<<itr->second->className()
|
||||
<<" ptr="<<itr->second<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
osg::StateSet* stateset = node.getOrCreateStateSet();
|
||||
osg::Material* material = new osg::Material;
|
||||
material->setColorMode(osg::Material::OFF);
|
||||
stateset->setAttribute(material);
|
||||
|
||||
switch(tid->lod)
|
||||
{
|
||||
case(0): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); break;
|
||||
case(1): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,0.0f,1.0f)); break;
|
||||
case(2): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,1.0f,0.0f,1.0f)); break;
|
||||
case(3): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,1.0f,1.0f)); break;
|
||||
case(4): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,1.0f,1.0f)); break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
_tileStack.pop_back();
|
||||
}
|
||||
|
||||
// pop the culling mode.
|
||||
popCurrentMask();
|
||||
}
|
||||
|
||||
void TileMapper::apply(osg::Geode&)
|
||||
{
|
||||
_containsGeode = true;
|
||||
}
|
||||
|
||||
void TileMapper::apply(osg::PagedLOD& node)
|
||||
{
|
||||
if (isCulled(node)) return;
|
||||
|
||||
// push the culling mode.
|
||||
pushCurrentMask();
|
||||
|
||||
TXPPagedLOD* txpPagedLOD = dynamic_cast<TXPPagedLOD*>(&node);
|
||||
if (txpPagedLOD)
|
||||
{
|
||||
|
||||
_tileStack.push_back(TileStack::value_type(txpPagedLOD->_tileIdentifier,&node));
|
||||
|
||||
_containsGeode = false;
|
||||
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
|
||||
if (txpPagedLOD)
|
||||
{
|
||||
if (_containsGeode)
|
||||
{
|
||||
insertTile(txpPagedLOD->_tileIdentifier);
|
||||
|
||||
_containsGeode = false;
|
||||
|
||||
#if 0
|
||||
std::cout<<"found txpPagedLOD LOD="<<txpPagedLOD->_tileIdentifier.lod
|
||||
<<" X="<<txpPagedLOD->_tileIdentifier.x
|
||||
<<" Y="<<txpPagedLOD->_tileIdentifier.y
|
||||
<<" ptr="<<txpPagedLOD<<std::endl;
|
||||
|
||||
std::cout<<" inheritance list "<<_tileStack.size()<<std::endl;
|
||||
for(TileStack::iterator itr=_tileStack.begin();
|
||||
itr!=_tileStack.end();
|
||||
++itr)
|
||||
{
|
||||
std::cout<<" LOD="<<itr->first.lod
|
||||
<<" X="<<itr->first.x
|
||||
<<" Y="<<itr->first.y
|
||||
<<" className="<<itr->second->className()
|
||||
<<" ptr="<<itr->second<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
osg::StateSet* stateset = txpPagedLOD->getOrCreateStateSet();
|
||||
osg::Material* material = new osg::Material;
|
||||
material->setColorMode(osg::Material::OFF);
|
||||
stateset->setAttribute(material);
|
||||
|
||||
switch(txpPagedLOD->_tileIdentifier.lod)
|
||||
{
|
||||
case(0): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); break;
|
||||
case(1): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,0.0f,1.0f)); break;
|
||||
case(2): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,1.0f,0.0f,1.0f)); break;
|
||||
case(3): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,1.0f,1.0f)); break;
|
||||
case(4): material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,0.0f,1.0f,1.0f)); break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
_tileStack.pop_back();
|
||||
}
|
||||
|
||||
// pop the culling mode.
|
||||
popCurrentMask();
|
||||
}
|
||||
|
||||
void TileMapper::insertTile(const TileIdentifier& tid)
|
||||
{
|
||||
_tileMap.insert(TileMap::value_type(tid,_tileStack));
|
||||
}
|
||||
|
||||
bool TileMapper::canParentBeTraversed(const TileIdentifier& tid) const
|
||||
{
|
||||
// find the tiles parents.
|
||||
TileMap::const_iterator itr = _tileMap.find(tid);
|
||||
if (itr==_tileMap.end())
|
||||
{
|
||||
// not found tile in _tileMap, what should we do??
|
||||
// return true as a fallback right now.
|
||||
std::cout<<"TileMapper::canDescend() Not found tile in map"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
const TileStack& ts = itr->second;
|
||||
|
||||
// note tile here, is tid's parent.
|
||||
const TileStack::value_type* tile = (ts.size()>=2) ? &ts[ts.size()-2] : 0;
|
||||
|
||||
// note parent here, is tid's parents parent.
|
||||
const TileStack::value_type* parent = (ts.size()>=3) ? &ts[ts.size()-3] : 0;
|
||||
|
||||
if (!tile)
|
||||
{
|
||||
// no self!!! so we can descend safely?!! shouldn't ever get here.
|
||||
//std::cout<<"TileMapper::canDescend() tile==0"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!parent)
|
||||
{
|
||||
// no parent so we can descend safely.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tileHasNorthNeighour = _tileMap.count(TileIdentifier(tid.x,tid.y+1,tid.lod))!=0;
|
||||
bool tileHasEastNeighour = _tileMap.count(TileIdentifier(tid.x+1,tid.y,tid.lod))!=0;
|
||||
bool tileHasSouthNeighour = _tileMap.count(TileIdentifier(tid.x,tid.y-1,tid.lod))!=0;
|
||||
bool tileHasWestNeighour = _tileMap.count(TileIdentifier(tid.x-1,tid.y,tid.lod))!=0;
|
||||
|
||||
if (tileHasNorthNeighour && tileHasEastNeighour && tileHasSouthNeighour && tileHasWestNeighour)
|
||||
{
|
||||
// tile has neigbours on all sides at the same lod level, so its safe to descend.
|
||||
//std::cout<<"TileMapper::canDescend() has neightbours on all sides"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
const TileIdentifier& parent_tid = parent->first;
|
||||
|
||||
bool parentHasNorthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y+1,parent_tid.lod))!=0;
|
||||
bool parentHasEastNeighour = _tileMap.count(TileIdentifier(parent_tid.x+1,parent_tid.y,parent_tid.lod))!=0;
|
||||
bool parentHasSouthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y-1,parent_tid.lod))!=0;
|
||||
bool parentHasWestNeighour = _tileMap.count(TileIdentifier(parent_tid.x-1,parent_tid.y,parent_tid.lod))!=0;
|
||||
|
||||
|
||||
// identify whether the tile is a NE/SE/SW/NW tile relative to its parent.
|
||||
osg::Vec3 delta = tile->second->getBound().center() - parent->second->getBound().center();
|
||||
|
||||
if (delta.y()>=0.0f) // noth side
|
||||
{
|
||||
if (delta.x()>=0.0f)
|
||||
{
|
||||
// NE, only traverse if our parent doesn't have any neighbours to the north or east.
|
||||
return (!parentHasNorthNeighour && !parentHasEastNeighour);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NW, only traverse if our parent doesn't have any neighbours to the north or west.
|
||||
return (!parentHasNorthNeighour && !parentHasWestNeighour);
|
||||
}
|
||||
}
|
||||
else // south side
|
||||
{
|
||||
if (delta.x()>=0.0f)
|
||||
{
|
||||
// SE, only traverse if our parent doesn't have any neighbours to the south or east.
|
||||
return (!parentHasSouthNeighour && !parentHasEastNeighour);
|
||||
}
|
||||
else
|
||||
{
|
||||
// SW, only traverse if our parent doesn't have any neighbours to the south or west.
|
||||
return (!parentHasSouthNeighour && !parentHasWestNeighour);
|
||||
}
|
||||
}
|
||||
// we shouldn't get here...
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TileMapper::checkValidityOfAllVisibleTiles()
|
||||
{
|
||||
typedef std::vector<TileIdentifier> ToRemoveList;
|
||||
typedef std::vector<TileStack> ToAddList;
|
||||
|
||||
ToRemoveList toRemoveList;
|
||||
ToAddList toAddList;
|
||||
|
||||
do
|
||||
{
|
||||
// std::cout<<"doing checkAllVisibleTiles() loop with "<<_tileMap.size()<<std::endl;
|
||||
|
||||
toRemoveList.clear();
|
||||
toAddList.clear();
|
||||
|
||||
for(TileMap::iterator itr=_tileMap.begin();
|
||||
itr!=_tileMap.end();
|
||||
++itr)
|
||||
{
|
||||
if (!canParentBeTraversed(itr->first))
|
||||
{
|
||||
// need to remove.
|
||||
toRemoveList.push_back(itr->first);
|
||||
|
||||
// trim the end of itr's TileStack and add into toAddList
|
||||
toAddList.push_back(itr->second);
|
||||
|
||||
// std::cout<<"Tile failed"
|
||||
// <<" LOD="<<itr->first.lod
|
||||
// <<" X="<<itr->first.x
|
||||
// <<" Y="<<itr->first.y<<std::endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(ToRemoveList::iterator ritr=toRemoveList.begin();
|
||||
ritr!=toRemoveList.end();
|
||||
++ritr)
|
||||
{
|
||||
//std::cout<<"Removing Tile"<<std::endl;
|
||||
_tileMap.erase(*ritr);
|
||||
}
|
||||
|
||||
for(ToAddList::iterator aitr=toAddList.begin();
|
||||
aitr!=toAddList.end();
|
||||
++aitr)
|
||||
{
|
||||
//std::cout<<"Adding Parents Tile back in"<<std::endl;
|
||||
aitr->pop_back();
|
||||
_blackListedNodeSet.insert(aitr->back().second);
|
||||
_tileMap.insert(TileMap::value_type(aitr->back().first,*aitr));
|
||||
}
|
||||
|
||||
} while (!toRemoveList.empty());
|
||||
|
||||
if (!_blackListedNodeSet.empty()) std::cout<<"********** We have blacked list "<<_blackListedNodeSet.size()<<std::endl;
|
||||
|
||||
}
|
||||
|
||||
bool TileMapper::isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx, int dy) const
|
||||
{
|
||||
if (_tileMap.count(TileIdentifier(tid.x+dx,tid.y+dy,tid.lod))!=0)
|
||||
{
|
||||
// we have a neightbour at the same lod level.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// find the tiles parents.
|
||||
TileMap::const_iterator itr = _tileMap.find(tid);
|
||||
if (itr==_tileMap.end())
|
||||
{
|
||||
// not found tile in _tileMap, what should we do??
|
||||
// return true as a fallback right now.
|
||||
std::cout<<"TileMapper::isTileNeighbourALowerLODLevel() Not found tile in map"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const TileStack& ts = itr->second;
|
||||
|
||||
// note tile here, is tid's parent.
|
||||
const TileStack::value_type* tile = (ts.size()>=1) ? &ts[ts.size()-1] : 0;
|
||||
|
||||
if (!tile)
|
||||
{
|
||||
// no tile, so must assume taht neight is now at a lower level
|
||||
return false;
|
||||
}
|
||||
|
||||
// note parent here, is tid's parents parent.
|
||||
const TileStack::value_type* parent = (ts.size()>=2) ? &ts[ts.size()-2] : 0;
|
||||
|
||||
if (!parent)
|
||||
{
|
||||
// no parent so we must assume that is not at a lower level
|
||||
return false;
|
||||
}
|
||||
|
||||
const TileIdentifier& parent_tid = parent->first;
|
||||
|
||||
bool parentHasNorthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y+1,parent_tid.lod))!=0;
|
||||
bool parentHasEastNeighour = _tileMap.count(TileIdentifier(parent_tid.x+1,parent_tid.y,parent_tid.lod))!=0;
|
||||
bool parentHasSouthNeighour = _tileMap.count(TileIdentifier(parent_tid.x,parent_tid.y-1,parent_tid.lod))!=0;
|
||||
bool parentHasWestNeighour = _tileMap.count(TileIdentifier(parent_tid.x-1,parent_tid.y,parent_tid.lod))!=0;
|
||||
|
||||
|
||||
// identify whether the tile is a NE/SE/SW/NW tile relative to its parent.
|
||||
osg::Vec3 delta = tile->second->getBound().center() - parent->second->getBound().center();
|
||||
|
||||
if (delta.y()>=0.0f) // noth side
|
||||
{
|
||||
if (delta.x()>=0.0f)
|
||||
{
|
||||
// NE
|
||||
if (dy==1) return parentHasNorthNeighour;
|
||||
else if (dx==1) return parentHasEastNeighour;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NW
|
||||
if (dy==1) return parentHasNorthNeighour;
|
||||
else if (dx==-1) return parentHasWestNeighour;
|
||||
}
|
||||
}
|
||||
else // south side
|
||||
{
|
||||
if (delta.x()>=0.0f)
|
||||
{
|
||||
// SE
|
||||
if (dy==-1) return parentHasSouthNeighour;
|
||||
else if (dx==1) return parentHasEastNeighour;
|
||||
}
|
||||
else
|
||||
{
|
||||
// SW
|
||||
if (dy==-1) return parentHasSouthNeighour;
|
||||
else if (dx==-1) return parentHasWestNeighour;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,73 +1,137 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2004 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library 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
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __TILEMAPPER_H_
|
||||
#define __TILEMAPPER_H_
|
||||
|
||||
#include "trpage_sys.h"
|
||||
#include "trpage_read.h"
|
||||
|
||||
#include <osg/Referenced>
|
||||
#include <osg/PagedLOD>
|
||||
#include <osg/CullStack>
|
||||
#include <osg/NodeVisitor>
|
||||
|
||||
#include <OpenThreads/Mutex>
|
||||
#include <set>
|
||||
|
||||
namespace txp
|
||||
{
|
||||
class TileMapper : public osg::Referenced
|
||||
|
||||
struct TileIdentifier : public osg::Referenced
|
||||
{
|
||||
TileIdentifier():
|
||||
x(-1),
|
||||
y(-1),
|
||||
lod(-1) {}
|
||||
|
||||
TileIdentifier(int ax, int ay, int alod):
|
||||
x(ax),
|
||||
y(ay),
|
||||
lod(alod) {}
|
||||
|
||||
TileIdentifier(const TileIdentifier& rhs):
|
||||
osg::Referenced(),
|
||||
x(rhs.x),
|
||||
y(rhs.y),
|
||||
lod(rhs.lod) {}
|
||||
|
||||
TileIdentifier& operator = (const TileIdentifier& rhs)
|
||||
{
|
||||
if (this==&rhs) return *this;
|
||||
x = rhs.x;
|
||||
y = rhs.y;
|
||||
lod = rhs.lod;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set(int ax, int ay, int alod)
|
||||
{
|
||||
x = ax;
|
||||
y = ay;
|
||||
lod = alod;
|
||||
}
|
||||
|
||||
bool operator < (const TileIdentifier& rhs) const
|
||||
{
|
||||
if (lod<rhs.lod)
|
||||
return true;
|
||||
if (lod>rhs.lod)
|
||||
return false;
|
||||
if (x<rhs.x)
|
||||
return true;
|
||||
if (x>rhs.x)
|
||||
return false;
|
||||
if (y<rhs.y)
|
||||
return true;
|
||||
if (y>rhs.y)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
int x,y,lod;
|
||||
|
||||
};
|
||||
|
||||
class TileMapper : public osg::NodeVisitor, public osg::CullStack
|
||||
{
|
||||
public:
|
||||
|
||||
typedef osg::Matrix::value_type value_type;
|
||||
|
||||
static TileMapper* instance();
|
||||
|
||||
TileMapper():
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {}
|
||||
|
||||
|
||||
virtual osg::Vec3 getEyePoint() const { return getEyeLocal(); }
|
||||
virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const;
|
||||
virtual float getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODScale) const;
|
||||
|
||||
virtual void apply(osg::Node& node);
|
||||
virtual void apply(osg::Group& node);
|
||||
virtual void apply(osg::Geode& node);
|
||||
virtual void apply(osg::PagedLOD& node);
|
||||
|
||||
osg::PagedLOD* getPagedLOD(int x, int y, int lod);
|
||||
void insertTile(const TileIdentifier& tid);
|
||||
|
||||
void insertPagedLOD(int x, int y, int lod, osg::PagedLOD* pagedLod);
|
||||
bool canParentBeTraversed(const TileIdentifier& tid) const;
|
||||
|
||||
void removePagedLOD(int x, int y, int lod);
|
||||
void checkValidityOfAllVisibleTiles();
|
||||
|
||||
void prunePagedLOD();
|
||||
bool containsBlackListedNodes() const
|
||||
{
|
||||
return !_blackListedNodeSet.empty();
|
||||
}
|
||||
|
||||
inline bool isNodeBlackListed(const osg::Node* node) const
|
||||
{
|
||||
return _blackListedNodeSet.count(node)!=0;
|
||||
}
|
||||
|
||||
bool isTileNeighbourALowerLODLevel(const TileIdentifier& tid, int dx, int dy) const;
|
||||
|
||||
protected:
|
||||
|
||||
// Constructor
|
||||
TileMapper()
|
||||
{}
|
||||
typedef std::vector< std::pair<TileIdentifier,osg::Node*> > TileStack;
|
||||
typedef std::map< TileIdentifier, TileStack > TileMap;
|
||||
typedef std::set< const osg::Node* > BlacklistedNodeSet;
|
||||
|
||||
// Destructor
|
||||
virtual ~TileMapper()
|
||||
{}
|
||||
|
||||
struct TileTriple
|
||||
{
|
||||
TileTriple(int ax, int ay, int alod):
|
||||
x(ax),y(ay),lod(alod)
|
||||
{}
|
||||
|
||||
int x,y,lod;
|
||||
|
||||
bool operator < (const TileTriple& rhs) const
|
||||
{
|
||||
if (x<rhs.x)
|
||||
return true;
|
||||
if (x>rhs.x)
|
||||
return false;
|
||||
if (y<rhs.y)
|
||||
return true;
|
||||
if (y>rhs.y)
|
||||
return false;
|
||||
if (lod<rhs.lod)
|
||||
return true;
|
||||
if (lod>rhs.lod)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map< TileTriple, osg::PagedLOD* > TileMap;
|
||||
|
||||
OpenThreads::Mutex _mutex;
|
||||
TileStack _tileStack;
|
||||
TileMap _tileMap;
|
||||
bool _containsGeode;
|
||||
|
||||
BlacklistedNodeSet _blackListedNodeSet;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __TXPARCHIVE_H_
|
||||
#endif // __TILEMAPPER_H_
|
||||
|
||||
Reference in New Issue
Block a user