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

Revision 7497, 28.6 kB (checked in by robert, 7 years ago)

From Adrian Egli, "update the PSSM, i did some bug fixes and added new features to move the camera virtual against the view direction by applaying a simple distance factor (a), which is calculated camera eye - camera center distance. and we can move the "light camera" against the light direction (b).

(a) some objects behind the camera can cast shadow
(b) object aboive the camera can cast shadow

then i fixed the shadow map orientation, now screen x coordinate alinged which improve the quality"

  • 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
45#include <osgDB/ReadFile>
46#include <osgDB/WriteFile>
47
48#include <iostream>
49
50// for the grid data..
51#include "../osghangglide/terrain_coords.h"
52
53const int ReceivesShadowTraversalMask = 0x1;
54const int CastsShadowTraversalMask = 0x2;
55 
56namespace ModelOne
57{
58
59    enum Faces
60    {
61        FRONT_FACE = 1,
62        BACK_FACE = 2,
63        LEFT_FACE = 4,
64        RIGHT_FACE = 8,
65        TOP_FACE = 16,
66        BOTTOM_FACE = 32       
67    };
68
69    osg::Node* createCube(unsigned int mask)
70    {
71        osg::Geode* geode = new osg::Geode;
72
73        osg::Geometry* geometry = new osg::Geometry;
74        geode->addDrawable(geometry);
75
76        osg::Vec3Array* vertices = new osg::Vec3Array;
77        geometry->setVertexArray(vertices);
78
79        osg::Vec3Array* normals = new osg::Vec3Array;
80        geometry->setNormalArray(normals);
81        geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
82
83        osg::Vec4Array* colours = new osg::Vec4Array;
84        geometry->setColorArray(colours);
85        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
86        colours->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
87
88
89        osg::Vec3 origin(0.0f,0.0f,0.0f);
90        osg::Vec3 dx(2.0f,0.0f,0.0f);
91        osg::Vec3 dy(0.0f,1.0f,0.0f);
92        osg::Vec3 dz(0.0f,0.0f,1.0f);
93
94        osg::Vec3 px(1.0f,0.0,0.0f);
95        osg::Vec3 nx(-1.0f,0.0,0.0f);
96        osg::Vec3 py(0.0f,1.0f,0.0f);
97        osg::Vec3 ny(0.0f,-1.0f,0.0f);
98        osg::Vec3 pz(0.0f,0.0f,1.0f);
99        osg::Vec3 nz(0.0f,0.0f,-1.0f);
100
101        if (mask & FRONT_FACE)
102        {
103            // front face   
104            vertices->push_back(origin);
105            vertices->push_back(origin+dx);
106            vertices->push_back(origin+dx+dz);
107            vertices->push_back(origin+dz);
108            normals->push_back(ny);
109            normals->push_back(ny);
110            normals->push_back(ny);
111            normals->push_back(ny);
112        }
113
114        if (mask & BACK_FACE)
115        {
116            // back face   
117            vertices->push_back(origin+dy);
118            vertices->push_back(origin+dy+dz);
119            vertices->push_back(origin+dy+dx+dz);
120            vertices->push_back(origin+dy+dx);
121            normals->push_back(py);
122            normals->push_back(py);
123            normals->push_back(py);
124            normals->push_back(py);
125        }
126
127        if (mask & LEFT_FACE)
128        {
129            // left face   
130            vertices->push_back(origin+dy);
131            vertices->push_back(origin);
132            vertices->push_back(origin+dz);
133            vertices->push_back(origin+dy+dz);
134            normals->push_back(nx);
135            normals->push_back(nx);
136            normals->push_back(nx);
137            normals->push_back(nx);
138        }
139
140        if (mask & RIGHT_FACE)
141        {
142            // right face   
143            vertices->push_back(origin+dx+dy);
144            vertices->push_back(origin+dx+dy+dz);
145            vertices->push_back(origin+dx+dz);
146            vertices->push_back(origin+dx);
147            normals->push_back(px);
148            normals->push_back(px);
149            normals->push_back(px);
150            normals->push_back(px);
151        }
152
153        if (mask & TOP_FACE)
154        {
155            // top face   
156            vertices->push_back(origin+dz);
157            vertices->push_back(origin+dz+dx);
158            vertices->push_back(origin+dz+dx+dy);
159            vertices->push_back(origin+dz+dy);
160            normals->push_back(pz);
161            normals->push_back(pz);
162            normals->push_back(pz);
163            normals->push_back(pz);
164        }
165
166        if (mask & BOTTOM_FACE)
167        {
168            // bottom face   
169            vertices->push_back(origin);
170            vertices->push_back(origin+dy);
171            vertices->push_back(origin+dx+dy);
172            vertices->push_back(origin+dx);
173            normals->push_back(nz);
174            normals->push_back(nz);
175            normals->push_back(nz);
176            normals->push_back(nz);
177        }
178
179        geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, vertices->size()));
180
181        return geode;
182    }
183
184    class SwitchHandler : public osgGA::GUIEventHandler
185    {
186    public:
187
188        SwitchHandler():
189            _childNum(0) {}
190
191        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& /*aa*/, osg::Object* object, osg::NodeVisitor* /*nv*/)
192        {
193            osg::Switch* sw = dynamic_cast<osg::Switch*>(object);
194            if (!sw) return false;
195
196            if (ea.getHandled()) return false;
197
198            switch(ea.getEventType())
199            {
200                case(osgGA::GUIEventAdapter::KEYDOWN):
201                {
202                    if (ea.getKey()=='n')
203                    {
204                        ++_childNum;
205                        if (_childNum >= sw->getNumChildren()) _childNum = 0;
206
207                        sw->setSingleChildOn(_childNum);
208                        return true;
209                    }               
210                    break;
211                }
212                default:
213                    break;
214            }
215            return false;
216        }
217
218    protected:
219
220        virtual ~SwitchHandler() {}
221        unsigned int    _childNum;
222
223    };
224
225
226    osg::Node* createModel(osg::ArgumentParser& /*arguments*/)
227    {
228        osg::Switch* sw = new osg::Switch;
229        sw->setEventCallback(new ModelOne::SwitchHandler);
230
231        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE), true);
232        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE), false);
233        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE), false);
234        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE | ModelOne::RIGHT_FACE), false);
235        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE | ModelOne::RIGHT_FACE | ModelOne::TOP_FACE), false);
236        sw->addChild(ModelOne::createCube(ModelOne::FRONT_FACE | ModelOne::BACK_FACE | ModelOne::LEFT_FACE | ModelOne::RIGHT_FACE | ModelOne::TOP_FACE | ModelOne::BOTTOM_FACE), false);
237       
238        return sw;   
239    }
240}
241
242namespace ModelTwo
243{
244    osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
245    {
246        // set up the animation path
247        osg::AnimationPath* animationPath = new osg::AnimationPath;
248        animationPath->setLoopMode(osg::AnimationPath::LOOP);
249
250        int numSamples = 40;
251        float yaw = 0.0f;
252        float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
253        float roll = osg::inDegrees(30.0f);
254
255        double time=0.0f;
256        double time_delta = looptime/(double)numSamples;
257        for(int i=0;i<numSamples;++i)
258        {
259            osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
260            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)));
261
262            animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
263
264            yaw += yaw_delta;
265            time += time_delta;
266
267        }
268        return animationPath;   
269    }
270
271    osg::Node* createBase(const osg::Vec3& center,float radius)
272    {
273
274        osg::Geode* geode = new osg::Geode;
275
276        // set up the texture of the base.
277        osg::StateSet* stateset = new osg::StateSet();
278        osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
279        if (image)
280        {
281            osg::Texture2D* texture = new osg::Texture2D;
282            texture->setImage(image);
283            stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
284        }
285
286        geode->setStateSet( stateset );
287
288
289        osg::HeightField* grid = new osg::HeightField;
290        grid->allocate(38,39);
291        grid->setOrigin(center+osg::Vec3(-radius,-radius,0.0f));
292        grid->setXInterval(radius*2.0f/(float)(38-1));
293        grid->setYInterval(radius*2.0f/(float)(39-1));
294
295        float minHeight = FLT_MAX;
296        float maxHeight = -FLT_MAX;
297
298
299        unsigned int r;
300        for(r=0;r<39;++r)
301        {
302            for(unsigned int c=0;c<38;++c)
303            {
304                float h = vertex[r+c*39][2];
305                if (h>maxHeight) maxHeight=h;
306                if (h<minHeight) minHeight=h;
307            }
308        }
309
310        float hieghtScale = radius*0.5f/(maxHeight-minHeight);
311        float hieghtOffset = -(minHeight+maxHeight)*0.5f;
312
313        for(r=0;r<39;++r)
314        {
315            for(unsigned int c=0;c<38;++c)
316            {
317                float h = vertex[r+c*39][2];
318                grid->setHeight(c,r,(h+hieghtOffset)*hieghtScale);
319            }
320        }
321
322        geode->addDrawable(new osg::ShapeDrawable(grid));
323
324        osg::Group* group = new osg::Group;
325        group->addChild(geode);
326
327        return group;
328
329    }
330
331    osg::Node* createMovingModel(const osg::Vec3& center, float radius)
332    {
333        float animationLength = 10.0f;
334
335        osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
336
337        osg::Group* model = new osg::Group;
338
339        osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
340        if (cessna)
341        {
342            const osg::BoundingSphere& bs = cessna->getBound();
343
344            float size = radius/bs.radius()*0.3f;
345            osg::MatrixTransform* positioned = new osg::MatrixTransform;
346            positioned->setDataVariance(osg::Object::STATIC);
347            positioned->setMatrix(osg::Matrix::translate(-bs.center())*
348                                  osg::Matrix::scale(size,size,size)*
349                                  osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,2.0f));
350
351            positioned->addChild(cessna);
352
353            osg::MatrixTransform* xform = new osg::MatrixTransform;
354            xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
355            xform->addChild(positioned);
356
357            model->addChild(xform);
358        }
359
360        return model;
361    }
362
363    osg::Node* createModel(osg::ArgumentParser& /*arguments*/)
364    {
365        osg::Vec3 center(0.0f,0.0f,0.0f);
366        float radius = 100.0f;
367        osg::Vec3 lightPosition(center+osg::Vec3(0.0f,0.0f,radius));
368
369        // the shadower model
370        osg::Node* shadower = createMovingModel(center,radius*0.5f);
371        shadower->setNodeMask(CastsShadowTraversalMask);
372
373        // the shadowed model
374        osg::Node* shadowed = createBase(center-osg::Vec3(0.0f,0.0f,radius*0.25),radius);
375        shadowed->setNodeMask(ReceivesShadowTraversalMask);
376       
377        osg::Group* group = new osg::Group;
378
379        group->addChild(shadowed);
380        group->addChild(shadower);
381       
382        return group;
383    }
384}
385
386namespace ModelThree
387{
388    osg::Group* createModel(osg::ArgumentParser& arguments)
389    {
390        osg::Group* scene = new osg::Group;
391
392        osg::ref_ptr<osg::Geode> geode_1 = new osg::Geode;
393        scene->addChild(geode_1.get());
394
395        osg::ref_ptr<osg::Geode> geode_2 = new osg::Geode;
396        osg::ref_ptr<osg::MatrixTransform> transform_2 = new osg::MatrixTransform;
397        transform_2->addChild(geode_2.get());
398        transform_2->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(45.0f)));
399        scene->addChild(transform_2.get());
400
401        osg::ref_ptr<osg::Geode> geode_3 = new osg::Geode;
402        osg::ref_ptr<osg::MatrixTransform> transform_3 = new osg::MatrixTransform;
403        transform_3->addChild(geode_3.get());
404        transform_3->setUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0, 0, 0), osg::Z_AXIS, osg::inDegrees(-22.5f)));
405        scene->addChild(transform_3.get());
406
407        const float radius = 0.8f;
408        const float height = 1.0f;
409        osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
410        hints->setDetailRatio(2.0f);
411        osg::ref_ptr<osg::ShapeDrawable> shape;
412
413        shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, -2.0f), 10, 10.0f, 0.1f), hints.get());
414        shape->setColor(osg::Vec4(0.5f, 0.5f, 0.7f, 1.0f));
415        geode_1->addDrawable(shape.get());
416
417        shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), radius * 2), hints.get());
418        shape->setColor(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f));
419        geode_1->addDrawable(shape.get());
420
421        shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(-3.0f, 0.0f, 0.0f), radius), hints.get());
422        shape->setColor(osg::Vec4(0.6f, 0.8f, 0.8f, 1.0f));
423        geode_2->addDrawable(shape.get());
424
425        shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(3.0f, 0.0f, 0.0f), 2 * radius), hints.get());
426        shape->setColor(osg::Vec4(0.4f, 0.9f, 0.3f, 1.0f));
427        geode_2->addDrawable(shape.get());
428
429        shape = new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0.0f, -3.0f, 0.0f), radius, height), hints.get());
430        shape->setColor(osg::Vec4(0.2f, 0.5f, 0.7f, 1.0f));
431        geode_2->addDrawable(shape.get());
432
433        shape = new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.0f, 3.0f, 0.0f), radius, height), hints.get());
434        shape->setColor(osg::Vec4(1.0f, 0.3f, 0.3f, 1.0f));
435        geode_2->addDrawable(shape.get());
436
437        shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 3.0f), 2.0f, 2.0f, 0.1f), hints.get());
438        shape->setColor(osg::Vec4(0.8f, 0.8f, 0.4f, 1.0f));
439        geode_3->addDrawable(shape.get());
440
441        // material
442        osg::ref_ptr<osg::Material> matirial = new osg::Material;
443        matirial->setColorMode(osg::Material::DIFFUSE);
444        matirial->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
445        matirial->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1));
446        matirial->setShininess(osg::Material::FRONT_AND_BACK, 64.0f);
447        scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), osg::StateAttribute::ON);
448
449        bool withBaseTexture = true;
450        while(arguments.read("--with-base-texture")) { withBaseTexture = true; }
451        while(arguments.read("--no-base-texture")) { withBaseTexture = false; }
452
453        if (withBaseTexture)
454        {
455            scene->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")), osg::StateAttribute::ON);
456        }
457
458        return scene;
459    }
460   
461}
462
463
464osg::Node* createTestModel(osg::ArgumentParser& arguments)
465{
466    if (arguments.read("-1"))
467    {
468        return ModelOne::createModel(arguments);
469    }
470    else if (arguments.read("-2"))
471    {
472        return ModelTwo::createModel(arguments);
473    }
474    else /*if (arguments.read("-3"))*/
475    {
476        return ModelThree::createModel(arguments);
477    }
478   
479}
480
481int main(int argc, char** argv)
482{
483    // use an ArgumentParser object to manage the program arguments.
484    osg::ArgumentParser arguments(&argc, argv);
485
486    // set up the usage document, in case we need to print out how to use this program.
487    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class");
488    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
489    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
490    arguments.getApplicationUsage()->addCommandLineOption("--positionalLight", "Use a positional light.");
491    arguments.getApplicationUsage()->addCommandLineOption("--directionalLight", "Use a direction light.");
492    arguments.getApplicationUsage()->addCommandLineOption("--noUpdate", "Disable the updating the of light source.");
493    arguments.getApplicationUsage()->addCommandLineOption("--base", "Add a base geometry to test shadows.");
494    arguments.getApplicationUsage()->addCommandLineOption("--sv", "Select ShadowVolume implementation.");
495    arguments.getApplicationUsage()->addCommandLineOption("--ssm", "Select SoftShadowMap implementation.");
496    arguments.getApplicationUsage()->addCommandLineOption("--sm", "Select ShadowMap implementation.");
497//    arguments.getApplicationUsage()->addCommandLineOption("--pssm", "Select ParallelSplitShadowMap implementation.");
498    arguments.getApplicationUsage()->addCommandLineOption("--pssm", "Select ParallelSplitShadowMap implementation.");//ADEGLI
499    arguments.getApplicationUsage()->addCommandLineOption("--mapcount", "ParallelSplitShadowMap texture count.");//ADEGLI
500    arguments.getApplicationUsage()->addCommandLineOption("--mapres", "ParallelSplitShadowMap texture resolution.");//ADEGLI
501    arguments.getApplicationUsage()->addCommandLineOption("--debug-color", "ParallelSplitShadowMap display debugging color (only the first 3 maps are color r=0,g=1,b=2.");//ADEGLI
502    arguments.getApplicationUsage()->addCommandLineOption("--minNearSplit", "ParallelSplitShadowMap shadow map near offset.");//ADEGLI
503    arguments.getApplicationUsage()->addCommandLineOption("--maxFarDist", "ParallelSplitShadowMap max far distance to shadow.");//ADEGLI
504    arguments.getApplicationUsage()->addCommandLineOption("--moveVCamFactor", "ParallelSplitShadowMap move the virtual frustum behind the real camera, (also back ground object can cast shadow).");//ADEGLI
505    arguments.getApplicationUsage()->addCommandLineOption("--NVidea", "ParallelSplitShadowMap set default PolygonOffset for NVidea.");//ADEGLI
506    arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Factor", "ParallelSplitShadowMap set PolygonOffset factor.");//ADEGLI
507    arguments.getApplicationUsage()->addCommandLineOption("--PolyOffset-Unit", "ParallelSplitShadowMap set PolygonOffset unit.");//ADEGLI
508    arguments.getApplicationUsage()->addCommandLineOption("--CullFaceFront", "ParallelSplitShadowMap add a cull face: front.");//ADEGLI
509
510   
511    arguments.getApplicationUsage()->addCommandLineOption("-1", "Use test model one.");
512    arguments.getApplicationUsage()->addCommandLineOption("-2", "Use test model two.");
513    arguments.getApplicationUsage()->addCommandLineOption("-3", "Use test model three.");
514    arguments.getApplicationUsage()->addCommandLineOption("--two-sided", "Use two-sided stencil extension for shadow volumes.");
515    arguments.getApplicationUsage()->addCommandLineOption("--two-pass", "Use two-pass stencil for shadow volumes.");
516
517
518    // construct the viewer.
519    osgViewer::Viewer viewer;
520
521    // if user request help write it out to cout.
522    if (arguments.read("-h") || arguments.read("--help"))
523    {
524        arguments.getApplicationUsage()->write(std::cout);
525        return 1;
526    }
527
528    // default to single threaded during dev work.
529    viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
530   
531    while (arguments.read("--SingleThreaded")) viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
532    while (arguments.read("--CullDrawThreadPerContext")) viewer.setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
533    while (arguments.read("--DrawThreadPerContext")) viewer.setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
534    while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) viewer.setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
535
536
537    bool postionalLight = true;
538    while (arguments.read("--positionalLight")) postionalLight = true;
539    while (arguments.read("--directionalLight")) postionalLight = false;
540
541    bool updateLightPosition = true;
542    while (arguments.read("--noUpdate")) updateLightPosition = false;
543
544
545    int screenNum = -1;
546    while (arguments.read("--screen", screenNum)) viewer.setUpViewOnSingleScreen(screenNum);
547
548    // set up the camera manipulators.
549    {
550        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
551
552        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
553        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
554        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
555        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
556
557        std::string pathfile;
558        char keyForAnimationPath = '5';
559        while (arguments.read("-p",pathfile))
560        {
561            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
562            if (apm || !apm->valid())
563            {
564                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
565                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
566                keyswitchManipulator->selectMatrixManipulator(num);
567                ++keyForAnimationPath;
568            }
569        }
570
571        viewer.setCameraManipulator( keyswitchManipulator.get() );
572    }
573
574    // add the state manipulator
575    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
576
577    // add stats
578    viewer.addEventHandler( new osgViewer::StatsHandler() );
579
580
581
582    osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene;
583   
584    shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
585    shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask);
586   
587   
588    if (arguments.read("--sv"))
589    {
590        // hint to tell viewer to request stencil buffer when setting up windows
591        osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
592
593        osg::ref_ptr<osgShadow::ShadowVolume> sv = new osgShadow::ShadowVolume;
594        sv->setDynamicShadowVolumes(updateLightPosition);
595        while (arguments.read("--two-sided")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED);
596        while (arguments.read("--two-pass")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_PASS);
597
598        shadowedScene->setShadowTechnique(sv.get());
599    }
600    else if (arguments.read("--st"))
601    {
602        osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture;
603        shadowedScene->setShadowTechnique(st.get());
604    }
605    else if (arguments.read("--pssm"))
606    {
607        int mapcount = 3;
608        while (arguments.read("--mapcount", mapcount));
609        osg::ref_ptr<osgShadow::ParallelSplitShadowMap> pssm = new osgShadow::ParallelSplitShadowMap(NULL,mapcount);
610
611        int mapres = 1024;
612        while (arguments.read("--mapres", mapres))
613            pssm->setTextureResolution(mapres);
614       
615        while (arguments.read("--debug-color")) { pssm->setDebugColorOn(); }
616         
617
618        int minNearSplit=0;
619        while (arguments.read("--minNearSplit", minNearSplit))
620            if ( minNearSplit > 0 ) {
621                pssm->setMinNearDistanceForSplits(minNearSplit);
622                std::cout << "ParallelSplitShadowMap : setMinNearDistanceForSplits(" << minNearSplit <<")" << std::endl;
623            }
624
625        int maxfardist = 0;
626        while (arguments.read("--maxFarDist", maxfardist))
627            if ( maxfardist > 0 ) {
628                pssm->setMaxFarDistance(maxfardist);
629                std::cout << "ParallelSplitShadowMap : setMaxFarDistance(" << maxfardist<<")" << std::endl;
630            }
631
632        int moveVCamFactor = 0;
633        while (arguments.read("--moveVCamFactor", moveVCamFactor))
634            if ( maxfardist > 0 ) {
635                pssm->setMoveVCamBehindRCamFactor(moveVCamFactor);
636                std::cout << "ParallelSplitShadowMap : setMoveVCamBehindRCamFactor(" << moveVCamFactor<<")" << std::endl;
637            }
638           
639
640        double polyoffsetfactor = -0.02;
641        double polyoffsetunit = 1.0;
642        while (arguments.read("--PolyOffset-Factor", polyoffsetfactor));
643        while (arguments.read("--PolyOffset-Unit", polyoffsetunit));
644        pssm->setPolygonOffset(osg::Vec2(polyoffsetfactor,polyoffsetunit)); //ATI Radeon
645
646        if (arguments.read("--NVidea")){
647            //pssm->setPolygonOffset(osg::Vec2(-0.02,1.0)); //ATI Radeon
648            pssm->setPolygonOffset(osg::Vec2(10.0f,20.0f)); //NVidea
649        }
650
651        if ( arguments.read("--CullFaceFront") ) {
652            pssm->forceFrontCullFace();
653        }
654
655        shadowedScene->setShadowTechnique(pssm.get());
656    }
657    else if (arguments.read("--ssm"))
658    {
659        osg::ref_ptr<osgShadow::SoftShadowMap> sm = new osgShadow::SoftShadowMap;
660        shadowedScene->setShadowTechnique(sm.get());
661    }
662    else /* if (arguments.read("--sm")) */
663    {
664        osg::ref_ptr<osgShadow::ShadowMap> sm = new osgShadow::ShadowMap;
665        shadowedScene->setShadowTechnique(sm.get());
666    }
667   
668    osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
669    if (model.valid())
670    {
671        model->setNodeMask(CastsShadowTraversalMask | ReceivesShadowTraversalMask);
672    }
673    else
674    {
675        model = createTestModel(arguments);
676    }
677
678    // get the bounds of the model.   
679    osg::ComputeBoundsVisitor cbbv;
680    model->accept(cbbv);
681    osg::BoundingBox bb = cbbv.getBoundingBox();
682
683    osg::Vec4 lightpos;
684   
685    if (postionalLight)
686    {
687        lightpos.set(bb.center().x(), bb.center().y(), bb.zMax() + bb.radius()  ,1.0f);
688    }
689    else
690    {
691        lightpos.set(0.5f,0.25f,0.8f,0.0f);
692    }
693
694
695    if ( arguments.read("--base"))
696    {
697
698        osg::Geode* geode = new osg::Geode;
699       
700        osg::Vec3 widthVec(bb.radius(), 0.0f, 0.0f);
701        osg::Vec3 depthVec(0.0f, bb.radius(), 0.0f);
702        osg::Vec3 centerBase( (bb.xMin()+bb.xMax())*0.5f, (bb.yMin()+bb.yMax())*0.5f, bb.zMin()-bb.radius()*0.1f );
703       
704        geode->addDrawable( osg::createTexturedQuadGeometry( centerBase-widthVec*1.5f-depthVec*1.5f,
705                                                             widthVec*3.0f, depthVec*3.0f) );
706                                                             
707        geode->setNodeMask(shadowedScene->getReceivesShadowTraversalMask());
708       
709        geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile("Images/lz.rgb")));
710
711        shadowedScene->addChild(geode);
712    }
713
714    osg::ref_ptr<osg::LightSource> ls = new osg::LightSource;
715    ls->getLight()->setPosition(lightpos);
716    if ( arguments.read("--coloured-light"))
717    {
718        ls->getLight()->setAmbient(osg::Vec4(1.0,0.0,0.0,1.0));
719        ls->getLight()->setDiffuse(osg::Vec4(0.0,1.0,0.0,1.0));
720    }
721    else
722    {
723        ls->getLight()->setAmbient(osg::Vec4(0.2,0.2,0.2,1.0));
724        ls->getLight()->setDiffuse(osg::Vec4(0.8,0.8,0.8,1.0));
725    }
726
727    shadowedScene->addChild(model.get());
728    shadowedScene->addChild(ls.get());
729   
730    viewer.setSceneData(shadowedScene.get());
731   
732    // create the windows and run the threads.
733    viewer.realize();
734
735    // osgDB::writeNodeFile(*group,"test.osg");
736
737    while (!viewer.done())
738    {
739        if (updateLightPosition)
740        {
741            float t = viewer.getFrameStamp()->getSimulationTime();
742            if (postionalLight)
743            {
744                lightpos.set(bb.center().x()+sinf(t)*bb.radius(), bb.center().y() + cosf(t)*bb.radius(), bb.zMax() + bb.radius()  ,1.0f);
745            }
746            else
747            {
748                lightpos.set(sinf(t),cosf(t),1.0f,0.0f);
749            }
750            ls->getLight()->setPosition(lightpos);
751           
752            osg::Vec3f lightDir(-lightpos.x(),-lightpos.y(),-lightpos.z());
753            lightDir.normalize();
754            ls->getLight()->setDirection(lightDir);
755        }
756
757        viewer.frame();
758    }
759   
760    return 0;
761}
Note: See TracBrowser for help on using the browser.