root/OpenSceneGraph/trunk/examples/osglight/osglight.cpp @ 1983

Revision 1983, 12.0 kB (checked in by don, 11 years ago)

*** empty log message ***

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osgProducer/Viewer>
2
3#include <osg/Group>
4#include <osg/Node>
5
6#include <osg/Light>
7#include <osg/LightSource>
8#include <osg/StateAttribute>
9#include <osg/Geometry>
10#include <osg/Point>
11
12#include <osg/MatrixTransform>
13#include <osg/PositionAttitudeTransform>
14
15#include <osgDB/Registry>
16#include <osgDB/ReadFile>
17
18#include <osgUtil/Optimizer>
19#include <osgUtil/SmoothingVisitor>
20
21#include "stdio.h"
22
23
24// callback to make the loaded model oscilate up and down.
25class ModelTransformCallback : public osg::NodeCallback
26{
27    public:
28
29        ModelTransformCallback(const osg::BoundingSphere& bs)
30        {
31            _firstTime = 0.0;
32            _period = 4.0f;
33            _range = bs.radius()*0.5f;
34        }
35   
36        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
37        {
38            osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>(node);
39            const osg::FrameStamp* frameStamp = nv->getFrameStamp();
40            if (pat && frameStamp)
41            {
42                if (_firstTime==0.0)
43                {
44                    _firstTime = frameStamp->getReferenceTime();
45                }
46               
47                double phase = (frameStamp->getReferenceTime()-_firstTime)/_period;
48                phase -= floor(phase);
49                phase *= (2.0 * osg::PI);
50           
51                osg::Quat rotation;
52                rotation.makeRotate(phase,1.0f,1.0f,1.0f);
53               
54                pat->setAttitude(rotation);
55               
56                pat->setPosition(osg::Vec3(0.0f,0.0f,sin(phase))*_range);
57            }
58       
59            // must traverse the Node's subgraph           
60            traverse(node,nv);
61        }
62       
63        double _firstTime;
64        double _period;
65        double _range;
66
67};
68
69
70osg::Node* createLights(osg::BoundingBox& bb,osg::StateSet* rootStateSet)
71{
72    osg::Group* lightGroup = new osg::Group;
73   
74    float modelSize = bb.radius();
75
76    // create a spot light.
77    osg::Light* myLight1 = new osg::Light;
78    myLight1->setLightNum(0);
79    myLight1->setPosition(osg::Vec4(bb.corner(4),1.0f));
80    myLight1->setAmbient(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
81    myLight1->setDiffuse(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
82    myLight1->setSpotCutoff(20.0f);
83    myLight1->setSpotExponent(50.0f);
84    myLight1->setDirection(osg::Vec3(1.0f,1.0f,-1.0f));
85
86    osg::LightSource* lightS1 = new osg::LightSource;   
87    lightS1->setLight(myLight1);
88    lightS1->setLocalStateSetModes(osg::StateAttribute::ON);
89
90    lightS1->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
91    lightGroup->addChild(lightS1);
92   
93
94    // create a local light.
95    osg::Light* myLight2 = new osg::Light;
96    myLight2->setLightNum(1);
97    myLight2->setPosition(osg::Vec4(0.0,0.0,0.0,1.0f));
98    myLight2->setAmbient(osg::Vec4(0.0f,1.0f,1.0f,1.0f));
99    myLight2->setDiffuse(osg::Vec4(0.0f,1.0f,1.0f,1.0f));
100    myLight2->setConstantAttenuation(1.0f);
101    myLight2->setLinearAttenuation(2.0f/modelSize);
102    myLight2->setQuadraticAttenuation(2.0f/osg::square(modelSize));
103
104    osg::LightSource* lightS2 = new osg::LightSource;   
105    lightS2->setLight(myLight2);
106    lightS2->setLocalStateSetModes(osg::StateAttribute::ON);
107
108    lightS2->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
109   
110    osg::MatrixTransform* mt = new osg::MatrixTransform();
111    {
112        // set up the animation path
113        osg::AnimationPath* animationPath = new osg::AnimationPath;
114        animationPath->insert(0.0,osg::AnimationPath::ControlPoint(bb.corner(0)));
115        animationPath->insert(1.0,osg::AnimationPath::ControlPoint(bb.corner(1)));
116        animationPath->insert(2.0,osg::AnimationPath::ControlPoint(bb.corner(2)));
117        animationPath->insert(3.0,osg::AnimationPath::ControlPoint(bb.corner(3)));
118        animationPath->insert(4.0,osg::AnimationPath::ControlPoint(bb.corner(4)));
119        animationPath->insert(5.0,osg::AnimationPath::ControlPoint(bb.corner(5)));
120        animationPath->insert(6.0,osg::AnimationPath::ControlPoint(bb.corner(6)));
121        animationPath->insert(7.0,osg::AnimationPath::ControlPoint(bb.corner(7)));
122        animationPath->insert(8.0,osg::AnimationPath::ControlPoint(bb.corner(0)));
123        animationPath->setLoopMode(osg::AnimationPath::SWING);
124       
125        mt->setUpdateCallback(new osg::AnimationPathCallback(animationPath));
126    }
127   
128    // create marker for point light.
129    osg::Geometry* marker = new osg::Geometry;
130    osg::Vec3Array* vertices = new osg::Vec3Array;
131    vertices->push_back(osg::Vec3(0.0,0.0,0.0));
132    marker->setVertexArray(vertices);
133    marker->addPrimitiveSet(new osg::DrawArrays(GL_POINTS,0,1));
134   
135    osg::StateSet* stateset = new osg::StateSet;
136    osg::Point* point = new osg::Point;
137    point->setSize(4.0f);
138    stateset->setAttribute(point);
139   
140    marker->setStateSet(stateset);
141   
142    osg::Geode* markerGeode = new osg::Geode;
143    markerGeode->addDrawable(marker);
144   
145    mt->addChild(lightS2);
146    mt->addChild(markerGeode);
147   
148    lightGroup->addChild(mt);
149
150    return lightGroup;
151}
152
153osg::Geometry* createWall(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,osg::StateSet* stateset)
154{
155
156   // create a drawable for occluder.
157    osg::Geometry* geom = new osg::Geometry;
158   
159    geom->setStateSet(stateset);
160
161    unsigned int noXSteps = 100;
162    unsigned int noYSteps = 100;
163   
164    osg::Vec3Array* coords = new osg::Vec3Array;
165    coords->reserve(noXSteps*noYSteps);
166   
167   
168    osg::Vec3 dx = (v2-v1)/((float)noXSteps-1.0f);
169    osg::Vec3 dy = (v3-v1)/((float)noYSteps-1.0f);
170   
171    unsigned int row;
172    osg::Vec3 vRowStart = v1;
173    for(row=0;row<noYSteps;++row)
174    {
175        osg::Vec3 v = vRowStart;
176        for(unsigned int col=0;col<noXSteps;++col)       
177        {
178            coords->push_back(v);
179            v += dx;
180        }
181        vRowStart+=dy;
182    }
183   
184    geom->setVertexArray(coords);
185   
186    osg::Vec4Array* colors = new osg::Vec4Array(1);
187    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
188    geom->setColorArray(colors);
189    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
190   
191   
192    for(row=0;row<noYSteps-1;++row)
193    {
194        osg::DrawElementsUShort* quadstrip = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP);
195        quadstrip->reserve(noXSteps*2);
196        for(unsigned int col=0;col<noXSteps;++col)       
197        {
198            quadstrip->push_back((row+1)*noXSteps+col);
199            quadstrip->push_back(row*noXSteps+col);
200        }   
201        geom->addPrimitiveSet(quadstrip);
202    }
203   
204    // create the normals.   
205    osgUtil::SmoothingVisitor::smooth(*geom);
206   
207    return geom;
208 
209}
210
211
212osg::Node* createRoom(osg::Node* loadedModel)
213{
214    // default scale for this model.
215    osg::BoundingSphere bs(osg::Vec3(0.0f,0.0f,0.0f),1.0f);
216
217    osg::Group* root = new osg::Group;
218
219    if (loadedModel)
220    {
221        const osg::BoundingSphere& loaded_bs = loadedModel->getBound();
222
223        osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform();
224        pat->setPivotPoint(loaded_bs.center());
225       
226        pat->setUpdateCallback(new ModelTransformCallback(loaded_bs));
227        pat->addChild(loadedModel);
228       
229        bs = pat->getBound();
230       
231        root->addChild(pat);
232
233    }
234
235    bs.radius()*=1.5f;
236
237    // create a bounding box, which we'll use to size the room.
238    osg::BoundingBox bb;
239    bb.expandBy(bs);
240
241
242    // create statesets.
243    osg::StateSet* rootStateSet = new osg::StateSet;
244    root->setStateSet(rootStateSet);
245
246    osg::StateSet* wall = new osg::StateSet;
247    wall->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
248   
249    osg::StateSet* floor = new osg::StateSet;
250    floor->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
251
252    osg::StateSet* roof = new osg::StateSet;
253    roof->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
254
255    osg::Geode* geode = new osg::Geode;
256   
257    // create front side.
258    geode->addDrawable(createWall(bb.corner(0),
259                                  bb.corner(4),
260                                  bb.corner(1),
261                                  wall));
262
263    // right side
264    geode->addDrawable(createWall(bb.corner(1),
265                                  bb.corner(5),
266                                  bb.corner(3),
267                                  wall));
268
269    // left side
270    geode->addDrawable(createWall(bb.corner(2),
271                                  bb.corner(6),
272                                  bb.corner(0),
273                                  wall));
274    // back side
275    geode->addDrawable(createWall(bb.corner(3),
276                                  bb.corner(7),
277                                  bb.corner(2),
278                                  wall));
279
280    // floor
281    geode->addDrawable(createWall(bb.corner(0),
282                                  bb.corner(1),
283                                  bb.corner(2),
284                                  floor));
285
286    // roof
287    geode->addDrawable(createWall(bb.corner(6),
288                                  bb.corner(7),
289                                  bb.corner(4),
290                                  roof));
291
292    root->addChild(geode);
293   
294    root->addChild(createLights(bb,rootStateSet));
295
296    return root;
297   
298}   
299
300int main( int argc, char **argv )
301{
302    // use an ArgumentParser object to manage the program arguments.
303    osg::ArgumentParser arguments(&argc,argv);
304
305    // set up the usage document, in case we need to print out how to use this program.
306    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of OpenGL vertex lighting.");
307    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
308    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
309
310    // construct the viewer.
311    osgProducer::Viewer viewer(arguments);
312
313    // set up the value with sensible default event handlers.
314    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
315
316    // get details on keyboard and mouse bindings used by the viewer.
317    viewer.getUsage(*arguments.getApplicationUsage());
318
319    // if user request help write it out to cout.
320    if (arguments.read("-h") || arguments.read("--help"))
321    {
322        arguments.getApplicationUsage()->write(std::cout);
323        return 1;
324    }
325
326    // any option left unread are converted into errors to write out later.
327    arguments.reportRemainingOptionsAsUnrecognized();
328
329    // report any errors if they have occured when parsing the program aguments.
330    if (arguments.errors())
331    {
332        arguments.writeErrorMessages(std::cout);
333        return 1;
334    }
335
336    // load the nodes from the commandline arguments.
337    osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
338
339    // create a room made of foor walls, a floor, a roof, and swinging light fitting.
340    osg::Node* rootnode = createRoom(loadedModel);
341
342    // run optimization over the scene graph
343    osgUtil::Optimizer optimzer;
344    optimzer.optimize(rootnode);
345     
346    // add a viewport to the viewer and attach the scene graph.
347    viewer.setSceneData( rootnode );
348   
349
350    // create the windows and run the threads.
351    viewer.realize();
352
353    // set all the sceneview's up so that their left and right add cull masks are set up.
354    for(osgProducer::OsgCameraGroup::SceneHandlerList::iterator itr=viewer.getSceneHandlerList().begin();
355        itr!=viewer.getSceneHandlerList().end();
356        ++itr)
357    {
358        // switch off small feature culling to prevent the light points from being culled.
359        osgUtil::SceneView* sceneview = (*itr)->getSceneView();
360        sceneview->setCullingMode( sceneview->getCullingMode() & ~osg::CullStack::SMALL_FEATURE_CULLING);
361    }
362
363    while( !viewer.done() )
364    {
365        // wait for all cull and draw threads to complete.
366        viewer.sync();
367
368        // update the scene by traversing it with the the update visitor which will
369        // call all node update callbacks and animations.
370        viewer.update();
371         
372        // fire off the cull and draw traversals of the scene.
373        viewer.frame();
374   
375        // wait for all cull and draw threads to complete before exit.
376        viewer.sync();
377       
378    }
379
380    return 0;
381}
Note: See TracBrowser for help on using the browser.