From Trajce Nikolov, support for use of PagedLOD in the txp plugin.
This commit is contained in:
parent
c199e74bfc
commit
fa8a06990d
@ -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;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user