void TerrainTile::traverse(osg::NodeVisitor& nv) { if (!_hasBeenTraversal) { if (!_terrain) { osg::NodePath& nodePath = nv.getNodePath(); if (!nodePath.empty()) { for(osg::NodePath::reverse_iterator itr = nodePath.rbegin(); itr != nodePath.rend() && !_terrain; ++itr) { osgTerrain::Terrain* ts = dynamic_cast<Terrain*>(*itr); if (ts) { OSG_INFO<<"Assigning terrain system "<<ts<<std::endl; setTerrain(ts); } } } } init(getDirtyMask(), false); _hasBeenTraversal = true; } if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) { osg::ClusterCullingCallback* ccc = dynamic_cast<osg::ClusterCullingCallback*>(getCullCallback()); if (ccc) { if (ccc->cull(&nv,0,static_cast<State *>(0))) return; } } if (_terrainTechnique.valid()) { _terrainTechnique->traverse(nv); } else { osg::Group::traverse(nv); } }
void VolumeTile::traverse(osg::NodeVisitor& nv) { if (!_hasBeenTraversal) { if (!_volume) { osg::NodePath& nodePath = nv.getNodePath(); if (!nodePath.empty()) { for(osg::NodePath::reverse_iterator itr = nodePath.rbegin(); itr != nodePath.rend() && !_volume; ++itr) { osgVolume::Volume* volume = dynamic_cast<Volume*>(*itr); if (volume) { OSG_INFO<<"Assigning volume system "<<volume<<std::endl; setVolume(volume); } } } } _hasBeenTraversal = true; } if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR && _layer->requiresUpdateTraversal()) { _layer->update(nv); } if (_volumeTechnique.valid()) { _volumeTechnique->traverse(nv); } else { osg::Group::traverse(nv); } }
void DrapingCullSet::accept(osg::NodeVisitor& nv) { if ( nv.getVisitorType() == nv.CULL_VISITOR ) { osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( &nv ); // We will use the visitor's path to prevent doubely-applying the statesets // of common ancestors const osg::NodePath& nvPath = nv.getNodePath(); int frame = nv.getFrameStamp() ? nv.getFrameStamp()->getFrameNumber() : 0u; for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry ) { if ( frame - entry->_frame > 1 ) continue; // If there's an active (non-identity matrix), apply it if ( entry->_matrix.valid() ) { entry->_matrix->postMult( *cv->getModelViewMatrix() ); cv->pushModelViewMatrix( entry->_matrix.get(), osg::Transform::RELATIVE_RF ); } // After pushing the matrix, we can perform the culling bounds test. if ( !cv->isCulled( entry->_node->getBound() ) ) { // Apply the statesets in the entry's node path, but skip over the ones that are // shared with the current visitor's path since they are already in effect. // Count them so we can pop them later. int numStateSets = 0; osg::RefNodePath nodePath; if ( entry->_path.getRefNodePath(nodePath) ) { for(unsigned i=0; i<nodePath.size(); ++i) { if (nodePath[i].valid()) { if (i >= nvPath.size() || nvPath[i] != nodePath[i].get()) { osg::StateSet* stateSet = nodePath[i]->getStateSet(); if ( stateSet ) { cv->pushStateSet( stateSet ); ++numStateSets; } } } } } // Cull the DrapeableNode's children (but not the DrapeableNode itself!) // TODO: make sure we aren't skipping any cull callbacks, etc. by calling traverse // instead of accept. (Cannot call accept b/c that calls traverse) for(unsigned i=0; i<entry->_node->getNumChildren(); ++i) { entry->_node->getChild(i)->accept( nv ); } // pop the same number we pushed for(int i=0; i<numStateSets; ++i) { cv->popStateSet(); } } // pop the model view: if ( entry->_matrix.valid() ) { cv->popModelViewMatrix(); } } // mark this set so it will reset for the next frame _frameCulled = true; } else { for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry ) { } } }
void SoundNode::traverse(osg::NodeVisitor &nv) { // continue only if the visitor actually is a cull visitor if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) { // Make sure we only execute this once during this frame. // There could be two or more culls for stereo/multipipe... if (!m_sound_state.valid()) { // call the inherited method osg::notify(osg::DEBUG_INFO) << "SoundNode::traverse() No soundstate attached to soundnode" << std::endl; Node::traverse(nv); return; } if ( m_sound_state.valid() && nv.getTraversalNumber() != m_last_traversal_number && nv.getFrameStamp()) { m_last_traversal_number = nv.getTraversalNumber(); // retrieve the current time double t = nv.getFrameStamp()->getReferenceTime(); double time = t - m_last_time; if(time >= m_sound_manager->getUpdateFrequency()) { osg::Matrix m; m = osg::computeLocalToWorld(nv.getNodePath()); osg::Vec3 pos = m.getTrans(); m_sound_state->setPosition(pos); //Calculate velocity osg::Vec3 velocity(0,0,0); if (m_first_run) { m_first_run = false; m_last_time = t; m_last_pos = pos; } else { velocity = pos - m_last_pos; m_last_pos = pos; m_last_time = t; velocity /= time; } if(m_sound_manager->getClampVelocity()) { float max_vel = m_sound_manager->getMaxVelocity(); float len = velocity.length(); if ( len > max_vel) { velocity.normalize(); velocity *= max_vel; } } m_sound_state->setVelocity(velocity); //Get new direction osg::Vec3 dir(0,1,0); dir = dir * m; dir.normalize(); m_sound_state->setDirection(dir); // Only do occlusion calculations if the sound is playing if (m_sound_state->getPlay() && m_occlude_callback.valid()) m_occlude_callback->apply(m_sound_manager->getListenerMatrix(), pos, m_sound_state.get()); } // if } } // if cullvisitor // call the inherited method Node::traverse(nv); }
void ClampingCullSet::accept(osg::NodeVisitor& nv) { if ( nv.getVisitorType() == nv.CULL_VISITOR ) { ProxyCullVisitor* cv = dynamic_cast<ProxyCullVisitor*>(&nv); // We will use the visitor's path to prevent doubely-applying the statesets // of common ancestors const osg::NodePath& nvPath = nv.getNodePath(); int frame = nv.getFrameStamp() ? nv.getFrameStamp()->getFrameNumber() : 0u; unsigned passed = 0u; for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry ) { if ( frame - entry->_frame > 1 ) continue; // If there's an active (non-identity matrix), apply it if ( entry->_matrix.valid() ) { entry->_matrix->postMult( *cv->getModelViewMatrix() ); cv->pushModelViewMatrix( entry->_matrix.get(), osg::Transform::RELATIVE_RF ); } // After pushing the matrix, we can perform the culling bounds test. if (!cv->isCulledByProxyFrustum(*entry->_node.get())) { // Apply the statesets in the entry's node path, but skip over the ones that are // shared with the current visitor's path since they are already in effect. // Count them so we can pop them later. int numStateSets = 0; osg::RefNodePath nodePath; if ( entry->_path.getRefNodePath(nodePath) ) { for(unsigned i=0; i<nodePath.size(); ++i) { if (nodePath[i].valid()) { if (i >= nvPath.size() || nvPath[i] != nodePath[i].get()) { osg::StateSet* stateSet = nodePath[i]->getStateSet(); if ( stateSet ) { cv->getCullVisitor()->pushStateSet( stateSet ); ++numStateSets; } } } } } // Cull the DrapeableNode's children (but not the DrapeableNode itself!) for(unsigned i=0; i<entry->_node->getNumChildren(); ++i) { entry->_node->getChild(i)->accept( nv ); } // pop the same number we pushed for(int i=0; i<numStateSets; ++i) { cv->getCullVisitor()->popStateSet(); } ++passed; } // pop the model view: if ( entry->_matrix.valid() ) { cv->popModelViewMatrix(); } //Registry::instance()->startActivity("ClampingCullSet", Stringify() << std::hex << this << std::dec << " / " << passed << "/" << _entries.size()); } // mark this set so it will reset for the next frame _frameCulled = true; } }
// MOST of this is copied and pasted from OSG's osg::PagedLOD::traverse, // except where otherwise noted with an "osgEarth" comment. void TilePagedLOD::traverse(osg::NodeVisitor& nv) { // set the frame number of the traversal so that external nodes can find out how active this // node is. if (nv.getFrameStamp() && nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) { setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber()); // osgEarth: update our progress tracker to prevent tile cancelation. if (_progress.valid()) { _progress->update( nv.getFrameStamp()->getFrameNumber() ); } } double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0; unsigned int frameNumber = nv.getFrameStamp()?nv.getFrameStamp()->getFrameNumber():0; bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR; switch(nv.getTraversalMode()) { case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN): std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv)); break; case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): { osg::ref_ptr<MPTerrainEngineNode> engine; MPTerrainEngineNode::getEngineByUID( _engineUID, engine ); if (!engine.valid()) return; // Compute the required range. float required_range = -1.0; if (engine->getComputeRangeCallback()) { required_range = (*engine->getComputeRangeCallback())(this, nv); } // If we don't have a callback or it return a negative number fallback on the original calculation. if (required_range < 0.0) { if (_rangeMode==DISTANCE_FROM_EYE_POINT) { required_range = nv.getDistanceToViewPoint(getCenter(),true); if (_rangeFactor.isSet()) required_range /= _rangeFactor.get(); } else { osg::CullStack* cullStack = dynamic_cast<osg::CullStack*>(&nv); if (cullStack && cullStack->getLODScale()>0.0f) { required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale(); } else { // fallback to selecting the highest res tile by // finding out the max range for(unsigned int i=0;i<_rangeList.size();++i) { required_range = osg::maximum(required_range,_rangeList[i].first); } } } } int lastChildTraversed = -1; bool needToLoadChild = false; for(unsigned int i=0;i<_rangeList.size();++i) { if (_rangeList[i].first<=required_range && required_range<_rangeList[i].second) { if (i<_children.size()) { if (updateTimeStamp) { _perRangeDataList[i]._timeStamp=timeStamp; _perRangeDataList[i]._frameNumber=frameNumber; } _children[i]->accept(nv); lastChildTraversed = (int)i; } else { needToLoadChild = true; } } } #ifdef INHERIT_VIEWPOINT_CAMERAS_CANNOT_SUBDIVIDE // Prevents an INHERIT_VIEWPOINT camera from invoking tile subdivision if (needToLoadChild) { osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv); if ( cv && cv->getCurrentCamera() && cv->getCurrentCamera()->getReferenceFrame() == osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT ) needToLoadChild = false; } #endif if (needToLoadChild) { unsigned int numChildren = _children.size(); // select the last valid child. if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed) { if (updateTimeStamp) { _perRangeDataList[numChildren-1]._timeStamp=timeStamp; _perRangeDataList[numChildren-1]._frameNumber=frameNumber; } _children[numChildren-1]->accept(nv); } // now request the loading of the next unloaded child. if (!_disableExternalChildrenPaging && nv.getDatabaseRequestHandler() && numChildren<_perRangeDataList.size()) { // osgEarth: Perform a tile visibility check before requesting the new tile. // Intersect the tile's earth-aligned bounding box with the current culling frustum. bool tileIsVisible = true; if (nv.getVisitorType() == nv.CULL_VISITOR && numChildren < _childBBoxes.size() && _childBBoxes[numChildren].valid()) { osgUtil::CullVisitor* cv = Culling::asCullVisitor( nv ); // wish that CullStack::createOrReuseRefMatrix() was public osg::ref_ptr<osg::RefMatrix> mvm = new osg::RefMatrix(*cv->getModelViewMatrix()); mvm->preMult( _childBBoxMatrices[numChildren] ); cv->pushModelViewMatrix( mvm.get(), osg::Transform::RELATIVE_RF ); tileIsVisible = !cv->isCulled( _childBBoxes[numChildren] ); cv->popModelViewMatrix(); } if ( tileIsVisible ) { // [end:osgEarth] // compute priority from where abouts in the required range the distance falls. float priority = (_rangeList[numChildren].second-required_range)/(_rangeList[numChildren].second-_rangeList[numChildren].first); // invert priority for PIXEL_SIZE_ON_SCREEN mode if(_rangeMode==PIXEL_SIZE_ON_SCREEN) { priority = -priority; } // modify the priority according to the child's priority offset and scale. priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale; if (_databasePath.empty()) { nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get()); } else { // prepend the databasePath to the child's filename. nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get()); } } } } break; } default: break; } }
void PrecipitationEffect::traverse(osg::NodeVisitor& nv) { if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) { if (_dirty) update(); if (nv.getFrameStamp()) { double currentTime = nv.getFrameStamp()->getSimulationTime(); if (_previousFrameTime==FLT_MAX) _previousFrameTime = currentTime; double delta = currentTime - _previousFrameTime; _origin += _wind * delta; _previousFrameTime = currentTime; } return; } if (nv.getVisitorType() == osg::NodeVisitor::NODE_VISITOR) { if (_dirty) update(); osgUtil::GLObjectsVisitor* globjVisitor = dynamic_cast<osgUtil::GLObjectsVisitor*>(&nv); if (globjVisitor) { if (globjVisitor->getMode() & osgUtil::GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES) { compileGLObjects(globjVisitor->getRenderInfo()); } } return; } if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR) { return; } osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv); if (!cv) { return; } ViewIdentifier viewIndentifier(cv, nv.getNodePath()); { PrecipitationDrawableSet* precipitationDrawableSet = 0; { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex); precipitationDrawableSet = &(_viewDrawableMap[viewIndentifier]); if (!precipitationDrawableSet->_quadPrecipitationDrawable) { precipitationDrawableSet->_quadPrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_quadPrecipitationDrawable->setRequiresPreviousMatrix(true); precipitationDrawableSet->_quadPrecipitationDrawable->setGeometry(_quadGeometry.get()); precipitationDrawableSet->_quadPrecipitationDrawable->setStateSet(_quadStateSet.get()); precipitationDrawableSet->_quadPrecipitationDrawable->setDrawType(GL_QUADS); precipitationDrawableSet->_linePrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_linePrecipitationDrawable->setRequiresPreviousMatrix(true); precipitationDrawableSet->_linePrecipitationDrawable->setGeometry(_lineGeometry.get()); precipitationDrawableSet->_linePrecipitationDrawable->setStateSet(_lineStateSet.get()); precipitationDrawableSet->_linePrecipitationDrawable->setDrawType(GL_LINES); precipitationDrawableSet->_pointPrecipitationDrawable = new PrecipitationDrawable; precipitationDrawableSet->_pointPrecipitationDrawable->setRequiresPreviousMatrix(false); precipitationDrawableSet->_pointPrecipitationDrawable->setGeometry(_pointGeometry.get()); precipitationDrawableSet->_pointPrecipitationDrawable->setStateSet(_pointStateSet.get()); precipitationDrawableSet->_pointPrecipitationDrawable->setDrawType(GL_POINTS); } } cull(*precipitationDrawableSet, cv); cv->pushStateSet(_stateset.get()); float depth = 0.0f; if (!precipitationDrawableSet->_quadPrecipitationDrawable->getCurrentCellMatrixMap().empty()) { cv->pushStateSet(precipitationDrawableSet->_quadPrecipitationDrawable->getStateSet()); cv->addDrawableAndDepth(precipitationDrawableSet->_quadPrecipitationDrawable.get(),cv->getModelViewMatrix(),depth); cv->popStateSet(); } if (!precipitationDrawableSet->_linePrecipitationDrawable->getCurrentCellMatrixMap().empty()) { cv->pushStateSet(precipitationDrawableSet->_linePrecipitationDrawable->getStateSet()); cv->addDrawableAndDepth(precipitationDrawableSet->_linePrecipitationDrawable.get(),cv->getModelViewMatrix(),depth); cv->popStateSet(); } if (!precipitationDrawableSet->_pointPrecipitationDrawable->getCurrentCellMatrixMap().empty()) { cv->pushStateSet(precipitationDrawableSet->_pointPrecipitationDrawable->getStateSet()); cv->addDrawableAndDepth(precipitationDrawableSet->_pointPrecipitationDrawable.get(),cv->getModelViewMatrix(),depth); cv->popStateSet(); } cv->popStateSet(); } }
void Widget::updateFocus(osg::NodeVisitor& nv) { osgGA::EventVisitor* ev = nv.asEventVisitor(); osgGA::GUIActionAdapter* aa = ev ? ev->getActionAdapter() : 0; if (ev && aa) { osgGA::EventQueue::Events& events = ev->getEvents(); for(osgGA::EventQueue::Events::iterator itr = events.begin(); itr != events.end(); ++itr) { osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter(); if (ea) { bool previousFocus = _hasEventFocus; if (_focusBehaviour==CLICK_TO_FOCUS) { if (ea->getEventType()==osgGA::GUIEventAdapter::PUSH) { int numButtonsPressed = 0; if (ea->getButtonMask()&osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) ++numButtonsPressed; if (ea->getButtonMask()&osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) ++numButtonsPressed; if (ea->getButtonMask()&osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) ++numButtonsPressed; if (numButtonsPressed==1) { osgUtil::LineSegmentIntersector::Intersections intersections; bool withinWidget = aa->computeIntersections(*ea, nv.getNodePath(), intersections); if (withinWidget) _hasEventFocus = true; else _hasEventFocus = false; } } } else if (_focusBehaviour==FOCUS_FOLLOWS_POINTER) { bool checkWithinWidget = false; if (!_hasEventFocus) { checkWithinWidget = (ea->getEventType()!=osgGA::GUIEventAdapter::FRAME) && ea->getButtonMask()==0; } else { // if mouse move or mouse release check to see if mouse still within widget to retain focus if (ea->getEventType()==osgGA::GUIEventAdapter::MOVE) { checkWithinWidget = true; } else if (ea->getEventType()==osgGA::GUIEventAdapter::RELEASE) { // if no buttons pressed then check if (ea->getButtonMask()==0) checkWithinWidget = true; } } if (checkWithinWidget) { osgUtil::LineSegmentIntersector::Intersections intersections; bool withinWidget = aa->computeIntersections(*ea, nv.getNodePath(), intersections); _hasEventFocus = withinWidget; } } if (previousFocus != _hasEventFocus) { if (_hasEventFocus) { enter(); #if 0 if (view->getCameraManipulator()) { view->getCameraManipulator()->finishAnimation(); view->requestContinuousUpdate( false ); } #endif } else { leave(); } } } } } }
void TXPPagedLOD::traverse(osg::NodeVisitor& nv) { //TileMapper* tileMapper = dynamic_cast<TileMapper*>(nv.getUserData()); //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; unsigned int frameNumber = nv.getFrameStamp()?nv.getFrameStamp()->getFrameNumber():0; // set the frame number of the traversal so that external nodes can find out how active this // node is. if (nv.getFrameStamp() && nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) { setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber()); } switch(nv.getTraversalMode()) { case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN): std::for_each(_children.begin(),_children.end(),osg::NodeAcceptOp(nv)); break; case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): { float distance = nv.getDistanceToEyePoint(getCenter(),true); int lastChildTraversed = -1; bool needToLoadChild = false; unsigned maxRangeSize = _rangeList.size(); if (maxRangeSize!=0 && forceUseOfFirstChild) 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]._frameNumber=frameNumber; } _children[i]->accept(nv); lastChildTraversed = (int)i; } else { needToLoadChild = true; } } } 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; _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, nv.getNodePath(), priority, nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest); } } break; } default: break; } }