diff --git a/VisualStudio/osgPlugins/txp/txp.dsp b/VisualStudio/osgPlugins/txp/txp.dsp index 7c07147d7..11bbc42d7 100644 --- a/VisualStudio/osgPlugins/txp/txp.dsp +++ b/VisualStudio/osgPlugins/txp/txp.dsp @@ -110,6 +110,10 @@ SOURCE=..\..\..\src\osgPlugins\txp\TXPNode.cpp # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\txp\TXPPageLOD.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\txp\TXPPageManager.cpp # End Source File # Begin Source File @@ -234,6 +238,10 @@ SOURCE=..\..\..\src\osgPlugins\txp\TXPNode.h # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\txp\TXPPagedNode.h +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\txp\TXPPageManager.h # End Source File # Begin Source File diff --git a/src/osgPlugins/txp/GNUmakefile b/src/osgPlugins/txp/GNUmakefile index da5ab703a..98db0cdcf 100644 --- a/src/osgPlugins/txp/GNUmakefile +++ b/src/osgPlugins/txp/GNUmakefile @@ -10,6 +10,7 @@ CXXFILES =\ TXPTileNode.cpp\ TXPParser.cpp\ TXPSeamLOD.cpp\ + TXPPagedLOD.cpp\ TileMapper.cpp\ trpage_basic.cpp\ trpage_compat.cpp\ diff --git a/src/osgPlugins/txp/TXPArchive.cpp b/src/osgPlugins/txp/TXPArchive.cpp index 0b57f6fd8..053ffcdb2 100644 --- a/src/osgPlugins/txp/TXPArchive.cpp +++ b/src/osgPlugins/txp/TXPArchive.cpp @@ -26,6 +26,8 @@ #include "TXPArchive.h" #include "TXPParser.h" +#include + using namespace txp; #define TXPArchiveERROR(s) osg::notify(osg::NOTICE) << "txp::TXPArchive::" << (s) << " error: " @@ -538,46 +540,42 @@ bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info) info.center.set(0.f,0.f,0.f); info.bbox.set(0.f,0.f,0.f,0.f,0.f,0.f); - const trpgHeader *header = GetHeader(); - const trpgTileTable *tileTable = GetTileTable(); - if (header && tileTable) - { - header->GetLodRange(lod,info.maxRange); - header->GetLodRange(lod+1,info.minRange); + OpenThreads::ScopedLock lock(_mutex); - trpg2dPoint sw,ne; - header->GetExtents(sw,ne); + header.GetLodRange(lod,info.maxRange); + header.GetLodRange(lod+1,info.minRange); - trpg2dPoint size; - header->GetTileSize(lod,size); + trpg2dPoint sw,ne; + header.GetExtents(sw,ne); - trpgwAppAddress addr; - float minz = 0.f; - float maxz = 0.f; - tileTable->GetTile(x,y,lod,addr,minz,maxz); + trpg2dPoint size; + header.GetTileSize(lod,size); - info.center.set( - sw.x+(x*size.x)+(size.x/2.f), - sw.y+(y*size.y)+(size.y/2.f), - (minz+maxz)/2.f - ); - info.bbox.set( - osg::Vec3( - info.center.x()-(size.x/2.f), - info.center.y()-(size.y/2.f), - minz - ), - osg::Vec3( - info.center.x()+(size.x/2.f), - info.center.y()+(size.y/2.f), - maxz - ) - ); - info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length() * 1.3; + trpgwAppAddress addr; + float minz = 0.f; + float maxz = 0.f; + tileTable.GetTile(x,y,lod,addr,minz,maxz); - return true; - } - return false; + info.center.set( + sw.x+(x*size.x)+(size.x/2.f), + sw.y+(y*size.y)+(size.y/2.f), + (minz+maxz)/2.f + ); + info.bbox.set( + osg::Vec3( + info.center.x()-(size.x/2.f), + info.center.y()-(size.y/2.f), + minz + ), + osg::Vec3( + info.center.x()+(size.x/2.f), + info.center.y()+(size.y/2.f), + maxz + ) + ); + info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length() * 1.3; + + return true; } osg::Group* TXPArchive::getTileContent( @@ -601,3 +599,19 @@ osg::Group* TXPArchive::getTileContent( osg::Group *tileGroup = _parser->parseScene(buf,_gstates,_models,realMinRange,realMaxRange,usedMaxRange); return tileGroup; } + +bool TXPArchive::getLODSize(int lod, int& x, int& y) +{ + x = y = 0; + + OpenThreads::ScopedLock lock(_mutex); + + trpg2iPoint size; + if (header.GetLodSize(lod,size)) + { + x = size.x; + y = size.y; + } + + return true; +} diff --git a/src/osgPlugins/txp/TXPArchive.h b/src/osgPlugins/txp/TXPArchive.h index 869d0ba90..badf5668d 100644 --- a/src/osgPlugins/txp/TXPArchive.h +++ b/src/osgPlugins/txp/TXPArchive.h @@ -45,6 +45,8 @@ #include #include +#include + namespace txp { // this one handles different placement of light direction in osg and terrapage @@ -140,6 +142,9 @@ public: double realMinRange, double realMaxRange, double usedMaxRange); + + // Get the number of tiles for given LOD + bool getLODSize(int lod, int& x, int& y); protected: @@ -170,6 +175,9 @@ protected: // Light attributes vector std::vector _lights; + + // + OpenThreads::Mutex _mutex; }; diff --git a/src/osgPlugins/txp/TXPNode.cpp b/src/osgPlugins/txp/TXPNode.cpp index 2ff0e0d7c..8ea498f25 100644 --- a/src/osgPlugins/txp/TXPNode.cpp +++ b/src/osgPlugins/txp/TXPNode.cpp @@ -8,6 +8,7 @@ #include "TileMapper.h" #include "TXPNode.h" +#include "TXPPagedLOD.h" using namespace txp; @@ -187,14 +188,25 @@ osg::Node* TXPNode::addPagedLODTile(int x, int y, int lod) TXPArchive::TileInfo info; _archive->getTileInfo(x,y,lod,info); - osg::PagedLOD* pagedLOD = new osg::PagedLOD; + TXPPagedLOD* pagedLOD = new TXPPagedLOD; pagedLOD->setFileName(0,pagedLODfile); - pagedLOD->setPriorityOffset(0,1.0f); + //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); diff --git a/src/osgPlugins/txp/TXPPagedLOD.cpp b/src/osgPlugins/txp/TXPPagedLOD.cpp new file mode 100644 index 000000000..66f3aa669 --- /dev/null +++ b/src/osgPlugins/txp/TXPPagedLOD.cpp @@ -0,0 +1,124 @@ +#include "TileMapper.h" +#include "TXPPagedLOD.h" +using namespace txp; + +TXPPagedLOD::TXPPagedLOD(): +PagedLOD(), +_tileX(-1), +_tileY(-1), +_tileLOD(-1) +{ +} + +TXPPagedLOD::TXPPagedLOD(const TXPPagedLOD& plod,const osg::CopyOp& copyop): +PagedLOD(plod,copyop), +_tileX(plod._tileX), +_tileY(plod._tileY), +_tileLOD(plod._tileLOD) +{ +} + +TXPPagedLOD::~TXPPagedLOD() +{ +} + +void TXPPagedLOD::traverse(osg::NodeVisitor& nv) +{ + + 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): + std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv)); + break; + case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): + { + float distance = nv.getDistanceToEyePoint(getCenter(),true); + + int lastChildTraversed = -1; + bool needToLoadChild = false; + bool rollBack = false; + for(unsigned int i=0;i<_rangeList.size();++i) + { + if (_rangeList[i].first<=distance && distance<_rangeList[i].second) + { + if (i<_children.size()) + { + bool acceptThisChild = true; + + 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; + } + } + else + { + needToLoadChild = true; + } + } + } + + if (rollBack) + { + if (updateTimeStamp) _perRangeDataList[0]._timeStamp=timeStamp; + _children[0]->accept(nv); + lastChildTraversed = 0; + //std::cout << "Rolling back" << std::endl; + } + + if (needToLoadChild) + { + unsigned int numChildren = _children.size(); + + //std::cout<<"PagedLOD::traverse() - falling back "<0 && ((int)numChildren-1)!=lastChildTraversed) + { + //std::cout<<" to child "<accept(nv); + } + + // now request the loading of the next unload child. + if (nv.getDatabaseRequestHandler() && numChildren<_perRangeDataList.size()) + { + // compute priority from where abouts in the required range the distance falls. + float priority = (_rangeList[numChildren].second-distance)/(_rangeList[numChildren].second-_rangeList[numChildren].first); + + // modify the priority according to the child's priority offset and scale. + priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale; + + //std::cout<<" requesting child "<<_fileNameList[numChildren]<<" priotity = "<requestNodeFile(_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp()); + } + + + } + + + break; + } + default: + break; + } +} + + diff --git a/src/osgPlugins/txp/TXPPagedLOD.h b/src/osgPlugins/txp/TXPPagedLOD.h new file mode 100644 index 000000000..6f2f53feb --- /dev/null +++ b/src/osgPlugins/txp/TXPPagedLOD.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * 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 __TXPPAGEDLOD_H_ +#define __TXPPAGEDLOD_H_ + +#include + +namespace txp +{ + class TXPPagedLOD : public osg::PagedLOD + { + public: + TXPPagedLOD(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + TXPPagedLOD(const TXPPagedLOD&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(txp, TXPPagedLOD); + + virtual void traverse(osg::NodeVisitor& nv); + + inline void setTileId(int x, int y, int lod) + { + _tileX = x; _tileY = y; _tileLOD = lod; + } + + inline void addNeighbour(int x,int y) + { + Neighbour n; + n._x = x; + n._y = y; + _neighbours.push_back(n); + } + + protected: + virtual ~TXPPagedLOD(); + + int _tileX; + int _tileY; + int _tileLOD; + + struct Neighbour + { + int _x, _y; + }; + std::vector _neighbours; + }; + +} // namespace + +#endif // __TXPPAGEDLOD_H_ diff --git a/src/osgPlugins/txp/TXPSeamLOD.cpp b/src/osgPlugins/txp/TXPSeamLOD.cpp index 7b8d8b092..31fa996bc 100644 --- a/src/osgPlugins/txp/TXPSeamLOD.cpp +++ b/src/osgPlugins/txp/TXPSeamLOD.cpp @@ -48,6 +48,7 @@ void TXPSeamLOD::traverse(osg::NodeVisitor& nv) #if 1 osg::PagedLOD* pagedLOD = TileMapper::instance()->getPagedLOD(_neighbourTileX,_neighbourTileY, _neighbourTileLOD); + bool acceptLoRes = true; if (pagedLOD) { @@ -63,11 +64,12 @@ void TXPSeamLOD::traverse(osg::NodeVisitor& nv) if (distance<=pagedLOD->getMaxRange(i)) { getChild(i)->accept(nv); - return; + acceptLoRes = false; + break; } } } - else + if (acceptLoRes) { getChild(0)->accept(nv); // pick low res } diff --git a/src/osgPlugins/txp/TXPTileNode.cpp b/src/osgPlugins/txp/TXPTileNode.cpp index 88780111f..08a85e576 100644 --- a/src/osgPlugins/txp/TXPTileNode.cpp +++ b/src/osgPlugins/txp/TXPTileNode.cpp @@ -4,7 +4,7 @@ #include "TXPTileNode.h" #include "TXPArchive.h" #include "TXPSeamLOD.h" - +#include "TXPPagedLOD.h" using namespace txp; class PrintVisitor : public osg::NodeVisitor @@ -216,14 +216,26 @@ bool TXPTileNode::loadTile(int x, int y, int lod) _archive->getId() ); - osg::ref_ptr pagedLOD = new osg::PagedLOD; + osg::ref_ptr 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->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());