root/OpenSceneGraph/trunk/examples/osgshadow/osgshadow.cpp @ 5779

Revision 5779, 7.3 kB (checked in by robert, 8 years ago)

Added movement of the light source to test performance of update the shadow volumes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/ArgumentParser>
2
3#include <osgProducer/Viewer>
4
5#include <osgShadow/OccluderGeometry>
6
7#include <osgDB/ReadFile>
8
9
10class ComputeBoundingBoxVisitor : public osg::NodeVisitor
11{
12public:
13    ComputeBoundingBoxVisitor():
14        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
15    {
16    }
17   
18    virtual void reset()
19    {
20        _matrixStack.clear();
21        _bb.init();
22    }
23   
24    osg::BoundingBox& getBoundingBox() { return _bb; }
25
26    void getPolytope(osg::Polytope& polytope, float margin=0.1) const
27    {
28        float delta = _bb.radius()*margin;
29        polytope.add( osg::Plane(0.0, 0.0, 1.0, -(_bb.zMin()-delta)) );
30        polytope.add( osg::Plane(0.0, 0.0, -1.0, (_bb.zMax()+delta)) );
31
32        polytope.add( osg::Plane(1.0, 0.0, 0.0, -(_bb.xMin()-delta)) );
33        polytope.add( osg::Plane(-1.0, 0.0, 0.0, (_bb.xMax()+delta)) );
34
35        polytope.add( osg::Plane(0.0, 1.0, 0.0, -(_bb.yMin()-delta)) );
36        polytope.add( osg::Plane(0.0, -1.0, 0.0, (_bb.yMax()+delta)) );
37    }
38       
39    void apply(osg::Node& node)
40    {
41        traverse(node);
42    }
43   
44    void apply(osg::Transform& transform)
45    {
46        osg::Matrix matrix;
47        if (!_matrixStack.empty()) matrix = _matrixStack.back();
48       
49        transform.computeLocalToWorldMatrix(matrix,this);
50       
51        pushMatrix(matrix);
52       
53        traverse(transform);
54       
55        popMatrix();
56    }
57   
58    void apply(osg::Geode& geode)
59    {
60        for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
61        {
62            apply(geode.getDrawable(i));
63        }
64    }
65   
66    void pushMatrix(osg::Matrix& matrix)
67    {
68        _matrixStack.push_back(matrix);
69    }
70   
71    void popMatrix()
72    {
73        _matrixStack.pop_back();
74    }
75
76    void apply(osg::Drawable* drawable)
77    {
78        if (_matrixStack.empty()) _bb.expandBy(drawable->getBound());
79        else
80        {
81            osg::Matrix& matrix = _matrixStack.back();
82            const osg::BoundingBox& dbb = drawable->getBound();
83            if (dbb.valid())
84            {
85                _bb.expandBy(dbb.corner(0) * matrix);
86                _bb.expandBy(dbb.corner(1) * matrix);
87                _bb.expandBy(dbb.corner(2) * matrix);
88                _bb.expandBy(dbb.corner(3) * matrix);
89                _bb.expandBy(dbb.corner(4) * matrix);
90                _bb.expandBy(dbb.corner(5) * matrix);
91                _bb.expandBy(dbb.corner(6) * matrix);
92                _bb.expandBy(dbb.corner(7) * matrix);
93            }
94        }
95    }
96   
97protected:
98   
99    typedef std::vector<osg::Matrix> MatrixStack;
100
101    MatrixStack         _matrixStack;
102    osg::BoundingBox    _bb;
103};
104
105
106
107int main(int argc, char** argv)
108{
109    // use an ArgumentParser object to manage the program arguments.
110    osg::ArgumentParser arguments(&argc, argv);
111
112    // set up the usage document, in case we need to print out how to use this program.
113    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class");
114    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
115    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
116    arguments.getApplicationUsage()->addCommandLineOption("--with-base-texture", "Adde base texture to shadowed model.");
117    arguments.getApplicationUsage()->addCommandLineOption("--no-base-texture", "Adde base texture to shadowed model.");
118
119    // construct the viewer.
120    osgProducer::Viewer viewer(arguments);
121
122    // set up the value with sensible default event handlers.
123    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
124
125    // get details on keyboard and mouse bindings used by the viewer.
126    viewer.getUsage(*arguments. getApplicationUsage());
127
128    // if user request help write it out to cout.
129    if (arguments.read("-h") || arguments.read("--help"))
130    {
131        arguments.getApplicationUsage()->write(std::cout);
132        return 1;
133    }
134
135    bool postionalLight = false;
136    while (arguments.read("--positionalLight")) postionalLight = true;
137    while (arguments.read("--directionalLight")) postionalLight = false;
138
139    bool addOccluderToScene = false;
140    while (arguments.read("addOccluderToScene")) addOccluderToScene = true;
141
142    bool updateLightPosition = true;
143
144    // any option left unread are converted into errors to write out later.
145    arguments.reportRemainingOptionsAsUnrecognized();
146
147    // report any errors if they have occured when parsing the program aguments.
148    if (arguments.errors())
149    {
150      arguments.writeErrorMessages(std::cout);
151      return 1;
152    }
153
154
155    osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
156    if (!model)
157    {
158        osg::notify(osg::NOTICE)<<"No model loaded, please specify a model to load."<<std::endl;
159        return 1;
160    }
161
162    // get the bounds of the model.   
163    ComputeBoundingBoxVisitor cbbv;
164    model->accept(cbbv);
165    osg::BoundingBox bb = cbbv.getBoundingBox();
166   
167    osg::ref_ptr<osg::Group> group = new osg::Group;
168    group->addChild(model.get());
169
170    // set up the occluder
171    osg::ref_ptr<osgShadow::OccluderGeometry> occluder = new osgShadow::OccluderGeometry;
172    occluder->computeOccluderGeometry(model.get());
173    cbbv.getPolytope(occluder->getBoundingPolytope(),0.001);
174
175    if (addOccluderToScene)
176    {
177        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
178        geode->addDrawable(occluder.get());
179        group->addChild(geode.get());
180    }
181   
182    osg::ref_ptr<osgShadow::ShadowVolumeGeometry> shadowVolume = new osgShadow::ShadowVolumeGeometry;
183
184    shadowVolume->setUseDisplayList(!updateLightPosition);
185
186    osg::Vec4 lightpos;
187   
188    if (postionalLight)
189    {
190        lightpos.set(bb.center().x(), bb.center().y(), bb.zMax() + bb.radius()  ,1.0f);
191    }
192    else
193    {
194        lightpos.set(0.5f,0.25f,-0.8f,0.0f);
195    }
196
197    {
198        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
199        occluder->comptueShadowVolumeGeometry(lightpos, *shadowVolume);
200        geode->addDrawable(shadowVolume.get());
201        group->addChild(geode.get());
202    }
203
204
205
206    viewer.setSceneData(group.get());
207
208    // create the windows and run the threads.
209    viewer.realize();
210
211    while (!viewer.done())
212    {
213      // wait for all cull and draw threads to complete.
214      viewer.sync();
215
216        if (updateLightPosition)
217        {
218            float t = viewer.getFrameStamp()->getReferenceTime();
219            if (postionalLight)
220            {
221                lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius()  ,1.0f);
222            }
223            else
224            {
225                lightpos.set(sinf(t),cosf(t),-0.8f,0.0f);
226            }
227            occluder->comptueShadowVolumeGeometry(lightpos, *shadowVolume);
228       }
229
230      // update the scene by traversing it with the the update visitor which will
231      // call all node update callbacks and animations.
232      viewer.update();
233         
234      // fire off the cull and draw traversals of the scene.
235      viewer.frame();
236    }
237   
238    // wait for all cull and draw threads to complete.
239    viewer.sync();
240
241    // run a clean up frame to delete all OpenGL objects.
242    viewer.cleanup_frame();
243
244    // wait for all the clean up frame to complete.
245    viewer.sync();
246
247    return 0;
248}
Note: See TracBrowser for help on using the browser.