Created
October 8, 2015 20:12
-
-
Save gwaldron/7750ebee8417fc1708b6 to your computer and use it in GitHub Desktop.
Use a CullVisitor to collect information about a scene
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* -*-c++-*- */ | |
| /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph | |
| * Copyright 2015 Pelican Mapping | |
| * http://osgearth.org | |
| * | |
| * osgEarth is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU Lesser General Public License as published by | |
| * the Free Software Foundation; either version 2 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| * IN THE SOFTWARE. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public License | |
| * along with this program. If not, see <http://www.gnu.org/licenses/> | |
| */ | |
| #include <osgViewer/Viewer> | |
| #include <osgEarth/Notify> | |
| #include <osgEarthUtil/EarthManipulator> | |
| #include <osgEarthUtil/ExampleResources> | |
| #include <osgEarth/Units> | |
| #include <osgEarth/Viewpoint> | |
| #define LC "[viewer] " | |
| using namespace osgEarth; | |
| using namespace osgEarth::Util; | |
| void | |
| extractBounds(osgUtil::StateGraph* sg, const osg::Matrix& viewToWorld, osg::BoundingSphere& worldBS) | |
| { | |
| // Do a depth-first recursive traversal of the state graph: | |
| for(osgUtil::StateGraph::ChildList::const_iterator i = sg->_children.begin(); i != sg->_children.end(); ++i) | |
| { | |
| extractBounds( i->second.get(), viewToWorld, worldBS ); | |
| } | |
| // Each StateGraph has a list of render leaves, each containing a Drawable | |
| // and a modelview/projection matrix pair. We only care about the modelview | |
| // matrix at this time. | |
| for(osgUtil::StateGraph::LeafList::const_iterator i = sg->_leaves.begin(); i != sg->_leaves.end(); ++i) | |
| { | |
| osgUtil::RenderLeaf* leaf = i->get(); | |
| // The modelview matrix, which will transform geometry into camera space | |
| const osg::Matrix& localToView = (*leaf->_modelview); | |
| const osg::Drawable* drawable = leaf->getDrawable(); | |
| // Cast the drawable to a geometry: | |
| const osg::Geometry* geometry = drawable->asGeometry(); | |
| if ( geometry ) | |
| { | |
| // The list of local-space vertices in this geometry: | |
| const osg::Vec3Array* vertices = dynamic_cast<const osg::Vec3Array*>(geometry->getVertexArray()); | |
| for(osg::Vec3Array::const_iterator v = vertices->begin(); v != vertices->end(); ++v) | |
| { | |
| const osg::Vec3f& vert = *v; | |
| // transform into view space (aka camera space) | |
| osg::Vec3d vertView = vert * localToView; | |
| // optional viewport clipping: Discard any verts that are outside the current viewpoint. | |
| osg::Vec4d vertClip = osg::Vec4d(vertView.x(), vertView.y(), vertView.z(), 1.0) * (*leaf->_projection); | |
| double absw = fabs(vertClip.w()); | |
| if ( fabs(vertClip.x()) > absw || fabs(vertClip.y()) > absw || fabs(vertClip.z()) > absw ) | |
| continue; | |
| // transform into world space | |
| osg::Vec3d vertWorld = vertView * viewToWorld; | |
| // use that to expand our bounds. | |
| worldBS.expandBy( vertWorld ); | |
| } | |
| } | |
| } | |
| } | |
| int | |
| main(int argc, char** argv) | |
| { | |
| osg::ArgumentParser arguments(&argc,argv); | |
| // create a viewer: | |
| osgViewer::Viewer viewer(arguments); | |
| viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false ); | |
| viewer.setCameraManipulator( new EarthManipulator(arguments) ); | |
| // load an earth file, and support all or our example command-line options | |
| // and earth file <external> tags | |
| osg::Node* node = MapNodeHelper().load( arguments, &viewer ); | |
| if ( node ) | |
| { | |
| viewer.setSceneData( node ); | |
| while(!viewer.done()) | |
| { | |
| viewer.frame(); | |
| // Construct a cull visitor to collect data in view: | |
| osg::ref_ptr<osgUtil::CullVisitor> cv = osgUtil::CullVisitor::create(); | |
| cv->setStateGraph( new osgUtil::StateGraph() ); | |
| cv->setRenderStage( new osgUtil::RenderStage() ); | |
| // Set the framestamp to that of the view. This is important so that paging | |
| // doesn't get interrupted. | |
| cv->setFrameStamp( viewer.getFrameStamp() ); | |
| // Run the visitor against our main camera's scene graph: | |
| viewer.getCamera()->accept( *cv.get() ); | |
| // Go through the results and calculate the world-space bounds: | |
| osg::BoundingSphere worldBS; | |
| extractBounds( cv->getRootStateGraph(), viewer.getCamera()->getInverseViewMatrix(), worldBS ); | |
| OE_NOTICE << "Approximate visible radius = " << worldBS.radius() << std::endl; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment