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

Revision 7904, 7.4 kB (checked in by robert, 7 years ago)

Removed single threaded setting

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