root/OpenSceneGraph/trunk/examples/osgsequence/osgsequence.cpp @ 6912

Revision 6912, 7.3 kB (checked in by robert, 8 years ago)

Added fallback for when no command line args are passed in.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// -*-c++-*-
2
3/*
4 * This application is open source and may be redistributed and/or modified   
5 * freely and without restriction, both in commericial and non commericial
6 * applications,as long as this copyright notice is maintained.
7 *
8 * This application is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11*/
12
13#include <osgText/Text>
14#include <osg/Geode>
15#include <osg/Group>
16#include <osg/Projection>
17#include <osg/Sequence>
18#include <osg/MatrixTransform>
19
20#include <osgDB/ReadFile>
21
22#include <osgViewer/Viewer>
23
24#include <iostream>
25
26// create text drawable at 'pos'
27osg::Geode* createText(const std::string& str, const osg::Vec3& pos)
28{
29    // text drawable
30    osgText::Text* text = new osgText::Text;
31    text->setFont(std::string("fonts/arial.ttf"));
32    text->setPosition(pos);
33    text->setText(str);
34
35    // geode
36    osg::Geode* geode = new osg::Geode;
37    geode->addDrawable(text);
38
39    return geode;
40}
41
42osg::Node* createTextGroup(const char** text)
43{
44    osg::Group* group = new osg::Group;
45
46    osg::Vec3 pos(120.0f, 800.0f, 0.0f);
47    const osg::Vec3 delta(0.0f, -60.0f, 0.0f);
48
49    // header
50    const char** t = text;
51    group->addChild(createText(*t++, pos));
52    pos += delta;
53
54    // remainder of text under sequence
55    osg::Sequence* seq = new osg::Sequence;
56    group->addChild(seq);
57    while (*t) {
58        seq->addChild(createText(*t++, pos));
59        seq->setTime(seq->getNumChildren()-1, 2.0f);
60        pos += delta;
61    }
62
63    // loop through all children
64    seq->setInterval(osg::Sequence::LOOP, 0,-1);
65
66    // real-time playback, repeat indefinitively
67    seq->setDuration(1.0f, -1);
68
69    // must be started explicitly
70    seq->setMode(osg::Sequence::START);
71
72    return group;
73}
74
75osg::Node* createHUD(osg::Node* node)
76{
77    // absolute transform
78    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
79    modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
80    modelview_abs->setMatrix(osg::Matrix::identity());
81    modelview_abs->addChild(node);
82
83    // 2D projection node
84    osg::Projection* projection = new osg::Projection;
85    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
86    projection->addChild(modelview_abs);
87
88    // turn off lighting and depth test
89    osg::StateSet* state = modelview_abs->getOrCreateStateSet();
90    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
91    state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
92
93    return projection;
94}
95
96osg::Node* createScaledNode(osg::Node* node, float targetScale)
97{
98    // create scale matrix
99    osg::MatrixTransform* transform = new osg::MatrixTransform;
100
101    const osg::BoundingSphere& bsphere = node->getBound();
102    float scale = targetScale / bsphere._radius;
103    transform->setMatrix(osg::Matrix::scale(scale,scale,scale));
104    transform->setDataVariance(osg::Object::STATIC);
105    transform->addChild(node);
106
107    // rescale normals
108    osg::StateSet* state = transform->getOrCreateStateSet();
109    state->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
110
111    return transform;
112}
113
114osg::Sequence* createSequence(osg::ArgumentParser& arguments)
115{
116    // assumes any remaining parameters are models
117    osg::Sequence* seq = new osg::Sequence;
118
119    typedef std::vector<std::string> Filenames;
120    Filenames filenames;
121   
122    if (arguments.argc() > 1)
123    {
124        for (int i = 1; i < arguments.argc(); ++i)
125        {
126            filenames.push_back(arguments[i]);
127        }
128    }
129    else
130    {
131        filenames.push_back("cow.osg");
132        filenames.push_back("dumptruck.osg");
133        filenames.push_back("cessna.osg");
134        filenames.push_back("glider.osg");
135    }
136   
137    for(Filenames::iterator itr = filenames.begin();
138        itr != filenames.end();
139        ++itr)       
140    {
141        // load model
142        osg::Node* node = osgDB::readNodeFile(*itr);
143
144        if (node)
145        {
146            seq->addChild(createScaledNode(node, 100.0f));
147            seq->setTime(seq->getNumChildren()-1, 1.0f);
148        }
149    }
150
151    // loop through all children
152    seq->setInterval(osg::Sequence::LOOP, 0,-1);
153
154    // real-time playback, repeat indefinitively
155    seq->setDuration(1.0f, -1);
156
157    seq->setMode(osg::Sequence::START);
158
159    return seq;
160}
161
162// event handler to control sequence
163class SequenceEventHandler : public osgGA::GUIEventHandler
164{
165public:
166    SequenceEventHandler(osg::Sequence* seq)
167    {
168        _seq = seq;
169    }
170
171    // handle keydown events
172    virtual bool handle(const osgGA::GUIEventAdapter& ea,
173                        osgGA::GUIActionAdapter&)
174    {
175        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) {
176            switch (ea.getKey()) {
177            case 's':
178                {
179                    osg::Sequence::SequenceMode mode = _seq->getMode();
180                    if (mode == osg::Sequence::STOP) {
181                        mode = osg::Sequence::START;
182                        std::cerr << "Start" << std::endl;
183                    }
184                    else if (mode == osg::Sequence::PAUSE) {
185                        mode = osg::Sequence::RESUME;
186                        std::cerr << "Resume" << std::endl;
187                    }
188                    else {
189                        mode = osg::Sequence::PAUSE;
190                        std::cerr << "Pause" << std::endl;
191                    }
192                    _seq->setMode(mode);
193                }
194                break;
195            case 'l':
196                {
197                    osg::Sequence::LoopMode mode;
198                    int begin, end;
199                    _seq->getInterval(mode, begin, end);
200                    if (mode == osg::Sequence::LOOP) {
201                        mode = osg::Sequence::SWING;
202                        std::cerr << "Swing" << std::endl;
203                    }
204                    else {
205                        mode = osg::Sequence::LOOP;
206                        std::cerr << "Loop" << std::endl;
207                    }
208                    _seq->setInterval(mode, begin, end);
209                }
210                break;
211            default:
212                break;
213            }
214        }
215
216        return false;
217    }
218
219private:
220    osg::ref_ptr<osg::Sequence> _seq;
221};
222
223
224int main( int argc, char **argv )
225{
226    // use an ArgumentParser object to manage the program arguments.
227    osg::ArgumentParser arguments(&argc,argv);
228   
229    // construct the viewer.
230    osgViewer::Viewer viewer;
231    // root
232    osg::Group* rootNode = new osg::Group;
233
234    // create info display
235    const char* text[] = {
236        "osg::Sequence Mini-Howto",
237        "- can be used for simple flip-book-style animation",
238        "- is subclassed from osg::Switch",
239        "- assigns a display duration to each child",
240        "- can loop or swing through an interval of it's children",
241        "- can repeat the interval a number of times or indefinitively",
242        "- press 's' to start/pause/resume",
243        "- press 'l' to toggle loop/swing mode",
244        NULL
245    };
246    rootNode->addChild(createHUD(createTextGroup(text)));
247
248    // add sequence of models from command line
249    osg::Sequence* seq = createSequence(arguments);
250    rootNode->addChild(seq);
251
252    // add model to viewer.
253    viewer.setSceneData(rootNode);
254
255    // add event handler to control sequence
256    viewer.addEventHandler(new SequenceEventHandler(seq));
257
258    return viewer.run();
259}
Note: See TracBrowser for help on using the browser.