I have been postponing the occlusion for now. So far things seem to be working 
alright. I have found all the intersections and made a geode to collect them 
all, using storeGeode->containsDrawable(draws) to remove any duplicates.

But with the a file (that I'm not sure I can share, for copyright issues) that 
I'm using that contains 4 chairs, it only seems to detect three of them. 
However, when I draw single bounding boxes around items (by moving the camera 
around and drawing a bounding box around the first item intersected with the 
polytopeintersector), it will draw a box around each individual chair.

So that I can see what objects are being detected, I was thinking it might be 
good to add multiple selection boxes  of different colours, around every 
drawable that intersected with the polytopevisitor. The selection box is a 
matrixtransform on a geode, which gets moved and sized by the handler. But I 
don't know how to make multiple selection boxes. Help?


I've added my code, which is a mishmash of example code stuck together. The 
relevant code is in the keyhandler (search: KEY_F3).

Thank you,

Sterling

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=49414#49414



/* OpenSceneGraph example, osganimate.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  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.
*/

// This exampl demonstrates use of OcclusionQueryNode.
//
// In general, you use OcclusionQueryNode by simply attaching a subgraph
// or subgraphs as children, and it performs an OpenGL oclusion query
// to determine whether to draw the subgraphs or not.
//
// You can manually insert OcclusionQueryNodes at strategic locations
// in your scene graph, or you can write a NodeVisitor to insert them
// automatically, as this example shows.
//
// Run this example with no command line arguments, and it creates
// a "stock scene" to show how OcclusionQueryNode can be used.
//
// Or, run this example with a model on the command line, and the
// example uses a NodeVisitor to try to find worthwhile locations
// for OcclusionQueryNodes in your the scene graph.


#include <osg/MatrixTransform>
#include <osg/ShapeDrawable>

#include <osg/NodeVisitor>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/StateSet>
#include <osg/StateAttribute>
#include <osg/PolygonMode>
#include <osg/ColorMask>
#include <osg/PolygonOffset>
#include <osg/Depth>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/StateSetManipulator>

#include <osg/OcclusionQueryNode>

#include <iostream>
#include <sstream>


// NodeVisitors and utility functions for OcclusionQueryNode

// Use this visitor to insert OcclusionQueryNodes (OQNs) in the
//   visited subgraph. Only one OQN will test any particular node
//   (no nesting). See also OcclusionQueryNonFlatVisitor.
class OcclusionQueryVisitor : public osg::NodeVisitor
{
public:
    OcclusionQueryVisitor();
    virtual ~OcclusionQueryVisitor();

    // Specify the vertex count threshold for performing occlusion
    //   query tests. Nodes in the scene graph whose total child geometry
    //   contains fewer vertices than the specified threshold will
    //   never be tested, just drawn. (In fact, they will br treated as
    //   potential occluders and rendered first in front-to-back order.)
    void setOccluderThreshold( int vertices );
    int getOccluderThreshold() const;

    virtual void apply( osg::OcclusionQueryNode& oqn );
    virtual void apply( osg::Group& group );
    virtual void apply( osg::Geode& geode );
        

protected:
    void addOQN( osg::Node& node );

    // When an OQR creates all OQNs and each OQN shares the same OQC,
    //   these methods are used to uniquely name all OQNs. Handy
    //   for debugging.
    std::string getNextOQNName();
    int getNameIdx() const { return _nameIdx; }

    osg::ref_ptr<osg::StateSet> _state;
    osg::ref_ptr<osg::StateSet> _debugState;

    unsigned int _nameIdx;

    int _occluderThreshold;
};

// Find all OQNs in the visited scene graph and set their visibility threshold.
class VisibilityThresholdVisitor : public osg::NodeVisitor
{
public:
    VisibilityThresholdVisitor( unsigned int threshold=50 ) //5000
      : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
        _visThreshold( threshold ) {}
    virtual ~VisibilityThresholdVisitor() {}

    virtual void apply( osg::OcclusionQueryNode& oqn );


protected:
    unsigned int _visThreshold;
};

class InfoVisitor : public osg::NodeVisitor
{
public:
    InfoVisitor() : _level(0)
    {
        setTraversalMode( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN );
    }
    
    std::string spaces()
    { return std::string(_level*2, ' '); }
    
    void apply( osg::Node& node )
    {
        std::cout << spaces() << node.libraryName() << ":NODE:" << 
node.className() << " " << node.getName() << std::endl;
        
        _level++;
        traverse( node );
        _level--;
    }
    
    void apply( osg::Geode& geode )
    {
        std::cout << spaces() << geode.libraryName() << ":GEODE:" << 
geode.className() << " " << geode.getName() << std::endl;
        
        _level++;
        for ( unsigned int i=0; i<geode.getNumDrawables(); ++i )
        {
            osg::Drawable* drawable = geode.getDrawable(i);
            std::cout << spaces() << drawable->libraryName() << ":DRAWABLE:" << 
drawable->className() << " " << drawable->getName() << std::endl;
        }
        
        traverse( geode );
        _level--;
    }
    
protected:
    unsigned int _level;
};
// Find all OQNs in the visited scene graph and set the number of frames
//   between queries.
class QueryFrameCountVisitor : public osg::NodeVisitor
{
public:
    QueryFrameCountVisitor( int count=5 )
      : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
        _count( count ) {}
    virtual ~QueryFrameCountVisitor() {}

    virtual void apply( osg::OcclusionQueryNode& oqn );

protected:
    unsigned int _count;
};

// Find all OQNs in the visited scene graph and enable or disable queries..
class EnableQueryVisitor : public osg::NodeVisitor
{
public:
    EnableQueryVisitor( bool enable=true )
      : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
        _enabled( enable ) {}
    virtual ~EnableQueryVisitor() {}

    virtual void apply( osg::OcclusionQueryNode& oqn );

protected:
    bool _enabled;
};

// Find all OQNs in the visited scene graph and enable or disable the
//   debug bounding volume display.
class DebugDisplayVisitor : public osg::NodeVisitor
{
public:
    DebugDisplayVisitor( bool debug=true )
      : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
        _debug( debug ) {}
    virtual ~DebugDisplayVisitor() {}

    virtual void apply( osg::OcclusionQueryNode& oqn );

protected:
    bool _debug;
};

// Remove all OQNs from the visited scene graph.
class RemoveOcclusionQueryVisitor : public osg::NodeVisitor
{
public:
    RemoveOcclusionQueryVisitor();
    virtual ~RemoveOcclusionQueryVisitor();

    virtual void apply( osg::OcclusionQueryNode& oqn );

protected:
};

// Gather statistics about OQN performance in the visited scene graph.
class StatisticsVisitor : public osg::NodeVisitor
{
public:
    StatisticsVisitor( osg::NodeVisitor::TraversalMode 
mode=osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN );
    virtual ~StatisticsVisitor();

    virtual void apply( osg::OcclusionQueryNode& oqn );

    void reset();
    unsigned int getNumOQNs() const;
    unsigned int getNumPassed() const;

protected:
    unsigned int _numOQNs;
    unsigned int _numPassed;
};


unsigned int countGeometryVertices( osg::Geometry* geom )
{
    if (!geom->getVertexArray())
        return 0;

    // TBD This will eventually iterate over the PrimitiveSets and total the
    //   number of vertices actually used. But for now, it just returns the
    //   size of the vertex array.

    return geom->getVertexArray()->getNumElements();
}

class VertexCounter : public osg::NodeVisitor
{
public:
    VertexCounter( int limit )
      : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
        _limit( limit ),
        _total( 0 ) {}
    ~VertexCounter() {}

    int getTotal() { return _total; }
    bool exceeded() const { return _total > _limit; }
    void reset() { _total = 0; }

    virtual void apply( osg::Node& node )
    {
                std::cout << "Node2" << std::endl;      
                // Check for early abort. If out total already exceeds the
        //   max number of vertices, no need to traverse further.
        if (exceeded())
            return;
        traverse( node );
    }

    virtual void apply( osg::Geode& geode )
    {
                std::cout << "Geode2" << std::endl;
                // Possible early abort.
        if (exceeded())
            return;

        unsigned int i;
        for( i = 0; i < geode.getNumDrawables(); i++ )
        {
            osg::Geometry* geom = dynamic_cast<osg::Geometry 
*>(geode.getDrawable(i));
            if( !geom )
                continue;

            _total += countGeometryVertices( geom );

            if (_total > _limit)
                break;
        }
    }

protected:
    int _limit;
    int _total;
};



OcclusionQueryVisitor::OcclusionQueryVisitor()
  : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
    _nameIdx( 0 ),
    _occluderThreshold( 5000 ) //5000
{
    // Create a dummy OcclusionQueryNode just so we can get its state.
    // We'll then share that state between all OQNs we add to the visited scene 
graph.
    osg::ref_ptr<osg::OcclusionQueryNode> oqn = new osg::OcclusionQueryNode;

    _state = oqn->getQueryStateSet();
    _debugState = oqn->getDebugStateSet();
}

OcclusionQueryVisitor::~OcclusionQueryVisitor()
{
    osg::notify( osg::INFO ) <<
        "osgOQ: OcclusionQueryVisitor: Added " << getNameIdx() <<
        " OQNodes." << std::endl;
}

void
OcclusionQueryVisitor::setOccluderThreshold( int vertices )
{
    _occluderThreshold = vertices;
}
int
OcclusionQueryVisitor::getOccluderThreshold() const
{
    return _occluderThreshold;
}

void
OcclusionQueryVisitor::apply( osg::OcclusionQueryNode& oqn )
{
        
    // A subgraph is already under osgOQ control.
    // Don't traverse further.
        std::cout << "Done." << std::endl;
    return;
}

void
OcclusionQueryVisitor::apply( osg::Group& group )
{
        std::cout << "GROUP" << std::endl;
    if (group.getNumParents() == 0)
    {
        // Can't add an OQN above a root node.
        traverse( group );
        return;
    }

    int preTraverseOQNCount = getNameIdx();
    traverse( group );

    if (getNameIdx() > preTraverseOQNCount)
        // A least one OQN was added below the current node.
        //   Don't add one here to avoid hierarchical nesting.
        return;

    // There are no OQNs below this group. If the vertex
    //   count exceeds the threshold, add an OQN here.
    addOQN( group );
}

void
OcclusionQueryVisitor::apply( osg::Geode& geode )
{
        std::cout << "GEODE" << std::endl;
    if (geode.getNumParents() == 0)
    {
        
                // Can't add an OQN above a root node.
        traverse( geode );
        return;
    }

    addOQN( geode );
}

void
OcclusionQueryVisitor::addOQN( osg::Node& node )
{
        std::cout << "addOQN" << std::endl;
    VertexCounter vc( _occluderThreshold );
    node.accept( vc );
    if (vc.exceeded())
    {
        // Insert OQN(s) above this node.
        unsigned int np = node.getNumParents();
        while (np--)
        {
            osg::Group* parent = dynamic_cast<osg::Group*>( node.getParent( np 
) );
            if (parent != NULL)
            {
                osg::ref_ptr<osg::OcclusionQueryNode> oqn = new 
osg::OcclusionQueryNode();
                oqn->addChild( &node );
                parent->replaceChild( &node, oqn.get() );

                oqn->setName( getNextOQNName() );
                // Set all OQNs to use the same query StateSets (instead of 
multiple copies
                //   of the same StateSet) for efficiency.
                oqn->setQueryStateSet( _state.get() );
                oqn->setDebugStateSet( _debugState.get() );
            }
        }
    }
}

std::string
OcclusionQueryVisitor::getNextOQNName()
{
    std::ostringstream ostr;
    ostr << "OQNode_" << _nameIdx++;
    return ostr.str();
}




//
void
VisibilityThresholdVisitor::apply( osg::OcclusionQueryNode& oqn )
{
        std::cout << "oqn??" << std::endl;
    oqn.setVisibilityThreshold( _visThreshold );

    traverse( oqn );
}


void
QueryFrameCountVisitor::apply( osg::OcclusionQueryNode& oqn )
{
        std::cout << "oqn Frame" << std::endl;
    oqn.setQueryFrameCount( _count );

    traverse( oqn );
}

void
EnableQueryVisitor::apply( osg::OcclusionQueryNode& oqn )
{
        std::cout << "Enable oqn" << std::endl;
    oqn.setQueriesEnabled( _enabled );

    traverse( oqn );
}


void
DebugDisplayVisitor::apply( osg::OcclusionQueryNode& oqn )
{
        std::cout << "debugDisplay" << std::endl;
    oqn.setDebugDisplay( _debug );

    traverse( oqn );
}


RemoveOcclusionQueryVisitor::RemoveOcclusionQueryVisitor()
  : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
{
}

RemoveOcclusionQueryVisitor::~RemoveOcclusionQueryVisitor()
{
}

void
RemoveOcclusionQueryVisitor::apply( osg::OcclusionQueryNode& oqn )
{
    if (oqn.getNumParents() == 0)
    {
        // Even if this is an OQN, can't delete it because it's the root.
        traverse( oqn );
        return;
    }

    osg::ref_ptr<osg::OcclusionQueryNode> oqnPtr = &oqn;

    unsigned int np = oqn.getNumParents();
    while (np--)
    {
        osg::Group* parent = dynamic_cast<osg::Group*>( oqn.getParent( np ) );
        if (parent != NULL)
        {
            // Remove OQN from parent.
            parent->removeChild( oqnPtr.get() );

            // Add OQN's children to parent.
            unsigned int nc = oqn.getNumChildren();
            while (nc--)
                parent->addChild( oqn.getChild( nc ) );
        }
    }
}



StatisticsVisitor::StatisticsVisitor( osg::NodeVisitor::TraversalMode mode )
  : osg::NodeVisitor( mode ),
    _numOQNs( 0 ),
    _numPassed( 0 )
{
}

StatisticsVisitor::~StatisticsVisitor()
{
}

void
StatisticsVisitor::apply( osg::OcclusionQueryNode& oqn )
{
        std::cout << "Statistics oqn" << oqn.getName() << std::endl;
    _numOQNs++;
    if (oqn.getPassed())
        _numPassed++;

    traverse( oqn );
}

void
StatisticsVisitor::reset()
{
    _numOQNs = _numPassed = 0;
}

unsigned int
StatisticsVisitor::getNumOQNs() const
{
    return _numOQNs;
}
unsigned int
StatisticsVisitor::getNumPassed() const
{
    return _numPassed;
}

// End NodeVisitors



// KetHandler --
// Allow user to do interesting things with an
// OcclusionQueryNode-enabled scene graph at run time.
class KeyHandler : public osgGA::GUIEventHandler
{
public:
        KeyHandler( osg::Node& node, osg::Camera& camera )
      : _node( node ),
                _camera( camera ),
        _enable( true ),
        _debug( false )
    {}
    osg::Node* getOrCreateSelectionBox()
    {
        if ( !_selectionBox )
        {
            osg::ref_ptr<osg::Geode> geode = new osg::Geode;
                        osg::ref_ptr<osg::ShapeDrawable> sd = new 
osg::ShapeDrawable(new osg::Box(osg::Vec3(), 1.0f));
                        geode->addDrawable(sd);
            //geode->addDrawable(
            //    new osg::ShapeDrawable(new osg::Box(osg::Vec3(), 1.0f)) );
                        
                        sd->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // white


                        _selectionBox = new osg::MatrixTransform;
            _selectionBox->setNodeMask( 0x1 );
            _selectionBox->addChild( geode.get() );
            
            osg::StateSet* ss = _selectionBox->getOrCreateStateSet();
                        
            ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
            ss->setAttributeAndModes( new osg::PolygonMode(
                osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE) );
        }
        return _selectionBox.get();
    }

    bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& )
    {
        switch( ea.getEventType() ) 
        {
            case(osgGA::GUIEventAdapter::KEYUP):
            {
                                if (ea.getKey() == 
osgGA::GUIEventAdapter::KEY_F3)
                                {
                                        //std::cout << "f3" << std::endl;
                                        std::cout << "F3 pressed" << std::endl;
                                        
osg::ref_ptr<osgUtil::PolytopeIntersector> intersector = new 
osgUtil::PolytopeIntersector(
                                                
osgUtil::PolytopeIntersector::WINDOW, 0, 0, 400, 400);//0,0,400,400
                                        osgUtil::IntersectionVisitor iv( 
intersector.get() );
                                        _camera.accept(iv);

                                        if ( 
intersector->containsIntersections())
                                        {
                                                std::cout << "ok." << std::endl;
                                                
osgUtil::PolytopeIntersector::Intersections& intersections = 
intersector->getIntersections();
                                                int count = 0;
                                                osg::ref_ptr<osg::Geode> 
storeGeode = new osg::Geode;
                                                
for(osgUtil::PolytopeIntersector::Intersections::iterator itr = 
intersections.begin(); itr != intersections.end(); ++itr)
                                                {
                                                        //std::cout << 
itr->distance;
                                                        
osg::ref_ptr<osg::Drawable> drw = itr->drawable.get();
                                                        osg::ref_ptr<osg::Node> 
nod = drw->getParent(0);
                                                        
osg::ref_ptr<osg::Group> grp = nod->getParent(0);
                                                        
osg::ref_ptr<osg::Geometry> geom = drw->asGeometry();
                                                        
osg::ref_ptr<osg::Geode> geod = drw->getParent(0)->asGeode();
                                                        
                                                        
                                                        
                                                        
                                                        std::cout << "geode 
name:" << geod->getName() << std::endl;
                                                        std::cout << "geom 
name:" << geom->getName() << std::endl;                                         
             
                                                        std::cout << "grp 
name:" << grp->getName() << "grp class:" << grp->className() << std::endl;
                                                        std::cout << "drw 
name:" << drw->getName() << " drw class:" << drw->className() << std::endl;
                                                        std::cout << 
nod->getName() << " libName:" << nod->libraryName() << " class:" << 
nod->className()  << " NumDescriptions:" 
                                                                << 
nod->getParent(0)->className() << std::endl;
                                                
                                                        std::cout << 
itr->distance << std::endl;
                                                        
                                                        if 
(storeGeode->containsDrawable(drw))
                                                        {
                                                                
;//storeGeode->addDrawable(drw);
                                                        }
                                                        else
                                                        {
                                                                
storeGeode->addDrawable(drw);

                                                                
//geod->removeDrawable(drw);
                                                                //InfoVisitor 
infVist;
                                                                
//grp->accept(infVist);
                                                        }
                                                
                                                        
//storeGeode->addDrawable(drw);
                                                        /*if 
(storeGeode->containsDrawable(drw))
                                                        {
                                                                std::cout << 
"contains." << std::endl;
                                                        }
                                                        */

                                                        //std::cout << 
geod->removeDrawable(drw);
                                                        //break;
                                                        
                                                        osg::BoundingBox bb = 
drw->getBound();// drw->getBound();
                                                        osg::Vec3 worldCenter = 
bb.center() * osg::computeLocalToWorld(itr->nodePath);
                                                        
_selectionBox->setMatrix(
                                                                
osg::Matrix::scale(bb.xMax()-bb.xMin(), bb.yMax()-bb.yMin(), 
bb.zMax()-bb.zMin()) *
                                                                
osg::Matrix::translate(worldCenter) );
                                                        
                                                        count++;
                                                        break;
                                                }

                                                std::cout << count << std::endl;
                                                std::cout << 
storeGeode->getNumDrawables() << std::endl;
                                                //InfoVisitor infoV;
                                                //storeGeode->accept(infoV);
                                                
                                                osg::Geode::DrawableList 
drwList = storeGeode->getDrawableList();
                                                
                                                /*for 
(osg::Geode::DrawableList::iterator itr=drwList.begin(); itr<drwList.end(); 
itr++)
                                                {
                                                        
osg::ref_ptr<osg::Drawable> drw = itr->get();
                                                        osg::ref_ptr<osg::Node> 
nod = drw->getParent(0);
                                                        
osg::ref_ptr<osg::Group> grp = nod->getParent(0);
                                                        
osg::ref_ptr<osg::Geometry> geom = drw->asGeometry();
                                                        
//osg::ref_ptr<osg::Geode> geod = drw->getParent(0)->asGeode();
                                                        
                                                        //std::cout << "geode 
name:" << geod->getName() << std::endl;
                                                        std::cout << "geom 
name:" << geom->getName() << std::endl;                                         
             
                                                        std::cout << "grp 
name:" << grp->getName() << "grp class:" << grp->className() << std::endl;

                                                        std::cout << "drw 
name:" << drw->getName() << " drw class:" << drw->className() << std::endl;
                                                        std::cout << 
nod->getName() << " libName:" << nod->libraryName() << " class:" << 
nod->className()  << " NumDescriptions:" 
                                                                << 
nod->getParent(0)->className() << std::endl << std::endl;
                                                        
                                                        //std::cout << 
itr->distance << std::endl;
                                                }*/
                                                                                
                                        }

                                }

                                if (ea.getKey() == 
osgGA::GUIEventAdapter::KEY_F4)
                                {
                                        std::cout << "F4 pressed" << std::endl;
                                        InfoVisitor infoVisitor;
                                        _node.accept( infoVisitor );
                                }
                                if (ea.getKey() == 
osgGA::GUIEventAdapter::KEY_F5)
                                {

                                        OcclusionQueryVisitor oqv;
                                        _node.accept( oqv );
                                        std::cout << "F5" << std::endl;

                                        return true;
                                }
                if (ea.getKey()==osgGA::GUIEventAdapter::KEY_F6)
                {
                    // F6 -- Toggle osgOQ testing.
                                        std::cout << "F6" << std::endl;
                    _enable = !_enable;
                    EnableQueryVisitor eqv( _enable );
                    _node.accept( eqv );
                    return true;
                }
                else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_F7)
                {
                    // F7 -- Toggle display of OQ test bounding volumes
                    _debug = !_debug;
                    DebugDisplayVisitor ddv( _debug );
                    _node.accept( ddv );
                    return true;
                }
                else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_F8)
                {
                    // F8 -- Gether stats and display
                    StatisticsVisitor sv;
                    _node.accept( sv );
                    std::cout << "osgOQ: Stats: numOQNs " << sv.getNumOQNs() << 
", numPased " << sv.getNumPassed() << std::endl;
                    return true;
                }
                else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_F9)
                {
                    // F9 -- Remove all OcclusionQueryNodes
                                        std::cout << "F9 - remove OQN" << 
std::endl;
                    RemoveOcclusionQueryVisitor roqv;
                    _node.accept( roqv );
                    return true;
                }
                else if (ea.getKey()=='o')
                {
                    if (osgDB::writeNodeFile( _node, "saved_model.osgt" ))
                        osg::notify( osg::ALWAYS ) << "osgOQ: Wrote scene graph 
to \"saved_model.osgt\"" << std::endl;
                    else
                        osg::notify( osg::ALWAYS ) << "osgOQ: Wrote failed for 
\"saved_model.osgt\"" << std::endl;
                    return true;
                }
                return false;
            }
            default:
                break;
        }
        return false;
    }

    osg::Node& _node;
        osg::Camera& _camera;
        //osg::Viewer& _viewer;

    bool _enable, _debug;

