~ubuntu-branches/ubuntu/trusty/openscenegraph/trusty

« back to all changes in this revision

Viewing changes to OpenSceneGraph/examples/osgmultitexturecontrol/osgmultitexturecontrol.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-07-29 04:34:38 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 lenny)
  • Revision ID: james.westby@ubuntu.com-20080729043438-no1h9h0dpsrlzp1y
* Non-maintainer upload.
* No longer try to detect (using /proc/cpuinfo when available) how many
  CPUs are available, fixing the FTBFS (due to -j0) on various platforms
  (Closes: #477353). The right way to do it is to support parallel=n in
  DEB_BUILD_OPTIONS (see Debian Policy §4.9.1), and adequate support has
  been implemented.
* Add patch to fix FTBFS due to the build system now refusing to handle
  whitespaces (Policy CMP0004 say the logs), thanks to Andreas Putzo who
  provided it (Closes: #482239):
   - debian/patches/fix-cmp0004-build-failure.dpatch
* Remove myself from Uploaders, as requested a while ago, done by Luk in
  his 2.2.0-2.1 NMU, which was never acknowledged.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include <osgGA/AnimationPathManipulator>
 
33
#include <osgGA/TrackballManipulator>
 
34
#include <osgGA/FlightManipulator>
 
35
#include <osgGA/DriveManipulator>
 
36
#include <osgGA/KeySwitchMatrixManipulator>
 
37
#include <osgGA/StateSetManipulator>
 
38
#include <osgGA/AnimationPathManipulator>
 
39
#include <osgGA/TerrainManipulator>
 
40
 
 
41
#include <osgTerrain/Terrain>
 
42
 
 
43
#include <osgViewer/ViewerEventHandlers>
 
44
#include <osgViewer/Viewer>
 
45
 
 
46
 
 
47
#include <iostream>
 
48
 
 
49
template<class T>
 
50
class FindTopMostNodeOfTypeVisitor : public osg::NodeVisitor
 
51
{
 
52
public:
 
53
    FindTopMostNodeOfTypeVisitor():
 
54
        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
 
55
        _foundNode(0)
 
56
    {}
 
57
    
 
58
    void apply(osg::Node& node)
 
59
    {
 
60
        T* result = dynamic_cast<T*>(&node);
 
61
        if (result)
 
62
        {
 
63
            _foundNode = result;
 
64
        }
 
65
        else
 
66
        {
 
67
            traverse(node);
 
68
        }
 
69
    }
 
70
    
 
71
    T* _foundNode;
 
72
};
 
73
 
 
74
template<class T>
 
75
T* findTopMostNodeOfType(osg::Node* node)
 
76
{
 
77
    if (!node) return 0;
 
78
 
 
79
    FindTopMostNodeOfTypeVisitor<T> fnotv;
 
80
    node->accept(fnotv);
 
81
    
 
82
    return fnotv._foundNode;
 
83
}
 
84
 
 
85
/** Callback used to track the elevation of the camera and update the texture weights in an MultiTextureControl node.*/
 
86
class ElevationLayerBlendingCallback : public osg::NodeCallback
 
87
{
 
88
    public:
 
89
    
 
90
        typedef std::vector<double> Elevations;
 
91
 
 
92
        ElevationLayerBlendingCallback(osgFX::MultiTextureControl* mtc, const Elevations& elevations, float animationTime=4.0f):
 
93
            _previousFrame(-1),
 
94
            _previousTime(0.0),
 
95
            _mtc(mtc),
 
96
            _elevations(elevations),
 
97
            _animationTime(animationTime) {}
 
98
    
 
99
        /** Callback method called by the NodeVisitor when visiting a node.*/
 
100
        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
 
101
        { 
 
102
            if (!nv->getFrameStamp() || _previousFrame==nv->getFrameStamp()->getFrameNumber())
 
103
            {
 
104
                // we've already updated for this frame so no need to do it again, just traverse children.
 
105
                traverse(node,nv);
 
106
                return;
 
107
            }
 
108
            
 
109
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
 
110
            
 
111
            float deltaTime = 0.01f;
 
112
            if (_previousFrame!=-1)
 
113
            {
 
114
                deltaTime = float(nv->getFrameStamp()->getReferenceTime() - _previousTime);
 
115
            }
 
116
            
 
117
            _previousTime = nv->getFrameStamp()->getReferenceTime();
 
118
            _previousFrame = nv->getFrameStamp()->getFrameNumber();
 
119
 
 
120
            double elevation = nv->getViewPoint().z();
 
121
        
 
122
            osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(node);
 
123
            if (csn) 
 
124
            {
 
125
                osg::EllipsoidModel* em = csn->getEllipsoidModel();
 
126
                if (em)
 
127
                {
 
128
                    double X = nv->getViewPoint().x();
 
129
                    double Y = nv->getViewPoint().y();
 
130
                    double Z = nv->getViewPoint().z();
 
131
                    double latitude, longitude;
 
132
                    em->convertXYZToLatLongHeight(X,Y,Z,latitude, longitude, elevation);
 
133
                }
 
134
            }
 
135
        
 
136
            if (_mtc.valid() && !_elevations.empty())
 
137
            {
 
138
                unsigned int index = _mtc->getNumTextureWeights()-1;
 
139
                for(unsigned int i=0; i<_elevations.size(); ++i)
 
140
                {
 
141
                    if (elevation>_elevations[i]) 
 
142
                    {
 
143
                        index = i;
 
144
                        break;
 
145
                    }
 
146
                }
 
147
                
 
148
                float delta = std::min(deltaTime/_animationTime, 1.0f);
 
149
                
 
150
                for(unsigned int i=0; i<_mtc->getNumTextureWeights(); ++i)
 
151
                {
 
152
                    float currentValue = _mtc->getTextureWeight(i);
 
153
                    float desiredValue = (i==index) ? 1.0f : 0.0f;
 
154
                    if (desiredValue != currentValue)
 
155
                    {
 
156
                        if (currentValue<desiredValue)
 
157
                        {
 
158
                            desiredValue = std::min(currentValue + delta, desiredValue);
 
159
                        }
 
160
                        else
 
161
                        {
 
162
                            desiredValue = std::max(currentValue - delta, desiredValue);
 
163
                        }
 
164
                    
 
165
                        _mtc->setTextureWeight(i, desiredValue);
 
166
                    }
 
167
                }
 
168
                
 
169
            }
 
170
        
 
171
            traverse(node,nv);
 
172
        }
 
173
 
 
174
        int                                             _previousFrame;
 
175
        double                                          _previousTime;
 
176
        float                                           _animationTime;
 
177
        osg::observer_ptr<osgFX::MultiTextureControl>   _mtc;
 
178
        Elevations                                      _elevations;
 
179
        
 
180
        OpenThreads::Mutex                              _mutex;
 
181
};
 
182
 
 
183
 
 
184
int main( int argc, char **argv )
 
185
{
 
186
    // use an ArgumentParser object to manage the program arguments.
 
187
    osg::ArgumentParser arguments(&argc,argv);
 
188
   
 
189
    // construct the viewer.
 
190
    osgViewer::Viewer viewer(arguments);
 
191
 
 
192
 
 
193
    // add all the event handlers to the viewer
 
194
    {
 
195
        // add the state manipulator
 
196
        viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
 
197
 
 
198
        // add the thread model handler
 
199
        viewer.addEventHandler(new osgViewer::ThreadingHandler);
 
200
 
 
201
        // add the window size toggle handler
 
202
        viewer.addEventHandler(new osgViewer::WindowSizeHandler);
 
203
 
 
204
        // add the stats handler
 
205
        viewer.addEventHandler(new osgViewer::StatsHandler);
 
206
 
 
207
        // add the help handler
 
208
        viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
 
209
 
 
210
        // add the record camera path handler
 
211
        viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
 
212
 
 
213
        // add the LOD Scale handler
 
214
        viewer.addEventHandler(new osgViewer::LODScaleHandler);
 
215
    }
 
216
 
 
217
    // add all the camera manipulators
 
218
    {
 
219
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
 
220
 
 
221
        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
 
222
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
 
223
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
 
224
 
 
225
        unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
 
226
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
 
227
 
 
228
        std::string pathfile;
 
229
        char keyForAnimationPath = '5';
 
230
        while (arguments.read("-p",pathfile))
 
231
        {
 
232
            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
 
233
            if (apm || !apm->valid()) 
 
234
            {
 
235
                num = keyswitchManipulator->getNumMatrixManipulators();
 
236
                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
 
237
                ++keyForAnimationPath;
 
238
            }
 
239
        }
 
240
 
 
241
        keyswitchManipulator->selectMatrixManipulator(num);
 
242
 
 
243
        viewer.setCameraManipulator( keyswitchManipulator.get() );
 
244
    }
 
245
 
 
246
    // set up the scene graph
 
247
    {
 
248
        // load the nodes from the commandline arguments.
 
249
        osg::Node* rootnode = osgDB::readNodeFiles(arguments);
 
250
 
 
251
        if (!rootnode)
 
252
        {
 
253
            osg::notify(osg::NOTICE)<<"Warning: no valid data loaded, please specify a database on the command line."<<std::endl;
 
254
            return 1;
 
255
        }
 
256
 
 
257
        osgTerrain::Terrain* terrain = findTopMostNodeOfType<osgTerrain::Terrain>(rootnode);
 
258
        if (!terrain)
 
259
        {
 
260
            terrain = new osgTerrain::Terrain;
 
261
            terrain->addChild(rootnode);
 
262
            terrain->setSampleRatio(0.25f);
 
263
 
 
264
            rootnode = terrain;
 
265
        }    
 
266
 
 
267
        osg::CoordinateSystemNode* csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(rootnode);
 
268
 
 
269
        unsigned int numLayers = 1;
 
270
        osgFX::MultiTextureControl* mtc = findTopMostNodeOfType<osgFX::MultiTextureControl>(rootnode);
 
271
        if (mtc)
 
272
        {
 
273
            numLayers = mtc->getNumTextureWeights();
 
274
        }
 
275
 
 
276
        if (numLayers<2)
 
277
        {
 
278
            osg::notify(osg::NOTICE)<<"Warning: scene must have MultiTextureControl node with at least 2 texture units defined."<<std::endl;
 
279
            return 1;
 
280
        }
 
281
 
 
282
        double maxElevationTransition = 1e6;
 
283
        ElevationLayerBlendingCallback::Elevations elevations;
 
284
        for(unsigned int i=0; i<numLayers; ++i)
 
285
        {
 
286
            elevations.push_back(maxElevationTransition);
 
287
            maxElevationTransition /= 2.0;
 
288
        }
 
289
 
 
290
        ElevationLayerBlendingCallback* elbc = new ElevationLayerBlendingCallback(mtc, elevations);
 
291
 
 
292
        // assign to the most appropriate node (the CoordinateSystemNode is best as it provides the elevation on the globe.)
 
293
        if (csn) csn->setCullCallback(elbc);    
 
294
        else if (mtc) mtc->setCullCallback(elbc);
 
295
        else rootnode->setCullCallback(elbc);
 
296
 
 
297
        // add a viewport to the viewer and attach the scene graph.
 
298
        viewer.setSceneData( rootnode );
 
299
    }
 
300
    
 
301
    // create the windows and run the threads.
 
302
    viewer.realize();
 
303
 
 
304
    return viewer.run();
 
305
}