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

Revision 13108, 46.3 kB (checked in by robert, 10 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, 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    arguments.getApplicationUsage()->addCommandLineOption("--near-far-mode","COMPUTE_NEAR_USING_PRIMITIVES, COMPUTE_NEAR_FAR_USING_PRIMITIVES, COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES, DO_NOT_COMPUTE_NEAR_FAR");
745
746    // construct the viewer.
747    osgViewer::Viewer viewer(arguments);
748
749    // if user request help write it out to cout.
750    if (arguments.read("-h") || arguments.read("--help"))
751    {
752        arguments.getApplicationUsage()->write(std::cout);
753        return 1;
754    }
755
756    double zNear=1.0, zMid=10.0, zFar=1000.0;
757    if (arguments.read("--depth-partition",zNear, zMid, zFar))
758    {
759        // set up depth partitioning
760        osg::ref_ptr<osgViewer::DepthPartitionSettings> dps = new osgViewer::DepthPartitionSettings;
761        dps->_mode = osgViewer::DepthPartitionSettings::FIXED_RANGE;
762        dps->_zNear = zNear;
763        dps->_zMid = zMid;
764        dps->_zFar = zFar;
765        viewer.setUpDepthPartition(dps.get());
766    }
767
768    if (arguments.read("--dp"))
769    {
770        // set up depth partitioning
771        viewer.setUpDepthPartition();
772    }
773
774    float fov = 0.0;
775    while (arguments.read("--fov",fov)) {}
776
777    osg::Vec4 lightpos(0.0,0.0,1,0.0);
778    bool spotlight = false;
779    while (arguments.read("--positionalLight")) { lightpos.set(0.5,0.5,1.5,1.0); }
780    while (arguments.read("--directionalLight")) { lightpos.set(0.0,0.0,1,0.0); }
781    while (arguments.read("--spotLight")) { lightpos.set(0.5,0.5,1.5,1.0); spotlight = true; }
782
783    bool keepLightPos = false;
784    osg::Vec3 spotLookat(0.0,0.0,0.0);
785    while ( arguments.read("--light-pos", lightpos.x(), lightpos.y(), lightpos.z(), lightpos.w())) { keepLightPos = true; }
786    while ( arguments.read("--light-pos", lightpos.x(), lightpos.y(), lightpos.z())) { lightpos.w()=1.0; keepLightPos = true; }
787    while ( arguments.read("--light-dir", lightpos.x(), lightpos.y(), lightpos.z())) { lightpos.w()=0.0; keepLightPos = true; }
788    while ( arguments.read("--spot-lookat", spotLookat.x(), spotLookat.y(), spotLookat.z())) { }
789
790
791    while (arguments.read("--castsShadowMask", CastsShadowTraversalMask ));
792    while (arguments.read("--receivesShadowMask", ReceivesShadowTraversalMask ));
793
794    bool updateLightPosition = true;
795    while (arguments.read("--noUpdate")) updateLightPosition = false;
796
797    // set up the camera manipulators.
798    {
799        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
800
801        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
802        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
803        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
804        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
805
806        std::string pathfile;
807        char keyForAnimationPath = '5';
808        while (arguments.read("-p",pathfile))
809        {
810            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
811            if (apm || !apm->valid())
812            {
813                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
814                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
815                keyswitchManipulator->selectMatrixManipulator(num);
816                ++keyForAnimationPath;
817            }
818        }
819
820        viewer.setCameraManipulator( keyswitchManipulator.get() );
821    }
822
823    // add the state manipulator
824    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
825
826    // add stats
827    viewer.addEventHandler( new osgViewer::StatsHandler() );
828
829    // add the record camera path handler
830    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
831
832    // add the window size toggle handler
833    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
834
835    // add the threading handler
836    viewer.addEventHandler( new osgViewer::ThreadingHandler() );
837
838    osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;
839
840    osgShadow::ShadowSettings* settings = shadowedScene->getShadowSettings();
841    settings->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
842    settings->setCastsShadowTraversalMask(CastsShadowTraversalMask);
843
844    std::string nearFarMode("");
845    if (arguments.read("--near-far-mode",nearFarMode))
846    {
847        if (nearFarMode=="COMPUTE_NEAR_USING_PRIMITIVES")                settings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_USING_PRIMITIVES);
848        else if (nearFarMode=="COMPUTE_NEAR_FAR_USING_PRIMITIVES")       settings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
849        else if (nearFarMode=="DO_NOT_COMPUTE_NEAR_FAR")                 settings->setComputeNearFarModeOverride(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
850        else if (nearFarMode=="COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES") settings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
851
852        OSG_NOTICE<<"ComputeNearFarModeOverride set to ";
853        switch(settings->getComputeNearFarModeOverride())
854        {
855            case(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES): OSG_NOTICE<<"COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES"; break;
856            case(osg::CullSettings::COMPUTE_NEAR_USING_PRIMITIVES): OSG_NOTICE<<"COMPUTE_NEAR_USING_PRIMITIVES"; break;
857            case(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES): OSG_NOTICE<<"COMPUTE_NEAR_FAR_USING_PRIMITIVES"; break;
858            case(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR): OSG_NOTICE<<"DO_NOT_COMPUTE_NEAR_FAR"; break;
859        }
860        OSG_NOTICE<<std::endl;
861    }
862   
863    osg::ref_ptr<osgShadow::MinimalShadowMap> msm = NULL;
864    if (arguments.read("--no-shadows"))
865    {
866        OSG_NOTICE<<"Not using a ShadowTechnique"<<std::endl;
867        shadowedScene->setShadowTechnique(0);
868    }
869    else if (arguments.read("--sv"))
870    {
871        // hint to tell viewer to request stencil buffer when setting up windows
872        osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
873
874        osg::ref_ptr<osgShadow::ShadowVolume> sv = new osgShadow::ShadowVolume;
875        sv->setDynamicShadowVolumes(updateLightPosition);
876        while (arguments.read("--two-sided")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED);
877        while (arguments.read("--two-pass")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_PASS);
878
879        shadowedScene->setShadowTechnique(sv.get());
880    }
881    else if (arguments.read("--st"))
882    {
883        osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture;
884        shadowedScene->setShadowTechnique(st.get());
885    }
886    else if (arguments.read("--stsm"))
887    {
888        osg::ref_ptr<osgShadow::StandardShadowMap> st = new osgShadow::StandardShadowMap;
889        shadowedScene->setShadowTechnique(st.get());
890    }
891    else if (arguments.read("--pssm"))
892    {
893        int mapcount = 3;
894        while (arguments.read("--mapcount", mapcount));
895        osg::ref_ptr<osgShadow::ParallelSplitShadowMap> pssm = new osgShadow::ParallelSplitShadowMap(NULL,mapcount);
896
897        int mapres = 1024;
898        while (arguments.read("--mapres", mapres))
899            pssm->setTextureResolution(mapres);
900
901        while (arguments.read("--debug-color")) { pssm->setDebugColorOn(); }
902
903
904        int minNearSplit=0;
905        while (arguments.read("--minNearSplit", minNearSplit))
906            if ( minNearSplit > 0 ) {
907                pssm->setMinNearDistanceForSplits(minNearSplit);
908                std::cout << "ParallelSplitShadowMap : setMinNearDistanceForSplits(" << minNearSplit <<")" << std::endl;
909            }
910
911        int maxfardist = 0;
912        while (arguments.read("--maxFarDist", maxfardist))
913            if ( maxfardist > 0 ) {
914                pssm->setMaxFarDistance(maxfardist);
915                std::cout << "ParallelSplitShadowMap : setMaxFarDistance(" << maxfardist<<")" << std::endl;
916            }
917
918        int moveVCamFactor = 0;
919        while (arguments.read("--moveVCamFactor", moveVCamFactor))
920            if ( maxfardist > 0 ) {
921                pssm->setMoveVCamBehindRCamFactor(moveVCamFactor);
922                std::cout << "ParallelSplitShadowMap : setMoveVCamBehindRCamFactor(" << moveVCamFactor<<")" << std::endl;
923            }
924
925
926
927        double polyoffsetfactor = pssm->getPolygonOffset().x();
928        double polyoffsetunit   = pssm->getPolygonOffset().y();
929        while (arguments.read("--PolyOffset-Factor", polyoffsetfactor));
930        while (arguments.read("--PolyOffset-Unit", polyoffsetunit));
931        pssm->setPolygonOffset(osg::Vec2(polyoffsetfactor,polyoffsetunit));
932
933        shadowedScene->setShadowTechnique(pssm.get());
934    }
935    else if (arguments.read("--ssm"))
936    {
937        osg::ref_ptr<osgShadow::SoftShadowMap> sm = new osgShadow::SoftShadowMap;
938        shadowedScene->setShadowTechnique(sm.get());
939    }
940    else if( arguments.read("--vdsm") )
941    {
942        while( arguments.read("--debugHUD") ) settings->setDebugDraw( true );
943        if (arguments.read("--persp")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::PERSPECTIVE_SHADOW_MAP);
944        if (arguments.read("--ortho")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::ORTHOGRAPHIC_SHADOW_MAP);
945
946        unsigned int unit=1;
947        if (arguments.read("--unit",unit)) settings->setBaseShadowTextureUnit(unit);
948
949        double n=0.0;
950        if (arguments.read("-n",n)) settings->setMinimumShadowMapNearFarRatio(n);
951
952        unsigned int numShadowMaps;
953        if (arguments.read("--num-sm",numShadowMaps)) settings->setNumShadowMapsPerLight(numShadowMaps);
954
955        if (arguments.read("--parallel-split") || arguments.read("--ps") ) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::PARALLEL_SPLIT);
956        if (arguments.read("--cascaded")) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::CASCADED);
957
958
959        int mapres = 1024;
960        while (arguments.read("--mapres", mapres))
961            settings->setTextureSize(osg::Vec2s(mapres,mapres));
962
963        osg::ref_ptr<osgShadow::ViewDependentShadowMap> vdsm = new osgShadow::ViewDependentShadowMap;
964        shadowedScene->setShadowTechnique(vdsm.get());
965    }
966    else if ( arguments.read("--lispsm") )
967    {
968        if( arguments.read( "--ViewBounds" ) )
969            msm = new osgShadow::LightSpacePerspectiveShadowMapVB;
970        else if( arguments.read( "--CullBounds" ) )
971            msm = new osgShadow::LightSpacePerspectiveShadowMapCB;
972        else // if( arguments.read( "--DrawBounds" ) ) // default
973            msm = new osgShadow::LightSpacePerspectiveShadowMapDB;
974    }
975    else if( arguments.read("--msm") )
976    {
977       if( arguments.read( "--ViewBounds" ) )
978            msm = new osgShadow::MinimalShadowMap;
979       else if( arguments.read( "--CullBounds" ) )
980            msm = new osgShadow::MinimalCullBoundsShadowMap;
981       else // if( arguments.read( "--DrawBounds" ) ) // default
982            msm = new osgShadow::MinimalDrawBoundsShadowMap;
983    }
984    else /* if (arguments.read("--sm")) */
985    {
986        osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
987        shadowedScene->setShadowTechnique(sm.get());
988
989        int mapres = 1024;
990        while (arguments.read("--mapres", mapres))
991            sm->setTextureSize(osg::Vec2s(mapres,mapres));
992    }
993
994    if( msm )// Set common MSM & LISPSM arguments
995    {
996        shadowedScene->setShadowTechnique( msm.get() );
997        while( arguments.read("--debugHUD") ) msm->setDebugDraw( true );
998
999        float minLightMargin = 10.f;
1000        float maxFarPlane = 0;
1001        unsigned int texSize = 1024;
1002        unsigned int baseTexUnit = 0;
1003        unsigned int shadowTexUnit = 1;
1004
1005        while ( arguments.read("--moveVCamFactor", minLightMargin ) );
1006        while ( arguments.read("--minLightMargin", minLightMargin ) );
1007        while ( arguments.read("--maxFarDist", maxFarPlane ) );
1008        while ( arguments.read("--mapres", texSize ));
1009        while ( arguments.read("--baseTextureUnit", baseTexUnit) );
1010        while ( arguments.read("--shadowTextureUnit", shadowTexUnit) );
1011
1012        msm->setMinLightMargin( minLightMargin );
1013        msm->setMaxFarPlane( maxFarPlane );
1014        msm->setTextureSize( osg::Vec2s( texSize, texSize ) );
1015        msm->setShadowTextureCoordIndex( shadowTexUnit );
1016        msm->setShadowTextureUnit( shadowTexUnit );
1017        msm->setBaseTextureCoordIndex( baseTexUnit );
1018        msm->setBaseTextureUnit( baseTexUnit );
1019    }
1020
1021    OSG_INFO<<"shadowedScene->getShadowTechnique()="<<shadowedScene->getShadowTechnique()<<std::endl;
1022
1023    osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
1024    if (model.valid())
1025    {
1026        model->setNodeMask(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
1027    }
1028    else
1029    {
1030        model = createTestModel(arguments);
1031    }
1032
1033    // get the bounds of the model.
1034    osg::ComputeBoundsVisitor cbbv;
1035    model->accept(cbbv);
1036    osg::BoundingBox bb = cbbv.getBoundingBox();
1037
1038    if (lightpos.w()==1.0 && !keepLightPos)
1039    {
1040        lightpos.x() = bb.xMin()+(bb.xMax()-bb.xMin())*lightpos.x();
1041        lightpos.y() = bb.yMin()+(bb.yMax()-bb.yMin())*lightpos.y();
1042        lightpos.z() = bb.zMin()+(bb.zMax()-bb.zMin())*lightpos.z();
1043    }
1044
1045    if ( arguments.read("--base"))
1046    {
1047
1048        osg::Geode* geode = new osg::Geode;
1049
1050        osg::Vec3 widthVec(bb.radius(), 0.0f, 0.0f);
1051        osg::Vec3 depthVec(0.0f, bb.radius(), 0.0f);
1052        osg::Vec3 centerBase( (bb.xMin()+bb.xMax())*0.5f, (bb.yMin()+bb.yMax())*0.5f, bb.zMin()-bb.radius()*0.1f );
1053
1054        geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*1.5f-depthVec*1.5f,
1055                                                             widthVec*3.0f, depthVec*3.0f) );
1056
1057        geode->setNodeMask(shadowedScene->getReceivesShadowTraversalMask());
1058
1059        geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")));
1060
1061        shadowedScene->addChild(geode);
1062    }
1063
1064    osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
1065    ls->getLight()->setPosition(lightpos);
1066
1067    if (spotlight)
1068    {
1069        osg::Vec3 center = spotLookat;
1070        osg::Vec3 lightdir = center - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z());
1071        lightdir.normalize();
1072        ls->getLight()->setDirection(lightdir);
1073        ls->getLight()->setSpotCutoff(25.0f);
1074
1075        //set the LightSource, only for checking, there is only 1 light in the scene
1076        osgShadow::ShadowMap* shadowMap = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
1077        if( shadowMap ) shadowMap->setLight(ls.get());
1078    }
1079
1080    if ( arguments.read("--coloured-light"))
1081    {
1082        ls->getLight()->setAmbient(osg::Vec4(1.0,0.0,0.0,1.0));
1083        ls->getLight()->setDiffuse(osg::Vec4(0.0,1.0,0.0,1.0));
1084    }
1085    else
1086    {
1087        ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
1088        ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
1089    }
1090
1091    shadowedScene->addChild(model.get());
1092    shadowedScene->addChild(ls.get());
1093
1094    viewer.setSceneData(shadowedScene.get());
1095
1096    osg::ref_ptr< DumpShadowVolumesHandler > dumpShadowVolumes = new DumpShadowVolumesHandler;
1097
1098    viewer.addEventHandler(new ChangeFOVHandler(viewer.getCamera()));
1099    viewer.addEventHandler( dumpShadowVolumes.get() );
1100
1101    // create the windows and run the threads.
1102    viewer.realize();
1103
1104    if (fov!=0.0)
1105    {
1106        double fovy, aspectRatio, zNear, zFar;
1107        viewer.getCamera()->getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
1108
1109        std::cout << "Setting FOV to " << fov << std::endl;
1110        viewer.getCamera()->getProjectionMatrix().makePerspective(fov, aspectRatio, zNear, zFar);
1111    }
1112
1113    // it is done after viewer.realize() so that the windows are already initialized
1114    if ( arguments.read("--debugHUD"))
1115    {
1116        osgViewer::Viewer::Windows windows;
1117        viewer.getWindows(windows);
1118
1119        if (windows.empty()) return 1;
1120
1121        osgShadow::ShadowMap* sm = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
1122        if( sm ) {
1123            osg::ref_ptr<osg::Camera> hudCamera = sm->makeDebugHUD();
1124
1125            // set up cameras to rendering on the first window available.
1126            hudCamera->setGraphicsContext(windows[0]);
1127            hudCamera->setViewport(0,0,windows[0]->getTraits()->width, windows[0]->getTraits()->height);
1128
1129            viewer.addSlave(hudCamera.get(), false);
1130        }
1131    }
1132
1133    osg::ref_ptr<LightAnimationHandler> lightAnimationHandler = updateLightPosition ? new LightAnimationHandler : 0;
1134    if (lightAnimationHandler) viewer.addEventHandler(lightAnimationHandler.get());
1135
1136
1137    // osgDB::writeNodeFile(*group,"test.osgt");
1138
1139    while (!viewer.done())
1140    {
1141        {
1142            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );
1143
1144            if( msm ) {
1145
1146                // If scene decorated by CoordinateSystemNode try to find localToWorld
1147                // and set modellingSpaceToWorld matrix to optimize scene bounds computation
1148
1149                osg::NodePath np = viewer.getCoordinateSystemNodePath();
1150                if( !np.empty() ) {
1151                    osg::CoordinateSystemNode * csn =
1152                        dynamic_cast<osg::CoordinateSystemNode *>( np.back() );
1153
1154                    if( csn ) {
1155                        osg::Vec3d pos =
1156                            viewer.getCameraManipulator()->getMatrix().getTrans();
1157
1158                        msm->setModellingSpaceToWorldTransform
1159                            ( csn->computeLocalCoordinateFrame( pos ) );
1160                    }
1161                }
1162            }
1163        }
1164
1165        if (lightAnimationHandler.valid() && lightAnimationHandler ->getAnimating())
1166        {
1167            float t = viewer.getFrameStamp()->getSimulationTime();
1168
1169            if (lightpos.w()==1.0)
1170            {
1171                lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius()*3.0f  ,1.0f);
1172            }
1173            else
1174            {
1175                lightpos.set(sinf(t),cosf(t),1.0f,0.0f);
1176            }
1177            ls->getLight()->setPosition(lightpos);
1178
1179            osg::Vec3f lightDir(-lightpos.x(),-lightpos.y(),-lightpos.z());
1180            if(spotlight)
1181                lightDir =  osg::Vec3(bb.center().x()+sinf(t)*bb.radius()/2.0, bb.center().y() + cosf(t)*bb.radius()/2.0, bb.center().z())
1182                - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z()) ;
1183            lightDir.normalize();
1184            ls->getLight()->setDirection(lightDir);
1185        }
1186
1187        if( dumpShadowVolumes->get() )
1188        {
1189            dumpShadowVolumes->set( false );
1190
1191            static int dumpFileNo = 0;
1192            dumpFileNo ++;
1193            char filename[256];
1194            std::sprintf( filename, "shadowDump%d.osgt", dumpFileNo );
1195
1196            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );
1197
1198            if( msm ) msm->setDebugDump( filename );
1199        }
1200
1201        viewer.frame();
1202    }
1203
1204    return 0;
1205}
Note: See TracBrowser for help on using the browser.