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

Revision 13107, 44.7 kB (checked in by robert, 12 hours ago)

From Jason Beverage, "It looks like the Callback header got accidentally removed from the CMakeLists.txt in the submission yesterday for the geometry instancing example."

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgshadow.
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 <osg/ArgumentParser>
20#include <osg/ComputeBoundsVisitor>
21#include <osg/Texture2D>
22#include <osg/ShapeDrawable>
23#include <osg/MatrixTransform>
24#include <osg/Geometry>
25
26#include <osgGA/TrackballManipulator>
27#include <osgGA/FlightManipulator>
28#include <osgGA/DriveManipulator>
29#include <osgGA/KeySwitchMatrixManipulator>
30#include <osgGA/AnimationPathManipulator>
31#include <osgGA/TerrainManipulator>
32#include <osgGA/AnimationPathManipulator>
33#include <osgGA/StateSetManipulator>
34
35#include <osgViewer/Viewer>
36#include <osgViewer/ViewerEventHandlers>
37
38#include <osgShadow/ShadowedScene>
39#include <osgShadow/ShadowVolume>
40#include <osgShadow/ShadowTexture>
41#include <osgShadow/ShadowMap>
42#include <osgShadow/SoftShadowMap>
43#include <osgShadow/ParallelSplitShadowMap>
44#include <osgShadow/LightSpacePerspectiveShadowMap>
45#include <osgShadow/StandardShadowMap>
46#include <osgShadow/ViewDependentShadowMap>
47
48#include <osgUtil/Optimizer>
49
50#include <osgDB/ReadFile>
51#include <osgDB/WriteFile>
52
53#include <osg/io_utils>
54#include <iostream>
55
56
57// for the grid data..
58#include "terrain_coords.h"
59// for the model number four - island scene
60#include "IslandScene.h"
61
62
63class ChangeFOVHandler : public osgGA::GUIEventHandler
64{
65public:
66    ChangeFOVHandler(osg::Camera* camera)
67        : _camera(camera)
68    {
69        double fovy, aspectRatio, zNear, zFar;
70        _camera->getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
71        std::cout << "FOV is " << fovy << std::endl;
72    }
73
74    /** Deprecated, Handle events, return true if handled, false otherwise. */
75    virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
76    {
77        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYUP)
78        {
79            if (ea.getKey() == '-' || ea.getKey() == '=' || ea.getKey() == '0')
80            {
81                double fovy, aspectRatio, zNear, zFar;
82                _camera->getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
83
84                if (ea.getKey() == '-')
85                {
86                    fovy -= 5.0;
87                }
88
89                if (ea.getKey() == '=')
90                {
91                    fovy += 5.0;
92                }
93
94                if (ea.getKey() == '0')
95                {
96                    fovy = 45.0;
97                }
98
99                std::cout << "Setting FOV to " << fovy << std::endl;
100                _camera->getProjectionMatrix().makePerspective(fovy, aspectRatio, zNear, zFar);
101
102                return true;
103            }
104        }
105
106        return false;
107    }
108
109    osg::ref_ptr<osg::Camera> _camera;
110};
111
112
113class DumpShadowVolumesHandler : public osgGA::GUIEventHandler
114{
115public:
116    DumpShadowVolumesHandler(  )
117    {
118        set( false );
119    }
120
121    bool get() { return _value; }
122    void set( bool value ) { _value = value; }
123
124    /** Deprecated, Handle events, return true if handled, false otherwise. */
125    virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
126    {
127        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYUP)
128        {
129            if (ea.getKey() == 'D' )
130            {
131                set( true );
132                return true;
133            }
134        }
135
136        return false;
137    }
138
139    bool  _value;
140};
141
142
143class LightAnimationHandler : public osgGA::GUIEventHandler
144{
145public:
146    LightAnimationHandler(bool flag=true): _animating(flag) {}
147
148    void setAnimating(bool flag) { _animating = flag; }
149    bool getAnimating() const { return _animating; }
150
151    /** Deprecated, Handle events, return true if handled, false otherwise. */
152    virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
153    {
154        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYUP)
155        {
156            if (ea.getKey() == 'p' )
157            {
158                _animating = !_animating;
159                return true;
160            }
161        }
162
163        return false;
164    }
165
166    bool  _animating;
167};
168
169
170static int ReceivesShadowTraversalMask = 0x1;
171static int CastsShadowTraversalMask = 0x2;
172
173namespace ModelOne
174{
175
176    enum Faces
177    {
178        FRONT_FACE = 1,
179        BACK_FACE = 2,
180        LEFT_FACE = 4,
181        RIGHT_FACE = 8,
182        TOP_FACE = 16,
183        BOTTOM_FACE = 32
184    };
185
186    osg::Node* createCube(unsigned int mask)
187    {
188        osg::Geode* geode = new osg::Geode;
189
190        osg::Geometry* geometry = new osg::Geometry;
191        geode->addDrawable(geometry);
192
193        osg::Vec3Array* vertices = new osg::Vec3Array;
194        geometry->setVertexArray(vertices);
195
196        osg::Vec3Array* normals = new osg::Vec3Array;
197        geometry->setNormalArray(normals);
198        geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
199
200        osg::Vec4Array* colours = new osg::Vec4Array;
201        geometry->setColorArray(colours);
202        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
203        colours->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
204
205
206        osg::Vec3 origin(0.0f,0.0f,0.0f);
207        osg::Vec3 dx(2.0f,0.0f,0.0f);
208        osg::Vec3 dy(0.0f,1.0f,0.0f);
209        osg::Vec3 dz(0.0f,0.0f,1.0f);
210
211        osg::Vec3 px(1.0f,0.0,0.0f);
212        osg::Vec3 nx(-1.0f,0.0,0.0f);
213        osg::Vec3 py(0.0f,1.0f,0.0f);
214        osg::Vec3 ny(0.0f,-1.0f,0.0f);
215        osg::Vec3 pz(0.0f,0.0f,1.0f);
216        osg::Vec3 nz(0.0f,0.0f,-1.0f);
217
218        if (mask & FRONT_FACE)
219        {
220            // front face
221            vertices->push_back(origin);
222            vertices->push_back(origin+dx);
223            vertices->push_back(origin+dx+dz);
224            vertices->push_back(origin+dz);
225            normals->push_back(ny);
226            normals->push_back(ny);
227            normals->push_back(ny);
228            normals->push_back(ny);
229        }
230
231        if (mask & BACK_FACE)
232        {
233            // back face
234            vertices->push_back(origin+dy);
235            vertices->push_back(origin+dy+dz);
236            vertices->push_back(origin+dy+dx+dz);
237            vertices->push_back(origin+dy+dx);
238            normals->push_back(py);
239            normals->push_back(py);
240            normals->push_back(py);
241            normals->push_back(py);
242        }
243
244        if (mask & LEFT_FACE)
245        {
246            // left face
247            vertices->push_back(origin+dy);
248            vertices->push_back(origin);
249            vertices->push_back(origin+dz);
250            vertices->push_back(origin+dy+dz);
251            normals->push_back(nx);
252            normals->push_back(nx);
253            normals->push_back(nx);
254            normals->push_back(nx);
255        }
256
257        if (mask & RIGHT_FACE)
258        {
259            // right face
260            vertices->push_back(origin+dx+dy);
261            vertices->push_back(origin+dx+dy+dz);
262            vertices->push_back(origin+dx+dz);
263            vertices->push_back(origin+dx);
264            normals->push_back(px);
265            normals->push_back(px);
266            normals->push_back(px);
267            normals->push_back(px);
268        }
269
270        if (mask & TOP_FACE)
271        {
272            // top face
273            vertices->push_back(origin+dz);
274            vertices->push_back(origin+dz+dx);
275            vertices->push_back(origin+dz+dx+dy);
276            vertices->push_back(origin+dz+dy);
277            normals->push_back(pz);
278            normals->push_back(pz);
279            normals->push_back(pz);
280            normals->push_back(pz);
281        }
282
283        if (mask & BOTTOM_FACE)
284        {
285            // bottom face
286            vertices->push_back(origin);
287            vertices->push_back(origin+dy);
288            vertices->push_back(origin+dx+dy);
289            vertices->push_back(origin+dx);
290            normals->push_back(nz);
291            normals->push_back(nz);
292            normals->push_back(nz);
293            normals->push_back(nz);
294        }
295
296        geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, vertices->size()));
297
298        return geode;
299    }
300
301    class SwitchHandler : public osgGA::GUIEventHandler
302    {
303    public:
304
305        SwitchHandler():
306            _childNum(0) {}
307
308        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& /*aa*/, osg::Object* object, osg::NodeVisitor* /*nv*/)
309        {
310            osg::Switch* sw = dynamic_cast<osg::Switch*>(object);
311            if (!sw) return false;
312
313            if (ea.getHandled()) return false;
314
315            switch(ea.getEventType())
316            {
317                case(osgGA::GUIEventAdapter::KEYDOWN):
318                {
319                    if (ea.getKey()=='n')
320                    {
321                        ++_childNum;
322                        if (_childNum >= sw->getNumChildren()) _childNum = 0;
323
324                        sw->setSingleChildOn(_childNum);
325                        return true;
326                    }
327                    break;
328                }
329                default:
330                    break;
331            }
332            return false;
333        }
334
335    protected:
336
337        virtual ~SwitchHandler() {}
338        unsigned int    _childNum;
339
340    };
341
342
343    osg::Node* createModel(osg::ArgumentParser& /*arguments*/)
344    {
345        osg::Switch* sw = new osg::Switch;
346        sw->setEventCallback(new ModelOne::SwitchHandler);
347
348        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE), true);
349        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE), false);
350        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE), false);
351        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE | ModelOne::RIGHT_FACE), false);
352        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE | ModelOne::RIGHT_FACE | ModelOne::TOP_FACE), false);
353        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE | ModelOne::RIGHT_FACE | ModelOne::TOP_FACE | ModelOne::BOTTOM_FACE), false);
354
355        return sw;
356    }
357}
358
359namespace ModelTwo
360{
361    osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
362    {
363        // set up the animation path
364        osg::AnimationPath* animationPath = new osg::AnimationPath;
365        animationPath->setLoopMode(osg::AnimationPath::LOOP);
366
367        int numSamples = 40;
368        float yaw = 0.0f;
369        float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
370        float roll = osg::inDegrees(30.0f);
371
372        double time=0.0f;
373        double time_delta = looptime/(double)numSamples;
374        for(int i=0;i<numSamples;++i)
375        {
376            osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
377            osg::Quat rotation(osg::Quat(roll,osg::Vec3(0.0,1.0,0.0))*osg::Quat(-(yaw+osg::inDegrees(90.0f)),osg::Vec3(0.0,0.0,1.0)));
378
379            animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
380
381            yaw += yaw_delta;
382            time += time_delta;
383
384        }
385        return animationPath;
386    }
387
388    osg::Node* createBase(const osg::Vec3& center,float radius)
389    {
390
391        osg::Geode* geode = new osg::Geode;
392
393        // set up the texture of the base.
394        osg::StateSet* stateset = new osg::StateSet();
395        osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
396        if (image)
397        {
398            osg::Texture2D* texture = new osg::Texture2D;
399            texture->setImage(image);
400            stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
401        }
402
403        geode->setStateSet( stateset );
404
405
406        osg::HeightField* grid = new osg::HeightField;
407        grid->allocate(38,39);
408        grid->setOrigin(center+osg::Vec3(-radius,-radius,0.0f));
409        grid->setXInterval(radius*2.0f/(float)(38-1));
410        grid->setYInterval(radius*2.0f/(float)(39-1));
411
412        float minHeight = FLT_MAX;
413        float maxHeight = -FLT_MAX;
414
415
416        unsigned int r;
417        for(r=0;r<39;++r)
418        {
419            for(unsigned int c=0;c<38;++c)
420            {
421                float h = vertex[r+c*39][2];
422                if (h>maxHeight) maxHeight=h;
423                if (h<minHeight) minHeight=h;
424            }
425        }
426
427        float hieghtScale = radius*0.5f/(maxHeight-minHeight);
428        float hieghtOffset = -(minHeight+maxHeight)*0.5f;
429
430        for(r=0;r<39;++r)
431        {
432            for(unsigned int c=0;c<38;++c)
433            {
434                float h = vertex[r+c*39][2];
435                grid->setHeight(c,r,(h+hieghtOffset)*hieghtScale);
436            }
437        }
438
439        geode->addDrawable(new osg::ShapeDrawable(grid));
440
441        osg::Group* group = new osg::Group;
442        group->addChild(geode);
443
444        return group;
445
446    }
447
448    osg::Node* createMovingModel(const osg::Vec3& center, float radius)
449    {
450        float animationLength = 10.0f;
451
452        osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
453
454        osg::Group* model = new osg::Group;
455
456        osg::Node* cessna = osgDB::readNodeFile("cessna.osgt");
457        if (cessna)
458        {
459            const osg::BoundingSphere& bs = cessna->getBound();
460
461            float size = radius/bs.radius()*0.3f;
462            osg::MatrixTransform* positioned = new osg::MatrixTransform;
463            positioned->setDataVariance(osg::Object::STATIC);
464            positioned->setMatrix(osg::Matrix::translate(-bs.center())*
465                                  osg::Matrix::scale(size,size,size)*
466                                  osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,2.0f));
467
468            positioned->addChild(cessna);
469
470            osg::MatrixTransform* xform = new osg::MatrixTransform;
471            xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
472            xform->addChild(positioned);
473
474            model->addChild(xform);
475        }
476
477        return model;
478    }
479
480    osg::Node* createModel(osg::ArgumentParser& /*arguments*/)
481    {
482        osg::Vec3 center(0.0f,0.0f,0.0f);
483        float radius = 100.0f;
484        osg::Vec3 lightPosition(center+osg::Vec3(0.0f,0.0f,radius));
485
486        // the shadower model
487        osg::Node* shadower = createMovingModel(center,radius*0.5f);
488        shadower->setNodeMask(CastsShadowTraversalMask);
489
490        // the shadowed model
491        osg::Node* shadowed = createBase(center-osg::Vec3(0.0f,0.0f,radius*0.25),radius);
492        shadowed->setNodeMask(ReceivesShadowTraversalMask);
493
494        osg::Group* group = new osg::Group;
495
496        group->addChild(shadowed);
497        group->addChild(shadower);
498
499        return group;
500    }
501}
502
503namespace ModelThree
504{
505    osg::Group* createModel(osg::ArgumentParser& arguments)
506    {
507        osg::Group* scene = new osg::Group;
508
509        osg::ref_ptr<osg::Geode> geode_1 = new osg::Geode;
510        scene->addChild(geode_1.get());
511
512        osg::ref_ptr<osg::Geode> geode_2 = new osg::Geode;
513        osg::ref_ptr<osg::MatrixTransform> transform_2 = new osg::MatrixTransform;
514        transform_2->addChild(geode_2.get());
515//        transform_2->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(45.0f)));
516        scene->addChild(transform_2.get());
517
518        osg::ref_ptr<osg::Geode> geode_3 = new osg::Geode;
519        osg::ref_ptr<osg::MatrixTransform> transform_3 = new osg::MatrixTransform;
520        transform_3->addChild(geode_3.get());
521//        transform_3->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(-22.5f)));
522        scene->addChild(transform_3.get());
523
524        const float radius = 0.8f;
525        const float height = 1.0f;
526        osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
527        hints->setDetailRatio(2.0f);
528        osg::ref_ptr<osg::ShapeDrawable> shape;
529        shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, -2.0f), 10, 10.0f, 0.1f), hints.get());
530        shape->setColor(osg::Vec4(0.5f, 0.5f, 0.7f, 1.0f));
531        shape->setName("base box");
532        geode_1->addDrawable(shape.get());
533
534        shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), radius * 2), hints.get());
535        shape->setColor(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f));
536        shape->setName("center sphere");
537        geode_1->addDrawable(shape.get());
538
539        shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(-3.0f, 0.0f, 0.0f), radius), hints.get());
540        shape->setColor(osg::Vec4(0.6f, 0.8f, 0.8f, 1.0f));
541        shape->setName("cyan sphere");
542        geode_2->addDrawable(shape.get());
543
544        shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(3.0f, 0.0f, 0.0f), 2 * radius), hints.get());
545        shape->setColor(osg::Vec4(0.4f, 0.9f, 0.3f, 1.0f));
546        shape->setName("green box");
547        geode_2->addDrawable(shape.get());
548
549        shape = new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0.0f, -3.0f, 0.0f), radius, height), hints.get());
550        shape->setColor(osg::Vec4(0.2f, 0.5f, 0.7f, 1.0f));
551        shape->setName("blue cone");
552        geode_2->addDrawable(shape.get());
553
554        shape = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.0f, 3.0f, 0.0f), radius, height), hints.get());
555        shape->setColor(osg::Vec4(1.0f, 0.3f, 0.3f, 1.0f));
556        shape->setName("red cyclinder");
557        geode_2->addDrawable(shape.get());
558
559        shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 3.0f), 2.0f, 2.0f, 0.1f), hints.get());
560        shape->setColor(osg::Vec4(0.8f, 0.8f, 0.4f, 1.0f));
561        shape->setName("rotating box");
562        geode_3->addDrawable(shape.get());
563
564        // material
565        osg::ref_ptr<osg::Material> matirial = new osg::Material;
566        matirial->setColorMode(osg::Material::DIFFUSE);
567        matirial->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
568        matirial->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1));
569        matirial->setShininess(osg::Material::FRONT_AND_BACK, 64.0f);
570        scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), osg::StateAttribute::ON);
571
572        bool withBaseTexture = true;
573        while(arguments.read("--with-base-texture")) { withBaseTexture = true; }
574        while(arguments.read("--no-base-texture")) { withBaseTexture = false; }
575
576        if (withBaseTexture)
577        {
578            scene->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")), osg::StateAttribute::ON);
579        }
580
581        return scene;
582    }
583
584}
585
586
587namespace ModelFive
588{
589    struct UseVBOVisitor : public osg::NodeVisitor
590    {
591        UseVBOVisitor():
592            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
593
594        virtual void apply(osg::Geode& geode)
595        {
596            for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
597            {
598                osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(geode.getDrawable(i));
599                if (geometry)
600                {
601                    geometry->setUseVertexBufferObjects(true);
602                }
603            }
604        }
605    };
606
607
608    osg::AnimationPathCallback* createAnimationPathCallback( float radius, float time )
609    {
610        osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;
611        path->setLoopMode( osg::AnimationPath::LOOP );
612
613        unsigned int numSamples = 32;
614        float delta_yaw = 2.0f * osg::PI/((float)numSamples - 1.0f);
615        float delta_time = time / (float)numSamples;
616        for ( unsigned int i=0; i<numSamples; ++i )
617        {
618            float yaw = delta_yaw * (float)i;
619            osg::Vec3 pos( sinf(yaw)*radius, cosf(yaw)*radius, 0.0f );
620            osg::Quat rot( -yaw, osg::Z_AXIS );
621            path->insert( delta_time * (float)i, osg::AnimationPath::ControlPoint(pos, rot) );
622        }
623
624        osg::ref_ptr<osg::AnimationPathCallback> apcb = new osg::AnimationPathCallback;
625        apcb->setAnimationPath( path.get() );
626        return apcb.release();
627    }
628
629    osg::Group* createModel(osg::ArgumentParser& arguments)
630    {
631        // Set the ground (only receives shadow)
632        osg::ref_ptr<osg::MatrixTransform> groundNode = new osg::MatrixTransform;
633        groundNode->addChild( osgDB::readNodeFile("lz.osg") );
634        groundNode->setMatrix( osg::Matrix::translate(200.0f, 200.0f,-200.0f) );
635        groundNode->setNodeMask( ReceivesShadowTraversalMask );
636
637        // Set the cessna (only casts shadow)
638        osg::ref_ptr<osg::MatrixTransform> cessnaNode = new osg::MatrixTransform;
639        cessnaNode->addChild( osgDB::readNodeFile("cessna.osg.0,0,90.rot") );
640        cessnaNode->addUpdateCallback( createAnimationPathCallback(50.0f, 6.0f) );
641        cessnaNode->setNodeMask( CastsShadowTraversalMask );
642
643        // cessna is really poorly optimized so fix this by optimizing the mesh and use VBO's.
644        osgUtil::Optimizer optimizer;
645        optimizer.optimize(cessnaNode.get(), osgUtil::Optimizer::INDEX_MESH |
646                                             osgUtil::Optimizer::VERTEX_POSTTRANSFORM |
647                                             osgUtil::Optimizer::VERTEX_PRETRANSFORM);
648
649        UseVBOVisitor useVBOVisitor;
650        cessnaNode->accept(useVBOVisitor);
651
652
653        osg::ref_ptr<osg::Group> shadowRoot = new osg::Group;
654        shadowRoot->addChild( groundNode.get() );
655        for ( unsigned int i=0; i<10; ++i )
656        {
657            for ( unsigned int j=0; j<10; ++j )
658            {
659                osg::ref_ptr<osg::MatrixTransform> cessnaInstance = new osg::MatrixTransform;
660                cessnaInstance->setMatrix( osg::Matrix::translate((float)i*50.0f-25.0f, (float)j*50.0f-25.0f, 0.0f) );
661                cessnaInstance->addChild( cessnaNode.get() );
662                shadowRoot->addChild( cessnaInstance.get() );
663            }
664        }
665
666
667        return shadowRoot.release();
668    }
669}
670
671osg::Node* createTestModel(osg::ArgumentParser& arguments)
672{
673    if (arguments.read("-1"))
674    {
675        return ModelOne::createModel(arguments);
676    }
677    else if (arguments.read("-2"))
678    {
679        return ModelTwo::createModel(arguments);
680    }
681    else if (arguments.read("-4"))
682    {
683        return ModelFour::createModel(arguments);
684    }
685    else if (arguments.read("-5"))
686    {
687        return ModelFive::createModel(arguments);
688    }
689    else /*if (arguments.read("-3"))*/
690    {
691        return ModelThree::createModel(arguments);
692    }
693
694}
695
696
697int main(int argc, char** argv)
698{
699    // use an ArgumentParser object to manage the program arguments.
700    osg::ArgumentParser arguments(&argc, argv);
701
702    // set up the usage document, in case we need to print out how to use this program.
703    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class");
704    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
705    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
706    arguments.getApplicationUsage()->addCommandLineOption("--positionalLight", "Use a positional light.");
707    arguments.getApplicationUsage()->addCommandLineOption("--directionalLight", "Use a direction light.");
708    arguments.getApplicationUsage()->addCommandLineOption("--noUpdate", "Disable the updating the of light source.");
709
710    arguments.getApplicationUsage()->addCommandLineOption("--castsShadowMask", "Override default castsShadowMask (default - 0x2)");
711    arguments.getApplicationUsage()->addCommandLineOption("--receivesShadowMask", "Override default receivesShadowMask (default - 0x1)");
712
713    arguments.getApplicationUsage()->addCommandLineOption("--base", "Add a base geometry to test shadows.");
714    arguments.getApplicationUsage()->addCommandLineOption("--sv", "Select ShadowVolume implementation.");
715    arguments.getApplicationUsage()->addCommandLineOption("--ssm", "Select SoftShadowMap implementation.");
716    arguments.getApplicationUsage()->addCommandLineOption("--sm", "Select ShadowMap implementation.");
717
718    arguments.getApplicationUsage()->addCommandLineOption("--pssm", "Select ParallelSplitShadowMap implementation.");//ADEGLI
719    arguments.getApplicationUsage()->addCommandLineOption("--mapcount", "ParallelSplitShadowMap texture count.");//ADEGLI
720    arguments.getApplicationUsage()->addCommandLineOption("--mapres", "ParallelSplitShadowMap texture resolution.");//ADEGLI
721    arguments.getApplicationUsage()->addCommandLineOption("--debug-color", "ParallelSplitShadowMap display debugging color (only the first 3 maps are color r=0,g=1,b=2.");//ADEGLI
722    arguments.getApplicationUsage()->addCommandLineOption("--minNearSplit", "ParallelSplitShadowMap shadow map near offset.");//ADEGLI
723    arguments.getApplicationUsage()->addCommandLineOption("--maxFarDist", "ParallelSplitShadowMap max far distance to shadow.");//ADEGLI
724    arguments.getApplicationUsage()->addCommandLineOption("--moveVCamFactor", "ParallelSplitShadowMap move the virtual frustum behind the real camera, (also back ground object can cast shadow).");//ADEGLI
725    arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Factor", "ParallelSplitShadowMap set PolygonOffset factor.");//ADEGLI
726    arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Unit", "ParallelSplitShadowMap set PolygonOffset unit.");//ADEGLI
727
728    arguments.getApplicationUsage()->addCommandLineOption("--lispsm", "Select LightSpacePerspectiveShadowMap implementation.");
729    arguments.getApplicationUsage()->addCommandLineOption("--msm", "Select MinimalShadowMap implementation.");
730    arguments.getApplicationUsage()->addCommandLineOption("--ViewBounds", "MSM, LiSPSM optimize shadow for view frustum (weakest option)");
731    arguments.getApplicationUsage()->addCommandLineOption("--CullBounds", "MSM, LiSPSM optimize shadow for bounds of culled objects in view frustum (better option).");
732    arguments.getApplicationUsage()->addCommandLineOption("--DrawBounds", "MSM, LiSPSM optimize shadow for bounds of predrawn pixels in view frustum (best & default).");
733    arguments.getApplicationUsage()->addCommandLineOption("--mapres", "MSM, LiSPSM & texture resolution.");
734    arguments.getApplicationUsage()->addCommandLineOption("--maxFarDist", "MSM, LiSPSM max far distance to shadow.");
735    arguments.getApplicationUsage()->addCommandLineOption("--moveVCamFactor", "MSM, LiSPSM move the virtual frustum behind the real camera, (also back ground object can cast shadow).");
736    arguments.getApplicationUsage()->addCommandLineOption("--minLightMargin", "MSM, LiSPSM the same as --moveVCamFactor.");
737
738    arguments.getApplicationUsage()->addCommandLineOption("-1", "Use test model one.");
739    arguments.getApplicationUsage()->addCommandLineOption("-2", "Use test model two.");
740    arguments.getApplicationUsage()->addCommandLineOption("-3", "Use test model three (default).");
741    arguments.getApplicationUsage()->addCommandLineOption("-4", "Use test model four - island scene.");
742    arguments.getApplicationUsage()->addCommandLineOption("--two-sided", "Use two-sided stencil extension for shadow volumes.");
743    arguments.getApplicationUsage()->addCommandLineOption("--two-pass", "Use two-pass stencil for shadow volumes.");
744
745    // construct the viewer.
746    osgViewer::Viewer viewer(arguments);
747
748    // if user request help write it out to cout.
749    if (arguments.read("-h") || arguments.read("--help"))
750    {
751        arguments.getApplicationUsage()->write(std::cout);
752        return 1;
753    }
754
755    double zNear=1.0, zMid=10.0, zFar=1000.0;
756    if (arguments.read("--depth-partition",zNear, zMid, zFar))
757    {
758        // set up depth partitioning
759        osg::ref_ptr<osgViewer::DepthPartitionSettings> dps = new osgViewer::DepthPartitionSettings;
760        dps->_mode = osgViewer::DepthPartitionSettings::FIXED_RANGE;
761        dps->_zNear = zNear;
762        dps->_zMid = zMid;
763        dps->_zFar = zFar;
764        viewer.setUpDepthPartition(dps.get());
765    }
766
767    if (arguments.read("--dp"))
768    {
769        // set up depth partitioning
770        viewer.setUpDepthPartition();
771    }
772
773    float fov = 0.0;
774    while (arguments.read("--fov",fov)) {}
775
776    osg::Vec4 lightpos(0.0,0.0,1,0.0);
777    bool spotlight = false;
778    while (arguments.read("--positionalLight")) { lightpos.set(0.5,0.5,1.5,1.0); }
779    while (arguments.read("--directionalLight")) { lightpos.set(0.0,0.0,1,0.0); }
780    while (arguments.read("--spotLight")) { lightpos.set(0.5,0.5,1.5,1.0); spotlight = true; }
781
782    bool keepLightPos = false;
783    osg::Vec3 spotLookat(0.0,0.0,0.0);
784    while ( arguments.read("--light-pos", lightpos.x(), lightpos.y(), lightpos.z(), lightpos.w())) { keepLightPos = true; }
785    while ( arguments.read("--light-pos", lightpos.x(), lightpos.y(), lightpos.z())) { lightpos.w()=1.0; keepLightPos = true; }
786    while ( arguments.read("--light-dir", lightpos.x(), lightpos.y(), lightpos.z())) { lightpos.w()=0.0; keepLightPos = true; }
787    while ( arguments.read("--spot-lookat", spotLookat.x(), spotLookat.y(), spotLookat.z())) { }
788
789
790    while (arguments.read("--castsShadowMask", CastsShadowTraversalMask ));
791    while (arguments.read("--receivesShadowMask", ReceivesShadowTraversalMask ));
792
793    bool updateLightPosition = true;
794    while (arguments.read("--noUpdate")) updateLightPosition = false;
795
796    // set up the camera manipulators.
797    {
798        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
799
800        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
801        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
802        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
803        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
804
805        std::string pathfile;
806        char keyForAnimationPath = '5';
807        while (arguments.read("-p",pathfile))
808        {
809            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
810            if (apm || !apm->valid())
811            {
812                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
813                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
814                keyswitchManipulator->selectMatrixManipulator(num);
815                ++keyForAnimationPath;
816            }
817        }
818
819        viewer.setCameraManipulator( keyswitchManipulator.get() );
820    }
821
822    // add the state manipulator
823    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
824
825    // add stats
826    viewer.addEventHandler( new osgViewer::StatsHandler() );
827
828    // add the record camera path handler
829    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
830
831    // add the window size toggle handler
832    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
833
834    // add the threading handler
835    viewer.addEventHandler( new osgViewer::ThreadingHandler() );
836
837    osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;
838
839    osgShadow::ShadowSettings* settings = shadowedScene->getShadowSettings();
840    settings->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
841    settings->setCastsShadowTraversalMask(CastsShadowTraversalMask);
842
843    osg::ref_ptr<osgShadow::MinimalShadowMap> msm = NULL;
844    if (arguments.read("--no-shadows"))
845    {
846        OSG_NOTICE<<"Not using a ShadowTechnique"<<std::endl;
847        shadowedScene->setShadowTechnique(0);
848    }
849    else if (arguments.read("--sv"))
850    {
851        // hint to tell viewer to request stencil buffer when setting up windows
852        osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
853
854        osg::ref_ptr<osgShadow::ShadowVolume> sv = new osgShadow::ShadowVolume;
855        sv->setDynamicShadowVolumes(updateLightPosition);
856        while (arguments.read("--two-sided")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED);
857        while (arguments.read("--two-pass")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_PASS);
858
859        shadowedScene->setShadowTechnique(sv.get());
860    }
861    else if (arguments.read("--st"))
862    {
863        osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture;
864        shadowedScene->setShadowTechnique(st.get());
865    }
866    else if (arguments.read("--stsm"))
867    {
868        osg::ref_ptr<osgShadow::StandardShadowMap> st = new osgShadow::StandardShadowMap;
869        shadowedScene->setShadowTechnique(st.get());
870    }
871    else if (arguments.read("--pssm"))
872    {
873        int mapcount = 3;
874        while (arguments.read("--mapcount", mapcount));
875        osg::ref_ptr<osgShadow::ParallelSplitShadowMap> pssm = new osgShadow::ParallelSplitShadowMap(NULL,mapcount);
876
877        int mapres = 1024;
878        while (arguments.read("--mapres", mapres))
879            pssm->setTextureResolution(mapres);
880
881        while (arguments.read("--debug-color")) { pssm->setDebugColorOn(); }
882
883
884        int minNearSplit=0;
885        while (arguments.read("--minNearSplit", minNearSplit))
886            if ( minNearSplit > 0 ) {
887                pssm->setMinNearDistanceForSplits(minNearSplit);
888                std::cout << "ParallelSplitShadowMap : setMinNearDistanceForSplits(" << minNearSplit <<")" << std::endl;
889            }
890
891        int maxfardist = 0;
892        while (arguments.read("--maxFarDist", maxfardist))
893            if ( maxfardist > 0 ) {
894                pssm->setMaxFarDistance(maxfardist);
895                std::cout << "ParallelSplitShadowMap : setMaxFarDistance(" << maxfardist<<")" << std::endl;
896            }
897
898        int moveVCamFactor = 0;
899        while (arguments.read("--moveVCamFactor", moveVCamFactor))
900            if ( maxfardist > 0 ) {
901                pssm->setMoveVCamBehindRCamFactor(moveVCamFactor);
902                std::cout << "ParallelSplitShadowMap : setMoveVCamBehindRCamFactor(" << moveVCamFactor<<")" << std::endl;
903            }
904
905
906
907        double polyoffsetfactor = pssm->getPolygonOffset().x();
908        double polyoffsetunit   = pssm->getPolygonOffset().y();
909        while (arguments.read("--PolyOffset-Factor", polyoffsetfactor));
910        while (arguments.read("--PolyOffset-Unit", polyoffsetunit));
911        pssm->setPolygonOffset(osg::Vec2(polyoffsetfactor,polyoffsetunit));
912
913        shadowedScene->setShadowTechnique(pssm.get());
914    }
915    else if (arguments.read("--ssm"))
916    {
917        osg::ref_ptr<osgShadow::SoftShadowMap> sm = new osgShadow::SoftShadowMap;
918        shadowedScene->setShadowTechnique(sm.get());
919    }
920    else if( arguments.read("--vdsm") )
921    {
922        while( arguments.read("--debugHUD") ) settings->setDebugDraw( true );
923        if (arguments.read("--persp")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::PERSPECTIVE_SHADOW_MAP);
924        if (arguments.read("--ortho")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::ORTHOGRAPHIC_SHADOW_MAP);
925
926        unsigned int unit=1;
927        if (arguments.read("--unit",unit)) settings->setBaseShadowTextureUnit(unit);
928
929        double n=0.0;
930        if (arguments.read("-n",n)) settings->setMinimumShadowMapNearFarRatio(n);
931
932        unsigned int numShadowMaps;
933        if (arguments.read("--num-sm",numShadowMaps)) settings->setNumShadowMapsPerLight(numShadowMaps);
934
935        if (arguments.read("--parallel-split") || arguments.read("--ps") ) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::PARALLEL_SPLIT);
936        if (arguments.read("--cascaded")) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::CASCADED);
937
938
939        int mapres = 1024;
940        while (arguments.read("--mapres", mapres))
941            settings->setTextureSize(osg::Vec2s(mapres,mapres));
942
943        osg::ref_ptr<osgShadow::ViewDependentShadowMap> vdsm = new osgShadow::ViewDependentShadowMap;
944        shadowedScene->setShadowTechnique(vdsm.get());
945    }
946    else if ( arguments.read("--lispsm") )
947    {
948        if( arguments.read( "--ViewBounds" ) )
949            msm = new osgShadow::LightSpacePerspectiveShadowMapVB;
950        else if( arguments.read( "--CullBounds" ) )
951            msm = new osgShadow::LightSpacePerspectiveShadowMapCB;
952        else // if( arguments.read( "--DrawBounds" ) ) // default
953            msm = new osgShadow::LightSpacePerspectiveShadowMapDB;
954    }
955    else if( arguments.read("--msm") )
956    {
957       if( arguments.read( "--ViewBounds" ) )
958            msm = new osgShadow::MinimalShadowMap;
959       else if( arguments.read( "--CullBounds" ) )
960            msm = new osgShadow::MinimalCullBoundsShadowMap;
961       else // if( arguments.read( "--DrawBounds" ) ) // default
962            msm = new osgShadow::MinimalDrawBoundsShadowMap;
963    }
964    else /* if (arguments.read("--sm")) */
965    {
966        osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
967        shadowedScene->setShadowTechnique(sm.get());
968
969        int mapres = 1024;
970        while (arguments.read("--mapres", mapres))
971            sm->setTextureSize(osg::Vec2s(mapres,mapres));
972    }
973
974    if( msm )// Set common MSM & LISPSM arguments
975    {
976        shadowedScene->setShadowTechnique( msm.get() );
977        while( arguments.read("--debugHUD") ) msm->setDebugDraw( true );
978
979        float minLightMargin = 10.f;
980        float maxFarPlane = 0;
981        unsigned int texSize = 1024;
982        unsigned int baseTexUnit = 0;
983        unsigned int shadowTexUnit = 1;
984
985        while ( arguments.read("--moveVCamFactor", minLightMargin ) );
986        while ( arguments.read("--minLightMargin", minLightMargin ) );
987        while ( arguments.read("--maxFarDist", maxFarPlane ) );
988        while ( arguments.read("--mapres", texSize ));
989        while ( arguments.read("--baseTextureUnit", baseTexUnit) );
990        while ( arguments.read("--shadowTextureUnit", shadowTexUnit) );
991
992        msm->setMinLightMargin( minLightMargin );
993        msm->setMaxFarPlane( maxFarPlane );
994        msm->setTextureSize( osg::Vec2s( texSize, texSize ) );
995        msm->setShadowTextureCoordIndex( shadowTexUnit );
996        msm->setShadowTextureUnit( shadowTexUnit );
997        msm->setBaseTextureCoordIndex( baseTexUnit );
998        msm->setBaseTextureUnit( baseTexUnit );
999    }
1000
1001    OSG_INFO<<"shadowedScene->getShadowTechnique()="<<shadowedScene->getShadowTechnique()<<std::endl;
1002
1003    osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
1004    if (model.valid())
1005    {
1006        model->setNodeMask(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
1007    }
1008    else
1009    {
1010        model = createTestModel(arguments);
1011    }
1012
1013    // get the bounds of the model.
1014    osg::ComputeBoundsVisitor cbbv;
1015    model->accept(cbbv);
1016    osg::BoundingBox bb = cbbv.getBoundingBox();
1017
1018    if (lightpos.w()==1.0 && !keepLightPos)
1019    {
1020        lightpos.x() = bb.xMin()+(bb.xMax()-bb.xMin())*lightpos.x();
1021        lightpos.y() = bb.yMin()+(bb.yMax()-bb.yMin())*lightpos.y();
1022        lightpos.z() = bb.zMin()+(bb.zMax()-bb.zMin())*lightpos.z();
1023    }
1024
1025    if ( arguments.read("--base"))
1026    {
1027
1028        osg::Geode* geode = new osg::Geode;
1029
1030        osg::Vec3 widthVec(bb.radius(), 0.0f, 0.0f);
1031        osg::Vec3 depthVec(0.0f, bb.radius(), 0.0f);
1032        osg::Vec3 centerBase( (bb.xMin()+bb.xMax())*0.5f, (bb.yMin()+bb.yMax())*0.5f, bb.zMin()-bb.radius()*0.1f );
1033
1034        geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*1.5f-depthVec*1.5f,
1035                                                             widthVec*3.0f, depthVec*3.0f) );
1036
1037        geode->setNodeMask(shadowedScene->getReceivesShadowTraversalMask());
1038
1039        geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")));
1040
1041        shadowedScene->addChild(geode);
1042    }
1043
1044    osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
1045    ls->getLight()->setPosition(lightpos);
1046
1047    if (spotlight)
1048    {
1049        osg::Vec3 center = spotLookat;
1050        osg::Vec3 lightdir = center - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z());
1051        lightdir.normalize();
1052        ls->getLight()->setDirection(lightdir);
1053        ls->getLight()->setSpotCutoff(25.0f);
1054
1055        //set the LightSource, only for checking, there is only 1 light in the scene
1056        osgShadow::ShadowMap* shadowMap = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
1057        if( shadowMap ) shadowMap->setLight(ls.get());
1058    }
1059
1060    if ( arguments.read("--coloured-light"))
1061    {
1062        ls->getLight()->setAmbient(osg::Vec4(1.0,0.0,0.0,1.0));
1063        ls->getLight()->setDiffuse(osg::Vec4(0.0,1.0,0.0,1.0));
1064    }
1065    else
1066    {
1067        ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
1068        ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
1069    }
1070
1071    shadowedScene->addChild(model.get());
1072    shadowedScene->addChild(ls.get());
1073
1074    viewer.setSceneData(shadowedScene.get());
1075
1076    osg::ref_ptr< DumpShadowVolumesHandler > dumpShadowVolumes = new DumpShadowVolumesHandler;
1077
1078    viewer.addEventHandler(new ChangeFOVHandler(viewer.getCamera()));
1079    viewer.addEventHandler( dumpShadowVolumes.get() );
1080
1081    // create the windows and run the threads.
1082    viewer.realize();
1083
1084    if (fov!=0.0)
1085    {
1086        double fovy, aspectRatio, zNear, zFar;
1087        viewer.getCamera()->getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
1088
1089        std::cout << "Setting FOV to " << fov << std::endl;
1090        viewer.getCamera()->getProjectionMatrix().makePerspective(fov, aspectRatio, zNear, zFar);
1091    }
1092
1093    // it is done after viewer.realize() so that the windows are already initialized
1094    if ( arguments.read("--debugHUD"))
1095    {
1096        osgViewer::Viewer::Windows windows;
1097        viewer.getWindows(windows);
1098
1099        if (windows.empty()) return 1;
1100
1101        osgShadow::ShadowMap* sm = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
1102        if( sm ) {
1103            osg::ref_ptr<osg::Camera> hudCamera = sm->makeDebugHUD();
1104
1105            // set up cameras to rendering on the first window available.
1106            hudCamera->setGraphicsContext(windows[0]);
1107            hudCamera->setViewport(0,0,windows[0]->getTraits()->width, windows[0]->getTraits()->height);
1108
1109            viewer.addSlave(hudCamera.get(), false);
1110        }
1111    }
1112
1113    osg::ref_ptr<LightAnimationHandler> lightAnimationHandler = updateLightPosition ? new LightAnimationHandler : 0;
1114    if (lightAnimationHandler) viewer.addEventHandler(lightAnimationHandler.get());
1115
1116
1117    // osgDB::writeNodeFile(*group,"test.osgt");
1118
1119    while (!viewer.done())
1120    {
1121        {
1122            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );
1123
1124            if( msm ) {
1125
1126                // If scene decorated by CoordinateSystemNode try to find localToWorld
1127                // and set modellingSpaceToWorld matrix to optimize scene bounds computation
1128
1129                osg::NodePath np = viewer.getCoordinateSystemNodePath();
1130                if( !np.empty() ) {
1131                    osg::CoordinateSystemNode * csn =
1132                        dynamic_cast<osg::CoordinateSystemNode *>( np.back() );
1133
1134                    if( csn ) {
1135                        osg::Vec3d pos =
1136                            viewer.getCameraManipulator()->getMatrix().getTrans();
1137
1138                        msm->setModellingSpaceToWorldTransform
1139                            ( csn->computeLocalCoordinateFrame( pos ) );
1140                    }
1141                }
1142            }
1143        }
1144
1145        if (lightAnimationHandler.valid() && lightAnimationHandler ->getAnimating())
1146        {
1147            float t = viewer.getFrameStamp()->getSimulationTime();
1148
1149            if (lightpos.w()==1.0)
1150            {
1151                lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius()*3.0f  ,1.0f);
1152            }
1153            else
1154            {
1155                lightpos.set(sinf(t),cosf(t),1.0f,0.0f);
1156            }
1157            ls->getLight()->setPosition(lightpos);
1158
1159            osg::Vec3f lightDir(-lightpos.x(),-lightpos.y(),-lightpos.z());
1160            if(spotlight)
1161                lightDir =  osg::Vec3(bb.center().x()+sinf(t)*bb.radius()/2.0, bb.center().y() + cosf(t)*bb.radius()/2.0, bb.center().z())
1162                - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z()) ;
1163            lightDir.normalize();
1164            ls->getLight()->setDirection(lightDir);
1165        }
1166
1167        if( dumpShadowVolumes->get() )
1168        {
1169            dumpShadowVolumes->set( false );
1170
1171            static int dumpFileNo = 0;
1172            dumpFileNo ++;
1173            char filename[256];
1174            std::sprintf( filename, "shadowDump%d.osgt", dumpFileNo );
1175
1176            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );
1177
1178            if( msm ) msm->setDebugDump( filename );
1179        }
1180
1181        viewer.frame();
1182    }
1183
1184    return 0;
1185}
Note: See TracBrowser for help on using the browser.