root/OpenSceneGraph/trunk/examples/osgspotlight/osgspotlight.cpp @ 3462

Revision 3462, 10.4 kB (checked in by robert, 10 years ago)

Added new osgspotlight demo

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Notify>
2#include <osg/MatrixTransform>
3#include <osg/ShapeDrawable>
4#include <osg/PositionAttitudeTransform>
5#include <osg/Geometry>
6#include <osg/Texture2D>
7#include <osg/Geode>
8#include <osg/LightSource>
9#include <osg/TexGenNode>
10
11#include <osgUtil/Optimizer>
12
13#include <osgDB/Registry>
14#include <osgDB/ReadFile>
15
16#include <osgProducer/Viewer>
17
18
19// for the grid data..
20#include "../osghangglide/terrain_coords.h"
21
22
23osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power)
24{
25    osg::Image* image = new osg::Image;
26    image->allocateImage(size,size,1,
27                         GL_RGBA,GL_UNSIGNED_BYTE);
28     
29     
30    float mid = (float(size)-1)*0.5f;
31    float div = 2.0f/float(size);
32    for(unsigned int r=0;r<size;++r)
33    {
34        unsigned char* ptr = image->data(0,r,0);
35        for(unsigned int c=0;c<size;++c)
36        {
37            float dx = (float(c) - mid)*div;
38            float dy = (float(r) - mid)*div;
39            float r = powf(1.0f-sqrtf(dx*dx+dy*dy),power);
40            if (r<0.0f) r=0.0f;
41            osg::Vec4 color = centerColour*r+backgroudColour*(1.0f-r);
42            *ptr++ = (unsigned char)((color[0])*255.0f);
43            *ptr++ = (unsigned char)((color[1])*255.0f);
44            *ptr++ = (unsigned char)((color[2])*255.0f);
45            *ptr++ = (unsigned char)((color[3])*255.0f);
46        }
47    }
48    return image;
49
50    //return osgDB::readImageFile("spot.dds");
51}
52
53osg::StateSet* createSpotLightDecoratorState(unsigned int lightNum, unsigned int textureUnit)
54{
55    osg::StateSet* stateset = new osg::StateSet;
56   
57    stateset->setMode(GL_LIGHT0+lightNum, osg::StateAttribute::ON);
58
59    osg::Vec4 centerColour(1.0f,1.0f,1.0f,1.0f);
60    osg::Vec4 ambientColour(0.05f,0.05f,0.05f,1.0f);
61
62    // set up spot light texture
63    osg::Texture2D* texture = new osg::Texture2D();
64    texture->setImage(createSpotLightImage(centerColour, ambientColour, 64, 1.0));
65    texture->setBorderColor(osg::Vec4(ambientColour));
66    texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_BORDER);
67    texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_BORDER);
68    texture->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_BORDER);
69   
70    stateset->setTextureAttributeAndModes(textureUnit, texture, osg::StateAttribute::ON);
71   
72    // set up tex gens
73    stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
74    stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
75    stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON);
76    stateset->setTextureMode(textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON);
77   
78    return stateset;
79}
80
81
82osg::Node* createSpotLightNode(const osg::Vec3& position, const osg::Vec3& direction, float angle, unsigned int lightNum, unsigned int textureUnit)
83{
84    osg::Group* group = new osg::Group;
85   
86    // create light source.
87    osg::LightSource* lightsource = new osg::LightSource;
88    osg::Light* light = lightsource->getLight();
89    light->setLightNum(lightNum);
90    light->setPosition(osg::Vec4(position,1.0f));
91    light->setAmbient(osg::Vec4(0.00f,0.00f,0.05f,1.0f));
92    light->setDiffuse(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
93    group->addChild(lightsource);
94   
95    // create tex gen.
96   
97    osg::Vec3 up(0.0f,0.0f,1.0f);
98    up = (direction ^ up) ^ direction;
99    up.normalize();
100   
101    osg::TexGenNode* texgenNode = new osg::TexGenNode;
102    texgenNode->setTextureUnit(textureUnit);
103    osg::TexGen* texgen = texgenNode->getTexGen();
104    texgen->setMode(osg::TexGen::EYE_LINEAR);
105    texgen->setPlanesFromMatrix(osg::Matrixd::lookAt(position, position+direction, up)*
106                                osg::Matrixd::perspective(angle,1.0,0.1,100));
107
108   
109    group->addChild(texgenNode);
110   
111    return group;
112   
113}
114
115
116osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
117{
118    // set up the animation path
119    osg::AnimationPath* animationPath = new osg::AnimationPath;
120    animationPath->setLoopMode(osg::AnimationPath::LOOP);
121   
122    int numSamples = 40;
123    float yaw = 0.0f;
124    float yaw_delta = 2.0f*osg::PI/((float)numSamples-1.0f);
125    float roll = osg::inDegrees(30.0f);
126   
127    double time=0.0f;
128    double time_delta = looptime/(double)numSamples;
129    for(int i=0;i<numSamples;++i)
130    {
131        osg::Vec3 position(center+osg::Vec3(sinf(yaw)*radius,cosf(yaw)*radius,0.0f));
132        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)));
133       
134        animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation));
135
136        yaw += yaw_delta;
137        time += time_delta;
138
139    }
140    return animationPath;   
141}
142
143osg::Node* createBase(const osg::Vec3& center,float radius)
144{
145
146    osg::Geode* geode = new osg::Geode;
147   
148    // set up the texture of the base.
149    osg::StateSet* stateset = new osg::StateSet();
150    osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
151    if (image)
152    {
153        osg::Texture2D* texture = new osg::Texture2D;
154        texture->setImage(image);
155        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
156    }
157   
158    geode->setStateSet( stateset );
159
160
161    osg::HeightField* grid = new osg::HeightField;
162    grid->allocateGrid(38,39);
163    grid->setOrigin(center+osg::Vec3(-radius,-radius,0.0f));
164    grid->setXInterval(radius*2.0f/(float)(38-1));
165    grid->setYInterval(radius*2.0f/(float)(39-1));
166   
167    float minHeight = FLT_MAX;
168    float maxHeight = -FLT_MAX;
169
170
171    unsigned int r;
172    for(r=0;r<39;++r)
173    {
174        for(unsigned int c=0;c<38;++c)
175        {
176            float h = vertex[r+c*39][2];
177            if (h>maxHeight) maxHeight=h;
178            if (h<minHeight) minHeight=h;
179        }
180    }
181   
182    float hieghtScale = radius*0.5f/(maxHeight-minHeight);
183    float hieghtOffset = -(minHeight+maxHeight)*0.5f;
184
185    for(r=0;r<39;++r)
186    {
187        for(unsigned int c=0;c<38;++c)
188        {
189            float h = vertex[r+c*39][2];
190            grid->setHeight(c,r,(h+hieghtOffset)*hieghtScale);
191        }
192    }
193   
194    geode->addDrawable(new osg::ShapeDrawable(grid));
195     
196    osg::Group* group = new osg::Group;
197    group->addChild(geode);
198     
199    return group;
200
201}
202
203osg::Node* createMovingModel(const osg::Vec3& center, float radius)
204{
205    float animationLength = 10.0f;
206
207    osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
208
209    osg::Group* model = new osg::Group;
210 
211    osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
212    if (cessna)
213    {
214        const osg::BoundingSphere& bs = cessna->getBound();
215
216        float size = radius/bs.radius()*0.3f;
217        osg::MatrixTransform* positioned = new osg::MatrixTransform;
218        positioned->setDataVariance(osg::Object::STATIC);
219        positioned->setMatrix(osg::Matrix::translate(-bs.center())*
220                              osg::Matrix::scale(size,size,size)*
221                              osg::Matrix::rotate(osg::inDegrees(180.0f),0.0f,0.0f,2.0f));
222   
223        positioned->addChild(cessna);
224   
225        osg::MatrixTransform* xform = new osg::MatrixTransform;
226        xform->setUpdateCallback(new osg::AnimationPathCallback(animationPath,0.0f,2.0));
227        xform->addChild(positioned);
228
229        xform->addChild(createSpotLightNode(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(0.0f,1.0f,-1.0f), 60.0f, 0, 1));
230
231        model->addChild(xform);
232    }
233   
234    return model;
235}
236
237
238
239
240osg::Node* createModel()
241{
242    osg::Vec3 center(0.0f,0.0f,0.0f);
243    float radius = 100.0f;
244    osg::Vec3 lightPosition(center+osg::Vec3(0.0f,0.0f,radius));
245
246    // the shadower model
247    osg::Node* shadower = createMovingModel(center,radius*0.5f);
248
249    // the shadowed model
250    osg::Node* shadowed = createBase(center-osg::Vec3(0.0f,0.0f,radius*0.1),radius);
251
252    // combine the models together to create one which has the shadower and the shadowed with the required callback.
253    osg::Group* root = new osg::Group;
254   
255    root->setStateSet(createSpotLightDecoratorState(0,1));
256
257    root->addChild(shadower);
258    root->addChild(shadowed);
259
260    return root;
261}
262
263
264int main( int argc, char **argv )
265{
266
267    // use an ArgumentParser object to manage the program arguments.
268    osg::ArgumentParser arguments(&argc,argv);
269
270    // set up the usage document, in case we need to print out how to use this program.
271    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of pre rendering to texture to create a shadow effect..");
272    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
273    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
274   
275    // construct the viewer.
276    osgProducer::Viewer viewer(arguments);
277
278    // set up the value with sensible default event handlers.
279    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
280
281    // get details on keyboard and mouse bindings used by the viewer.
282    viewer.getUsage(*arguments.getApplicationUsage());
283
284    // if user request help write it out to cout.
285    if (arguments.read("-h") || arguments.read("--help"))
286    {
287        arguments.getApplicationUsage()->write(std::cout);
288        return 1;
289    }
290
291    // any option left unread are converted into errors to write out later.
292    arguments.reportRemainingOptionsAsUnrecognized();
293
294    // report any errors if they have occured when parsing the program aguments.
295    if (arguments.errors())
296    {
297        arguments.writeErrorMessages(std::cout);
298        return 1;
299    }
300   
301    // load the nodes from the commandline arguments.
302    osg::Node* model = createModel();
303    if (!model)
304    {
305        return 1;
306    }
307   
308    // comment out optimization over the scene graph right now as it optimizers away the shadow... will look into this..
309    //osgUtil::Optimizer optimzer;
310    //optimzer.optimize(rootnode);
311     
312    // add a viewport to the viewer and attach the scene graph.
313    viewer.setSceneData( model );
314   
315    // create the windows and run the threads.
316    viewer.realize();
317
318    while( !viewer.done() )
319    {
320        // wait for all cull and draw threads to complete.
321        viewer.sync();
322
323        // update the scene by traversing it with the the update visitor which will
324        // call all node update callbacks and animations.
325        viewer.update();
326         
327        // fire off the cull and draw traversals of the scene.
328        viewer.frame();
329       
330    }
331   
332    // wait for all cull and draw threads to complete before exit.
333    viewer.sync();
334
335    return 0;
336}
Note: See TracBrowser for help on using the browser.