root/OpenSceneGraph/trunk/examples/osgoccluder/osgoccluder.cpp @ 5636

Revision 5636, 11.0 kB (checked in by robert, 8 years ago)

Removed deprecated GUIEventHandler method

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osgProducer/Viewer>
2
3#include <osg/MatrixTransform>
4#include <osg/Billboard>
5#include <osg/Geode>
6#include <osg/Group>
7#include <osg/Notify>
8#include <osg/LineSegment>
9#include <osg/io_utils>
10
11#include <osgDB/Registry>
12#include <osgDB/ReadFile>
13#include <osgDB/WriteFile>
14
15#include <osgGA/TrackballManipulator>
16#include <osgGA/FlightManipulator>
17#include <osgGA/DriveManipulator>
18
19#include <osgUtil/Optimizer>
20#include <osgUtil/IntersectVisitor>
21
22#include <osg/OccluderNode>
23#include <osg/Geometry>
24#include <osg/ShapeDrawable>
25
26
27class OccluderEventHandler : public osgGA::GUIEventHandler
28{
29    public:
30   
31        OccluderEventHandler(osgProducer::Viewer* viewer):_viewer(viewer) {}
32   
33        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
34
35        void addPoint(const osg::Vec3& pos);
36               
37        void endOccluder();
38       
39        osg::Group* rootNode() { return dynamic_cast<osg::Group*>(_viewer->getSceneData()); }
40       
41       
42        osgProducer::Viewer*                    _viewer;
43        osg::ref_ptr<osg::Group>                _occluders;
44        osg::ref_ptr<osg::ConvexPlanarOccluder> _convexPlanarOccluder;
45};
46
47bool OccluderEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
48{
49    switch(ea.getEventType())
50    {
51        case(osgGA::GUIEventAdapter::KEYDOWN):
52        {
53            if (ea.getKey()=='a')
54            {
55
56                float x = ea.getXnormalized();
57                float y = ea.getYnormalized();
58 
59                osgUtil::IntersectVisitor::HitList hitList;
60                if (!_viewer->computeIntersections(x,y,hitList))
61                {
62                     return true;
63                }
64
65                if (!hitList.empty())
66                {
67
68                    osgUtil::Hit& hit = hitList.front();
69                    addPoint(hit.getWorldIntersectPoint());
70                }
71
72                return true;
73            }
74            else if (ea.getKey()=='e')
75            {
76                endOccluder();
77                return true;
78            }
79            else if (ea.getKey()=='O')
80            {
81                if (_occluders.valid())
82                {
83                   
84                    if (osgDB::writeNodeFile(*_occluders,"saved_occluders.osg"))
85                        std::cout<<"saved occluders to 'saved_occluders.osg'"<<std::endl;
86                }
87                else
88                {
89                    std::cout<<"no occluders to save"<<std::endl;
90                }
91                return true;
92            }
93            return false;
94        }
95
96        default:
97            return false;
98    }
99}
100
101void OccluderEventHandler::addPoint(const osg::Vec3& pos)
102{
103    std::cout<<"add point "<<pos<<std::endl;
104   
105    if (!_convexPlanarOccluder.valid()) _convexPlanarOccluder = new osg::ConvexPlanarOccluder;
106   
107    osg::ConvexPlanarPolygon& occluder = _convexPlanarOccluder->getOccluder();
108    occluder.add(pos);
109
110//     
111//     osg::BoundingSphere bs = rootNode()->getBound();
112//
113//     osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(pos,bs.radius()*0.001f));
114//     osg::Geode* geode = new osg::Geode;
115//     geode->addDrawable(sd);
116//
117//     rootNode()->addChild(geode);
118//
119   
120}
121               
122void OccluderEventHandler::endOccluder()
123{
124    if (_convexPlanarOccluder.valid())
125    {
126        if (_convexPlanarOccluder->getOccluder().getVertexList().size()>=3)
127        {
128            osg::OccluderNode* occluderNode = new osg::OccluderNode;
129            occluderNode->setOccluder(_convexPlanarOccluder.get());
130
131            if (!_occluders.valid())
132            {
133                _occluders = new osg::Group;
134                if (rootNode()) rootNode()->addChild(_occluders.get());
135            }
136            _occluders->addChild(occluderNode);
137
138            std::cout<<"created occluder"<<std::endl;
139        }
140        else
141        {
142            std::cout<<"Occluder requires at least 3 points to create occluder."<<std::endl;
143        }
144    }
145    else
146    {
147        std::cout<<"No occluder points to create occluder with."<<std::endl;
148    }
149   
150    // reset current occluder.
151    _convexPlanarOccluder = NULL;
152}
153
154
155osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4,float holeRatio=-1.0f)
156{
157   // create and occluder which will site along side the loadmodel model.
158    osg::OccluderNode* occluderNode = new osg::OccluderNode;
159
160    // create the convex planer occluder
161    osg::ConvexPlanarOccluder* cpo = new osg::ConvexPlanarOccluder;
162
163    // attach it to the occluder node.
164    occluderNode->setOccluder(cpo);
165    occluderNode->setName("occluder");
166   
167    // set the occluder up for the front face of the bounding box.
168    osg::ConvexPlanarPolygon& occluder = cpo->getOccluder();
169    occluder.add(v1);
170    occluder.add(v2);
171    occluder.add(v3);
172    occluder.add(v4);
173
174    // create a whole at the center of the occluder if needed.
175    if (holeRatio>0.0f)
176    {
177        // create hole.
178        float ratio = holeRatio;
179        float one_minus_ratio = 1-ratio;
180        osg::Vec3 center = (v1+v2+v3+v4)*0.25f;
181        osg::Vec3 v1dash = v1*ratio + center*one_minus_ratio;
182        osg::Vec3 v2dash = v2*ratio + center*one_minus_ratio;
183        osg::Vec3 v3dash = v3*ratio + center*one_minus_ratio;
184        osg::Vec3 v4dash = v4*ratio + center*one_minus_ratio;
185
186        osg::ConvexPlanarPolygon hole;
187        hole.add(v1dash);
188        hole.add(v2dash);
189        hole.add(v3dash);
190        hole.add(v4dash);
191
192        cpo->addHole(hole);
193    }   
194   
195
196   // create a drawable for occluder.
197    osg::Geometry* geom = new osg::Geometry;
198   
199    osg::Vec3Array* coords = new osg::Vec3Array(occluder.getVertexList().begin(),occluder.getVertexList().end());
200    geom->setVertexArray(coords);
201   
202    osg::Vec4Array* colors = new osg::Vec4Array(1);
203    (*colors)[0].set(1.0f,1.0f,1.0f,0.5f);
204    geom->setColorArray(colors);
205    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
206   
207    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
208   
209    osg::Geode* geode = new osg::Geode;
210    geode->addDrawable(geom);
211   
212    osg::StateSet* stateset = new osg::StateSet;
213    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
214    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
215    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
216   
217    geom->setStateSet(stateset);
218   
219    // add the occluder geode as a child of the occluder,
220    // as the occluder can't self occlude its subgraph the
221    // geode will never be occluder by this occluder.
222    occluderNode->addChild(geode);   
223   
224    return occluderNode;
225 
226 }
227
228osg::Group* createOccludersAroundModel(osg::Node* model)
229{
230    osg::Group* scene = new osg::Group;
231    scene->setName("rootgroup");
232
233
234    // add the loaded model into a the scene group.
235    scene->addChild(model);
236    model->setName("model");
237
238    // get the bounding volume of the model.
239    const osg::BoundingSphere bs = model->getBound();
240   
241    // create a bounding box around the sphere.
242    osg::BoundingBox bb;
243    bb.expandBy(bs);
244
245   // front
246   scene->addChild(createOccluder(bb.corner(0),
247                                  bb.corner(1),
248                                  bb.corner(5),
249                                  bb.corner(4)));
250
251   // right side
252   scene->addChild(createOccluder(bb.corner(1),
253                                  bb.corner(3),
254                                  bb.corner(7),
255                                  bb.corner(5)));
256
257   // left side
258   scene->addChild(createOccluder(bb.corner(2),
259                                  bb.corner(0),
260                                  bb.corner(4),
261                                  bb.corner(6)));
262
263   // back side
264   scene->addChild(createOccluder(bb.corner(3),
265                                  bb.corner(2),
266                                  bb.corner(6),
267                                  bb.corner(7),
268                                  0.5f)); // create a hole half the size of the occluder.
269
270    return scene;
271}
272
273
274int main( int argc, char **argv )
275{
276
277    // use an ArgumentParser object to manage the program arguments.
278    osg::ArgumentParser arguments(&argc,argv);
279
280    // set up the usage document, in case we need to print out how to use this program.
281    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of convex planer occluders.");
282    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
283    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
284    arguments.getApplicationUsage()->addCommandLineOption("-m","Mannually create occluders");
285   
286    // initialize the viewer.
287    osgProducer::Viewer viewer(arguments);
288
289    // set up the value with sensible default event handlers.
290    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
291
292    bool manuallyCreateOccluders = false;
293    while (arguments.read("-m")) { manuallyCreateOccluders = true; }
294
295    if (manuallyCreateOccluders)
296    {
297        viewer.getEventHandlerList().push_front(new OccluderEventHandler(&viewer));
298    }
299
300    // get details on keyboard and mouse bindings used by the viewer.
301    viewer.getUsage(*arguments.getApplicationUsage());
302
303    // if user request help write it out to cout.
304    if (arguments.read("-h") || arguments.read("--help"))
305    {
306        arguments.getApplicationUsage()->write(std::cout);
307        return 1;
308    }
309
310    // any option left unread are converted into errors to write out later.
311    arguments.reportRemainingOptionsAsUnrecognized();
312
313    // report any errors if they have occured when parsing the program aguments.
314    if (arguments.errors())
315    {
316        arguments.writeErrorMessages(std::cout);
317        return 1;
318    }
319
320    // load the nodes from the commandline arguments.
321    osg::Node* loadedmodel = osgDB::readNodeFiles(arguments);
322    if (!loadedmodel)
323    {
324        return 1;
325    }
326   
327    // run optimization over the scene graph
328    osgUtil::Optimizer optimzer;
329    optimzer.optimize(loadedmodel);
330
331    // add the occluders to the loaded model.
332    osg::ref_ptr<osg::Group> rootnode;
333   
334    if (manuallyCreateOccluders)
335    {
336        rootnode = new osg::Group;
337        rootnode->addChild(loadedmodel);
338    }
339    else   
340    {
341        rootnode = createOccludersAroundModel(loadedmodel);
342    }
343   
344     
345    // add a viewport to the viewer and attach the scene graph.
346    viewer.setSceneData( rootnode.get() );
347
348
349    // create the windows and run the threads.
350    viewer.realize();
351
352
353    while( !viewer.done() )
354    {
355        // wait for all cull and draw threads to complete.
356        viewer.sync();
357
358        // update the scene by traversing it with the the update visitor which will
359        // call all node update callbacks and animations.
360        viewer.update();
361         
362        // fire off the cull and draw traversals of the scene.
363        viewer.frame();
364       
365    }
366
367    // wait for all cull and draw threads to complete.
368    viewer.sync();
369
370    // run a clean up frame to delete all OpenGL objects.
371    viewer.cleanup_frame();
372
373    // wait for all the clean up frame to complete.
374    viewer.sync();
375
376    return 0;
377}
Note: See TracBrowser for help on using the browser.