root/OpenSceneGraph/trunk/examples/osgfxbrowser/osgfxbrowser.cpp @ 6051

Revision 6051, 12.7 kB (checked in by robert, 8 years ago)

Added osg::FrameStamp::set/getSimulationTime().

Added setting of osg_SimulationTime and osg_DeltaSimulationTime to the uniforms set by SceneView?

Added frame(double simulationTime) and advance(double simulationTime) parameters to
osgViewer::SimpleViewer?, Vewer and CompositeViewer?.

Updated various examples and Nodes to use SimulationTime? where appropriate.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Group>
2#include <osg/Geometry>
3#include <osg/Geode>
4#include <osg/Projection>
5#include <osg/MatrixTransform>
6#include <osg/BlendFunc>
7#include <osg/LightSource>
8
9#include <osgViewer/Viewer>
10
11#include <osgDB/ReadFile>
12#include <osgDB/WriteFile>
13
14#include <osgText/Text>
15
16#include <osgUtil/Optimizer>
17
18#include <osgGA/GUIEventAdapter>
19#include <osgGA/GUIActionAdapter>
20
21#include <osgFX/Registry>
22#include <osgFX/Effect>
23
24#include "Frame.h"
25
26#include <vector>
27#include <string>
28#include <iostream>
29
30class RotateCallback: public osg::NodeCallback {
31public:
32    RotateCallback(): osg::NodeCallback(), enabled_(true) {}
33    void operator()(osg::Node* node, osg::NodeVisitor *nv)
34    {
35        osg::MatrixTransform *xform = dynamic_cast<osg::MatrixTransform *>(node);
36        if (xform && enabled_) {
37            double t = nv->getFrameStamp()->getSimulationTime();
38            xform->setMatrix(osg::Matrix::rotate(t, osg::Vec3(0, 0, 1)));
39        }
40        traverse(node, nv);
41    }
42
43    bool enabled_;
44};
45
46
47// yes, I know global variables are not good things in C++
48// but in this case it is useful... :-P
49RotateCallback *rotate_cb;
50
51
52class EffectPanel: public osgfxbrowser::Frame {
53public:
54
55    class KeyboardHandler: public osgGA::GUIEventHandler {
56    public:
57        KeyboardHandler(EffectPanel* ep): ep_(ep) {}
58
59        bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &)
60        {
61            if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) {
62                if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right) {
63                    ep_->setEffectIndex(ep_->getEffectIndex()+1);
64                    return true;
65                }
66                if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left) {
67                    ep_->setEffectIndex(ep_->getEffectIndex()-1);
68                    return true;
69                }
70                if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Return) {
71                    ep_->setNodeMask(0xffffffff - ep_->getNodeMask());
72                    return true;
73                }
74                if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Delete) {
75                    ep_->setEffectsEnabled(!ep_->getEffectsEnabled());
76                    return true;
77                }
78                if (ea.getKey() == 'x') {
79                    osgDB::writeNodeFile(*ep_->getRoot(), "osgfx_model.osg");
80                    std::cout << "written nodes to \"osgfx_model.osg\"\n";
81                    return true;
82                }
83                if (ea.getKey() == 'r') {
84                    rotate_cb->enabled_ = !rotate_cb->enabled_;
85                    return true;
86                }
87            }
88
89            return false;
90        }
91
92    private:
93        osg::ref_ptr<EffectPanel> ep_;
94    };
95
96    EffectPanel()
97    :    osgfxbrowser::Frame(),
98        _selected_fx(-1),
99        _fxen(true),
100        _root(new osg::Group),
101        _hints_color(0.75f, 0.75f, 0.75f, 1.0f),
102        _name_color(1, 1, 1, 1),
103        _desc_color(1, 1, 0.7f, 1)
104    {
105        setBackgroundColor(osg::Vec4(0.3f, 0.1f, 0.15f, 0.75f));
106
107        std::cout << "INFO: available osgFX effects:\n";
108        osgFX::Registry::EffectMap emap = osgFX::Registry::instance()->getEffectMap();
109        for (osgFX::Registry::EffectMap::const_iterator i=emap.begin(); i!=emap.end(); ++i) {
110            std::cout << "INFO: \t" << i->first << "\n";
111            osg::ref_ptr<osgFX::Effect> effect = static_cast<osgFX::Effect *>(i->second->cloneType());
112            _effects.push_back(effect.get());           
113        }
114
115        std::cout << "INFO: " << emap.size() << " effect(s) ready.\n";
116
117        if (!_effects.empty()) {
118            _selected_fx = 0;
119        }
120    }
121
122    inline osg::Group* getRoot() { return _root.get(); }
123    inline void setRoot(osg::Group* node) { _root = node; }
124
125    inline osg::Node* getScene() { return _scene.get(); }
126    inline void setScene(osg::Node* node) { _scene = node; }
127
128    inline bool getEffectsEnabled() const { return _fxen; }
129    inline void setEffectsEnabled(bool v)
130    {
131        _fxen = v;
132        if (getSelectedEffect()) {
133            getSelectedEffect()->setEnabled(_fxen);
134        }
135    }
136
137    inline int getEffectIndex() const { return _selected_fx; }
138    inline void setEffectIndex(int i)
139    {
140        if (i >= static_cast<int>(_effects.size())) i = 0;
141        if (i < 0) i = static_cast<int>(_effects.size()-1);       
142        _selected_fx = i;
143        rebuild();
144    }
145
146    inline osgFX::Effect *getSelectedEffect()
147    {
148        if (_selected_fx >= 0 && _selected_fx < static_cast<int>(_effects.size())) {
149            return _effects[_selected_fx].get();
150        }
151        return 0;
152    }
153
154protected:
155    void rebuild_client_area(const osgfxbrowser::Rect &client_rect)
156    {
157                float zPos = -0.1; // note from Robert, was 0.1f, but now must be -0.1f to keep text visible??#!? due
158                                   // to some other change in the OSG not tracked down yet...
159       
160        osg::ref_ptr<osgText::Font> arial = osgText::readFontFile("fonts/arial.ttf");
161
162        osg::ref_ptr<osgText::Text> hints = new osgText::Text;
163        hints->setFont(arial.get());
164        hints->setColor(_hints_color);
165        hints->setAlignment(osgText::Text::CENTER_BOTTOM);
166        hints->setCharacterSize(13);
167        hints->setFontResolution(13, 13);
168        hints->setPosition(osg::Vec3((client_rect.x0+client_rect.x1)/2, client_rect.y0 + 4, zPos));
169        hints->setText("<RETURN> show/hide this panel      <LEFT> previous effect      <RIGHT> next effect      <DEL> enable/disable effects      'x' save to file      'r' rotate/stop");
170        addDrawable(hints.get());
171
172        std::string effect_name = "No Effect Selected";
173        std::string effect_description = "";
174
175        if (_selected_fx >= 0 && _selected_fx < static_cast<int>(_effects.size())) {
176            effect_name = _effects[_selected_fx]->effectName();
177            std::string author_name = _effects[_selected_fx]->effectAuthor();
178            if (!author_name.empty()) {
179                effect_description = author_name = "AUTHOR: " + std::string(_effects[_selected_fx]->effectAuthor()) + std::string("\n\n");
180            }
181            effect_description += "DESCRIPTION:\n" + std::string(_effects[_selected_fx]->effectDescription());           
182
183            if (_scene.valid() && _root.valid()) {
184                _root->removeChildren(0, _root->getNumChildren());
185                osg::ref_ptr<osgFX::Effect> effect = _effects[_selected_fx].get();
186                effect->setEnabled(_fxen);
187                effect->removeChildren(0, effect->getNumChildren());
188                effect->addChild(_scene.get());
189                effect->setUpDemo();
190                _root->addChild(effect.get());
191            }
192        }
193
194        osg::ref_ptr<osgText::Text> ename = new osgText::Text;
195        ename->setFont(arial.get());
196        ename->setColor(_name_color);
197        ename->setAlignment(osgText::Text::CENTER_TOP);
198        ename->setCharacterSize(32);
199        ename->setFontResolution(32, 32);
200        ename->setPosition(osg::Vec3((client_rect.x0 + client_rect.x1) / 2, client_rect.y1 - 22, zPos));
201        ename->setText(effect_name);
202        addDrawable(ename.get());
203
204        osg::ref_ptr<osgText::Text> edesc = new osgText::Text;
205        edesc->setMaximumWidth(client_rect.width() - 16);
206        edesc->setFont(arial.get());
207        edesc->setColor(_desc_color);
208        edesc->setAlignment(osgText::Text::LEFT_TOP);
209        edesc->setCharacterSize(16);
210        edesc->setFontResolution(16, 16);
211        edesc->setPosition(osg::Vec3(client_rect.x0 + 8, client_rect.y1 - 60, zPos));
212        edesc->setText(effect_description);
213        addDrawable(edesc.get());
214    }
215
216private:
217    int _selected_fx;
218    typedef std::vector<osg::ref_ptr<osgFX::Effect> > Effect_list;
219    Effect_list _effects;
220    bool _fxen;
221    osg::ref_ptr<osg::Group> _root;
222    osg::ref_ptr<osg::Node> _scene;
223    osg::Vec4 _hints_color;
224    osg::Vec4 _name_color;
225    osg::Vec4 _desc_color;
226};
227
228
229osg::Group* build_hud_base(osg::Group* root)
230{
231    osg::ref_ptr<osg::Projection> proj = new osg::Projection(osg::Matrix::ortho2D(0, 1024, 0, 768));
232    proj->setCullingActive(false);
233    root->addChild(proj.get());
234
235    osg::ref_ptr<osg::MatrixTransform> xform = new osg::MatrixTransform(osg::Matrix::identity());
236    xform->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
237    proj->addChild(xform.get());
238
239    osg::StateSet *ss = xform->getOrCreateStateSet();
240    ss->setRenderBinDetails(100, "RenderBin");
241    ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
242    ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
243
244    osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc;
245    ss->setAttributeAndModes(bf.get());
246
247    return xform.release();
248}
249
250EffectPanel* build_gui(osg::Group* root)
251{
252    osg::ref_ptr<osg::Group> hud = build_hud_base(root);
253
254    osg::ref_ptr<EffectPanel> effect_panel = new EffectPanel;
255    effect_panel->setCaption("osgFX Effect Browser");
256    effect_panel->setRect(osgfxbrowser::Rect(20, 20, 1000, 280));   
257
258    hud->addChild(effect_panel.get());
259
260    return effect_panel.release();
261}
262
263void build_world(osg::Group* root, osg::Node* scene, osgViewer::Viewer& viewer)
264{
265    osg::ref_ptr<EffectPanel> effect_panel = build_gui(root);
266    effect_panel->setScene(scene);
267    effect_panel->rebuild();
268
269    viewer.addEventHandler(new EffectPanel::KeyboardHandler(effect_panel.get()));
270
271    root->addChild(effect_panel->getRoot());
272}
273
274int main(int argc, char *argv[])
275{
276    // use an ArgumentParser object to manage the program arguments.
277    osg::ArgumentParser arguments(&argc, argv);
278
279    // set up the usage document, in case we need to print out how to use this program.
280    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
281    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is a simple browser that allows you to apply osgFX effects to models interactively.");
282    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName() + " [options] filename ...");
283    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
284    arguments.getApplicationUsage()->addKeyboardMouseBinding("Left", "Apply previous effect");
285    arguments.getApplicationUsage()->addKeyboardMouseBinding("Right", "Apply next effect");
286    arguments.getApplicationUsage()->addKeyboardMouseBinding("Del", "Enable or disable osgFX");
287    arguments.getApplicationUsage()->addKeyboardMouseBinding("Return", "Show or hide the effect information panel");
288    arguments.getApplicationUsage()->addKeyboardMouseBinding("x", "Save the scene graph with current effect applied");
289
290
291    // construct the viewer.
292    osgViewer::Viewer viewer;
293
294    // if user request help write it out to cout.
295    if (arguments.read("-h") || arguments.read("--help")) {
296        arguments.getApplicationUsage()->write(std::cout);
297        return 1;
298    }
299
300    // any option left unread are converted into errors to write out later.
301    arguments.reportRemainingOptionsAsUnrecognized();
302
303    // report any errors if they have occured when parsing the program aguments.
304    if (arguments.errors()) {
305        arguments.writeErrorMessages(std::cout);
306        return 1;
307    }
308
309    if (arguments.argc() <= 1) {
310        arguments.getApplicationUsage()->write(std::cout, osg::ApplicationUsage::COMMAND_LINE_OPTION);
311        return 1;
312    }
313
314    osg::Timer timer;
315    osg::Timer_t start_tick = timer.tick();
316
317    // read the scene from the list of file specified commandline args.
318    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
319
320    // if no model has been successfully loaded report failure.
321    if (!loadedModel) {
322        std::cout << arguments.getApplicationName() << ": No data loaded" << std::endl;
323        return 1;
324    }
325
326    osg::Timer_t end_tick = timer.tick();
327
328    std::cout << "Time to load = " << timer.delta_s(start_tick,end_tick) << std::endl;
329
330    // optimize the scene graph, remove rendundent nodes and state etc.
331    osgUtil::Optimizer optimizer;
332    optimizer.optimize(loadedModel.get());
333
334    // set up a transform to rotate the model
335    osg::ref_ptr<osg::MatrixTransform> xform = new osg::MatrixTransform;
336    rotate_cb = new RotateCallback;
337    xform->setUpdateCallback(rotate_cb);
338    xform->addChild(loadedModel.get());
339
340    osg::ref_ptr<osg::Light> light = new osg::Light;
341    light->setLightNum(0);
342    light->setDiffuse(osg::Vec4(1, 1, 1, 1));
343    light->setSpecular(osg::Vec4(1, 1, 0.8f, 1));
344    light->setAmbient(osg::Vec4(0.2f, 0.2f, 0.2f, 0.2f));
345    light->setPosition(osg::Vec4(1, -1, 1, 0));
346
347    osg::ref_ptr<osg::LightSource> root = new osg::LightSource;
348    root->setLight(light.get());
349    root->setLocalStateSetModes();
350
351    build_world(root.get(), xform.get(), viewer);
352
353    // set the scene to render
354    viewer.setSceneData(root.get());
355
356    return viewer.run();
357}
Note: See TracBrowser for help on using the browser.