root/OpenSceneGraph/trunk/examples/osganimationmakepath/osganimationmakepath.cpp @ 9395

Revision 9395, 11.8 kB (checked in by robert, 5 years ago)

Fixed warnings

Line 
1/*  -*-c++-*-
2 *  Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
3 *
4 * This library is open source and may be redistributed and/or modified under 
5 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
6 * (at your option) any later version.  The full license is in LICENSE file
7 * included with this distribution, and on the openscenegraph.org website.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * OpenSceneGraph Public License for more details.
13 *
14 *  Authors:
15 *   Jeremy Moles  <jeremy@emperorlinux.com>
16 *   Cedric Pinson <mornifle@plopbyte.net>
17*/
18
19#include <iostream>
20#include <osg/io_utils>
21#include <osg/Geometry>
22#include <osg/Shape>
23#include <osg/ShapeDrawable>
24#include <osg/Material>
25#include <osg/MatrixTransform>
26#include <osgViewer/Viewer>
27#include <osgViewer/ViewerEventHandlers>
28#include <osgGA/TrackballManipulator>
29#include <osgAnimation/Sampler>
30
31  class AnimtkUpdateCallback : public osg::NodeCallback
32  {
33  public:
34      META_Object(osgAnimation, AnimtkUpdateCallback);
35
36      AnimtkUpdateCallback()
37      {
38          _sampler = new osgAnimation::Vec3CubicBezierSampler;
39          _playing = false;
40          _lastUpdate = 0;
41      }
42      AnimtkUpdateCallback(const AnimtkUpdateCallback& val, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY):
43          osg::Object(val, copyop),
44          osg::NodeCallback(val, copyop),
45          _sampler(val._sampler),
46          _startTime(val._startTime),
47          _currentTime(val._currentTime),
48          _playing(val._playing),
49          _lastUpdate(val._lastUpdate)
50      {
51      }
52
53      /** Callback method called by the NodeVisitor when visiting a node.*/
54      virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
55      {
56          if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR &&
57              nv->getFrameStamp() &&
58              nv->getFrameStamp()->getFrameNumber() != _lastUpdate)
59          {
60
61              _lastUpdate = nv->getFrameStamp()->getFrameNumber();
62              _currentTime = osg::Timer::instance()->tick();
63
64              if (_playing && _sampler.get() && _sampler->getKeyframeContainer())
65              {
66                  osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);
67                  if (transform) {
68                      osg::Vec3 result;
69                      float t = osg::Timer::instance()->delta_s(_startTime, _currentTime);
70                      float duration = _sampler->getEndTime() - _sampler->getStartTime();
71                      t = fmod(t, duration);
72                      t += _sampler->getStartTime();
73                      _sampler->getValueAt(t, result);
74                      transform->setMatrix(osg::Matrix::translate(result));
75                  }
76              }
77          }
78          // note, callback is responsible for scenegraph traversal so
79          // they must call traverse(node,nv) to ensure that the
80          // scene graph subtree (and associated callbacks) are traversed.
81          traverse(node,nv);
82      }
83
84      void start() { _startTime = osg::Timer::instance()->tick(); _currentTime = _startTime; _playing = true;}
85      void stop() { _currentTime = _startTime; _playing = false;}
86
87      osg::ref_ptr<osgAnimation::Vec3CubicBezierSampler> _sampler;
88      osg::Timer_t _startTime;
89      osg::Timer_t _currentTime;
90      bool _playing;
91      int _lastUpdate;
92  };
93
94
95class AnimtkStateSetUpdateCallback : public osg::StateSet::Callback
96{
97public:
98    META_Object(osgAnimation, AnimtkStateSetUpdateCallback);
99
100    AnimtkStateSetUpdateCallback()
101    {
102        _sampler = new osgAnimation::Vec4LinearSampler;
103        _playing = false;
104        _lastUpdate = 0;
105    }
106
107    AnimtkStateSetUpdateCallback(const AnimtkStateSetUpdateCallback& val, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY):
108        osg::Object(val, copyop),
109        osg::StateSet::Callback(val, copyop),
110        _sampler(val._sampler),
111        _startTime(val._startTime),
112        _currentTime(val._currentTime),
113        _playing(val._playing),
114        _lastUpdate(val._lastUpdate)
115    {
116    }
117
118    /** Callback method called by the NodeVisitor when visiting a node.*/
119    virtual void operator()(osg::StateSet* state, osg::NodeVisitor* nv)
120    {
121        if (state &&
122            nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR &&
123            nv->getFrameStamp() &&
124            nv->getFrameStamp()->getFrameNumber() != _lastUpdate) {
125
126            _lastUpdate = nv->getFrameStamp()->getFrameNumber();
127            _currentTime = osg::Timer::instance()->tick();
128
129            if (_playing && _sampler.get() && _sampler->getKeyframeContainer())
130            {
131                osg::Material* material = dynamic_cast<osg::Material*>(state->getAttribute(osg::StateAttribute::MATERIAL));
132                if (material)
133                {
134                    osg::Vec4 result;
135                    float t = osg::Timer::instance()->delta_s(_startTime, _currentTime);
136                    float duration = _sampler->getEndTime() - _sampler->getStartTime();
137                    t = fmod(t, duration);
138                    t += _sampler->getStartTime();
139                    _sampler->getValueAt(t, result);
140                    material->setDiffuse(osg::Material::FRONT_AND_BACK, result);
141                }
142            }
143        }
144    }
145
146    void start() { _startTime = osg::Timer::instance()->tick(); _currentTime = _startTime; _playing = true;}
147    void stop() { _currentTime = _startTime; _playing = false;}
148
149    osg::ref_ptr<osgAnimation::Vec4LinearSampler> _sampler;
150    osg::Timer_t _startTime;
151    osg::Timer_t _currentTime;
152    bool _playing;
153    int _lastUpdate;
154};
155
156// This won't really give good results in any situation, but it does demonstrate
157// on possible "fast" usage...
158class MakePathTimeCallback: public AnimtkUpdateCallback
159{
160    osg::ref_ptr<osg::Geode> _geode;
161    float _lastAdd;
162    float _addSeconds;
163
164public:
165    MakePathTimeCallback(osg::Geode* geode):
166        _geode(geode),
167        _lastAdd(0.0f),
168        _addSeconds(0.08f) {
169    }
170
171    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
172    {
173        float t = osg::Timer::instance()->delta_s(_startTime, _currentTime);
174
175        if(_lastAdd + _addSeconds <= t && t <= 8.0f)
176        {
177            osg::Vec3 pos;
178
179            _sampler->getValueAt(t, pos);
180
181            _geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(pos, 0.5f)));
182            _geode->dirtyBound();
183
184            _lastAdd += _addSeconds;
185        }
186
187        AnimtkUpdateCallback::operator()(node, nv);
188    }
189};
190
191// This will give great results if you DO NOT have VSYNC enabled and can generate
192// decent FPS.
193class MakePathDistanceCallback: public AnimtkUpdateCallback
194{
195    osg::ref_ptr<osg::Geode> _geode;
196    osg::Vec3 _lastAdd;
197    float _threshold;
198    unsigned int _count;
199
200public:
201    MakePathDistanceCallback(osg::Geode* geode):
202        _geode(geode),
203        _threshold(0.5f),
204        _count(0) {}
205
206    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
207    {
208        static bool countReported = false;
209
210        float t = osg::Timer::instance()->delta_s(_startTime, _currentTime);
211
212        osg::Vec3 pos;
213
214        _sampler->getValueAt(t, pos);
215
216        osg::Vec3 distance = _lastAdd - pos;
217
218        if(t <= 8.0f && distance.length() >= _threshold)
219        {
220            _geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(pos, 0.25f)));
221            _lastAdd = pos;
222            _count++;
223        }
224        else if(t > 8.0f)
225        {
226            if(!countReported) std::cout << "Created " << _count << " nodes." << std::endl;
227            countReported = true;
228        }
229
230        AnimtkUpdateCallback::operator()(node, nv);
231    }
232};
233
234osg::StateSet* setupStateSet()
235{
236    osg::StateSet* st = new osg::StateSet();
237   
238    st->setAttributeAndModes(new osg::Material(), true);
239    st->setMode(GL_BLEND, true);
240   
241    AnimtkStateSetUpdateCallback* callback = new AnimtkStateSetUpdateCallback();
242    osgAnimation::Vec4KeyframeContainer* keys = callback->_sampler->getOrCreateKeyframeContainer();
243    keys->push_back(osgAnimation::Vec4Keyframe(0, osg::Vec4(1,0,0,1)));
244    keys->push_back(osgAnimation::Vec4Keyframe(2, osg::Vec4(0.,1,0,1)));
245    keys->push_back(osgAnimation::Vec4Keyframe(4, osg::Vec4(0,0,1,1)));
246    keys->push_back(osgAnimation::Vec4Keyframe(6, osg::Vec4(0,0,1,1)));
247    keys->push_back(osgAnimation::Vec4Keyframe(8, osg::Vec4(0,1,0,1)));
248    keys->push_back(osgAnimation::Vec4Keyframe(10, osg::Vec4(1,0,0,1)));
249    callback->start();
250    st->setUpdateCallback(callback);
251   
252    return st;
253}
254
255osg::MatrixTransform* setupAnimtkNode(osg::Geode* staticGeode)
256{
257    osg::Vec3 v[5];
258
259    v[0] = osg::Vec3(  0,   0,   0);
260    v[1] = osg::Vec3(20, 40, 60);
261    v[2] = osg::Vec3(40, 60, 20);
262    v[3] = osg::Vec3(60, 20, 40);
263    v[4] = osg::Vec3( 0,  0,  0);
264
265    osg::MatrixTransform* node = new osg::MatrixTransform();
266    AnimtkUpdateCallback* callback = new MakePathDistanceCallback(staticGeode);
267    osgAnimation::Vec3CubicBezierKeyframeContainer* keys = callback->_sampler->getOrCreateKeyframeContainer();
268
269    keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(0, osgAnimation::Vec3CubicBezier(
270                                                        v[0],
271                                                        v[0] + (v[0] - v[3]),
272                                                        v[1] - (v[1] - v[0])
273                                                        )));
274
275    keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(2, osgAnimation::Vec3CubicBezier(
276                                                        v[1],
277                                                        v[1] + (v[1] - v[0]),
278                                                        v[2] - (v[2] - v[1])
279                                                        )));
280
281    keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(4, osgAnimation::Vec3CubicBezier(
282                                                        v[2],
283                                                        v[2] + (v[2] - v[1]),
284                                                        v[3] - (v[3] - v[2])
285                                                        )));
286
287    keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(6, osgAnimation::Vec3CubicBezier(
288                                                        v[3],
289                                                        v[3] + (v[3] - v[2]),
290                                                        v[4] - (v[4] - v[3])
291                                                        )));
292
293    keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(8, osgAnimation::Vec3CubicBezier(
294                                                        v[4],
295                                                        v[4] + (v[4] - v[3]),
296                                                        v[0] - (v[0] - v[4])
297                                                        )));
298
299    callback->start();
300    node->setUpdateCallback(callback);
301
302    osg::Geode* geode = new osg::Geode();
303   
304    geode->setStateSet(setupStateSet());
305    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 2)));
306   
307    node->addChild(geode);
308
309    return node;
310}
311
312int main(int argc, char** argv)
313{
314    osgViewer::Viewer viewer;
315   
316    osgGA::TrackballManipulator* tbm = new osgGA::TrackballManipulator();
317
318    viewer.setCameraManipulator(tbm);
319
320    viewer.addEventHandler(new osgViewer::StatsHandler());
321    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
322
323    osg::Group* root = new osg::Group();
324    osg::Geode* geode = new osg::Geode();
325
326    geode->setStateSet(setupStateSet());
327
328    root->setInitialBound(osg::BoundingSphere(osg::Vec3(10,0,20), 50));
329    root->addChild(setupAnimtkNode(geode));
330    root->addChild(geode);
331
332    viewer.setSceneData(root);
333
334    // tbm->setDistance(150);
335
336    return viewer.run();
337}
Note: See TracBrowser for help on using the browser.