From Trajce Nikolov, support for use of PagedLOD in the txp plugin.

This commit is contained in:
Robert Osfield 2003-10-19 11:46:34 +00:00
parent c199e74bfc
commit fa8a06990d
10 changed files with 173 additions and 16 deletions

View File

@ -37,6 +37,9 @@
bool osgDB::fileExists(const std::string& filename) 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; return access( filename.c_str(), F_OK ) == 0;
} }

View File

@ -3,6 +3,7 @@
#include <osgDB/Registry> #include <osgDB/Registry>
#include <osgDB/Input> #include <osgDB/Input>
#include <osgDB/Output> #include <osgDB/Output>
#include <osg/ref_ptr>
#include <iostream> #include <iostream>

View File

@ -16,14 +16,13 @@
using namespace txp; using namespace txp;
using namespace osg; using namespace osg;
osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) osgDB::ReaderWriter::ReadResult ReaderWriterTXP::readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options)
{ {
if( !acceptsExtension(osgDB::getFileExtension(fileName) )) if( !acceptsExtension(osgDB::getFileExtension(fileName) ))
return ReadResult::FILE_NOT_HANDLED; return ReadResult::FILE_NOT_HANDLED;
ref_ptr<TerrapageNode> pager = new TerrapageNode; osg::ref_ptr<txp::TerrapageNode> pager = new TerrapageNode;
pager->setDatabaseName(fileName); pager->setDatabaseName(fileName);
if (options) if (options)

View File

@ -1,15 +1,19 @@
#include "TerrapageNode.h" #include "TerrapageNode.h"
#include <osg/Notify> #include <osg/Notify>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
using namespace osg; using namespace osg;
namespace txp namespace txp
{ {
osg::ref_ptr<TrPageArchive> TerrapageNode::_archive = NULL;
TerrapageNode::TerrapageNode(): TerrapageNode::TerrapageNode():
_pageManager(0) _pageManager(0)
{ {
setNumChildrenRequiringUpdateTraversal(1); setNumChildrenRequiringUpdateTraversal(1);
_dbLoaded = false;
} }
TerrapageNode::TerrapageNode(const TerrapageNode& pager,const osg::CopyOp&): TerrapageNode::TerrapageNode(const TerrapageNode& pager,const osg::CopyOp&):
@ -21,6 +25,7 @@ TerrapageNode::TerrapageNode(const TerrapageNode& pager,const osg::CopyOp&):
_lastRecordEyePoint(pager._lastRecordEyePoint) _lastRecordEyePoint(pager._lastRecordEyePoint)
{ {
setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
_dbLoaded = pager._dbLoaded;
} }
TerrapageNode::~TerrapageNode() TerrapageNode::~TerrapageNode()
@ -49,6 +54,45 @@ void TerrapageNode::traverse(osg::NodeVisitor& nv)
bool TerrapageNode::loadDatabase() 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 // Open the TXP database
TrPageArchive *txpArchive = new TrPageArchive(); TrPageArchive *txpArchive = new TrPageArchive();
if (!txpArchive->OpenFile(_databaseName.c_str())) if (!txpArchive->OpenFile(_databaseName.c_str()))
@ -56,7 +100,7 @@ bool TerrapageNode::loadDatabase()
osg::notify(osg::WARN)<<"Couldn't load TerraPage archive "<<_databaseName<<std::endl; osg::notify(osg::WARN)<<"Couldn't load TerraPage archive "<<_databaseName<<std::endl;
return false; return false;
} }
// Note: Should be checking the return values // Note: Should be checking the return values
txpArchive->LoadMaterials(); txpArchive->LoadMaterials();
@ -66,6 +110,21 @@ bool TerrapageNode::loadDatabase()
// Note: Should be checking the return values // Note: Should be checking the return values
txpArchive->LoadLightAttributes(); 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<<std::endl;
TerrapageNode::_archive = NULL;
return false;
}
TerrapageNode::_archive->LoadMaterials();
TerrapageNode::_archive->LoadModels();
TerrapageNode::_archive->LoadLightAttributes();
}
// get the exents of the archive // get the exents of the archive
const trpgHeader *head = txpArchive->GetHeader(); const trpgHeader *head = txpArchive->GetHeader();
trpg2dPoint sw,ne; trpg2dPoint sw,ne;
@ -132,6 +191,8 @@ bool TerrapageNode::loadDatabase()
} }
_dbLoaded = true;
return true; return true;
} }

