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)
{
// hack for getting TXP plugin to utilise PagedLOD.
if (getLowerCaseFileExtension(filename)=="txp") return true;
return access( filename.c_str(), F_OK ) == 0;
}

View File

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

View File

@ -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<TerrapageNode> pager = new TerrapageNode;
osg::ref_ptr<txp::TerrapageNode> pager = new TerrapageNode;
pager->setDatabaseName(fileName);
if (options)

View File

@ -1,15 +1,19 @@
#include "TerrapageNode.h"
#include <osg/Notify>
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
using namespace osg;
namespace txp
{
osg::ref_ptr<TrPageArchive> 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<<std::endl;
return false;
}
// Note: Should be checking the return values
txpArchive->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<<std::endl;
TerrapageNode::_archive = NULL;
return false;
}
TerrapageNode::_archive->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;
}

View File

@ -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<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))
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

View File

@ -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();

View File

@ -36,7 +36,7 @@
#include <osg/Notify>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/PagedLOD>
#include <osgSim/LightPointNode>
#include <osg/Point>
@ -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<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
// scene graph.
@ -1000,6 +1043,13 @@ Group *TrPageParser::ParseScene(trpgReadBuffer &buf,vector<ref_ptr<StateSet> > &
notify(WARN) << "trpgFPParser::ParseScene failed to parse tile.\n";
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;
top = currTop = NULL;

View File

@ -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<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:
TrPageArchive* parent_; // The archive
GeodeGroup *currTop; // Current parent group

View File

@ -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;pi<parents.size();pi++) {
osg::Group *parent = parents[pi];
if(parent != rootNode)
//if(parent != rootNode)
{
//std::cout<<"removing "<<unhookMe<<" from "<<parent<<std::endl;
parent->removeChild(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