root/OpenSceneGraph/trunk/examples/osgmultitexturecontrol/osgmultitexturecontrol.cpp @ 7921

Revision 7921, 8.3 kB (checked in by robert, 7 years ago)

Added extra event handlers to make viewer more functional

Line 
1/* OpenSceneGraph example, osgmultitexture.
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
20#include <osg/Notify>
21
22#include <osg/Texture2D>
23#include <osg/io_utils>
24
25#include <osgDB/Registry>
26#include <osgDB/ReadFile>
27
28#include <osgFX/MultiTextureControl>
29
30#include <osgGA/TerrainManipulator>
31#include <osgGA/StateSetManipulator>
32
33#include <osgViewer/ViewerEventHandlers>
34#include <osgViewer/Viewer>
35
36
37#include <iostream>
38
39template<class T>
40class FindTopMostNodeOfTypeVisitor : public osg::NodeVisitor
41{
42public:
43    FindTopMostNodeOfTypeVisitor():
44        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
45        _foundNode(0)
46    {}
47   
48    void apply(osg::Node& node)
49    {
50        T* result = dynamic_cast<T*>(&node);
51        if (result)
52        {
53            _foundNode = result;
54        }
55        else
56        {
57            traverse(node);
58        }
59    }
60   
61    T* _foundNode;
62};
63
64template<class T>
65T* findTopMostNodeOfType(osg::Node* node)
66{
67    if (!node) return 0;
68
69    FindTopMostNodeOfTypeVisitor<T> fnotv;
70    node->accept(fnotv);
71   
72    return fnotv._foundNode;
73}
74
75/** Callback used to track the elevation of the camera and update the texture weights in an MultiTextureControl node.*/
76class ElevationLayerBlendingCallback : public osg::NodeCallback
77{
78    public:
79   
80        typedef std::vector<double> Elevations;
81
82        ElevationLayerBlendingCallback(osgFX::MultiTextureControl* mtc, const Elevations& elevations, float animationTime=4.0f):
83            _previousFrame(-1),
84            _previousTime(0.0),
85            _mtc(mtc),
86            _elevations(elevations),
87            _animationTime(animationTime) {}
88   
89        /** Callback method called by the NodeVisitor when visiting a node.*/
90        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
91        {
92            if (!nv->getFrameStamp() || _previousFrame==nv->getFrameStamp()->getFrameNumber())
93            {
94                // we've already updated for this frame so no need to do it again, just traverse children.
95                traverse(node,nv);
96                return;
97            }
98           
99            float deltaTime = 0.01f;
100            if (_previousFrame!=-1)
101            {
102                deltaTime = float(nv->getFrameStamp()->getReferenceTime() - _previousTime);
103            }
104           
105            _previousTime = nv->getFrameStamp()->getReferenceTime();
106            _previousFrame = nv->getFrameStamp()->getFrameNumber();
107
108            double elevation = nv->getViewPoint().z();
109       
110            osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(node);
111            if (csn)
112            {
113                osg::EllipsoidModel* em = csn->getEllipsoidModel();
114                if (em)
115                {
116                    double X = nv->getViewPoint().x();
117                    double Y = nv->getViewPoint().y();
118                    double Z = nv->getViewPoint().z();
119                    double latitude, longitude;
120                    em->convertXYZToLatLongHeight(X,Y,Z,latitude, longitude, elevation);
121                }
122            }
123       
124            if (_mtc.valid() && !_elevations.empty())
125            {
126                unsigned int index = _mtc->getNumTextureWeights()-1;
127                for(unsigned int i=0; i<_elevations.size(); ++i)
128                {
129                    if (elevation>_elevations[i])
130                    {
131                        index = i;
132                        break;
133                    }
134                }
135               
136                float delta = std::min(deltaTime/_animationTime, 1.0f);
137               
138                for(unsigned int i=0; i<_mtc->getNumTextureWeights(); ++i)
139                {
140                    float currentValue = _mtc->getTextureWeight(i);
141                    float desiredValue = (i==index) ? 1.0f : 0.0f;
142                    if (desiredValue != currentValue)
143                    {
144                        if (currentValue<desiredValue)
145                        {
146                            desiredValue = std::min(currentValue + delta, desiredValue);
147                        }
148                        else
149                        {
150                            desiredValue = std::max(currentValue - delta, desiredValue);
151                        }
152                   
153                        _mtc->setTextureWeight(i, desiredValue);
154                    }
155                }
156               
157            }
158       
159            traverse(node,nv);
160        }
161
162        int                                             _previousFrame;
163        double                                          _previousTime;
164        float                                           _animationTime;
165        osg::observer_ptr<osgFX::MultiTextureControl>   _mtc;
166        Elevations                                      _elevations;
167};
168
169
170int main( int argc, char **argv )
171{
172    // use an ArgumentParser object to manage the program arguments.
173    osg::ArgumentParser arguments(&argc,argv);
174   
175    // construct the viewer.
176    osgViewer::Viewer viewer(arguments);
177
178    // load the nodes from the commandline arguments.
179    osg::Node* rootnode = osgDB::readNodeFiles(arguments);
180
181    if (!rootnode)
182    {
183        osg::notify(osg::NOTICE)<<"Warning: no valid data loaded, please specify a database on the command line."<<std::endl;
184        return 1;
185    }
186   
187    osg::CoordinateSystemNode* csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(rootnode);
188
189    unsigned int numLayers = 1;
190    osgFX::MultiTextureControl* mtc = findTopMostNodeOfType<osgFX::MultiTextureControl>(rootnode);
191    if (mtc)
192    {
193        numLayers = mtc->getNumTextureWeights();
194    }
195   
196    if (numLayers<2)
197    {
198        osg::notify(osg::NOTICE)<<"Warning: scene must have MultiTextureControl node with at least 2 texture units defined."<<std::endl;
199        return 1;
200    }
201   
202    double maxElevationTransition = 1e6;
203    ElevationLayerBlendingCallback::Elevations elevations;
204    for(unsigned int i=0; i<numLayers; ++i)
205    {
206        elevations.push_back(maxElevationTransition);
207        maxElevationTransition /= 2.0;
208    }
209   
210    ElevationLayerBlendingCallback* elbc = new ElevationLayerBlendingCallback(mtc, elevations);
211
212    // assign to the most appropriate node (the CoordinateSystemNode is best as it provides the elevation on the globe.)
213    if (csn) csn->setCullCallback(elbc);   
214    else if (mtc) mtc->setCullCallback(elbc);
215    else rootnode->setCullCallback(elbc);
216
217    // add all the event handlers to the viewer
218    {
219        // add terrain manipulator
220        viewer.setCameraManipulator(new osgGA::TerrainManipulator);
221
222        // add the state manipulator
223        viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
224
225        // add the thread model handler
226        viewer.addEventHandler(new osgViewer::ThreadingHandler);
227
228        // add the window size toggle handler
229        viewer.addEventHandler(new osgViewer::WindowSizeHandler);
230
231        // add the stats handler
232        viewer.addEventHandler(new osgViewer::StatsHandler);
233
234        // add the help handler
235        viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
236
237        // add the record camera path handler
238        viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
239
240        // add the LOD Scale handler
241        viewer.addEventHandler(new osgViewer::LODScaleHandler);
242    }
243
244    // add a viewport to the viewer and attach the scene graph.
245    viewer.setSceneData( rootnode );
246   
247    // create the windows and run the threads.
248    viewer.realize();
249
250    return viewer.run();
251}
Note: See TracBrowser for help on using the browser.