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

Revision 13574, 10.7 kB (checked in by robert, 5 hours ago)

Removed usage of _appliedProgramObjectSet as it's no longer used by OSG applications and was causing a threading crash.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osglight.
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 <osgViewer/Viewer>
20
21#include <osg/Group>
22#include <osg/Node>
23
24#include <osg/Light>
25#include <osg/LightSource>
26#include <osg/StateAttribute>
27#include <osg/Geometry>
28#include <osg/Point>
29
30#include <osg/MatrixTransform>
31#include <osg/PositionAttitudeTransform>
32
33#include <osgDB/Registry>
34#include <osgDB/ReadFile>
35
36#include <osgUtil/Optimizer>
37#include <osgUtil/SmoothingVisitor>
38
39#include "stdio.h"
40
41
42// callback to make the loaded model oscilate up and down.
43class ModelTransformCallback : public osg::NodeCallback
44{
45    public:
46
47        ModelTransformCallback(const osg::BoundingSphere& bs)
48        {
49            _firstTime = 0.0;
50            _period = 4.0f;
51            _range = bs.radius()*0.5f;
52        }
53
54        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
55        {
56            osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>(node);
57            const osg::FrameStamp* frameStamp = nv->getFrameStamp();
58            if (pat && frameStamp)
59            {
60                if (_firstTime==0.0)
61                {
62                    _firstTime = frameStamp->getSimulationTime();
63                }
64
65                double phase = (frameStamp->getSimulationTime()-_firstTime)/_period;
66                phase -= floor(phase);
67                phase *= (2.0 * osg::PI);
68
69                osg::Quat rotation;
70                rotation.makeRotate(phase,1.0f,1.0f,1.0f);
71
72                pat->setAttitude(rotation);
73
74                pat->setPosition(osg::Vec3(0.0f,0.0f,sin(phase))*_range);
75            }
76
77            // must traverse the Node's subgraph
78            traverse(node,nv);
79        }
80
81        double _firstTime;
82        double _period;
83        double _range;
84
85};
86
87
88osg::Node* createLights(osg::BoundingBox& bb,osg::StateSet* rootStateSet)
89{
90    osg::Group* lightGroup = new osg::Group;
91
92    float modelSize = bb.radius();
93
94    // create a spot light.
95    osg::Light* myLight1 = new osg::Light;
96    myLight1->setLightNum(0);
97    myLight1->setPosition(osg::Vec4(bb.corner(4),1.0f));
98    myLight1->setAmbient(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
99    myLight1->setDiffuse(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
100    myLight1->setSpotCutoff(20.0f);
101    myLight1->setSpotExponent(50.0f);
102    myLight1->setDirection(osg::Vec3(1.0f,1.0f,-1.0f));
103
104    osg::LightSource* lightS1 = new osg::LightSource;
105    lightS1->setLight(myLight1);
106    lightS1->setLocalStateSetModes(osg::StateAttribute::ON);
107
108    lightS1->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
109    lightGroup->addChild(lightS1);
110
111
112    // create a local light.
113    osg::Light* myLight2 = new osg::Light;
114    myLight2->setLightNum(1);
115    myLight2->setPosition(osg::Vec4(0.0,0.0,0.0,1.0f));
116    myLight2->setAmbient(osg::Vec4(0.0f,1.0f,1.0f,1.0f));
117    myLight2->setDiffuse(osg::Vec4(0.0f,1.0f,1.0f,1.0f));
118    myLight2->setConstantAttenuation(1.0f);
119    myLight2->setLinearAttenuation(2.0f/modelSize);
120    myLight2->setQuadraticAttenuation(2.0f/osg::square(modelSize));
121
122    osg::LightSource* lightS2 = new osg::LightSource;
123    lightS2->setLight(myLight2);
124    lightS2->setLocalStateSetModes(osg::StateAttribute::ON);
125
126    lightS2->setStateSetModes(*rootStateSet,osg::StateAttribute::ON);
127
128    osg::MatrixTransform* mt = new osg::MatrixTransform();
129    {
130        // set up the animation path
131        osg::AnimationPath* animationPath = new osg::AnimationPath;
132        animationPath->insert(0.0,osg::AnimationPath::ControlPoint(bb.corner(0)));
133        animationPath->insert(1.0,osg::AnimationPath::ControlPoint(bb.corner(1)));
134        animationPath->insert(2.0,osg::AnimationPath::ControlPoint(bb.corner(2)));
135        animationPath->insert(3.0,osg::AnimationPath::ControlPoint(bb.corner(3)));
136        animationPath->insert(4.0,osg::AnimationPath::ControlPoint(bb.corner(4)));
137        animationPath->insert(5.0,osg::AnimationPath::ControlPoint(bb.corner(5)));
138        animationPath->insert(6.0,osg::AnimationPath::ControlPoint(bb.corner(6)));
139        animationPath->insert(7.0,osg::AnimationPath::ControlPoint(bb.corner(7)));
140        animationPath->insert(8.0,osg::AnimationPath::ControlPoint(bb.corner(0)));
141        animationPath->setLoopMode(osg::AnimationPath::SWING);
142
143        mt->setUpdateCallback(new osg::AnimationPathCallback(animationPath));
144    }
145
146    // create marker for point light.
147    osg::Geometry* marker = new osg::Geometry;
148    osg::Vec3Array* vertices = new osg::Vec3Array;
149    vertices->push_back(osg::Vec3(0.0,0.0,0.0));
150    marker->setVertexArray(vertices);
151    marker->addPrimitiveSet(new osg::DrawArrays(GL_POINTS,0,1));
152
153    osg::StateSet* stateset = new osg::StateSet;
154    osg::Point* point = new osg::Point;
155    point->setSize(4.0f);
156    stateset->setAttribute(point);
157
158    marker->setStateSet(stateset);
159
160    osg::Geode* markerGeode = new osg::Geode;
161    markerGeode->addDrawable(marker);
162
163    mt->addChild(lightS2);
164    mt->addChild(markerGeode);
165
166    lightGroup->addChild(mt);
167
168    return lightGroup;
169}
170
171osg::Geometry* createWall(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,osg::StateSet* stateset)
172{
173
174   // create a drawable for occluder.
175    osg::Geometry* geom = new osg::Geometry;
176
177    geom->setStateSet(stateset);
178
179    unsigned int noXSteps = 100;
180    unsigned int noYSteps = 100;
181
182    osg::Vec3Array* coords = new osg::Vec3Array;
183    coords->reserve(noXSteps*noYSteps);
184
185
186    osg::Vec3 dx = (v2-v1)/((float)noXSteps-1.0f);
187    osg::Vec3 dy = (v3-v1)/((float)noYSteps-1.0f);
188
189    unsigned int row;
190    osg::Vec3 vRowStart = v1;
191    for(row=0;row<noYSteps;++row)
192    {
193        osg::Vec3 v = vRowStart;
194        for(unsigned int col=0;col<noXSteps;++col)
195        {
196            coords->push_back(v);
197            v += dx;
198        }
199        vRowStart+=dy;
200    }
201
202    geom->setVertexArray(coords);
203
204    osg::Vec4Array* colors = new osg::Vec4Array(1);
205    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
206    geom->setColorArray(colors, osg::Array::BIND_OVERALL);
207
208
209    for(row=0;row<noYSteps-1;++row)
210    {
211        osg::DrawElementsUShort* quadstrip = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP);
212        quadstrip->reserve(noXSteps*2);
213        for(unsigned int col=0;col<noXSteps;++col)
214        {
215            quadstrip->push_back((row+1)*noXSteps+col);
216            quadstrip->push_back(row*noXSteps+col);
217        }
218        geom->addPrimitiveSet(quadstrip);
219    }
220
221    // create the normals.
222    osgUtil::SmoothingVisitor::smooth(*geom);
223
224    return geom;
225
226}
227
228
229osg::Node* createRoom(osg::Node* loadedModel)
230{
231    // default scale for this model.
232    osg::BoundingSphere bs(osg::Vec3(0.0f,0.0f,0.0f),1.0f);
233
234    osg::Group* root = new osg::Group;
235
236    if (loadedModel)
237    {
238        const osg::BoundingSphere& loaded_bs = loadedModel->getBound();
239
240        osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform();
241        pat->setPivotPoint(loaded_bs.center());
242
243        pat->setUpdateCallback(new ModelTransformCallback(loaded_bs));
244        pat->addChild(loadedModel);
245
246        bs = pat->getBound();
247
248        root->addChild(pat);
249
250    }
251
252    bs.radius()*=1.5f;
253
254    // create a bounding box, which we'll use to size the room.
255    osg::BoundingBox bb;
256    bb.expandBy(bs);
257
258
259    // create statesets.
260    osg::StateSet* rootStateSet = new osg::StateSet;
261    root->setStateSet(rootStateSet);
262
263    osg::StateSet* wall = new osg::StateSet;
264    wall->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
265
266    osg::StateSet* floor = new osg::StateSet;
267    floor->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
268
269    osg::StateSet* roof = new osg::StateSet;
270    roof->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
271
272    osg::Geode* geode = new osg::Geode;
273
274    // create front side.
275    geode->addDrawable(createWall(bb.corner(0),
276                                  bb.corner(4),
277                                  bb.corner(1),
278                                  wall));
279
280    // right side
281    geode->addDrawable(createWall(bb.corner(1),
282                                  bb.corner(5),
283                                  bb.corner(3),
284                                  wall));
285
286    // left side
287    geode->addDrawable(createWall(bb.corner(2),
288                                  bb.corner(6),
289                                  bb.corner(0),
290                                  wall));
291    // back side
292    geode->addDrawable(createWall(bb.corner(3),
293                                  bb.corner(7),
294                                  bb.corner(2),
295                                  wall));
296
297    // floor
298    geode->addDrawable(createWall(bb.corner(0),
299                                  bb.corner(1),
300                                  bb.corner(2),
301                                  floor));
302
303    // roof
304    geode->addDrawable(createWall(bb.corner(6),
305                                  bb.corner(7),
306                                  bb.corner(4),
307                                  roof));
308
309    root->addChild(geode);
310
311    root->addChild(createLights(bb,rootStateSet));
312
313    return root;
314
315}
316
317int main( int argc, char **argv )
318{
319    // use an ArgumentParser object to manage the program arguments.
320    osg::ArgumentParser arguments(&argc,argv);
321
322    // construct the viewer.
323    osgViewer::Viewer viewer;
324
325    // load the nodes from the commandline arguments.
326    osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
327
328    // if not loaded assume no arguments passed in, try use default mode instead.
329    if (!loadedModel) loadedModel = osgDB::readNodeFile("glider.osgt");
330
331    // create a room made of foor walls, a floor, a roof, and swinging light fitting.
332    osg::Node* rootnode = createRoom(loadedModel);
333
334    // run optimization over the scene graph
335    osgUtil::Optimizer optimzer;
336    optimzer.optimize(rootnode);
337
338    // add a viewport to the viewer and attach the scene graph.
339    viewer.setSceneData( rootnode );
340
341
342    // create the windows and run the threads.
343    viewer.realize();
344
345    viewer.getCamera()->setCullingMode( viewer.getCamera()->getCullingMode() & ~osg::CullStack::SMALL_FEATURE_CULLING);
346
347    return viewer.run();
348}
Note: See TracBrowser for help on using the browser.