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

Revision 6835, 13.1 kB (checked in by robert, 10 years ago)

Removed setting of font resolutions and added control of threading, with the default
theading set to SingleThreading? to avoid crashes associated with non thread safe
sections of osgFX - the need to be fixed!!!

  • 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->setPosition(osg::Vec3((client_rect.x0+client_rect.x1)/2, client_rect.y0 + 4, zPos));
168        hints->setText("<RETURN> show/hide this panel      <LEFT> previous effect      <RIGHT> next effect      <DEL> enable/disable effects      'x' save to file      'r' rotate/stop");
169        addDrawable(hints.get());
170
171        std::string effect_name = "No Effect Selected";
172        std::string effect_description = "";
173
174        if (_selected_fx >= 0 && _selected_fx < static_cast<int>(_effects.size())) {
175            effect_name = _effects[_selected_fx]->effectName();
176            std::string author_name = _effects[_selected_fx]->effectAuthor();
177            if (!author_name.empty()) {
178                effect_description = author_name = "AUTHOR: " + std::string(_effects[_selected_fx]->effectAuthor()) + std::string("\n\n");
179            }
180            effect_description += "DESCRIPTION:\n" + std::string(_effects[_selected_fx]->effectDescription());           
181
182            if (_scene.valid() && _root.valid()) {
183                _root->removeChildren(0, _root->getNumChildren());
184                osg::ref_ptr<osgFX::Effect> effect = _effects[_selected_fx].get();
185                effect->setEnabled(_fxen);
186                effect->removeChildren(0, effect->getNumChildren());
187                effect->addChild(_scene.get());
188                effect->setUpDemo();
189                _root->addChild(effect.get());
190            }
191        }
192
193        osg::ref_ptr<osgText::Text> ename = new osgText::Text;
194        ename->setFont(arial.get());
195        ename->setColor(_name_color);
196        ename->setAlignment(osgText::Text::CENTER_TOP);
197        ename->setCharacterSize(32);
198        ename->setPosition(osg::Vec3((client_rect.x0 + client_rect.x1) / 2, client_rect.y1 - 22, zPos));
199        ename->setText(effect_name);
200        addDrawable(ename.get());
201
202        osg::ref_ptr<osgText::Text> edesc = new osgText::Text;
203        edesc->setMaximumWidth(client_rect.width() - 16);
204        edesc->setFont(arial.get());
205        edesc->setColor(_desc_color);
206        edesc->setAlignment(osgText::Text::LEFT_TOP);
207        edesc->setCharacterSize(16);
208        edesc->setPosition(osg::Vec3(client_rect.x0 + 8, client_rect.y1 - 60, zPos));
209        edesc->setText(effect_description);
210        addDrawable(edesc.get());
211    }
212
213private:
214    int _selected_fx;
215    typedef std::vector<osg::ref_ptr<osgFX::Effect> > Effect_list;
216    Effect_list _effects;
217    bool _fxen;
218    osg::ref_ptr<osg::Group> _root;
219    osg::ref_ptr<osg::Node> _scene;
220    osg::Vec4 _hints_color;
221    osg::Vec4 _name_color;
222    osg::Vec4 _desc_color;
223};
224
225
226osg::Group* build_hud_base(osg::Group* root)
227{
228    osg::ref_ptr<osg::Projection> proj = new osg::Projection(osg::Matrix::ortho2D(0, 1024, 0, 768));
229    proj->setCullingActive(false);
230    root->addChild(proj.get());
231
232    osg::ref_ptr<osg::MatrixTransform> xform = new osg::MatrixTransform(osg::Matrix::identity());
233    xform->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
234    proj->addChild(xform.get());
235
236    osg::StateSet *ss = xform->getOrCreateStateSet();
237    ss->setRenderBinDetails(100, "RenderBin");
238    ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
239    ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
240
241    osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc;
242    ss->setAttributeAndModes(bf.get());
243
244    return xform.release();
245}
246
247EffectPanel* build_gui(osg::Group* root)
248{
249    osg::ref_ptr<osg::Group> hud = build_hud_base(root);
250
251    osg::ref_ptr<EffectPanel> effect_panel = new EffectPanel;
252    effect_panel->setCaption("osgFX Effect Browser");
253    effect_panel->setRect(osgfxbrowser::Rect(20, 20, 1000, 280));   
254
255    hud->addChild(effect_panel.get());
256
257    return effect_panel.release();
258}
259
260void build_world(osg::Group* root, osg::Node* scene, osgViewer::Viewer& viewer)
261{
262    osg::ref_ptr<EffectPanel> effect_panel = build_gui(root);
263    effect_panel->setScene(scene);
264    effect_panel->rebuild();
265
266    viewer.addEventHandler(new EffectPanel::KeyboardHandler(effect_panel.get()));
267
268    root->addChild(effect_panel->getRoot());
269}
270
271int main(int argc, char *argv[])
272{
273    // use an ArgumentParser object to manage the program arguments.
274    osg::ArgumentParser arguments(&argc, argv);
275
276    // set up the usage document, in case we need to print out how to use this program.
277    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
278    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is a simple browser that allows you to apply osgFX effects to models interactively.");
279    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName() + " [options] filename ...");
280    arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
281    arguments.getApplicationUsage()->addKeyboardMouseBinding("Left", "Apply previous effect");
282    arguments.getApplicationUsage()->addKeyboardMouseBinding("Right", "Apply next effect");
283    arguments.getApplicationUsage()->addKeyboardMouseBinding("Del", "Enable or disable osgFX");
284    arguments.getApplicationUsage()->addKeyboardMouseBinding("Return", "Show or hide the effect information panel");
285    arguments.getApplicationUsage()->addKeyboardMouseBinding("x", "Save the scene graph with current effect applied");
286
287
288    // construct the viewer.
289    osgViewer::Viewer viewer;
290
291    // if user request help write it out to cout.
292    if (arguments.read("-h") || arguments.read("--help")) {
293        arguments.getApplicationUsage()->write(std::cout);
294        return 1;
295    }
296
297    osgViewer::Viewer::ThreadingModel threading = osgViewer::Viewer::SingleThreaded;
298    while (arguments.read("--SingleThreaded")) threading = osgViewer::Viewer::SingleThreaded;
299    while (arguments.read("--CullDrawThreadPerContext")) threading = osgViewer::Viewer::CullDrawThreadPerContext;
300    while (arguments.read("--DrawThreadPerContext")) threading = osgViewer::Viewer::DrawThreadPerContext;
301    while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) threading = osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext;
302
303    viewer.setThreadingModel(threading);
304
305    // any option left unread are converted into errors to write out later.
306    arguments.reportRemainingOptionsAsUnrecognized();
307
308    // report any errors if they have occured when parsing the program aguments.
309    if (arguments.errors()) {
310        arguments.writeErrorMessages(std::cout);
311        return 1;
312    }
313
314    if (arguments.argc() <= 1) {
315        arguments.getApplicationUsage()->write(std::cout, osg::ApplicationUsage::COMMAND_LINE_OPTION);
316        return 1;
317    }
318
319    osg::Timer timer;
320    osg::Timer_t start_tick = timer.tick();
321
322    // read the scene from the list of file specified commandline args.
323    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments);
324
325    // if no model has been successfully loaded report failure.
326    if (!loadedModel) {
327        std::cout << arguments.getApplicationName() << ": No data loaded" << std::endl;
328        return 1;
329    }
330
331    osg::Timer_t end_tick = timer.tick();
332
333    std::cout << "Time to load = " << timer.delta_s(start_tick,end_tick) << std::endl;
334
335    // optimize the scene graph, remove rendundent nodes and state etc.
336    osgUtil::Optimizer optimizer;
337    optimizer.optimize(loadedModel.get());
338
339    // set up a transform to rotate the model
340    osg::ref_ptr<osg::MatrixTransform> xform = new osg::MatrixTransform;
341    rotate_cb = new RotateCallback;
342    xform->setUpdateCallback(rotate_cb);
343    xform->addChild(loadedModel.get());
344
345    osg::ref_ptr<osg::Light> light = new osg::Light;
346    light->setLightNum(0);
347    light->setDiffuse(osg::Vec4(1, 1, 1, 1));
348    light->setSpecular(osg::Vec4(1, 1, 0.8f, 1));
349    light->setAmbient(osg::Vec4(0.2f, 0.2f, 0.2f, 0.2f));
350    light->setPosition(osg::Vec4(1, -1, 1, 0));
351
352    osg::ref_ptr<osg::LightSource> root = new osg::LightSource;
353    root->setLight(light.get());
354    root->setLocalStateSetModes();
355
356    build_world(root.get(), xform.get(), viewer);
357
358    // set the scene to render
359    viewer.setSceneData(root.get());
360
361    return viewer.run();
362}
Note: See TracBrowser for help on using the browser.