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

Revision 13574, 10.7 kB (checked in by robert, 14 hours 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, 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.