protected:
    osg::ref_ptr<osg::MatrixTransform> _selectionBox;
};




// Create a cube with one side missing. This makes a great simple occluder.
osg::ref_ptr<osg::Node>
createBox()
{
    osg::ref_ptr<osg::Geode> box = new osg::Geode;

    osg::StateSet* state = box->getOrCreateStateSet();
    osg::PolygonMode* pm = new osg::PolygonMode(
        osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL );
    state->setAttributeAndModes( pm,
        osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );

    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
    osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
    geom->setVertexArray( v.get() );

    {
        const float x( 0.f );
        const float y( 0.f );
        const float z( 0.f );
        const float r( 1.1f );

        v->push_back( osg::Vec3( x-r, y-r, z-r ) ); //left -X
        v->push_back( osg::Vec3( x-r, y-r, z+r ) );
        v->push_back( osg::Vec3( x-r, y+r, z+r ) );
        v->push_back( osg::Vec3( x-r, y+r, z-r ) );

        v->push_back( osg::Vec3( x+r, y-r, z+r ) ); //right +X
        v->push_back( osg::Vec3( x+r, y-r, z-r ) );
        v->push_back( osg::Vec3( x+r, y+r, z-r ) );
        v->push_back( osg::Vec3( x+r, y+r, z+r ) );

        v->push_back( osg::Vec3( x-r, y-r, z-r ) ); // bottom -Z
        v->push_back( osg::Vec3( x-r, y+r, z-r ) );
        v->push_back( osg::Vec3( x+r, y+r, z-r ) );
        v->push_back( osg::Vec3( x+r, y-r, z-r ) );

        v->push_back( osg::Vec3( x-r, y-r, z+r ) ); // top +Z
        v->push_back( osg::Vec3( x+r, y-r, z+r ) );
        v->push_back( osg::Vec3( x+r, y+r, z+r ) );
        v->push_back( osg::Vec3( x-r, y+r, z+r ) );

        v->push_back( osg::Vec3( x-r, y+r, z-r ) ); // back +Y
        v->push_back( osg::Vec3( x-r, y+r, z+r ) );
        v->push_back( osg::Vec3( x+r, y+r, z+r ) );
        v->push_back( osg::Vec3( x+r, y+r, z-r ) );
    }

    osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
    geom->setColorArray( c.get() );
    geom->setColorBinding( osg::Geometry::BIND_OVERALL );
    c->push_back( osg::Vec4( 0.f, 1.f, 1.f, 1.f ) );

    osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
    geom->setNormalArray( n.get() );
    geom->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE );
    n->push_back( osg::Vec3( -1.f, 0.f, 0.f ) );
    n->push_back( osg::Vec3( 1.f, 0.f, 0.f ) );
    n->push_back( osg::Vec3( 0.f, 0.f, -1.f ) );
    n->push_back( osg::Vec3( 0.f, 0.f, 1.f ) );
    n->push_back( osg::Vec3( 0.f, 1.f, 0.f ) );

    geom->addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 20 ) );
    box->addDrawable( geom.get() );

    return box.get();
}

