root/OpenSceneGraph/trunk/examples/osgterrain/osgterrain.cpp @ 9618

Revision 9618, 30.5 kB (checked in by robert, 5 years ago)

Refactored osg::TransferFunction?1D to use an std::map internally which is kept in sync with the actual osg::Image that is passed to the GPU.

Added .osg support for osg::TransferFunction?1D.

Updated wrappers

Line 
1/* OpenSceneGraph example, osgterrain.
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 <OpenThreads/Block>
20
21#include <osg/Group>
22#include <osg/Geode>
23#include <osg/ShapeDrawable>
24#include <osg/Texture2D>
25#include <osg/PositionAttitudeTransform>
26#include <osg/MatrixTransform>
27#include <osg/CoordinateSystemNode>
28#include <osg/ClusterCullingCallback>
29#include <osg/ArgumentParser>
30
31
32#include <osgDB/FileUtils>
33#include <osgDB/fstream>
34#include <osgDB/ReadFile>
35
36#include <osgUtil/GLObjectsVisitor>
37
38#include <osgText/FadeText>
39
40#include <osgViewer/Viewer>
41#include <osgViewer/ViewerEventHandlers>
42
43#include <osgGA/TrackballManipulator>
44#include <osgGA/FlightManipulator>
45#include <osgGA/DriveManipulator>
46#include <osgGA/KeySwitchMatrixManipulator>
47#include <osgGA/StateSetManipulator>
48#include <osgGA/AnimationPathManipulator>
49#include <osgGA/TerrainManipulator>
50
51#include <osgTerrain/TerrainTile>
52#include <osgTerrain/GeometryTechnique>
53#include <osgTerrain/Layer>
54
55#include <iostream>
56
57
58typedef std::vector< osg::ref_ptr<osg::GraphicsThread> > GraphicsThreads;
59
60
61
62class LoadAndCompileOperation : public osg::Operation
63{
64public:
65
66    LoadAndCompileOperation(const std::string& filename, GraphicsThreads& graphicsThreads, osg::RefBlockCount* block):
67        Operation("Load and compile Operation", false),
68        _filename(filename),
69        _graphicsThreads(graphicsThreads),
70        _block(block) {}
71
72    virtual void operator () (osg::Object* object)
73    {
74        // osg::notify(osg::NOTICE)<<"LoadAndCompileOperation "<<_filename<<std::endl;
75
76        _loadedModel = osgDB::readNodeFile(_filename);
77        if (_loadedModel.valid() && !_graphicsThreads.empty())
78        {
79            osg::ref_ptr<osgUtil::GLObjectsOperation> compileOperation = new osgUtil::GLObjectsOperation(_loadedModel.get());
80
81            for(GraphicsThreads::iterator gitr = _graphicsThreads.begin();
82                gitr != _graphicsThreads.end();
83                ++gitr)
84            {
85                (*gitr)->add( compileOperation.get() );
86                // requiresBarrier = true;
87            }
88        }
89       
90        if (_block.valid()) _block->completed();
91
92        // osg::notify(osg::NOTICE)<<"done LoadAndCompileOperation "<<_filename<<std::endl;
93    }
94   
95    std::string                 _filename;
96    GraphicsThreads             _graphicsThreads;
97    osg::ref_ptr<osg::Node>     _loadedModel;
98    osg::ref_ptr<osg::RefBlockCount> _block;
99
100};
101
102class MasterOperation : public osg::Operation
103{
104public:
105
106    typedef std::set<std::string> Files;
107    typedef std::map<std::string, osg::ref_ptr<osg::Node> >  FilenameNodeMap;
108    typedef std::vector< osg::ref_ptr<osg::Node> >  Nodes;
109
110
111    MasterOperation(const std::string& filename):
112        Operation("Master reading operation",true),
113        _filename(filename)
114    {
115    }
116   
117    /** Set the OperationQueue that the MasterOperation can use to place tasks like file loading on for other processes to handle.*/ 
118    void setOperationQueue(osg::OperationQueue* oq) { _operationQueue = oq; }
119   
120    osg::OperationQueue* getOperationQueue() { return _operationQueue.get(); }
121   
122    bool readMasterFile(Files& files) const
123    {
124        osgDB::ifstream fin(_filename.c_str());
125        if (fin)
126        {
127            osgDB::Input fr;
128            fr.attach(&fin);
129
130            bool readFilename = false;
131
132            while(!fr.eof())
133            {
134                bool itrAdvanced = false;
135                if (fr.matchSequence("file %s") || fr.matchSequence("file %w") )
136                {
137                    files.insert(fr[1].getStr());
138                    fr += 2;
139                    itrAdvanced = true;
140                    readFilename = true;
141                }
142
143                if (!itrAdvanced)
144                {
145                    ++fr;
146                }
147            }
148           
149            return readFilename;
150        }
151        return false;
152    }
153   
154    bool open(osg::Group* group)
155    {
156        Files files;
157        readMasterFile(files);
158        for(Files::iterator itr = files.begin();
159            itr != files.end();
160            ++itr)
161        {
162            osg::Node* model = osgDB::readNodeFile(*itr);
163            if (model)
164            {
165                osg::notify(osg::NOTICE)<<"open: Loaded file "<<*itr<<std::endl;
166                group->addChild(model);
167                _existingFilenameNodeMap[*itr] = model;
168            }
169        }
170       
171        return true;
172    }
173   
174
175    virtual void operator () (osg::Object* callingObject)
176    {
177        // decided which method to call according to whole has called me.
178        osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(callingObject);
179
180        if (viewer) update(viewer->getSceneData());
181        else load();
182    }
183
184    void load()
185    {
186        //osg::notify(osg::NOTICE)<<"void load(Object)"<<std::endl;
187        Files filesA;
188        Files filesB;
189       
190        readMasterFile(filesB);
191        // osg::notify(osg::NOTICE)<<"First read "<<filesA.size()<<std::endl;
192
193        // itererate until the master file is stable
194        do
195        {
196            OpenThreads::Thread::microSleep(100000);
197
198            filesB.swap(filesA);
199            filesB.clear();
200            readMasterFile(filesB);
201
202            // osg::notify(osg::NOTICE)<<"second read "<<filesB.size()<<std::endl;
203           
204        } while (filesA!=filesB);
205
206        Files files;
207        files.swap(filesB);
208
209        // osg::notify(osg::NOTICE)<<"Now equal "<<files.size()<<std::endl;
210
211
212        Files newFiles;
213        Files removedFiles;
214
215        // find out which files are new, and which ones have been removed.
216        {           
217            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
218
219            for(Files::iterator fitr = files.begin();
220                fitr != files.end();
221                ++fitr)
222            {
223                if (_existingFilenameNodeMap.count(*fitr)==0) newFiles.insert(*fitr);
224            }
225
226            for(FilenameNodeMap::iterator litr = _existingFilenameNodeMap.begin();
227                litr != _existingFilenameNodeMap.end();
228                ++litr)
229            {
230                if (files.count(litr->first)==0)
231                {
232                    removedFiles.insert(litr->first);
233                }
234            }
235        }
236       
237#if 0
238        if (!newFiles.empty() || !removedFiles.empty())
239        {
240            osg::notify(osg::NOTICE)<<std::endl<<std::endl<<"void operator () files.size()="<<files.size()<<std::endl;
241        }
242#endif
243
244        // first load the new files.
245        FilenameNodeMap nodesToAdd;
246        if (!newFiles.empty())
247        {
248
249            typedef std::vector< osg::ref_ptr<osg::GraphicsThread> > GraphicsThreads;
250            GraphicsThreads threads;
251       
252            for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
253            {
254                osg::GraphicsContext* gc = osg::GraphicsContext::getCompileContext(i);
255                osg::GraphicsThread* gt = gc ? gc->getGraphicsThread() : 0;
256                if (gt) threads.push_back(gt);
257            }
258
259            bool requiresBarrier = false;
260
261
262            if (_operationQueue.valid())
263            {
264                // osg::notify(osg::NOTICE)<<"Using OperationQueue"<<std::endl;
265
266                _endOfLoadBlock = new osg::RefBlockCount(newFiles.size());
267               
268                _endOfLoadBlock->reset();
269     
270                typedef std::list< osg::ref_ptr<LoadAndCompileOperation> > LoadAndCompileList;
271                LoadAndCompileList loadAndCompileList;
272     
273                for(Files::iterator nitr = newFiles.begin();
274                    nitr != newFiles.end();
275                    ++nitr)
276                {
277                    // osg::notify(osg::NOTICE)<<"Adding LoadAndCompileOperation "<<*nitr<<std::endl;
278
279                    osg::ref_ptr<LoadAndCompileOperation> loadAndCompile = new LoadAndCompileOperation( *nitr, threads, _endOfLoadBlock.get() );
280                    loadAndCompileList.push_back(loadAndCompile);
281                    _operationQueue->add( loadAndCompile.get() );
282                }
283
284#if 1
285                osg::ref_ptr<osg::Operation> operation;
286                while ((operation=_operationQueue->getNextOperation()).valid())
287                {
288                    // osg::notify(osg::NOTICE)<<"Local running of operation"<<std::endl;
289                    (*operation)(0);
290                }
291#endif                               
292                // osg::notify(osg::NOTICE)<<"Waiting for completion of LoadAndCompile operations"<<std::endl;
293                _endOfLoadBlock->block();
294                // osg::notify(osg::NOTICE)<<"done ... Waiting for completion of LoadAndCompile operations"<<std::endl;
295               
296                for(LoadAndCompileList::iterator litr = loadAndCompileList.begin();
297                    litr != loadAndCompileList.end();
298                    ++litr)
299                {
300                    if ((*litr)->_loadedModel.valid())
301                    {
302                        nodesToAdd[(*litr)->_filename] = (*litr)->_loadedModel;
303                        requiresBarrier = true;
304                    }
305                }
306
307            }
308           
309            else
310            {
311                for(Files::iterator nitr = newFiles.begin();
312                    nitr != newFiles.end();
313                    ++nitr)
314                {
315                    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(*nitr);
316
317                    if (loadedModel.get())
318                    {
319                        nodesToAdd[*nitr] = loadedModel;
320
321                        osg::ref_ptr<osgUtil::GLObjectsOperation> compileOperation = new osgUtil::GLObjectsOperation(loadedModel.get());
322
323                        for(GraphicsThreads::iterator gitr = threads.begin();
324                            gitr != threads.end();
325                            ++gitr)
326                        {
327                            (*gitr)->add( compileOperation.get() );
328                            requiresBarrier = true;
329                        }
330                    }
331                }
332            }
333                       
334            if (requiresBarrier)
335            {
336                _endOfCompilebarrier = new osg::BarrierOperation(threads.size()+1);
337                _endOfCompilebarrier->setKeep(false);
338               
339                for(GraphicsThreads::iterator gitr = threads.begin();
340                    gitr != threads.end();
341                    ++gitr)
342                {
343                    (*gitr)->add(_endOfCompilebarrier.get());
344                }
345               
346                // osg::notify(osg::NOTICE)<<"Waiting for Compile to complete"<<std::endl;
347
348                // wait for the graphics threads to complete.
349                _endOfCompilebarrier->block();
350               
351                // osg::notify(osg::NOTICE)<<"done ... Waiting for Compile to complete"<<std::endl;
352            }
353        }
354       
355        bool requiresBlock = false;
356       
357        // pass the locally peppared data to MasterOperations shared data
358        // so that updated thread can merge these changes with the main scene
359        // graph.  This merge is carried out via the update(..) method.
360        if (!removedFiles.empty() || !nodesToAdd.empty())       
361        {
362            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
363            _nodesToRemove.swap(removedFiles);
364            _nodesToAdd.swap(nodesToAdd);
365            requiresBlock = true;
366        }
367
368        // now block so we don't try to load anything till the new data has been merged
369        // otherwise _existingFilenameNodeMap will get out of sync.
370        if (requiresBlock)
371        {
372            _updatesMergedBlock.block();
373        }
374        else
375        {
376            OpenThreads::Thread::YieldCurrentThread();
377        }
378
379    }
380   
381    // merge the changes with the main scene graph.
382    void update(osg::Node* scene)
383    {
384        // osg::notify(osg::NOTICE)<<"void update(Node*)"<<std::endl;
385
386        osg::Group* group = dynamic_cast<osg::Group*>(scene);
387        if (!group)
388        {
389            osg::notify(osg::NOTICE)<<"Error, MasterOperation::update(Node*) can only work with a Group as Viewer::getSceneData()."<<std::endl;
390            return;
391        }
392   
393        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
394       
395        if (!_nodesToRemove.empty() || !_nodesToAdd.empty())
396        {
397            osg::notify(osg::NOTICE)<<"update().................. "<<std::endl;
398        }
399
400        if (!_nodesToRemove.empty())
401        {
402            for(Files::iterator itr = _nodesToRemove.begin();
403                itr != _nodesToRemove.end();
404                ++itr)
405            {
406                FilenameNodeMap::iterator fnmItr = _existingFilenameNodeMap.find(*itr);
407                if (fnmItr != _existingFilenameNodeMap.end())
408                {
409                    osg::notify(osg::NOTICE)<<"  update():removing "<<*itr<<std::endl;
410               
411                    group->removeChild(fnmItr->second.get());
412                    _existingFilenameNodeMap.erase(fnmItr);
413                }
414            }
415
416            _nodesToRemove.clear();
417        }
418       
419        if (!_nodesToAdd.empty())
420        {
421            for(FilenameNodeMap::iterator itr = _nodesToAdd.begin();
422                itr != _nodesToAdd.end();
423                ++itr)
424            {
425                osg::notify(osg::NOTICE)<<"  update():inserting "<<itr->first<<std::endl;
426                group->addChild(itr->second.get());
427                _existingFilenameNodeMap[itr->first] = itr->second;
428            }
429           
430            _nodesToAdd.clear();
431        }
432
433        _updatesMergedBlock.release();
434
435    }
436   
437    // add release implementation so that any thread cancellation can
438    // work even when blocks and barriers are used.
439    virtual void release()
440    {
441        if (_operationQueue.valid()) _operationQueue->removeAllOperations();
442
443        _updatesMergedBlock.release();
444        if (_endOfCompilebarrier.valid()) _endOfCompilebarrier.release();
445        if (_endOfLoadBlock.valid()) _endOfLoadBlock.release();
446    }
447
448   
449    std::string                         _filename;
450   
451    OpenThreads::Mutex                  _mutex;
452    FilenameNodeMap                     _existingFilenameNodeMap;
453    Files                               _nodesToRemove;
454    FilenameNodeMap                     _nodesToAdd;
455    OpenThreads::Block                  _updatesMergedBlock;
456
457    osg::ref_ptr<osg::BarrierOperation> _endOfCompilebarrier;
458    osg::ref_ptr<osg::RefBlockCount>    _endOfLoadBlock;
459   
460    osg::ref_ptr<osg::OperationQueue>   _operationQueue;
461};
462
463class FilterHandler : public osgGA::GUIEventHandler
464{
465public:
466
467    FilterHandler(osgTerrain::GeometryTechnique* gt):
468        _gt(gt) {}
469
470    bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
471    {
472        if (!_gt) return false;
473
474        switch(ea.getEventType())
475        {
476        case(osgGA::GUIEventAdapter::KEYDOWN):
477            {
478                if (ea.getKey() == 'g')
479                {
480                    osg::notify(osg::NOTICE)<<"Gaussian"<<std::endl;
481                    _gt->setFilterMatrixAs(osgTerrain::GeometryTechnique::GAUSSIAN);
482                    return true;
483                }
484                else if (ea.getKey() == 's')
485                {
486                    osg::notify(osg::NOTICE)<<"Smooth"<<std::endl;
487                    _gt->setFilterMatrixAs(osgTerrain::GeometryTechnique::SMOOTH);
488                    return true;
489                }
490                else if (ea.getKey() == 'S')
491                {
492                    osg::notify(osg::NOTICE)<<"Sharpen"<<std::endl;
493                    _gt->setFilterMatrixAs(osgTerrain::GeometryTechnique::SHARPEN);
494                    return true;
495                }
496                else if (ea.getKey() == '+')
497                {
498                    _gt->setFilterWidth(_gt->getFilterWidth()*1.1);
499                    osg::notify(osg::NOTICE)<<"Filter width = "<<_gt->getFilterWidth()<<std::endl;
500                    return true;
501                }
502                else if (ea.getKey() == '-')
503                {
504                    _gt->setFilterWidth(_gt->getFilterWidth()/1.1);
505                    osg::notify(osg::NOTICE)<<"Filter width = "<<_gt->getFilterWidth()<<std::endl;
506                    return true;
507                }
508                else if (ea.getKey() == '>')
509                {
510                    _gt->setFilterBias(_gt->getFilterBias()+0.1);
511                    osg::notify(osg::NOTICE)<<"Filter bias = "<<_gt->getFilterBias()<<std::endl;
512                    return true;
513                }
514                else if (ea.getKey() == '<')
515                {
516                    _gt->setFilterBias(_gt->getFilterBias()-0.1);
517                    osg::notify(osg::NOTICE)<<"Filter bias = "<<_gt->getFilterBias()<<std::endl;
518                    return true;
519                }
520                break;
521            }
522        default:
523            break;
524        }
525        return false;
526
527    }
528
529protected:
530
531    osg::observer_ptr<osgTerrain::GeometryTechnique> _gt;
532
533};
534
535
536
537class LayerHandler : public osgGA::GUIEventHandler
538{
539public:
540
541    LayerHandler(osgTerrain::Layer* layer):
542        _layer(layer) {}
543
544    bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
545    {
546        if (!_layer) return false;
547
548        float scale = 1.2;
549
550        switch(ea.getEventType())
551        {
552        case(osgGA::GUIEventAdapter::KEYDOWN):
553            {
554                if (ea.getKey() == 'q')
555                {
556                    _layer->transform(0.0, scale);
557                    return true;
558                }
559                else if (ea.getKey() == 'a')
560                {
561                    _layer->transform(0.0, 1.0f/scale);
562                    return true;
563                }
564                break;
565            }
566        default:
567            break;
568        }
569        return false;
570
571    }
572
573protected:
574
575    osg::observer_ptr<osgTerrain::Layer> _layer;
576};
577
578int main(int argc, char** argv)
579{
580    osg::ArgumentParser arguments(&argc, argv);
581
582    // construct the viewer.
583    osgViewer::Viewer viewer(arguments);
584
585    // set up the camera manipulators.
586    {
587        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
588
589        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
590        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
591        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
592        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
593
594        std::string pathfile;
595        char keyForAnimationPath = '5';
596        while (arguments.read("-p",pathfile))
597        {
598            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
599            if (apm || !apm->valid())
600            {
601                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
602                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
603                keyswitchManipulator->selectMatrixManipulator(num);
604                ++keyForAnimationPath;
605            }
606        }
607
608        viewer.setCameraManipulator( keyswitchManipulator.get() );
609    }
610
611
612    // add the state manipulator
613    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
614
615    // add the stats handler
616    viewer.addEventHandler(new osgViewer::StatsHandler);
617
618    // add the record camera path handler
619    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
620
621
622    double x = 0.0;
623    double y = 0.0;
624    double w = 1.0;
625    double h = 1.0;
626
627    unsigned int numLoadThreads = 1;
628    while (arguments.read("--load-threads",numLoadThreads)) { }
629
630    osg::ref_ptr<MasterOperation> masterOperation;
631    std::string masterFilename;
632    while(arguments.read("-m",masterFilename))
633    {
634        masterOperation = new MasterOperation(masterFilename);
635    }
636   
637
638    osg::ref_ptr<osgTerrain::TerrainTile> terrainTile = new osgTerrain::TerrainTile;
639    osg::ref_ptr<osgTerrain::Locator> locator = new osgTerrain::Locator;
640    osg::ref_ptr<osgTerrain::ValidDataOperator> validDataOperator = new osgTerrain::NoDataValue(0.0);
641    osg::ref_ptr<osgTerrain::Layer> lastAppliedLayer;
642
643    locator->setCoordinateSystemType(osgTerrain::Locator::GEOCENTRIC);
644    locator->setTransformAsExtents(-osg::PI, -osg::PI*0.5, osg::PI, osg::PI*0.5);
645
646    unsigned int layerNum = 0;
647
648    std::string filterName;
649
650    osg::Texture::FilterMode filter = osg::Texture::LINEAR;
651
652    bool readParameter = false;
653    float minValue, maxValue;
654    float scale = 1.0f;
655    float offset = 0.0f;
656
657    int pos = 1;
658    while(pos<arguments.argc())
659    {
660        readParameter = false;
661        std::string filename;
662       
663        if (arguments.read(pos, "--layer",layerNum))
664        {
665            osg::notify(osg::NOTICE)<<"Set layer number to "<<layerNum<<std::endl;
666            readParameter = true;
667        }
668
669        else if (arguments.read(pos, "-b"))
670        {
671            terrainTile->setTreatBoundariesToValidDataAsDefaultValue(true);
672        }
673       
674        else if (arguments.read(pos, "-e",x,y,w,h))
675        {
676            // define the extents.
677            locator->setCoordinateSystemType(osgTerrain::Locator::GEOCENTRIC);
678            locator->setTransformAsExtents(x,y,x+w,y+h);
679            readParameter = true;
680        }
681
682        else if (arguments.read(pos, "--transform",offset, scale) || arguments.read(pos, "-t",offset, scale))
683        {
684            // define the extents.
685            readParameter = true;
686        }
687
688        else if (arguments.read(pos, "--cartesian",x,y,w,h))
689        {
690            // define the extents.
691            locator->setCoordinateSystemType(osgTerrain::Locator::PROJECTED);
692            locator->setTransformAsExtents(x,y,x+w,y+h);
693        }
694
695        else if (arguments.read(pos, "--hf",filename))
696        {
697            readParameter = true;
698           
699            osg::notify(osg::NOTICE)<<"--hf "<<filename<<std::endl;
700
701            osg::ref_ptr<osg::HeightField> hf = osgDB::readHeightFieldFile(filename);
702            if (hf.valid())
703            {
704                osg::ref_ptr<osgTerrain::HeightFieldLayer> hfl = new osgTerrain::HeightFieldLayer;
705                hfl->setHeightField(hf.get());
706               
707                hfl->setLocator(locator.get());
708                hfl->setValidDataOperator(validDataOperator.get());
709                hfl->setMagFilter(filter);
710               
711                if (offset!=0.0f || scale!=1.0f)
712                {
713                    hfl->transform(offset,scale);
714                }
715               
716                terrainTile->setElevationLayer(hfl.get());
717               
718                lastAppliedLayer = hfl.get();
719               
720                osg::notify(osg::NOTICE)<<"created osgTerrain::HeightFieldLayer"<<std::endl;
721            }
722            else
723            {
724                osg::notify(osg::NOTICE)<<"failed to create osgTerrain::HeightFieldLayer"<<std::endl;
725            }
726           
727            scale = 1.0f;
728            offset = 0.0f;
729           
730        }
731
732        else if (arguments.read(pos, "-d",filename) || arguments.read(pos, "--elevation-image",filename))
733        {
734            readParameter = true;
735            osg::notify(osg::NOTICE)<<"--elevation-image "<<filename<<std::endl;
736
737            osg::ref_ptr<osg::Image> image = osgDB::readImageFile(filename);
738            if (image.valid())
739            {
740                osg::ref_ptr<osgTerrain::ImageLayer> imageLayer = new osgTerrain::ImageLayer;
741                imageLayer->setImage(image.get());
742                imageLayer->setLocator(locator.get());
743                imageLayer->setValidDataOperator(validDataOperator.get());
744                imageLayer->setMagFilter(filter);
745               
746                if (offset!=0.0f || scale!=1.0f)
747                {
748                    imageLayer->transform(offset,scale);
749                }
750               
751                terrainTile->setElevationLayer(imageLayer.get());
752               
753                lastAppliedLayer = imageLayer.get();
754
755                osg::notify(osg::NOTICE)<<"created Elevation osgTerrain::ImageLayer"<<std::endl;
756            }
757            else
758            {
759                osg::notify(osg::NOTICE)<<"failed to create osgTerrain::ImageLayer"<<std::endl;
760            }
761
762            scale = 1.0f;
763            offset = 0.0f;
764           
765        }
766       
767        else if (arguments.read(pos, "-c",filename) || arguments.read(pos, "--image",filename))
768        {
769            readParameter = true;
770            osg::notify(osg::NOTICE)<<"--image "<<filename<<" x="<<x<<" y="<<y<<" w="<<w<<" h="<<h<<std::endl;
771
772            osg::ref_ptr<osg::Image> image = osgDB::readImageFile(filename);
773            if (image.valid())
774            {
775                osg::ref_ptr<osgTerrain::ImageLayer> imageLayer = new osgTerrain::ImageLayer;
776                imageLayer->setImage(image.get());
777                imageLayer->setLocator(locator.get());
778                imageLayer->setValidDataOperator(validDataOperator.get());
779                imageLayer->setMagFilter(filter);
780               
781                if (offset!=0.0f || scale!=1.0f)
782                {
783                    imageLayer->transform(offset,scale);
784                }
785
786                terrainTile->setColorLayer(layerNum, imageLayer.get());
787
788                lastAppliedLayer = imageLayer.get();
789
790                osg::notify(osg::NOTICE)<<"created Color osgTerrain::ImageLayer"<<std::endl;
791            }
792            else
793            {
794                osg::notify(osg::NOTICE)<<"failed to create osgTerrain::ImageLayer"<<std::endl;
795            }
796
797            scale = 1.0f;
798            offset = 0.0f;
799           
800        }
801
802        else if (arguments.read(pos, "--filter",filterName))
803        {
804            readParameter = true;
805           
806            if (filterName=="NEAREST")
807            {
808                osg::notify(osg::NOTICE)<<"--filter "<<filterName<<std::endl;
809                filter = osg::Texture::NEAREST;
810            }
811            else if (filterName=="LINEAR")
812            {
813                filter = osg::Texture::LINEAR;
814                osg::notify(osg::NOTICE)<<"--filter "<<filterName<<std::endl;
815            }
816            else
817            {
818                osg::notify(osg::NOTICE)<<"--filter "<<filterName<<" unrecognized filter name, please use LINEAER or NEAREST."<<std::endl;
819            }           
820
821            if (terrainTile->getColorLayer(layerNum))
822            {
823                terrainTile->getColorLayer(layerNum)->setMagFilter(filter);
824            }
825           
826        }
827
828        else if (arguments.read(pos, "--tf",minValue, maxValue))
829        {
830            readParameter = true;
831
832            osg::ref_ptr<osg::TransferFunction1D> tf = new osg::TransferFunction1D;
833           
834            unsigned int numCells = 6;
835            float delta = (maxValue-minValue)/float(numCells-1);
836            float v = minValue;
837           
838            tf->allocate(6);
839            tf->setColor(v, osg::Vec4(1.0,1.0,1.0,1.0)); v += delta;
840            tf->setColor(v, osg::Vec4(1.0,0.0,1.0,1.0)); v += delta;
841            tf->setColor(v, osg::Vec4(1.0,0.0,0.0,1.0)); v += delta;
842            tf->setColor(v, osg::Vec4(1.0,1.0,0.0,1.0)); v += delta;
843            tf->setColor(v, osg::Vec4(0.0,1.0,1.0,1.0)); v += delta;
844            tf->setColor(v, osg::Vec4(0.0,1.0,0.0,1.0));
845           
846            osg::notify(osg::NOTICE)<<"--tf "<<minValue<<" "<<maxValue<<std::endl;
847
848            terrainTile->setColorLayer(layerNum, new osgTerrain::ContourLayer(tf.get()));
849        }
850        else
851        {
852            ++pos;
853        }
854
855    }
856   
857
858    osg::ref_ptr<osg::Group> scene = new osg::Group;
859
860    if (terrainTile.valid() && (terrainTile->getElevationLayer() || terrainTile->getColorLayer(0)))
861    {
862        osg::notify(osg::NOTICE)<<"Terrain created"<<std::endl;
863   
864        scene->addChild(terrainTile.get());
865
866        osg::ref_ptr<osgTerrain::GeometryTechnique> geometryTechnique = new osgTerrain::GeometryTechnique;
867        terrainTile->setTerrainTechnique(geometryTechnique.get());
868        viewer.addEventHandler(new FilterHandler(geometryTechnique.get()));
869        viewer.addEventHandler(new LayerHandler(lastAppliedLayer.get()));
870    }
871
872    if (masterOperation.valid())
873    {
874        osg::notify(osg::NOTICE)<<"Master operation created"<<std::endl;
875
876        masterOperation->open(scene.get());
877    }
878   
879    if (scene->getNumChildren()==0)
880    {
881        osg::notify(osg::NOTICE)<<"No model created, please specify terrain or master file on command line."<<std::endl;
882        return 0;
883    }
884   
885    viewer.setSceneData(scene.get());
886
887
888    // start operation thread if a master file has been used.
889    osg::ref_ptr<osg::OperationThread> masterOperationThread;
890   
891    typedef std::list< osg::ref_ptr<osg::OperationThread> > OperationThreadList;
892    OperationThreadList generalThreadList;
893   
894    if (masterOperation.valid())
895    {
896        masterOperationThread = new osg::OperationThread;
897        masterOperationThread->startThread();
898       
899        masterOperationThread->add(masterOperation.get());
900
901//        if (numLoadThreads>0)
902        {
903            osg::ref_ptr<osg::OperationQueue> operationQueue = new osg::OperationQueue;
904            masterOperation->setOperationQueue(operationQueue.get());
905
906            for(unsigned int i=0; i<numLoadThreads; ++i)
907            {       
908                osg::ref_ptr<osg::OperationThread> thread = new osg::OperationThread;
909                thread->setOperationQueue(operationQueue.get());
910                thread->startThread();
911                generalThreadList.push_back(thread);
912            }
913        }
914       
915        viewer.addUpdateOperation(masterOperation.get());
916    }
917   
918    viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
919   
920    // enable the use of compile contexts and associated threads.
921    osg::DisplaySettings::instance()->setCompileContextsHint(true);
922
923    // realize the graphics windows.
924    viewer.realize();
925
926    // run the viewers main loop
927    return viewer.run();
928
929}
Note: See TracBrowser for help on using the browser.