From Brad Anderegg, "This submission fixes two bugs and helps some performance problems we have been having with txp databases.
The first bug is that the terrain tiles will page out to a lower LOD when they are right in front of you. The issue appears to be with the blacklisting heuristic which forces a tile to LOD 1, commenting out the usage of blacklisting with the LOD Nodes fixes our problem. This code change was made to line 29 of TXPPageLOD.cpp. The second bug we were experiencing is that the database reader options never make it through to the archive loader. The use case for us appeared when the FID codes for the terrain were no longer on the materials. As it turns out the archive was being created twice, once by TXPNode and once by the ReaderWriterTXP on getArchive() so the options never actually got set on the archive that was being loaded. The fix is to first create the archive by calling getArchive on the ReaderWriterTXP, which stores it in a map for reference later, and then passing that archive into the TXPNode for it to set its internal member. With this code change we only create one archive (not sure what creating two did) and our options flags get set properly on the database. The changes made are in TXPNode.h line 72 where the TXPArchive is now passed in. In the TXPNode.cpp the loadArchive(TXPArchive*) was changed to have the default behavior if NULL is passed in, if an archive is passed in then it does not load it since all the loading is done in the ReaderWriterTXP::getArchive(). The only other place that loadArchive is called is in TXPIO.cpp where a modification was made to pass in NULL which will have the same behavior as it used to. The last change is the little block of code starting on line 57 of ReaderWriterTXP.cpp, this was changed so that it first calls getArchive() which caches the archives in a map does some loading stuff and returns a pointer to it which is then passed in as a parameter to TXPNode::loadArchive(). The performance changes were made to TXPParser.cpp line 163 where we use to osgUtil::Optimizer on the node before passing it off, and on line 1456 we changed the geometry to use display lists. These small changes actually made drastic performance increases for us, as much as 1000% on certain laptops. As far as testing goes, we have tested these changes with at least 5 txp databases on a variety of different computers including Mac OS and Linux. The base version used is 2.4."
This commit is contained in:
@@ -49,21 +49,25 @@ osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::strin
|
||||
txpNode->setOptions(options->getOptionString());
|
||||
}
|
||||
|
||||
if (txpNode->loadArchive())
|
||||
{
|
||||
TXPArchive* archive = txpNode->getArchive();
|
||||
if (archive)
|
||||
{
|
||||
if (options && options->getOptionString().find("loadMaterialsToStateSet")!=std::string::npos)
|
||||
{
|
||||
archive->SetMaterialAttributesToStateSetVar(true);
|
||||
}
|
||||
|
||||
int id = _archiveId++;
|
||||
archive->setId(id);
|
||||
// txpNode->setArchive(getArchive(id,osgDB::getFilePath(fileName)));
|
||||
getArchive(id,osgDB::getFilePath(fileName));
|
||||
//modified by Brad Anderegg on May-27-08
|
||||
//calling getArchive will create a new TXPArchive if the specified one does not exist
|
||||
//we will set our osgdb loader options on the archive and set the appropriate archive on
|
||||
//the txpNode.
|
||||
int id = ++_archiveId;
|
||||
TXPArchive* archive = getArchive(id,osgDB::getFilePath(fileName));
|
||||
|
||||
if (archive != NULL)
|
||||
{
|
||||
archive->setId(id);
|
||||
|
||||
if (options && options->getOptionString().find("loadMaterialsToStateSet")!=std::string::npos)
|
||||
{
|
||||
archive->SetMaterialAttributesToStateSetVar(true);
|
||||
}
|
||||
|
||||
txpNode->loadArchive(archive);
|
||||
|
||||
return txpNode.get();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -36,7 +36,11 @@ bool TXPNode_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
if (fr.matchSequence("databaseName %s"))
|
||||
{
|
||||
txpNode.setArchiveName(fr[1].getStr());
|
||||
txpNode.loadArchive();
|
||||
|
||||
//modified by Brad Anderegg on May-27-08
|
||||
//this function now takes the archive to load as a parameter
|
||||
//passing in NULL will have the same effect as before.
|
||||
txpNode.loadArchive(NULL);
|
||||
|
||||
fr += 2;
|
||||
itrAdvanced = true;
|
||||
@@ -49,8 +53,8 @@ bool TXPNode_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
class Dump2Osg : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
Dump2Osg( osgDB::Output &fw ) : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ), _fw( fw )
|
||||
{}
|
||||
Dump2Osg( osgDB::Output &fw ) : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ), _fw( fw )
|
||||
{}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
@@ -65,10 +69,10 @@ bool TXPNode_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const txp::TXPNode &txpNode = static_cast<const txp::TXPNode&>(obj);
|
||||
|
||||
if ( !txpNode.getOptions().empty() )
|
||||
fw.indent() << "databaseOptions \"" << txpNode.getOptions() << "\"" << std::endl;
|
||||
if ( !txpNode.getArchiveName().empty() )
|
||||
fw.indent() << "databaseName \"" << txpNode.getArchiveName() << "\"" << std::endl;
|
||||
if ( !txpNode.getOptions().empty() )
|
||||
fw.indent() << "databaseOptions \"" << txpNode.getOptions() << "\"" << std::endl;
|
||||
if ( !txpNode.getArchiveName().empty() )
|
||||
fw.indent() << "databaseName \"" << txpNode.getArchiveName() << "\"" << std::endl;
|
||||
|
||||
osg::Group* grp = const_cast<osg::Group*>(txpNode.asGroup());
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class RetestCallback : public osg::NodeCallback
|
||||
public:
|
||||
RetestCallback()
|
||||
{
|
||||
timer = osg::Timer::instance(); // get static timer
|
||||
timer = osg::Timer::instance(); // get static timer
|
||||
prevTime = 0; // should this be instantiated with current time?
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
(n = (osg::Group *) pLOD->getChild(0)) &&
|
||||
(n->getNumChildren() == 0))
|
||||
{
|
||||
osg::Timer_t curTime = timer->tick();
|
||||
osg::Timer_t curTime = timer->tick();
|
||||
if ((prevTime + 2.0/timer->getSecondsPerTick() ) < curTime)
|
||||
{
|
||||
prevTime = curTime;
|
||||
@@ -64,7 +64,7 @@ _originX(0.0),
|
||||
_originY(0.0)
|
||||
{
|
||||
setNumChildrenRequiringUpdateTraversal(1);
|
||||
setCullingActive(false);
|
||||
setCullingActive(false);
|
||||
}
|
||||
|
||||
TXPNode::TXPNode(const TXPNode& txpNode,const osg::CopyOp& copyop):
|
||||
@@ -179,40 +179,32 @@ const std::string& TXPNode::getArchiveName() const
|
||||
return _archiveName;
|
||||
}
|
||||
|
||||
bool TXPNode::loadArchive()
|
||||
bool TXPNode::loadArchive(TXPArchive* archive)
|
||||
{
|
||||
if (_archive.get())
|
||||
{
|
||||
TXPNodeERROR("loadArchive()") << "archive already open" << std::endl;
|
||||
return false;
|
||||
}
|
||||
//if (_archive.get())
|
||||
//{
|
||||
// TXPNodeERROR("loadArchive()") << "archive already open" << std::endl;
|
||||
// return false;
|
||||
//}
|
||||
|
||||
_archive = new TXPArchive;
|
||||
if (_archive->openFile(_archiveName) == false)
|
||||
{
|
||||
TXPNodeERROR("loadArchive()") << "failed to load archive: \"" << _archiveName << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if (_archive->loadMaterials() == false)
|
||||
{
|
||||
TXPNodeERROR("loadArchive()") << "failed to load materials from archive: \"" << _archiveName << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_archive->loadModels() == false)
|
||||
{
|
||||
TXPNodeERROR("loadArchive()") << "failed to load models from archive: \"" << _archiveName << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_archive->loadLightAttributes() == false)
|
||||
{
|
||||
TXPNodeERROR("loadArchive()") << "failed to load light attributes from archive: \"" << _archiveName << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
//modified by Brad Anderegg on May-27-08
|
||||
//if NULL is passed in we will create a new archive and open the database
|
||||
//otherwise we will use the archive provided which should have already been loaded
|
||||
//by ReaderWriterTXP::getArchive(). See line 57-77 of ReaderWriterTXP.cpp.
|
||||
if(archive == NULL)
|
||||
{
|
||||
_archive = new TXPArchive;
|
||||
if (_archive->openFile(_archiveName) == false)
|
||||
{
|
||||
TXPNodeERROR("loadArchive()") << "failed to load archive: \"" << _archiveName << "\"" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_archive = archive;
|
||||
}
|
||||
|
||||
_archive->getOrigin(_originX,_originY);
|
||||
_archive->getExtents(_extents);
|
||||
|
||||
@@ -65,14 +65,18 @@ public:
|
||||
const std::string& getOptions() const;
|
||||
const std::string& getArchiveName() const;
|
||||
|
||||
bool loadArchive();
|
||||
//modified by Brad Anderegg on May-27-08
|
||||
//because the TXPArchives are kept in an std::map and referenced later
|
||||
//we do not want to create a new one, so we pass it in.
|
||||
//If NULL is passed into loadArchive it will do the same thing it used to.
|
||||
bool loadArchive(TXPArchive*);
|
||||
|
||||
TXPArchive* getArchive();
|
||||
|
||||
void setArchive( TXPArchive* archive )
|
||||
{
|
||||
_archive = archive;
|
||||
}
|
||||
void setArchive( TXPArchive* archive )
|
||||
{
|
||||
_archive = archive;
|
||||
}
|
||||
|
||||
virtual osg::BoundingSphere computeBound() const;
|
||||
|
||||
@@ -86,18 +90,18 @@ protected:
|
||||
// Create a page lod for lod 0 with givin grid location (x,y)
|
||||
osg::Node* addPagedLODTile(int x, int y);
|
||||
|
||||
std::string _archiveName;
|
||||
std::string _options;
|
||||
std::string _archiveName;
|
||||
std::string _options;
|
||||
|
||||
osg::ref_ptr<TXPArchive> _archive;
|
||||
osg::ref_ptr<TXPPageManager> _pageManager;
|
||||
osg::ref_ptr<TXPArchive> _archive;
|
||||
osg::ref_ptr<TXPPageManager> _pageManager;
|
||||
|
||||
double _originX;
|
||||
double _originY;
|
||||
osg::BoundingBox _extents;
|
||||
double _originX;
|
||||
double _originY;
|
||||
osg::BoundingBox _extents;
|
||||
|
||||
std::vector<osg::Node*> _nodesToAdd;
|
||||
std::vector<osg::Node*> _nodesToRemove;
|
||||
std::vector<osg::Node*> _nodesToAdd;
|
||||
std::vector<osg::Node*> _nodesToRemove;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
|
||||
TileMapper* tileMapper = dynamic_cast<TileMapper*>(nv.getUserData());
|
||||
bool forceUseOfFirstChild = tileMapper ? (tileMapper->isNodeBlackListed(this)) : false;
|
||||
//Modified by Brad Anderegg (May-27-08) because the black listing process appears to make tiles switch lods
|
||||
//when they clearly shouldnt, in the worst cases a tile will page out that is right in front of you.
|
||||
bool forceUseOfFirstChild = /*tileMapper ? (tileMapper->isNodeBlackListed(this)) :*/ false;
|
||||
|
||||
double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
|
||||
bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
|
||||
@@ -40,19 +42,19 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
|
||||
|
||||
int lastChildTraversed = -1;
|
||||
bool needToLoadChild = false;
|
||||
|
||||
|
||||
unsigned maxRangeSize = _rangeList.size();
|
||||
if (maxRangeSize!=0 && forceUseOfFirstChild)
|
||||
maxRangeSize=1;
|
||||
|
||||
maxRangeSize=1;
|
||||
|
||||
for(unsigned int i=0;i<maxRangeSize;++i)
|
||||
{
|
||||
{
|
||||
if (forceUseOfFirstChild || _rangeList[i].first<=distance && distance<_rangeList[i].second)
|
||||
{
|
||||
if (i<_children.size())
|
||||
{
|
||||
if (updateTimeStamp)
|
||||
_perRangeDataList[i]._timeStamp=timeStamp;
|
||||
_perRangeDataList[i]._timeStamp=timeStamp;
|
||||
|
||||
_children[i]->accept(nv);
|
||||
lastChildTraversed = (int)i;
|
||||
@@ -63,38 +65,43 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (needToLoadChild)
|
||||
{
|
||||
unsigned int numChildren = _children.size();
|
||||
|
||||
|
||||
//std::cout<<"PagedLOD::traverse() - falling back "<<std::endl;
|
||||
// select the last valid child.
|
||||
if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
|
||||
{
|
||||
//std::cout<<" to child "<<numChildren-1<<std::endl;
|
||||
if (updateTimeStamp)
|
||||
_perRangeDataList[numChildren-1]._timeStamp=timeStamp;
|
||||
_perRangeDataList[numChildren-1]._timeStamp=timeStamp;
|
||||
|
||||
_children[numChildren-1]->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 = "<<priority<<std::endl;
|
||||
nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp(),_perRangeDataList[numChildren]._databaseRequest);
|
||||
nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,
|
||||
this,
|
||||
priority,
|
||||
nv.getFrameStamp(),
|
||||
_perRangeDataList[numChildren]._databaseRequest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -109,10 +116,10 @@ osg::BoundingSphere TXPPagedLOD::computeBound() const
|
||||
// If this is not done, then externally referenced models will disappear
|
||||
// when the tile they are attached to leaves the view volume.
|
||||
osg::BoundingSphere result = osg::Group::computeBound();
|
||||
|
||||
|
||||
if (_centerMode==USER_DEFINED_CENTER && _radius>=0.0f)
|
||||
{
|
||||
float tempRadius = osg::maximum( _radius, result.radius() );
|
||||
float tempRadius = osg::maximum( _radius, result.radius() );
|
||||
result = osg::BoundingSphere(_userDefinedCenter,tempRadius);
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <osg/ApplicationUsage>
|
||||
#include <osgText/Text>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
#include "TXPParser.h"
|
||||
#include "TXPArchive.h"
|
||||
|
||||
@@ -150,8 +152,22 @@ osg::Group *TXPParser::parseScene(
|
||||
}
|
||||
_tileGroups.clear();
|
||||
|
||||
LayerVisitor lv;
|
||||
_root->accept(lv);
|
||||
try
|
||||
{
|
||||
LayerVisitor lv;
|
||||
_root->accept(lv);
|
||||
|
||||
//modified by Brad Anderegg May-27-08
|
||||
//running the optimizer on the terrain fixes some major preformance issues, unfortunately the texture atlas builder seems to get messed up
|
||||
//on some of the textures (usually around buildings) and the tri stripper seems to occasionally crash and also mess up the indices on certain buildings.
|
||||
osgUtil::Optimizer opt;
|
||||
opt.optimize(_root.get(), (osgUtil::Optimizer::ALL_OPTIMIZATIONS ^ osgUtil::Optimizer::TEXTURE_ATLAS_BUILDER) ^ osgUtil::Optimizer::TRISTRIP_GEOMETRY);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
osg::notify(osg::NOTICE) << "txp::TXPParser::parseScene(): exception thrown in the osg::Optimizer" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
return _root.get();
|
||||
}
|
||||
@@ -1433,10 +1449,11 @@ void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
|
||||
|
||||
if (geometry.valid() && top)
|
||||
{
|
||||
// added this set use display list off since terrapage will
|
||||
// be creating and deleting these geometry leaves on the fly
|
||||
// so we don't want to be creating short lived display lists either.
|
||||
geometry->setUseDisplayList(false);
|
||||
|
||||
//modifed by Brad Anderegg on May-27-08
|
||||
//using display lists actually increases our framerate by
|
||||
//a fair amount, on certain laptops it increased by as much as 1000%
|
||||
geometry->setUseDisplayList(true);
|
||||
|
||||
geometry->setVertexArray(vertices.get());
|
||||
if (normals.valid())
|
||||
|
||||
Reference in New Issue
Block a user