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

Revision 5927, 10.0 kB (checked in by robert, 7 years ago)

Ported following examples to osgViewer:

osggeodemo
osggeometry
osghud
osgimpostor
osgkeyboard
osglauncher
osglight
osglightpoint
osglogicop
osglogo
osgmovie
osgmultiplecameras
osgmultitexture
osgoccluder
osgparametric
osgparticle

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