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

Revision 13574, 10.8 kB (checked in by robert, 18 hours ago)

Changed the osgUI behaviour so that events are set to be handled by Widgets that have focus even if they don't directly use them.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgoccluder.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osgViewer/Viewer>
20
21#include <osg/MatrixTransform>
22#include <osg/Billboard>
23#include <osg/Geode>
24#include <osg/Group>
25#include <osg/Notify>
26#include <osg/io_utils>
27
28#include <osgDB/Registry>
29#include <osgDB/ReadFile>
30#include <osgDB/WriteFile>
31
32#include <osgGA/TrackballManipulator>
33#include <osgGA/FlightManipulator>
34#include <osgGA/DriveManipulator>
35
36#include <osgUtil/Optimizer>
37
38#include <osg/OccluderNode>
39#include <osg/Geometry>
40#include <osg/ShapeDrawable>
41
42#include <iostream>
43
44class OccluderEventHandler : public osgGA::GUIEventHandler
45{
46    public:
47
48        OccluderEventHandler(osgViewer::Viewer* viewer):_viewer(viewer) {}
49
50        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
51
52        void addPoint(const osg::Vec3& pos);
53
54        void endOccluder();
55
56        osg::Group* rootNode() { return dynamic_cast<osg::Group*>(_viewer->getSceneData()); }
57
58
59        osgViewer::Viewer*                    _viewer;
60        osg::ref_ptr<osg::Group>                _occluders;
61        osg::ref_ptr<osg::ConvexPlanarOccluder> _convexPlanarOccluder;
62};
63
64bool OccluderEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
65{
66    switch(ea.getEventType())
67    {
68        case(osgGA::GUIEventAdapter::KEYDOWN):
69        {
70            if (ea.getKey()=='a')
71
72            {
73                osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
74                osgUtil::LineSegmentIntersector::Intersections intersections;
75                if (view && view->computeIntersections(ea, intersections))
76                {
77                    const osgUtil::LineSegmentIntersector::Intersection& hit = *(intersections.begin());
78                    if (hit.matrix.valid()) addPoint(hit.localIntersectionPoint * (*hit.matrix));
79                    else addPoint(hit.localIntersectionPoint);
80                }
81
82                return true;
83            }
84            else if (ea.getKey()=='e')
85            {
86                endOccluder();
87                return true;
88            }
89            else if (ea.getKey()=='O')
90            {
91                if (_occluders.valid())
92                {
93
94                    if (osgDB::writeNodeFile(*_occluders,"saved_occluders.osgt"))
95                        std::cout<<"saved occluders to 'saved_occluders.osgt'"<<std::endl;
96                }
97                else
98                {
99                    std::cout<<"no occluders to save"<<std::endl;
100                }
101                return true;
102            }
103            return false;
104        }
105
106        default:
107            return false;
108    }
109}
110
111void OccluderEventHandler::addPoint(const osg::Vec3& pos)
112{
113    std::cout<<"add point "<<pos<<std::endl;
114
115    if (!_convexPlanarOccluder.valid()) _convexPlanarOccluder = new osg::ConvexPlanarOccluder;
116
117    osg::ConvexPlanarPolygon& occluder = _convexPlanarOccluder->getOccluder();
118    occluder.add(pos);
119
120//
121//     osg::BoundingSphere bs = rootNode()->getBound();
122//
123//     osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(pos,bs.radius()*0.001f));
124//     osg::Geode* geode = new osg::Geode;
125//     geode->addDrawable(sd);
126//
127//     rootNode()->addChild(geode);
128//
129
130}
131
132void OccluderEventHandler::endOccluder()
133{
134    if (_convexPlanarOccluder.valid())
135    {
136        if (_convexPlanarOccluder->getOccluder().getVertexList().size()>=3)
137        {
138            osg::OccluderNode* occluderNode = new osg::OccluderNode;
139            occluderNode->setOccluder(_convexPlanarOccluder.get());
140
141            if (!_occluders.valid())
142            {
143                _occluders = new osg::Group;
144                if (rootNode()) rootNode()->addChild(_occluders.get());
145            }
146            _occluders->addChild(occluderNode);
147
148            std::cout<<"created occluder"<<std::endl;
149        }
150        else
151        {
152            std::cout<<"Occluder requires at least 3 points to create occluder."<<std::endl;
153        }
154    }
155    else
156    {
157        std::cout<<"No occluder points to create occluder with."<<std::endl;
158    }
159
160    // reset current occluder.
161    _convexPlanarOccluder = NULL;
162}
163
164
165osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4,float holeRatio=-1.0f)
166{
167   // create an occluder which will sit alongside the loaded model.
168    osg::OccluderNode* occluderNode = new osg::OccluderNode;
169
170    // create the convex planar occluder
171    osg::ConvexPlanarOccluder* cpo = new osg::ConvexPlanarOccluder;
172
173    // attach it to the occluder node.
174    occluderNode->setOccluder(cpo);
175    occluderNode->setName("occluder");
176
177    // set the occluder up for the front face of the bounding box.
178    osg::ConvexPlanarPolygon& occluder = cpo->getOccluder();
179    occluder.add(v1);
180    occluder.add(v2);
181    occluder.add(v3);
182    occluder.add(v4);
183
184    // create a hole at the center of the occluder if needed.
185    if (holeRatio>0.0f)
186    {
187        // create hole.
188        float ratio = holeRatio;
189        float one_minus_ratio = 1-ratio;
190        osg::Vec3 center = (v1+v2+v3+v4)*0.25f;
191        osg::Vec3 v1dash = v1*ratio + center*one_minus_ratio;
192        osg::Vec3 v2dash = v2*ratio + center*one_minus_ratio;
193        osg::Vec3 v3dash = v3*ratio + center*one_minus_ratio;
194        osg::Vec3 v4dash = v4*ratio + center*one_minus_ratio;
195
196        osg::ConvexPlanarPolygon hole;
197        hole.add(v1dash);
198        hole.add(v2dash);
199        hole.add(v3dash);
200        hole.add(v4dash);
201
202        cpo->addHole(hole);
203    }
204
205
206   // create a drawable for occluder.
207    osg::Geometry* geom = new osg::Geometry;
208
209    osg::Vec3Array* coords = new osg::Vec3Array(occluder.getVertexList().begin(),occluder.getVertexList().end());
210    geom->setVertexArray(coords);
211
212    osg::Vec4Array* colors = new osg::Vec4Array(1);
213    (*colors)[0].set(1.0f,1.0f,1.0f,0.5f);
214    geom->setColorArray(colors, osg::Array::BIND_OVERALL);
215
216    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
217
218    osg::Geode* geode = new osg::Geode;
219    geode->addDrawable(geom);
220
221    osg::StateSet* stateset = new osg::StateSet;
222    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
223    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
224    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
225
226    geom->setStateSet(stateset);
227
228    // add the occluder geode as a child of the occluder,
229    // as the occluder can't self occlude its subgraph the
230    // geode will never be occluded by this occluder.
231    occluderNode->addChild(geode);
232
233    return occluderNode;
234
235 }
236
237osg::Group* createOccludersAroundModel(osg::Node* model)
238{
239    osg::Group* scene = new osg::Group;
240    scene->setName("rootgroup");
241
242
243    // add the loaded model into a the scene group.
244    scene->addChild(model);
245    model->setName("model");
246
247    // get the bounding volume of the model.
248    const osg::BoundingSphere bs = model->getBound();
249
250    // create a bounding box around the sphere.
251    osg::BoundingBox bb;
252    bb.expandBy(bs);
253
254   // front
255   scene->addChild(createOccluder(bb.corner(0),
256                                  bb.corner(1),
257                                  bb.corner(5),
258                                  bb.corner(4)));
259
260   // right side
261   scene->addChild(createOccluder(bb.corner(1),
262                                  bb.corner(3),
263                                  bb.corner(7),
264                                  bb.corner(5)));
265
266   // left side
267   scene->addChild(createOccluder(bb.corner(2),
268                                  bb.corner(0),
269                                  bb.corner(4),
270                                  bb.corner(6)));
271
272   // back side
273   scene->addChild(createOccluder(bb.corner(3),
274                                  bb.corner(2),
275                                  bb.corner(6),
276                                  bb.corner(7),
277                                  0.5f)); // create a hole half the size of the occluder.
278
279    return scene;
280}
281
282
283int main( int argc, char **argv )
284{
285
286    // use an ArgumentParser object to manage the program arguments.
287    osg::ArgumentParser arguments(&argc,argv);
288
289    // set up the usage document, in case we need to print out how to use this program.
290    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of convex planer occluders.");
291    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
292    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
293    arguments.getApplicationUsage()->addCommandLineOption("-m","Mannually create occluders");
294
295    // initialize the viewer.
296    osgViewer::Viewer viewer;
297
298    bool manuallyCreateOccluders = false;
299    while (arguments.read("-m")) { manuallyCreateOccluders = true; }
300
301    if (manuallyCreateOccluders)
302    {
303        viewer.addEventHandler(new OccluderEventHandler(&viewer));
304    }
305
306    // if user requests help write it out to cout.
307    if (arguments.read("-h") || arguments.read("--help"))
308    {
309        arguments.getApplicationUsage()->write(std::cout);
310        return 1;
311    }
312
313    // load the nodes from the commandline arguments.
314    osg::Node* loadedmodel = osgDB::readNodeFiles(arguments);
315
316    // if not loaded assume no arguments passed in, try using default mode instead.
317    if (!loadedmodel) loadedmodel = osgDB::readNodeFile("glider.osgt");
318
319    if (!loadedmodel)
320    {
321        osg::notify(osg::NOTICE)<<"Please specify a model filename on the command line."<<std::endl;
322        return 1;
323    }
324
325    // run optimization over the scene graph
326    osgUtil::Optimizer optimzer;
327    optimzer.optimize(loadedmodel);
328
329    // add the occluders to the loaded model.
330    osg::ref_ptr<osg::Group> rootnode;
331
332    if (manuallyCreateOccluders)
333    {
334        rootnode = new osg::Group;
335        rootnode->addChild(loadedmodel);
336    }
337    else
338    {
339        rootnode = createOccludersAroundModel(loadedmodel);
340    }
341
342
343    // add a viewport to the viewer and attach the scene graph.
344    viewer.setSceneData( rootnode.get() );
345
346    return viewer.run();
347}
Note: See TracBrowser for help on using the browser.