From fa8a06990de83bf4ac6f75da43843b121b2931bb Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 19 Oct 2003 11:46:34 +0000 Subject: [PATCH] From Trajce Nikolov, support for use of PagedLOD in the txp plugin. --- src/osgDB/FileUtils.cpp | 3 ++ src/osgPlugins/txp/IO_TerrapageNode.cpp | 1 + src/osgPlugins/txp/ReaderWriterTXP.cpp | 5 +- src/osgPlugins/txp/TerrapageNode.cpp | 65 +++++++++++++++++++++++- src/osgPlugins/txp/TerrapageNode.h | 5 +- src/osgPlugins/txp/TrPageArchive.cpp | 2 + src/osgPlugins/txp/TrPageArchive.h | 2 +- src/osgPlugins/txp/TrPageParser.cpp | 54 +++++++++++++++++++- src/osgPlugins/txp/TrPageParser.h | 31 +++++++++++ src/osgPlugins/txp/trPagePageManager.cpp | 21 +++++--- 10 files changed, 173 insertions(+), 16 deletions(-) diff --git a/src/osgDB/FileUtils.cpp b/src/osgDB/FileUtils.cpp index 906d82073..98e4db45e 100644 --- a/src/osgDB/FileUtils.cpp +++ b/src/osgDB/FileUtils.cpp @@ -37,6 +37,9 @@ bool osgDB::fileExists(const std::string& filename) { + // hack for getting TXP plugin to utilise PagedLOD. + if (getLowerCaseFileExtension(filename)=="txp") return true; + return access( filename.c_str(), F_OK ) == 0; } diff --git a/src/osgPlugins/txp/IO_TerrapageNode.cpp b/src/osgPlugins/txp/IO_TerrapageNode.cpp index 8dd4a1be4..b0879eae6 100644 --- a/src/osgPlugins/txp/IO_TerrapageNode.cpp +++ b/src/osgPlugins/txp/IO_TerrapageNode.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include diff --git a/src/osgPlugins/txp/ReaderWriterTXP.cpp b/src/osgPlugins/txp/ReaderWriterTXP.cpp index d462cfa7c..603d8717e 100644 --- a/src/osgPlugins/txp/ReaderWriterTXP.cpp +++ b/src/osgPlugins/txp/ReaderWriterTXP.cpp @@ -16,14 +16,13 @@ using namespace txp; using namespace osg; - osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) { if( !acceptsExtension(osgDB::getFileExtension(fileName) )) return ReadResult::FILE_NOT_HANDLED; - ref_ptr pager = new TerrapageNode; - + osg::ref_ptr pager = new TerrapageNode; + pager->setDatabaseName(fileName); if (options) diff --git a/src/osgPlugins/txp/TerrapageNode.cpp b/src/osgPlugins/txp/TerrapageNode.cpp index 76f29b0f9..c5c12aeee 100644 --- a/src/osgPlugins/txp/TerrapageNode.cpp +++ b/src/osgPlugins/txp/TerrapageNode.cpp @@ -1,15 +1,19 @@ #include "TerrapageNode.h" #include - +#include +#include using namespace osg; namespace txp { +osg::ref_ptr TerrapageNode::_archive = NULL; + TerrapageNode::TerrapageNode(): _pageManager(0) { setNumChildrenRequiringUpdateTraversal(1); + _dbLoaded = false; } TerrapageNode::TerrapageNode(const TerrapageNode& pager,const osg::CopyOp&): @@ -21,6 +25,7 @@ TerrapageNode::TerrapageNode(const TerrapageNode& pager,const osg::CopyOp&): _lastRecordEyePoint(pager._lastRecordEyePoint) { setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); + _dbLoaded = pager._dbLoaded; } TerrapageNode::~TerrapageNode() @@ -49,6 +54,45 @@ void TerrapageNode::traverse(osg::NodeVisitor& nv) bool TerrapageNode::loadDatabase() { + std::string name = osgDB::getSimpleFileName(_databaseName); + + // Here we load subtiles for a tile + if (strncmp(name.c_str(),"subtiles",8)==0) + { + std::string path = osgDB::getFilePath(_databaseName); + _databaseName = path+"\\archive.txp"; + + int lod; + int x; + int y; + sscanf(name.c_str(),"subtiles%d_%dx%d",&lod,&x,&y); + + float64 range; + TerrapageNode::_archive->GetHeader()->GetLodRange(lod+1,range); + + trpg2dPoint tileSize; + TerrapageNode::_archive->GetHeader()->GetTileSize(lod+1,tileSize); + + trpg2dPoint sw; + trpg2dPoint ne; + TerrapageNode::_archive->GetHeader()->GetExtents(sw,ne); + + for (int ix = 0; ix < 2; ix++) + for (int iy = 0; iy < 2; iy++) + { + int tileX = x*2+ix; + int tileY = y*2+iy; + int tileLOD = lod+1; + + int parentID; + addChild(TerrapageNode::_archive->LoadTile(tileX,tileY,tileLOD,parentID)); + } + + + //std::cout << "subtiles paged in: " << x << " " << y << " " << lod << std::endl; + return true; + } + // Open the TXP database TrPageArchive *txpArchive = new TrPageArchive(); if (!txpArchive->OpenFile(_databaseName.c_str())) @@ -56,7 +100,7 @@ bool TerrapageNode::loadDatabase() osg::notify(osg::WARN)<<"Couldn't load TerraPage archive "<<_databaseName<LoadMaterials(); @@ -66,6 +110,21 @@ bool TerrapageNode::loadDatabase() // Note: Should be checking the return values txpArchive->LoadLightAttributes(); + if (TerrapageNode::_archive == NULL) + { + TerrapageNode::_archive = new TrPageArchive(); + if (!TerrapageNode::_archive->OpenFile(_databaseName.c_str())) + { + osg::notify(osg::WARN)<<"Couldn't load interanal TerraPage archive "<<_databaseName<LoadMaterials(); + TerrapageNode::_archive->LoadModels(); + TerrapageNode::_archive->LoadLightAttributes(); + } + // get the exents of the archive const trpgHeader *head = txpArchive->GetHeader(); trpg2dPoint sw,ne; @@ -132,6 +191,8 @@ bool TerrapageNode::loadDatabase() } + _dbLoaded = true; + return true; } diff --git a/src/osgPlugins/txp/TerrapageNode.h b/src/osgPlugins/txp/TerrapageNode.h index 0490b34c9..40c018ca6 100644 --- a/src/osgPlugins/txp/TerrapageNode.h +++ b/src/osgPlugins/txp/TerrapageNode.h @@ -11,7 +11,7 @@ namespace txp { - +class TrPageArchive; class TerrapageNode : public osg::Group { public: @@ -54,6 +54,9 @@ class TerrapageNode : public osg::Group std::string _databaseOptions; OSGPageManager* _pageManager; mutable osg::Vec3 _lastRecordEyePoint; + + static osg::ref_ptr _archive; + bool _dbLoaded; }; diff --git a/src/osgPlugins/txp/TrPageArchive.cpp b/src/osgPlugins/txp/TrPageArchive.cpp index 8aa989393..d8fb27bfc 100644 --- a/src/osgPlugins/txp/TrPageArchive.cpp +++ b/src/osgPlugins/txp/TrPageArchive.cpp @@ -534,6 +534,7 @@ Group* TrPageArchive::LoadTile(int x,int y,int lod,int &parentID) if (!ReadTile(x,y,lod,buf)) return NULL; + parse->SetTile(x,y,lod); Group *tile = parse->ParseScene(buf, m_gstates , m_models); if (tile) { @@ -562,6 +563,7 @@ Group* TrPageArchive::LoadTile(Group *rootNode, return NULL; // Now parse it + parse->SetTile(x,y,lod); Group *gTile = parse->ParseScene(buf, m_gstates, m_models); if (gTile && rootNode) { // Hook it into its parent diff --git a/src/osgPlugins/txp/TrPageArchive.h b/src/osgPlugins/txp/TrPageArchive.h index 1c54dc55c..bb6e2ae9e 100644 --- a/src/osgPlugins/txp/TrPageArchive.h +++ b/src/osgPlugins/txp/TrPageArchive.h @@ -47,7 +47,7 @@ namespace txp osg::Vec3 attitude; }; /// main class for loading terrapage archives - class TrPageArchive : public trpgr_Archive + class TrPageArchive : public trpgr_Archive, public osg::Referenced { public: TrPageArchive(); diff --git a/src/osgPlugins/txp/TrPageParser.cpp b/src/osgPlugins/txp/TrPageParser.cpp index 4fe90533a..42edde5d1 100644 --- a/src/osgPlugins/txp/TrPageParser.cpp +++ b/src/osgPlugins/txp/TrPageParser.cpp @@ -36,7 +36,7 @@ #include #include #include - +#include #include #include @@ -676,7 +676,8 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) // This sets the parent ID for the current tile too int32 parentID; group.GetParentID(parentID); - parse->SetParentID(parentID); + + //parse->SetParentID(parentID); no need of this anymore. we force PagedLOD return (void *) osg_Group; } @@ -793,6 +794,10 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf) // Dump this group into the hierarchy parse->AddIntoSceneGraph(osg_Lod); + + // Sets the current parent as potentional PagedLOD + parse->SetPotentionalPagedLOD(parse->GetCurrTop()); + // Register for attachements int32 id; lod.GetID(id); @@ -982,6 +987,44 @@ trpgTileHeader *TrPageParser::GetTileHeaderRef() return &tileHead; } +//---------------------------------------------------------------------------- +// Converts to PagedLOD +void TrPageParser::ConvertToPagedLOD(osg::Group* group) +{ + if (group->getNumChildren() == 2) + { + osg::LOD* loLOD = dynamic_cast(group->getChild(0)); + osg::LOD* hiLOD = dynamic_cast(group->getChild(1)); + + if (loLOD && hiLOD) + { + osg::Group *g = dynamic_cast(hiLOD->getChild(0)); + if (!g) return; + if (g->getNumChildren()) return; + + char pagedLODfile[1024]; + sprintf(pagedLODfile, + "%s\\subtiles%d_%dx%d.txp", + parent_->getDir(), + _tileLOD, + _tileX, + _tileY + ); + + osg::PagedLOD* pagedlod = new osg::PagedLOD; + + pagedlod->addChild(loLOD->getChild(0),loLOD->getMinRange(0),loLOD->getMaxRange(0)); + pagedlod->setRange(1,0.0f,hiLOD->getMaxRange(0)); + pagedlod->setFileName(1,pagedLODfile); + pagedlod->setCenter(hiLOD->getCenter()); + + group->addChild(pagedlod); + + group->removeChild(loLOD); + group->removeChild(hiLOD); + } + } +} //---------------------------------------------------------------------------- // Parse a buffer and return a (chunk of) Performer // scene graph. @@ -1000,6 +1043,13 @@ Group *TrPageParser::ParseScene(trpgReadBuffer &buf,vector > & notify(WARN) << "trpgFPParser::ParseScene failed to parse tile.\n"; return NULL; } + + // Puts PagedLODs on the right places + for (std::map::iterator i = _pagedLods.begin(); i != _pagedLods.end(); i++) + { + ConvertToPagedLOD((*i).first); + } + _pagedLods.clear(); Group *ret = top; top = currTop = NULL; diff --git a/src/osgPlugins/txp/TrPageParser.h b/src/osgPlugins/txp/TrPageParser.h index 0d062cca4..b752660b0 100644 --- a/src/osgPlugins/txp/TrPageParser.h +++ b/src/osgPlugins/txp/TrPageParser.h @@ -160,6 +160,18 @@ namespace txp DefferedLightAttribute& GetLightAttribute(int attr_index); + // Sets the info about the tile that is being parsed + inline void SetTile(int x, int y, int lod) + { + _tileX = x; _tileY = y; _tileLOD = lod; + } + + // Sets a group as potentinal PagedLOD - see below + inline void SetPotentionalPagedLOD(osg::Group* group) + { + _pagedLods[group] = 1; + } + protected: // Called on start children bool StartChildren(void *); @@ -167,6 +179,25 @@ namespace txp // Called on end children bool EndChildren(void *); + // LOD parents + // These will help us to find the "LOD Bridges" in the scene graph. "LOD Bridge" is a + // group that holds two LOD nodes: one is the parent of the "current" LOD implementation of + // a tile, the other is parent of the quad of the higher-res LOD implementation of the same + // tile - it has four higher-res tiles. After a tile is loaded, we replace the "LOD bridge" + // with PagedLOD node + // nick@terrex.com + std::map _pagedLods; + + // Converts to PagedLOD + // If the given group is "LOD Bridge" this method will convert it into appropriate PagedLOD + void ConvertToPagedLOD(osg::Group* group); + + // Current tile that is being loaded + int _tileX; + int _tileY; + int _tileLOD; + double _tileRange; + protected: TrPageArchive* parent_; // The archive GeodeGroup *currTop; // Current parent group diff --git a/src/osgPlugins/txp/trPagePageManager.cpp b/src/osgPlugins/txp/trPagePageManager.cpp index a12523ef6..4b51c3946 100644 --- a/src/osgPlugins/txp/trPagePageManager.cpp +++ b/src/osgPlugins/txp/trPagePageManager.cpp @@ -251,15 +251,16 @@ bool OSGPageManager::ThreadLoop(PagingThread* t) //nextDelete.clear(); { - osgGuard g(changeListMutex); // Add to the unhook list for(unsigned int kk = 0; kk < unhook.size();kk++) { + osgGuard g(changeListMutex); toUnhook.push_back(unhook[kk]); } // Also get the list of deletions while we're here // use the stl Luke :-) swap is constant time operation that do a = b; b.clear() // if a is empty which is our case + osgGuard g(changeListMutex); nextDelete.swap(toDelete); } @@ -274,7 +275,7 @@ bool OSGPageManager::ThreadLoop(PagingThread* t) //osg::notify(WARN) << "Tile to load :" << x << ' ' << y << ' ' << lod << std::endl; //osg::notify(WARN) << "Position :" << loc.x << ' ' << loc.y << std::endl; - LoadOneTile(tile); + if (lod==0) LoadOneTile(tile); // Now add this tile to the merge list pageManage->AckLoad(); @@ -326,11 +327,14 @@ bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode) // Make local copies of the merge and unhook lists { - osgGuard g(changeListMutex); // use the stl Luke :-) swap is constant time operation that do a = b; b.clear() // if a is empty which is our case - mergeList.swap(toMerge); - unhookList.swap(toUnhook); + //if (changeListMutex.trylock()==0) + { + osgGuard g(changeListMutex); + mergeList.swap(toMerge); + unhookList.swap(toUnhook); + } } // visitor to go through unhooked subgraphs to release texture objects @@ -353,7 +357,7 @@ bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode) const osg::Node::ParentList &parents = unhookMe->getParents(); for (unsigned int pi=0;piremoveChild(unhookMe); @@ -363,9 +367,12 @@ bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode) // Append the unhooked things on to the list to delete { - osgGuard g(changeListMutex); + osgGuard g(changeListMutex); for (unsigned int i = 0; i < unhookList.size();i++) + { + toDelete.push_back(unhookList[i]); + } } // Do the merging last