source: geovis/trunk/Renderer.h @ 6354

Last change on this file since 6354 was 6354, checked in by ldelgass, 7 years ago

Add layer position index param to add*Layer methods. Add option to transform
selection box coords to another SRS.

File size: 20.4 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2015  HUBzero Foundation, LLC
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#ifndef GEOVIS_RENDERER_H
9#define GEOVIS_RENDERER_H
10
11#include <ctime> // For time_t
12#include <string>
13#include <vector>
14#include <tr1/unordered_map>
15#include <typeinfo>
16
17#include <osg/ref_ptr>
18#include <osg/Node>
19#include <osg/Image>
20#include <osg/TransferFunction>
21#include <osgText/String>
22#include <osgViewer/Viewer>
23#include <osgGA/StateSetManipulator>
24#include <osgUtil/IncrementalCompileOperation>
25
26#include <osgEarth/Version>
27#include <osgEarth/StringUtils>
28#include <osgEarth/Map>
29#include <osgEarth/Viewpoint>
30#include <osgEarth/ImageLayer>
31#include <osgEarth/ElevationLayer>
32#include <osgEarth/ModelLayer>
33#include <osgEarth/TileSource>
34#include <osgEarth/ModelSource>
35#include <osgEarth/GeoData>
36#include <osgEarthAnnotation/AnnotationNode>
37#include <osgEarthAnnotation/FeatureNode>
38#include <osgEarthUtil/Sky>
39#include <osgEarthUtil/RTTPicker>
40#include <osgEarthUtil/EarthManipulator>
41#include <osgEarthUtil/MouseCoordsTool>
42#include <osgEarthUtil/Controls>
43#include <osgEarthUtil/Formatter>
44#include <osgEarthUtil/MGRSFormatter>
45#include <osgEarthUtil/AutoClipPlaneHandler>
46#include <osgEarthUtil/VerticalScale>
47
48#define USE_RTT_PICKER
49
50#include "Types.h"
51#include "Trace.h"
52#include "MouseCoordsTool.h"
53#include "ScaleBar.h"
54#include "Placard.h"
55
56// Controls if TGA format is sent to client
57//#define RENDER_TARGA
58#define TARGA_BYTES_PER_PIXEL 3
59
60namespace GeoVis {
61
62class ScreenCaptureCallback : public osg::Camera::DrawCallback
63{
64public:
65    ScreenCaptureCallback(osg::Texture2D *texture = NULL) :
66        osg::Camera::DrawCallback(),
67        _texture(texture)
68    {
69        _image = new osg::Image;
70    }
71
72    virtual void operator()(osg::RenderInfo &renderInfo) const
73    {
74        FRAME("Enter ScreenCaptureCallback");
75        int width, height;
76        if (renderInfo.getCurrentCamera() == NULL) {
77            ERROR("No camera");
78            return;
79        }
80        if (renderInfo.getCurrentCamera()->getViewport() == NULL) {
81            ERROR("No viewport");
82            return;
83        }
84        width = (int)renderInfo.getCurrentCamera()->getViewport()->width();
85        height = (int)renderInfo.getCurrentCamera()->getViewport()->height();
86        FRAME("readPixels: %d x %d", width, height);
87#if 0 //USE_OFFSCREEN_FRAMEBUFFER
88        _image = _texture->getImage();
89#else
90#ifdef RENDER_TARGA
91        _image->readPixels(0, 0, width, height,
92                           GL_BGR, GL_UNSIGNED_BYTE);
93#else
94        _image->readPixels(0, 0, width, height,
95                           GL_RGB, GL_UNSIGNED_BYTE);
96#endif
97#endif
98    }
99
100    osg::Image *getImage()
101    {
102        return _image.get();
103    }
104
105    osg::Texture2D *getTexture()
106    {
107        return _texture.get();
108    }
109
110private:
111    osg::ref_ptr<osg::Texture2D> _texture;
112    osg::ref_ptr<osg::Image> _image;
113};
114
115/**
116 * \brief GIS Renderer
117 */
118class Renderer
119{
120public:
121    typedef std::string ColorMapId;
122    typedef std::string ViewpointId;
123
124    enum GraticuleType {
125        GRATICULE_UTM,
126        GRATICULE_MGRS,
127        GRATICULE_GEODETIC,
128        GRATICULE_SHADER
129    };
130
131    enum CoordinateDisplayType {
132        COORDS_LATLONG_DECIMAL_DEGREES,
133        COORDS_LATLONG_DEGREES_DECIMAL_MINUTES,
134        COORDS_LATLONG_DEGREES_MINUTES_SECONDS,
135        COORDS_MGRS
136    };
137
138    enum SelectMode {
139        SELECT_OFF,
140        SELECT_ON
141    };
142
143    Renderer();
144    virtual ~Renderer();
145
146    void setResourcePath(const std::string& path)
147    {
148        TRACE("Set resource path to %s", path.c_str());
149        _resourcePath = path;
150    }
151
152    void setCacheBaseDirectory(const std::string& path)
153    {
154        TRACE("Set cache base dir to %s", path.c_str());
155        _cacheBaseDir = path;
156    }
157
158    std::string getCacheDirectory() const
159    {
160        return _cacheDir;
161    }
162
163    void setupCache();
164
165    std::string getIconFile(const char *name) const;
166
167    std::string getBaseImage() const;
168
169    std::string getPinIcon() const;
170
171    void setAttribution(const std::string& attrib);
172
173    // Colormaps
174
175    void addColorMap(const ColorMapId& id, osg::TransferFunction1D *xfer);
176
177    void deleteColorMap(const ColorMapId& id);
178
179    void setColorMapNumberOfTableEntries(const ColorMapId& id, int numEntries);
180
181    bool renderColorMap(const ColorMapId& id, int width, int height,
182                        osg::Image *imgData,
183                        bool opaque, float bgColor[3],
184                        bool bgr = false,
185                        int bytesPerPixel = 3) const;
186
187    void getColorMapRange(const ColorMapId& id, float *min, float *max) const;
188
189    std::string getColorMapFilePath(const ColorMapId& id) const;
190
191    void saveCLRFile(const std::string& path, osg::TransferFunction1D *xfer);
192
193    // Scene
194
195    void loadEarthFile(const char *path);
196
197    void resetMap(osgEarth::MapOptions::CoordinateSystemType type,
198                  const osg::Vec4f& bgColor = osg::Vec4f(1,1,1,1),
199                  const char *profile = NULL,
200                  double bounds[4] = NULL);
201
202    void clearMap();
203
204    // Map options
205
206    void setCoordinateReadout(bool state,
207                              CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
208                              int precision = -1);
209
210    void setReadout(int mouseX, int mouseY);
211
212    void clearReadout();
213
214    void setScaleBar(bool state);
215
216    void setScaleBarUnits(ScaleBarUnits units);
217
218    void setGraticule(bool enable, GraticuleType type = GRATICULE_SHADER);
219
220    void setViewerLightType(osg::View::LightingMode mode);
221
222    void setLighting(bool state);
223
224    void setTerrainColor(const osg::Vec4f& color);
225
226    void setTerrainEdges(bool state) {}
227
228    void setTerrainLineColor(const osg::Vec4f& color) {}
229
230    void setTerrainLineWidth(float width) {}
231
232    void setTerrainLighting(bool state);
233
234    void setTerrainVerticalScale(double scale);
235
236    void setTerrainWireframe(bool state);
237
238    void setEphemerisTime(time_t utcTime);
239
240    void setEphemerisTime(int year, int month, int day, double hours);
241
242    void setSkyAmbient(float ambientLevel);
243
244    // Image raster layers
245
246    int getNumImageLayers() const
247    {
248        return (_map.valid() ? _map->getNumImageLayers() : 0);
249    }
250
251    void getImageLayerNames(std::vector<std::string>& names)
252    {
253        if (_map.valid()) {
254            osgEarth::ImageLayerVector layerVector;
255            _map->getImageLayers(layerVector);
256            osgEarth::ImageLayerVector::const_iterator itr;
257            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
258                //osgEarth::UID uid = (*itr)->getUID();
259                names.push_back((*itr)->getName());
260            }
261        }
262    }
263
264    bool addImageLayer(const char *name,
265                       osgEarth::TileSourceOptions& opts,
266                       unsigned int pos = UINT_MAX,
267                       bool enableCache = true,
268                       bool coverage = false,
269                       bool makeShared = false,
270                       bool visible = true,
271                       unsigned int minLOD = 0,
272                       unsigned int maxLOD = 23);
273
274    void removeImageLayer(const char *name);
275
276    void moveImageLayer(const char *name, unsigned int pos);
277
278    bool getImageLayerExtent(const char *name, osgEarth::GeoExtent &ext);
279
280    void setImageLayerVisibleRange(const char *name, float min, float max);
281
282    void setImageLayerLODRange(const char *name, int min, int max);
283
284    void setImageLayerOpacity(const char *name, double opacity);
285
286    void setImageLayerVisibility(const char *name, bool state);
287
288    void addColorFilter(const char *name, const char *shader);
289
290    void removeColorFilter(const char *name, int idx = -1);
291
292    // Elevation raster layers
293
294    int getNumElevationLayers() const
295    {
296        return (_map.valid() ? _map->getNumElevationLayers() : 0);
297    }
298
299    void getElevationLayerNames(std::vector<std::string>& names)
300    {
301        if (_map.valid()) {
302            osgEarth::ElevationLayerVector layerVector;
303            _map->getElevationLayers(layerVector);
304            osgEarth::ElevationLayerVector::const_iterator itr;
305            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
306                //osgEarth::UID uid = (*itr)->getUID();
307                names.push_back((*itr)->getName());
308            }
309        }
310    }
311
312    void addElevationLayer(const char *name,
313                           osgEarth::TileSourceOptions& opts,
314                           unsigned int pos = UINT_MAX,
315                           bool enableCache = true,
316                           bool visible = true,
317                           unsigned int minLOD = 0,
318                           unsigned int maxLOD = 23);
319
320    void removeElevationLayer(const char *name);
321
322    void moveElevationLayer(const char *name, unsigned int pos);
323
324    bool getElevationLayerExtent(const char *name, osgEarth::GeoExtent &ext);
325
326    void setElevationLayerVisibleRange(const char *name, float min, float max);
327
328    void setElevationLayerVisibility(const char *name, bool state);
329
330    // Model layers
331
332    int getNumModelLayers() const
333    {
334        return (_map.valid() ? _map->getNumModelLayers() : 0);
335    }
336
337    void getModelLayerNames(std::vector<std::string>& names)
338    {
339        if (_map.valid()) {
340            osgEarth::ModelLayerVector layerVector;
341            _map->getModelLayers(layerVector);
342            osgEarth::ModelLayerVector::const_iterator itr;
343            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
344                //osgEarth::UID uid = (*itr)->getUID();
345                names.push_back((*itr)->getName());
346            }
347        }
348    }
349
350    void addModelLayer(const char *name,
351                       osgEarth::ModelSourceOptions& opts,
352                       unsigned int pos = UINT_MAX,
353                       bool enableCache = true,
354                       bool lighting = true,
355                       bool visible = true);
356
357    void removeModelLayer(const char *name);
358
359    void moveModelLayer(const char *name, unsigned int pos);
360
361    bool getModelLayerExtent(const char *name, osgEarth::GeoExtent &ext);
362
363    //void setModelLayerVisibleRange(const char *name, float min, float max);
364
365    void setModelLayerOpacity(const char *name, double opacity);
366
367    void setModelLayerVisibility(const char *name, bool state);
368
369    // Render window
370
371    void setWindowSize(int width, int height);
372
373    int getWindowWidth() const
374    {
375        return _windowWidth;
376    }
377
378    int getWindowHeight() const
379    {
380        return _windowHeight;
381    }
382
383    // Camera
384
385    void saveNamedViewpoint(const char *name);
386
387    bool restoreNamedViewpoint(const char *name, double durationSecs);
388
389    bool removeNamedViewpoint(const char *name);
390
391    osgEarth::Viewpoint getViewpoint();
392
393    void setViewpoint(const osgEarth::Viewpoint& v, double durationSecs = 0.0);
394
395    double getMaxDistanceFromExtent(const osgEarth::GeoExtent& extent);
396
397    void setViewpointFromExtent(const osgEarth::GeoExtent& ext,
398                                double durationSecs = 0.0);
399
400    void setViewpointFromRect(double xmin, double ymin,
401                              double xmax, double ymax,
402                              const osgEarth::SpatialReference *srs = NULL,
403                              double durationSecs = 0.0);
404
405    void resetCamera(bool resetOrientation = true);
406
407    void setCameraOrientation(const double quat[4], bool absolute = true);
408
409    void panCamera(double x, double y);
410
411    void rotateCamera(double x, double y);
412
413    void zoomCamera(double z);
414
415    void setCameraDistance(double dist);
416
417    // Keyboard events
418
419    void keyPress(int key);
420
421    void keyRelease(int key);
422
423    // Mouse events
424
425    void setThrowingEnabled(bool state);
426
427    void mouseClick(int button, double x, double y);
428
429    void mouseDoubleClick(int button, double x, double y);
430
431    void mouseDrag(int button, double x, double y);
432
433    void mouseRelease(int button, double x, double y);
434
435    void mouseMotion(double x, double y);
436
437    void mouseScroll(int direction);
438
439    void pickPending(bool value)
440    { _pickPending = value; }
441
442    // Rendering an image
443
444    void setBackgroundColor(float color[3]);
445
446    void eventuallyRender();
447
448    bool render();
449
450    osg::Image *getRenderedFrame();
451
452    bool mapMouseCoords(float mouseX, float mouseY,
453                        osgEarth::GeoPoint &pt, bool invertY = true);
454
455    double computeMapScale();
456
457    const osgEarth::SpatialReference *getMapSRS()
458    {
459        if (_mapNode.valid()) {
460            return _mapNode->getMapSRS();
461        } else {
462            return NULL;
463        }
464    }
465
466    void addPlaceNode(double latitude, double longitude, char *labelText);
467
468    void hoverPlaceNode(int x, int y, bool invertY = true);
469
470    void deletePlaceNode(int x, int y, bool invertY = true);
471
472    bool getMousePoint(double *x, double *y, double *z)
473    {
474        return (_coordsCallback.valid() && _coordsCallback->report(x, y, z));
475    }
476
477    bool mouseToLatLong(int mouseX, int mouseY,
478                        double *latitude, double *longitude);
479
480    bool getWorldCoords(const osgEarth::GeoPoint& mapPt, osg::Vec3d *world);
481
482    bool worldToScreen(const osg::Vec3d& world, osg::Vec3d *screen,
483                       bool invertY = true);
484
485    bool worldToScreen(std::vector<osg::Vec3d>& coords, bool invertY = true);
486
487    void setMaximumFrameRateInHertz(double rate)
488    {
489        if (rate > 60.0)
490            rate = 60.0;
491        if (rate < 0.25)
492            rate = 0.25;
493        _minFrameTime = 1.0/rate;
494        if (_viewer.valid()) {
495            osgUtil::IncrementalCompileOperation *op =
496                _viewer->getDatabasePager()->getIncrementalCompileOperation();
497            if (op != NULL) {
498                TRACE("Setting DB Pager target frame rate to %g", rate);
499                op->setTargetFrameRate(rate);
500            }
501        }
502    }
503
504    void setMaximumBitrate(double bitsPerSecond)
505    {
506        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
507        double fps = bitsPerSecond / ((double)bitsPerFrame);
508        setMaximumFrameRateInHertz(fps);
509    }
510
511    double getMaximumFrameRateInHertz()
512    {
513        return (1.0/_minFrameTime);
514    }
515
516    double getMaximumBitrate()
517    {
518        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
519        return ((double)bitsPerFrame * getMaximumFrameRateInHertz());
520    }
521
522    void markFrameStart();
523
524    void markFrameEnd();
525
526    long getTimeout();
527
528    void mapNodeUpdate();
529
530    std::string getCanonicalPath(const std::string& url) const;
531
532    void writeScene(const std::string& file);
533
534    void enablePlacard(const char *layerName, bool state);
535
536    void setPlacardConfig(const Placard& placardConf, const char *layerName);
537
538    void setSelectMode(SelectMode mode);
539
540    void selectFeatures(std::vector<unsigned long>& featureIDs,
541                        const char *layerName, bool clear = true);
542
543    void deselectFeatures(std::vector<unsigned long>& featureIDs,
544                          const char *layerName);
545
546    void addPlacard(const osgEarth::GeoPoint& location,
547                    osgEarth::Features::Feature *feature,
548                    const char *layerName);
549
550    void clearSelection();
551
552    void addRhumbBox(double latMin, double latMax,
553                     double longMin, double longMax);
554
555    void initBoxSelection(int x, int y);
556    void updateBoxSelection(int x, int y);
557    void getBoxSelection(double *latMin, double *latMax,
558                         double *longMin, double *longMax,
559                         const osgEarth::SpatialReference *outSRS = NULL);
560    void clearBoxSelection();
561
562    bool select(osgEarth::Annotation::AnnotationNode *node)
563    {
564        if (_selected.find(node) == _selected.end()) {
565            _selected.insert(node);
566            return true;
567        } else {
568            return false;
569        }
570    }
571
572    std::set<osgEarth::Annotation::AnnotationNode*>& getHovered()
573    { return _hovered; }
574    std::set<osgEarth::Annotation::AnnotationNode*>& getSelected()
575    { return _selected; }
576    osg::Group *getSceneRoot()
577    { return _sceneRoot.get(); }
578    osgEarth::MapNode *getMapNode()
579    { return _mapNode.get(); }
580    osg::Group *getAnnotations()
581    {
582        initAnnotations();
583        return _annotations.get();
584    }
585    osg::Group *getPlaceNodes()
586    {
587        initAnnotations();
588        return _placeNodes.get();
589    }
590    Placard getPlacardConfig(const char *layerName)
591    {
592        Placard ret;
593        PlacardHashmap::iterator itr = _placardConfigs.find(layerName);
594        if (itr != _placardConfigs.end()) {
595            ret = itr->second;
596        }
597        return ret;
598    }
599
600private:
601    typedef std::tr1::unordered_map<ColorMapId, osg::ref_ptr<osg::TransferFunction1D> > ColorMapHashmap;
602    typedef std::tr1::unordered_map<ViewpointId, osgEarth::Viewpoint> ViewpointHashmap;
603    typedef std::tr1::unordered_map<std::string, Placard> PlacardHashmap;
604    typedef std::tr1::unordered_map<std::string, std::set<unsigned long> > FeatureSelectionHashmap;
605
606    void initAnnotations();
607
608    void clearSelectionAnnotationNodes();
609
610    void initViewer();
611
612    void finalizeViewer();
613   
614    void initControls();
615
616    void updateDebugLabel();
617
618    void initEarthManipulator();
619
620    void initMouseCoordsTool(CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
621                             int precision = -1);
622
623    osgEarth::Util::MGRSFormatter::Precision getMGRSPrecision(int precisionInMeters);
624
625    void initColorMaps();
626
627    void initCamera();
628
629    bool isPagerIdle();
630
631    bool checkNeedToDoFrame();
632
633    osgGA::EventQueue *getEventQueue();
634
635    bool _needsRedraw;
636    int _windowWidth, _windowHeight;
637    double _mapScale;
638    float _bgColor[3];
639
640    double _minFrameTime;
641    double _lastFrameTime;
642    double _renderTime;
643    osg::Timer_t _startFrameTime;
644    osg::Timer_t _renderStartTime;
645    osg::Timer_t _renderStopTime;
646
647    ColorMapHashmap _colorMaps;
648
649    std::string _resourcePath;
650    std::string _cacheBaseDir;
651    std::string _cacheDir;
652    std::string _baseURI;
653    std::string _attribution;
654
655    osg::ref_ptr<osg::Group> _sceneRoot;
656    osg::ref_ptr<osg::Group> _graticule;
657    osg::ref_ptr<osg::Group> _annotations;
658    PlacardHashmap _placardConfigs;
659    double _anchorLat, _anchorLong;
660    SelectMode _selectMode;
661    osg::ref_ptr<osgEarth::Annotation::FeatureNode> _selectionBox;
662#ifdef USE_RTT_PICKER
663    osg::ref_ptr<osgEarth::Util::RTTPicker> _picker;
664#endif
665    bool _pickPending;
666    osg::ref_ptr<osg::Group> _placeNodes;
667    FeatureSelectionHashmap _selectedFeatures;
668    std::set<osgEarth::Annotation::AnnotationNode *> _hovered;
669    std::set<osgEarth::Annotation::AnnotationNode *> _selected;
670    osg::ref_ptr<osgEarth::MapNode> _mapNode;
671    osg::ref_ptr<osgEarth::Map> _map;
672    osg::ref_ptr<osgEarth::Util::SkyNode> _skyNode;
673    osg::ref_ptr<osgViewer::Viewer> _viewer;
674    osg::ref_ptr<ScreenCaptureCallback> _captureCallback;
675    osg::ref_ptr<osgEarth::Util::AutoClipPlaneCullCallback> _clipPlaneCullCallback;
676    osg::ref_ptr<osgEarth::Util::Controls::HBox> _coordsBox;
677    osg::ref_ptr<MouseCoordsTool> _mouseCoordsTool;
678    osg::ref_ptr<MouseCoordsCallback> _coordsCallback;
679    osg::ref_ptr<osgEarth::Util::Controls::HBox> _debugBox;
680    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _debugLabel;
681    osg::ref_ptr<osgEarth::Util::Controls::HBox> _copyrightScaleBox;
682    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _copyrightLabel;
683    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _scaleLabel;
684    osg::ref_ptr<osgEarth::Util::Controls::Frame> _scaleBar;
685    ScaleBarUnits _scaleBarUnits;
686    osg::ref_ptr<osgEarth::Util::EarthManipulator> _manipulator;
687    osg::ref_ptr<osgGA::StateSetManipulator> _stateManip;
688    osg::ref_ptr<osgEarth::Util::VerticalScale> _verticalScale;
689    ViewpointHashmap _viewpoints;
690};
691
692class MapNodeCallback : public osg::NodeCallback
693{
694public:
695    MapNodeCallback(Renderer *renderer) :
696        _renderer(renderer)
697    {}
698
699    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
700    {
701        _renderer->mapNodeUpdate();
702        traverse(node, nv);
703    }
704private:
705    Renderer *_renderer;
706};
707
708class SelectPlaceNodesVisitor : public osg::NodeVisitor
709{
710public:
711    SelectPlaceNodesVisitor(Renderer *renderer,
712                            double latMin, double latMax,
713                            double longMin, double longMax) :
714        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
715        _renderer(renderer),
716        _latMin(latMin), _latMax(latMax),
717        _longMin(longMin), _longMax(longMax)
718    {}
719
720    virtual void apply(osg::Node& node);
721
722private:
723    Renderer *_renderer;
724    double _latMin, _latMax, _longMin, _longMax;
725};
726
727}
728
729#endif
Note: See TracBrowser for help on using the repository browser.