void Terrain::traverse(osg::NodeVisitor &nv) { if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { // need to check if any TerrainTechniques need to have their update called on them. osgUtil::UpdateVisitor *uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv); if (uv) { typedef std::list<osg::ref_ptr<TerrainTile> > TerrainTileList; TerrainTileList tiles; { OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_mutex); for (TerrainTileSet::iterator itr = _updateTerrainTileSet.begin(); itr != _updateTerrainTileSet.end(); ++itr) { // take a reference first to make sure that the referenceCount can be safely read without another thread decrementing it to zero. (*itr)->ref(); // only if referenceCount is 2 or more indicating there is still a reference held elsewhere is it safe to add it to list of tiles to be updated if ((*itr)->referenceCount() > 1) tiles.push_back(*itr); // use unref_nodelete to avoid any issues when the *itr TerrainTile has been deleted by another thread while this for loop has been running. (*itr)->unref_nodelete(); } _updateTerrainTileSet.clear(); } for (TerrainTileList::iterator itr = tiles.begin(); itr != tiles.end(); ++itr) { TerrainTile *tile = itr->get(); tile->traverse(nv); } } } if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor*>(&nv); osg::StateSet *ss = _geometryPool.valid() ? _geometryPool->getRootStateSetForTerrain(this) : 0; if (cv && ss) { cv->pushStateSet(ss); Group::traverse(nv); cv->popStateSet(); return; } } Group::traverse(nv); }
void Terrain::traverse(osg::NodeVisitor& nv) { if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) { // need to check if any TerrainTechniques need to have their update called on them. osgUtil::UpdateVisitor* uv = dynamic_cast<osgUtil::UpdateVisitor*>(&nv); if (uv) { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); for(TerrainTileSet::iterator itr = _updateTerrainTileSet.begin(); itr != _updateTerrainTileSet.end(); ++itr) { TerrainTile* tile = *itr; tile->traverse(nv); } _updateTerrainTileSet.clear(); } } Group::traverse(nv); }