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

Revision 13078, 44.7 kB (checked in by robert, 57 minutes 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    shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
840    shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask);
841
842    osg::ref_ptr<osgShadow::MinimalShadowMap> msm = NULL;
843    if (arguments.read("--no-shadows"))
844    {
845        OSG_NOTICE<<"Not using a ShadowTechnique"<<std::endl;
846        shadowedScene->setShadowTechnique(0);
847    }
848    else if (arguments.read("--sv"))
849    {
850        // hint to tell viewer to request stencil buffer when setting up windows
851        osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
852
853        osg::ref_ptr<osgShadow::ShadowVolume> sv = new osgShadow::ShadowVolume;
854        sv->setDynamicShadowVolumes(updateLightPosition);
855        while (arguments.read("--two-sided")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED);
856        while (arguments.read("--two-pass")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_PASS);
857
858        shadowedScene->setShadowTechnique(sv.get());
859    }
860    else if (arguments.read("--st"))
861    {
862        osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture;
863        shadowedScene->setShadowTechnique(st.get());
864    }
865    else if (arguments.read("--stsm"))
866    {
867        osg::ref_ptr<osgShadow::StandardShadowMap> st = new osgShadow::StandardShadowMap;
868        shadowedScene->setShadowTechnique(st.get());
869    }
870    else if (arguments.read("--pssm"))
871    {
872        int mapcount = 3;
873        while (arguments.read("--mapcount", mapcount));
874        osg::ref_ptr<osgShadow::ParallelSplitShadowMap> pssm = new osgShadow::ParallelSplitShadowMap(NULL,mapcount);
875
876        int mapres = 1024;
877        while (arguments.read("--mapres", mapres))
878            pssm->setTextureResolution(mapres);
879
880        while (arguments.read("--debug-color")) { pssm->setDebugColorOn(); }
881
882
883        int minNearSplit=0;
884        while (arguments.read("--minNearSplit", minNearSplit))
885            if ( minNearSplit > 0 ) {
886                pssm->setMinNearDistanceForSplits(minNearSplit);
887                std::cout << "ParallelSplitShadowMap : setMinNearDistanceForSplits(" << minNearSplit <<")" << std::endl;
888            }
889
890        int maxfardist = 0;
891        while (arguments.read("--maxFarDist", maxfardist))
892            if ( maxfardist > 0 ) {
893                pssm->setMaxFarDistance(maxfardist);
894                std::cout << "ParallelSplitShadowMap : setMaxFarDistance(" << maxfardist<<")" << std::endl;
895            }
896
897        int moveVCamFactor = 0;
898        while (arguments.read("--moveVCamFactor", moveVCamFactor))
899            if ( maxfardist > 0 ) {
900                pssm->setMoveVCamBehindRCamFactor(moveVCamFactor);
901                std::cout << "ParallelSplitShadowMap : setMoveVCamBehindRCamFactor(" << moveVCamFactor<<")" << std::endl;
902            }
903
904
905
906        double polyoffsetfactor = pssm->getPolygonOffset().x();
907        double polyoffsetunit   = pssm->getPolygonOffset().y();
908        while (arguments.read("--PolyOffset-Factor", polyoffsetfactor));
909        while (arguments.read("--PolyOffset-Unit", polyoffsetunit));
910        pssm->setPolygonOffset(osg::Vec2(polyoffsetfactor,polyoffsetunit));
911
912        shadowedScene->setShadowTechnique(pssm.get());
913    }
914    else if (arguments.read("--ssm"))
915    {
916        osg::ref_ptr<osgShadow::SoftShadowMap> sm = new osgShadow::SoftShadowMap;
917        shadowedScene->setShadowTechnique(sm.get());
918    }
919    else if( arguments.read("--vdsm") )
920    {
921        osgShadow::ShadowSettings* settings = new osgShadow::ShadowSettings;
922        shadowedScene->setShadowSettings(settings);
923
924        while( arguments.read("--debugHUD") ) settings->setDebugDraw( true );
925        if (arguments.read("--persp")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::PERSPECTIVE_SHADOW_MAP);
926        if (arguments.read("--ortho")) settings->setShadowMapProjectionHint(osgShadow::ShadowSettings::ORTHOGRAPHIC_SHADOW_MAP);
927
928        unsigned int unit=1;
929        if (arguments.read("--unit",unit)) settings->setBaseShadowTextureUnit(unit);
930
931        double n=0.0;
932        if (arguments.read("-n",n)) settings->setMinimumShadowMapNearFarRatio(n);
933
934        unsigned int numShadowMaps;
935        if (arguments.read("--num-sm",numShadowMaps)) settings->setNumShadowMapsPerLight(numShadowMaps);
936
937        if (arguments.read("--parallel-split") || arguments.read("--ps") ) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::PARALLEL_SPLIT);
938        if (arguments.read("--cascaded")) settings->setMultipleShadowMapHint(osgShadow::ShadowSettings::CASCADED);
939
940
941        int mapres = 1024;
942        while (arguments.read("--mapres", mapres))
943            settings->setTextureSize(osg::Vec2s(mapres,mapres));
944
945        osg::ref_ptr<osgShadow::ViewDependentShadowMap> vdsm = new osgShadow::ViewDependentShadowMap;
946        shadowedScene->setShadowTechnique(vdsm.get());
947    }
948    else if ( arguments.read("--lispsm") )
949    {
950        if( arguments.read( "--ViewBounds" ) )
951            msm = new osgShadow::LightSpacePerspectiveShadowMapVB;
952        else if( arguments.read( "--CullBounds" ) )
953            msm = new osgShadow::LightSpacePerspectiveShadowMapCB;
954        else // if( arguments.read( "--DrawBounds" ) ) // default
955            msm = new osgShadow::LightSpacePerspectiveShadowMapDB;
956    }
957    else if( arguments.read("--msm") )
958    {
959       if( arguments.read( "--ViewBounds" ) )
960            msm = new osgShadow::MinimalShadowMap;
961       else if( arguments.read( "--CullBounds" ) )
962            msm = new osgShadow::MinimalCullBoundsShadowMap;
963       else // if( arguments.read( "--DrawBounds" ) ) // default
964            msm = new osgShadow::MinimalDrawBoundsShadowMap;
965    }
966    else /* if (arguments.read("--sm")) */
967    {
968        osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
969        shadowedScene->setShadowTechnique(sm.get());
970
971        int mapres = 1024;
972        while (arguments.read("--mapres", mapres))
973            sm->setTextureSize(osg::Vec2s(mapres,mapres));
974    }
975
976    if( msm )// Set common MSM & LISPSM arguments
977    {
978        shadowedScene->setShadowTechnique( msm.get() );
979        while( arguments.read("--debugHUD") ) msm->setDebugDraw( true );
980
981        float minLightMargin = 10.f;
982        float maxFarPlane = 0;
983        unsigned int texSize = 1024;
984        unsigned int baseTexUnit = 0;
985        unsigned int shadowTexUnit = 1;
986
987        while ( arguments.read("--moveVCamFactor", minLightMargin ) );
988        while ( arguments.read("--minLightMargin", minLightMargin ) );
989        while ( arguments.read("--maxFarDist", maxFarPlane ) );
990        while ( arguments.read("--mapres", texSize ));
991        while ( arguments.read("--baseTextureUnit", baseTexUnit) );
992        while ( arguments.read("--shadowTextureUnit", shadowTexUnit) );
993
994        msm->setMinLightMargin( minLightMargin );
995        msm->setMaxFarPlane( maxFarPlane );
996        msm->setTextureSize( osg::Vec2s( texSize, texSize ) );
997        msm->setShadowTextureCoordIndex( shadowTexUnit );
998        msm->setShadowTextureUnit( shadowTexUnit );
999        msm->setBaseTextureCoordIndex( baseTexUnit );
1000        msm->setBaseTextureUnit( baseTexUnit );
1001    }
1002
1003    OSG_INFO<<"shadowedScene->getShadowTechnique()="<<shadowedScene->getShadowTechnique()<<std::endl;
1004
1005    osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
1006    if (model.valid())
1007    {
1008        model->setNodeMask(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
1009    }
1010    else
1011    {
1012        model = createTestModel(arguments);
1013    }
1014
1015    // get the bounds of the model.
1016    osg::ComputeBoundsVisitor cbbv;
1017    model->accept(cbbv);
1018    osg::BoundingBox bb = cbbv.getBoundingBox();
1019
1020    if (lightpos.w()==1.0 && !keepLightPos)
1021    {
1022        lightpos.x() = bb.xMin()+(bb.xMax()-bb.xMin())*lightpos.x();
1023        lightpos.y() = bb.yMin()+(bb.yMax()-bb.yMin())*lightpos.y();
1024        lightpos.z() = bb.zMin()+(bb.zMax()-bb.zMin())*lightpos.z();
1025    }
1026
1027    if ( arguments.read("--base"))
1028    {
1029
1030        osg::Geode* geode = new osg::Geode;
1031
1032        osg::Vec3 widthVec(bb.radius(), 0.0f, 0.0f);
1033        osg::Vec3 depthVec(0.0f, bb.radius(), 0.0f);
1034        osg::Vec3 centerBase( (bb.xMin()+bb.xMax())*0.5f, (bb.yMin()+bb.yMax())*0.5f, bb.zMin()-bb.radius()*0.1f );
1035
1036        geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*1.5f-depthVec*1.5f,
1037                                                             widthVec*3.0f, depthVec*3.0f) );
1038
1039        geode->setNodeMask(shadowedScene->getReceivesShadowTraversalMask());
1040
1041        geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")));
1042
1043        shadowedScene->addChild(geode);
1044    }
1045
1046    osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
1047    ls->getLight()->setPosition(lightpos);
1048
1049    if (spotlight)
1050    {
1051        osg::Vec3 center = spotLookat;
1052        osg::Vec3 lightdir = center - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z());
1053        lightdir.normalize();
1054        ls->getLight()->setDirection(lightdir);
1055        ls->getLight()->setSpotCutoff(25.0f);
1056
1057        //set the LightSource, only for checking, there is only 1 light in the scene
1058        osgShadow::ShadowMap* shadowMap = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
1059        if( shadowMap ) shadowMap->setLight(ls.get());
1060    }
1061
1062    if ( arguments.read("--coloured-light"))
1063    {
1064        ls->getLight()->setAmbient(osg::Vec4(1.0,0.0,0.0,1.0));
1065        ls->getLight()->setDiffuse(osg::Vec4(0.0,1.0,0.0,1.0));
1066    }
1067    else
1068    {
1069        ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
1070        ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
1071    }
1072
1073    shadowedScene->addChild(model.get());
1074    shadowedScene->addChild(ls.get());
1075
1076    viewer.setSceneData(shadowedScene.get());
1077
1078    osg::ref_ptr< DumpShadowVolumesHandler > dumpShadowVolumes = new DumpShadowVolumesHandler;
1079
1080    viewer.addEventHandler(new ChangeFOVHandler(viewer.getCamera()));
1081    viewer.addEventHandler( dumpShadowVolumes.get() );
1082
1083    // create the windows and run the threads.
1084    viewer.realize();
1085
1086    if (fov!=0.0)
1087    {
1088        double fovy, aspectRatio, zNear, zFar;
1089        viewer.getCamera()->getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
1090
1091        std::cout << "Setting FOV to " << fov << std::endl;
1092        viewer.getCamera()->getProjectionMatrix().makePerspective(fov, aspectRatio, zNear, zFar);
1093    }
1094
1095    // it is done after viewer.realize() so that the windows are already initialized
1096    if ( arguments.read("--debugHUD"))
1097    {
1098        osgViewer::Viewer::Windows windows;
1099        viewer.getWindows(windows);
1100
1101        if (windows.empty()) return 1;
1102
1103        osgShadow::ShadowMap* sm = dynamic_cast<osgShadow::ShadowMap*>(shadowedScene->getShadowTechnique());
1104        if( sm ) {
1105            osg::ref_ptr<osg::Camera> hudCamera = sm->makeDebugHUD();
1106
1107            // set up cameras to rendering on the first window available.
1108            hudCamera->setGraphicsContext(windows[0]);
1109            hudCamera->setViewport(0,0,windows[0]->getTraits()->width, windows[0]->getTraits()->height);
1110
1111            viewer.addSlave(hudCamera.get(), false);
1112        }
1113    }
1114
1115    osg::ref_ptr<LightAnimationHandler> lightAnimationHandler = updateLightPosition ? new LightAnimationHandler : 0;
1116    if (lightAnimationHandler) viewer.addEventHandler(lightAnimationHandler.get());
1117
1118
1119    // osgDB::writeNodeFile(*group,"test.osgt");
1120
1121    while (!viewer.done())
1122    {
1123        {
1124            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );
1125
1126            if( msm ) {
1127
1128                // If scene decorated by CoordinateSystemNode try to find localToWorld
1129                // and set modellingSpaceToWorld matrix to optimize scene bounds computation
1130
1131                osg::NodePath np = viewer.getCoordinateSystemNodePath();
1132                if( !np.empty() ) {
1133                    osg::CoordinateSystemNode * csn =
1134                        dynamic_cast<osg::CoordinateSystemNode *>( np.back() );
1135
1136                    if( csn ) {
1137                        osg::Vec3d pos =
1138                            viewer.getCameraManipulator()->getMatrix().getTrans();
1139
1140                        msm->setModellingSpaceToWorldTransform
1141                            ( csn->computeLocalCoordinateFrame( pos ) );
1142                    }
1143                }
1144            }
1145        }
1146
1147        if (lightAnimationHandler.valid() && lightAnimationHandler ->getAnimating())
1148        {
1149            float t = viewer.getFrameStamp()->getSimulationTime();
1150
1151            if (lightpos.w()==1.0)
1152            {
1153                lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius()*3.0f  ,1.0f);
1154            }
1155            else
1156            {
1157                lightpos.set(sinf(t),cosf(t),1.0f,0.0f);
1158            }
1159            ls->getLight()->setPosition(lightpos);
1160
1161            osg::Vec3f lightDir(-lightpos.x(),-lightpos.y(),-lightpos.z());
1162            if(spotlight)
1163                lightDir =  osg::Vec3(bb.center().x()+sinf(t)*bb.radius()/2.0, bb.center().y() + cosf(t)*bb.radius()/2.0, bb.center().z())
1164                - osg::Vec3(lightpos.x(), lightpos.y(), lightpos.z()) ;
1165            lightDir.normalize();
1166            ls->getLight()->setDirection(lightDir);
1167        }
1168
1169        if( dumpShadowVolumes->get() )
1170        {
1171            dumpShadowVolumes->set( false );
1172
1173            static int dumpFileNo = 0;
1174            dumpFileNo ++;
1175            char filename[256];
1176            std::sprintf( filename, "shadowDump%d.osgt", dumpFileNo );
1177
1178            osgShadow::MinimalShadowMap * msm = dynamic_cast<osgShadow::MinimalShadowMap*>( shadowedScene->getShadowTechnique() );
1179
1180            if( msm ) msm->setDebugDump( filename );
1181        }
1182
1183        viewer.frame();
1184    }
1185
1186    return 0;
1187}
Note: See TracBrowser for help on using the browser.