// Make a Geometry that renders slow intentionally.
// To make sure it renders slow, we do the following:
//  * Disable display lists
//  * Force glBegin/glEnd slow path
//  * Lots of vertices and color data per vertex
//  * No vertex sharing
//  * Draw the triangles as wireframe
osg::ref_ptr<osg::Node>
createRandomTriangles( unsigned int num )
{
    osg::ref_ptr<osg::Geode> tris = new osg::Geode;

    osg::StateSet* ss = tris->getOrCreateStateSet();

    // Force wireframe. Many gfx cards handle this poorly.
    osg::PolygonMode* pm = new osg::PolygonMode(
        osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE );
    ss->setAttributeAndModes( pm, osg::StateAttribute::ON |
        osg::StateAttribute::PROTECTED);
    ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF |
        osg::StateAttribute::PROTECTED);

    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
    // Disable display lists to decrease performance.
    geom->setUseDisplayList( false );

    osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
    geom->setVertexArray( v.get() );
    v->resize( num*3 );

    unsigned int i;
    srand( 0 );
#define RAND_NEG1_TO_1 ( ((rand()%20)-10)*.1 )
    for (i=0; i<num; i++)
    {
        osg::Vec3& v0 = (*v)[ i*3+0 ];
        osg::Vec3& v1 = (*v)[ i*3+1 ];
        osg::Vec3& v2 = (*v)[ i*3+2 ];
        v0 = osg::Vec3( RAND_NEG1_TO_1, RAND_NEG1_TO_1, RAND_NEG1_TO_1 );
        v1 = osg::Vec3( RAND_NEG1_TO_1, RAND_NEG1_TO_1, RAND_NEG1_TO_1 );
        v2 = osg::Vec3( RAND_NEG1_TO_1, RAND_NEG1_TO_1, RAND_NEG1_TO_1 );
    }

    osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;
    geom->setColorArray( c.get() );
    // Bind per primitive to force slow glBegin/glEnd path.
    geom->setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE );
    c->resize( num );

