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

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