View File

@ -11,7 +11,7 @@
namespace txp namespace txp
{ {
class TrPageArchive;
class TerrapageNode : public osg::Group class TerrapageNode : public osg::Group
{ {
public: public:
@ -54,6 +54,9 @@ class TerrapageNode : public osg::Group
std::string _databaseOptions; std::string _databaseOptions;
OSGPageManager* _pageManager; OSGPageManager* _pageManager;
mutable osg::Vec3 _lastRecordEyePoint; mutable osg::Vec3 _lastRecordEyePoint;
static osg::ref_ptr<TrPageArchive> _archive;
bool _dbLoaded;
}; };

View File

@ -534,6 +534,7 @@ Group* TrPageArchive::LoadTile(int x,int y,int lod,int &parentID)
if (!ReadTile(x,y,lod,buf)) if (!ReadTile(x,y,lod,buf))
return NULL; return NULL;
parse->SetTile(x,y,lod);
Group *tile = parse->ParseScene(buf, m_gstates , m_models); Group *tile = parse->ParseScene(buf, m_gstates , m_models);
if (tile) if (tile)
{ {
@ -562,6 +563,7 @@ Group* TrPageArchive::LoadTile(Group *rootNode,
return NULL; return NULL;
// Now parse it // Now parse it
parse->SetTile(x,y,lod);
Group *gTile = parse->ParseScene(buf, m_gstates, m_models); Group *gTile = parse->ParseScene(buf, m_gstates, m_models);
if (gTile && rootNode) { if (gTile && rootNode) {
// Hook it into its parent // Hook it into its parent

View File

@ -47,7 +47,7 @@ namespace txp
osg::Vec3 attitude; osg::Vec3 attitude;
}; };
/// main class for loading terrapage archives /// main class for loading terrapage archives
class TrPageArchive : public trpgr_Archive class TrPageArchive : public trpgr_Archive, public osg::Referenced
{ {
public: public:
TrPageArchive(); TrPageArchive();

View File

@ -36,7 +36,7 @@
#include <osg/Notify> #include <osg/Notify>
#include <osg/PolygonOffset> #include <osg/PolygonOffset>
#include <osg/MatrixTransform> #include <osg/MatrixTransform>
#include <osg/PagedLOD>
#include <osgSim/LightPointNode> #include <osgSim/LightPointNode>
#include <osg/Point> #include <osg/Point>
@ -676,7 +676,8 @@ void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// This sets the parent ID for the current tile too // This sets the parent ID for the current tile too
int32 parentID; int32 parentID;
group.GetParentID(parentID); group.GetParentID(parentID);
parse->SetParentID(parentID);
//parse->SetParentID(parentID); no need of this anymore. we force PagedLOD
return (void *) osg_Group; return (void *) osg_Group;
} }
@ -793,6 +794,10 @@ void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
// Dump this group into the hierarchy // Dump this group into the hierarchy
parse->AddIntoSceneGraph(osg_Lod); parse->AddIntoSceneGraph(osg_Lod);
// Sets the current parent as potentional PagedLOD
parse->SetPotentionalPagedLOD(parse->GetCurrTop());
// Register for attachements // Register for attachements
int32 id; int32 id;
lod.GetID(id); lod.GetID(id);
@ -982,6 +987,44 @@ trpgTileHeader *TrPageParser::GetTileHeaderRef()
return &tileHead; return &tileHead;
} }
//----------------------------------------------------------------------------
// Converts to PagedLOD
void TrPageParser::ConvertToPagedLOD(osg::Group* group)
{
if (group->getNumChildren() == 2)
{
osg::LOD* loLOD = dynamic_cast<osg::LOD*>(group->getChild(0));
osg::LOD* hiLOD = dynamic_cast<osg::LOD*>(group->getChild(1));
if (loLOD && hiLOD)
{
osg::Group *g = dynamic_cast<osg::Group*>(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 // Parse a buffer and return a (chunk of) Performer
// scene graph. // scene graph.
@ -1000,6 +1043,13 @@ Group *TrPageParser::ParseScene(trpgReadBuffer &buf,vector<ref_ptr<StateSet> > &
notify(WARN) << "trpgFPParser::ParseScene failed to parse tile.\n"; notify(WARN) << "trpgFPParser::ParseScene failed to parse tile.\n";
return NULL; return NULL;
} }
// Puts PagedLODs on the right places
for (std::map<osg::Group*,int>::iterator i = _pagedLods.begin(); i != _pagedLods.end(); i++)
{
ConvertToPagedLOD((*i).first);
}
_pagedLods.clear();
Group *ret = top; Group *ret = top;
top = currTop = NULL; top = currTop = NULL;

View File

@ -160,6 +160,18 @@ namespace txp
DefferedLightAttribute& GetLightAttribute(int attr_index); 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: protected:
// Called on start children // Called on start children
bool StartChildren(void *); bool StartChildren(void *);
@ -167,6 +179,25 @@ namespace txp
// Called on end children // Called on end children
bool EndChildren(void *); 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<osg::Group*,int> _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: protected:
TrPageArchive* parent_; // The archive TrPageArchive* parent_; // The archive
GeodeGroup *currTop; // Current parent group GeodeGroup *currTop; // Current parent group

View File

@ -251,15 +251,16 @@ bool OSGPageManager::ThreadLoop(PagingThread* t)
//nextDelete.clear(); //nextDelete.clear();
{ {
osgGuard g(changeListMutex);
// Add to the unhook list // Add to the unhook list
for(unsigned int kk = 0; kk < unhook.size();kk++) for(unsigned int kk = 0; kk < unhook.size();kk++)
{ {
osgGuard g(changeListMutex);
toUnhook.push_back(unhook[kk]); toUnhook.push_back(unhook[kk]);
} }
// Also get the list of deletions while we're here // 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() // use the stl Luke :-) swap is constant time operation that do a = b; b.clear()
// if a is empty which is our case // if a is empty which is our case
osgGuard g(changeListMutex);
nextDelete.swap(toDelete); 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) << "Tile to load :" << x << ' ' << y << ' ' << lod << std::endl;
//osg::notify(WARN) << "Position :" << loc.x << ' ' << loc.y << 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 // Now add this tile to the merge list
pageManage->AckLoad(); pageManage->AckLoad();
@ -326,11 +327,14 @@ bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode)
// Make local copies of the merge and unhook lists // 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() // use the stl Luke :-) swap is constant time operation that do a = b; b.clear()
// if a is empty which is our case // if a is empty which is our case
mergeList.swap(toMerge); //if (changeListMutex.trylock()==0)
unhookList.swap(toUnhook); {
osgGuard g(changeListMutex);
mergeList.swap(toMerge);
unhookList.swap(toUnhook);
}
} }
// visitor to go through unhooked subgraphs to release texture objects // 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(); const osg::Node::ParentList &parents = unhookMe->getParents();
for (unsigned int pi=0;pi<parents.size();pi++) { for (unsigned int pi=0;pi<parents.size();pi++) {
osg::Group *parent = parents[pi]; osg::Group *parent = parents[pi];
if(parent != rootNode) //if(parent != rootNode)
{ {
//std::cout<<"removing "<<unhookMe<<" from "<<parent<<std::endl; //std::cout<<"removing "<<unhookMe<<" from "<<parent<<std::endl;
parent->removeChild(unhookMe); parent->removeChild(unhookMe);
@ -363,9 +367,12 @@ bool OSGPageManager::MergeUpdateThread(osg::Group *rootNode)
// Append the unhooked things on to the list to delete // 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++) for (unsigned int i = 0; i < unhookList.size();i++)
{
toDelete.push_back(unhookList[i]); toDelete.push_back(unhookList[i]);
}
} }
// Do the merging last // Do the merging last