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

Revision 13376, 11.0 kB (checked in by robert, 13 days ago)

Moved widgets from VolumeEditorWidget? to TransferFunctionWidget?, and widget utilities into WidgetUtils?.

  • 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);
215    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
216   
217    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
218   
219    osg::Geode* geode = new osg::Geode;
220    geode->addDrawable(geom);
221   
222    osg::StateSet* stateset = new osg::StateSet;
223    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
224    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
225    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
226   
227    geom->setStateSet(stateset);
228   
229    // add the occluder geode as a child of the occluder,
230    // as the occluder can't self occlude its subgraph the
231    // geode will never be occluded by this occluder.
232    occluderNode->addChild(geode);   
233   
234    return occluderNode;
235 
236 }
237
238osg::Group* createOccludersAroundModel(osg::Node* model)
239{
240    osg::Group* scene = new osg::Group;
241    scene->setName("rootgroup");
242
243
244    // add the loaded model into a the scene group.
245    scene->addChild(model);
246    model->setName("model");
247
248    // get the bounding volume of the model.
249    const osg::BoundingSphere bs = model->getBound();
250   
251    // create a bounding box around the sphere.
252    osg::BoundingBox bb;
253    bb.expandBy(bs);
254
255   // front
256   scene->addChild(createOccluder(bb.corner(0),
257                                  bb.corner(1),
258                                  bb.corner(5),
259                                  bb.corner(4)));
260
261   // right side
262   scene->addChild(createOccluder(bb.corner(1),
263                                  bb.corner(3),
264                                  bb.corner(7),
265                                  bb.corner(5)));
266
267   // left side
268   scene->addChild(createOccluder(bb.corner(2),
269                                  bb.corner(0),
270                                  bb.corner(4),
271                                  bb.corner(6)));
272
273   // back side
274   scene->addChild(createOccluder(bb.corner(3),
275                                  bb.corner(2),
276                                  bb.corner(6),
277                                  bb.corner(7),
278                                  0.5f)); // create a hole half the size of the occluder.
279
280    return scene;
281}
282
283
284int main( int argc, char **argv )
285{
286
287    // use an ArgumentParser object to manage the program arguments.
288    osg::ArgumentParser arguments(&argc,argv);
289
290    // set up the usage document, in case we need to print out how to use this program.
291    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of convex planer occluders.");
292    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
293    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
294    arguments.getApplicationUsage()->addCommandLineOption("-m","Mannually create occluders");
295   
296    // initialize the viewer.
297    osgViewer::Viewer viewer;
298
299    bool manuallyCreateOccluders = false;
300    while (arguments.read("-m")) { manuallyCreateOccluders = true; }
301
302    if (manuallyCreateOccluders)
303    {
304        viewer.addEventHandler(new OccluderEventHandler(&viewer));
305    }
306
307    // if user requests help write it out to cout.
308    if (arguments.read("-h") || arguments.read("--help"))
309    {
310        arguments.getApplicationUsage()->write(std::cout);
311        return 1;
312    }
313
314    // load the nodes from the commandline arguments.
315    osg::Node* loadedmodel = osgDB::readNodeFiles(arguments);
316   
317    // if not loaded assume no arguments passed in, try using default mode instead.
318    if (!loadedmodel) loadedmodel = osgDB::readNodeFile("glider.osgt");
319   
320    if (!loadedmodel)
321    {
322        osg::notify(osg::NOTICE)<<"Please specify a model filename on the command line."<<std::endl;
323        return 1;
324    }
325   
326    // run optimization over the scene graph
327    osgUtil::Optimizer optimzer;
328    optimzer.optimize(loadedmodel);
329
330    // add the occluders to the loaded model.
331    osg::ref_ptr<osg::Group> rootnode;
332   
333    if (manuallyCreateOccluders)
334    {
335        rootnode = new osg::Group;
336        rootnode->addChild(loadedmodel);
337    }
338    else   
339    {
340        rootnode = createOccludersAroundModel(loadedmodel);
341    }
342   
343     
344    // add a viewport to the viewer and attach the scene graph.
345    viewer.setSceneData( rootnode.get() );
346
347    return viewer.run();
348}
Note: See TracBrowser for help on using the browser.