#define RAND_0_TO_1 ( (rand()%10)*.1 )
    for (i=0; i<num; i++)
    {
        osg::Vec4& c0 = (*c)[ i ];
        c0 = osg::Vec4( RAND_0_TO_1, RAND_0_TO_1, RAND_0_TO_1, 1. );
    }

    geom->addPrimitiveSet( new osg::DrawArrays( GL_TRIANGLES, 0, num*3 ) );
    tris->addDrawable( geom.get() );

    return tris.get();
}

// Create the stock scene:
// Top level Group
//   Geode (simple occluder
//   OcclusionQueryNode
//     Geode with complex, slow geometry.
osg::ref_ptr<osg::Node>
createStockScene()
{
    // Create a simple box occluder
    osg::ref_ptr<osg::Group> root = new osg::Group();
    root->addChild( createBox().get() );

    // Create a complex mess of triangles as a child below an
    //   OcclusionQueryNode. The OQN will ensure that the
    //   subgraph isn't rendered when it's not visible.
    osg::ref_ptr<osg::OcclusionQueryNode> oqn = new osg::OcclusionQueryNode;
    oqn->addChild( createRandomTriangles( 20000 ).get() );
    root->addChild( oqn.get() );

    return root.get();
}


int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+"
 demonstrates OpenGL occlusion query in OSG using the OcclusionQueryNode.");
    
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+"
 [options] [filename(s)]");
    arguments.getApplicationUsage()->addCommandLineOption("-h or 
--help","Display command line parameters");

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout, 
osg::ApplicationUsage::COMMAND_LINE_OPTION);
        return 1;
    }

    // report any errors if they have occurred when parsing the program 
arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    osgViewer::Viewer viewer( arguments );
        //osgViewer::Viewer viewer;
    // add the state manipulator
    viewer.addEventHandler( new 
osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the help handler
    viewer.addEventHandler(new 
osgViewer::HelpHandler(arguments.getApplicationUsage()));

    bool optimize = arguments.read( "--opt" );

    // load the specified model
        /*osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile( "cessna.osg" );
    osg::ref_ptr<osg::Node> model2 = osgDB::readNodeFile( "cow.osg" );
    
    osg::ref_ptr<osg::Group> root = new osg::Group;
    root->addChild( model1.get() );
    root->addChild( model2.get() );*/
    
        osg::ref_ptr<osg::Group> root = new osg::Group;
        //osg::ref_ptr<osg::Node> root = 0;

    if (arguments.argc()>1)
    {
        //root = osgDB::readNodeFiles( arguments );
                osg::ref_ptr<osg::Node> ch = osgDB::readNodeFiles(arguments);
                root->addChild(ch);
                if (root.valid())
        {
            // Run a NodeVisitor to insert OcclusionQueryNodes in the scene 
graph.
            OcclusionQueryVisitor oqv;
            root->accept( oqv );
        }
        else
        {
            std::cout << arguments.getApplicationName() <<": unable to load 
specified data." << std::endl;
            return 1;
        }
    }
    else
    {
        //root = createStockScene().get(); 
        if (!root)
        {
            std::cout << arguments.getApplicationName() <<": Failed to create 
stock scene." << std::endl;
            return 1;
        }
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occurred when parsing the program 
arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }


    // optimize the scene graph, remove redundant nodes and state etc.
    if (optimize)
    {
        osgUtil::Optimizer optimizer;
        optimizer.optimize( root.get() );
    }
        viewer.setUpViewInWindow(500, 500, 500, 500, 0);
        osg::ref_ptr<osg::Camera> camera = viewer.getCamera();

        osg::ref_ptr<KeyHandler> keyhandler = new KeyHandler(*root, *camera);
        root->addChild( keyhandler->getOrCreateSelectionBox() );

    viewer.setSceneData( root.get() );
        
        
        
        //keyhandler->getOrCreateSelectionBox();
    //KeyHandler* kh = new KeyHandler( *root, *camera );
        //kh->getOrCreateSelectionBox();
        
        //viewer.setSceneData( root.get() );
        
    viewer.addEventHandler( keyhandler.get() );
        
    return viewer.run();
}

_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to