source: geovis/trunk/Renderer.h @ 5972

Last change on this file since 5972 was 5944, checked in by ldelgass, 8 years ago

Add command to configure attributes to display in feature info placard.

File size: 18.8 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    Renderer();
139    virtual ~Renderer();
140
141    void setResourcePath(const std::string& path)
142    {
143        TRACE("Set resource path to %s", path.c_str());
144        _resourcePath = path;
145    }
146
147    void setCacheBaseDirectory(const std::string& path)
148    {
149        TRACE("Set cache base dir to %s", path.c_str());
150        _cacheBaseDir = path;
151    }
152
153    std::string getCacheDirectory() const
154    {
155        return _cacheDir;
156    }
157
158    void setupCache();
159
160    std::string getBaseImage() const;
161
162    std::string getPinIcon() const;
163
164    void setAttribution(const std::string& attrib);
165
166    // Colormaps
167
168    void addColorMap(const ColorMapId& id, osg::TransferFunction1D *xfer);
169
170    void deleteColorMap(const ColorMapId& id);
171
172    void setColorMapNumberOfTableEntries(const ColorMapId& id, int numEntries);
173
174    bool renderColorMap(const ColorMapId& id, int width, int height,
175                        osg::Image *imgData,
176                        bool opaque, float bgColor[3],
177                        bool bgr = false,
178                        int bytesPerPixel = 3) const;
179
180    void getColorMapRange(const ColorMapId& id, float *min, float *max) const;
181
182    std::string getColorMapFilePath(const ColorMapId& id) const;
183
184    void saveCLRFile(const std::string& path, osg::TransferFunction1D *xfer);
185
186    // Scene
187
188    void loadEarthFile(const char *path);
189
190    void resetMap(osgEarth::MapOptions::CoordinateSystemType type,
191                  const osg::Vec4f& bgColor = osg::Vec4f(1,1,1,1),
192                  const char *profile = NULL,
193                  double bounds[4] = NULL);
194
195    void clearMap();
196
197    // Map options
198
199    void setCoordinateReadout(bool state,
200                              CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
201                              int precision = -1);
202
203    void setReadout(int mouseX, int mouseY);
204
205    void clearReadout();
206
207    void setScaleBar(bool state);
208
209    void setScaleBarUnits(ScaleBarUnits units);
210
211    void setGraticule(bool enable, GraticuleType type = GRATICULE_SHADER);
212
213    void setViewerLightType(osg::View::LightingMode mode);
214
215    void setLighting(bool state);
216
217    void setTerrainColor(const osg::Vec4f& color);
218
219    void setTerrainEdges(bool state) {}
220
221    void setTerrainLineColor(const osg::Vec4f& color) {}
222
223    void setTerrainLineWidth(float width) {}
224
225    void setTerrainLighting(bool state);
226
227    void setTerrainVerticalScale(double scale);
228
229    void setTerrainWireframe(bool state);
230
231    void setEphemerisTime(time_t utcTime);
232
233    void setEphemerisTime(int year, int month, int day, double hours);
234
235    void setSkyAmbient(float ambientLevel);
236
237    // Image raster layers
238
239    int getNumImageLayers() const
240    {
241        return (_map.valid() ? _map->getNumImageLayers() : 0);
242    }
243
244    void getImageLayerNames(std::vector<std::string>& names)
245    {
246        if (_map.valid()) {
247            osgEarth::ImageLayerVector layerVector;
248            _map->getImageLayers(layerVector);
249            osgEarth::ImageLayerVector::const_iterator itr;
250            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
251                //osgEarth::UID uid = (*itr)->getUID();
252                names.push_back((*itr)->getName());
253            }
254        }
255    }
256
257    bool addImageLayer(const char *name, osgEarth::TileSourceOptions& opts,
258                       bool enableCache = true,
259                       bool coverage = false,
260                       bool makeShared = false,
261                       bool visible = true,
262                       unsigned int minLOD = 0,
263                       unsigned int maxLOD = 23);
264
265    void removeImageLayer(const char *name);
266
267    void moveImageLayer(const char *name, unsigned int pos);
268
269    bool getImageLayerExtent(const char *name, osgEarth::GeoExtent &ext);
270
271    void setImageLayerVisibleRange(const char *name, float min, float max);
272
273    void setImageLayerLODRange(const char *name, int min, int max);
274
275    void setImageLayerOpacity(const char *name, double opacity);
276
277    void setImageLayerVisibility(const char *name, bool state);
278
279    void addColorFilter(const char *name, const char *shader);
280
281    void removeColorFilter(const char *name, int idx = -1);
282
283    // Elevation raster layers
284
285    int getNumElevationLayers() const
286    {
287        return (_map.valid() ? _map->getNumElevationLayers() : 0);
288    }
289
290    void getElevationLayerNames(std::vector<std::string>& names)
291    {
292        if (_map.valid()) {
293            osgEarth::ElevationLayerVector layerVector;
294            _map->getElevationLayers(layerVector);
295            osgEarth::ElevationLayerVector::const_iterator itr;
296            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
297                //osgEarth::UID uid = (*itr)->getUID();
298                names.push_back((*itr)->getName());
299            }
300        }
301    }
302
303    void addElevationLayer(const char *name, osgEarth::TileSourceOptions& opts,
304                           bool enableCache = true,
305                           bool visible = true,
306                           unsigned int minLOD = 0,
307                           unsigned int maxLOD = 23);
308
309    void removeElevationLayer(const char *name);
310
311    void moveElevationLayer(const char *name, unsigned int pos);
312
313    bool getElevationLayerExtent(const char *name, osgEarth::GeoExtent &ext);
314
315    void setElevationLayerVisibleRange(const char *name, float min, float max);
316
317    void setElevationLayerVisibility(const char *name, bool state);
318
319    // Model layers
320
321    int getNumModelLayers() const
322    {
323        return (_map.valid() ? _map->getNumModelLayers() : 0);
324    }
325
326    void getModelLayerNames(std::vector<std::string>& names)
327    {
328        if (_map.valid()) {
329            osgEarth::ModelLayerVector layerVector;
330            _map->getModelLayers(layerVector);
331            osgEarth::ModelLayerVector::const_iterator itr;
332            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
333                //osgEarth::UID uid = (*itr)->getUID();
334                names.push_back((*itr)->getName());
335            }
336        }
337    }
338
339    void addModelLayer(const char *name, osgEarth::ModelSourceOptions& opts,
340                       bool enableCache = true,
341                       bool lighting = true,
342                       bool visible = true);
343
344    void removeModelLayer(const char *name);
345
346    void moveModelLayer(const char *name, unsigned int pos);
347
348    bool getModelLayerExtent(const char *name, osgEarth::GeoExtent &ext);
349
350    //void setModelLayerVisibleRange(const char *name, float min, float max);
351
352    void setModelLayerOpacity(const char *name, double opacity);
353
354    void setModelLayerVisibility(const char *name, bool state);
355
356    // Render window
357
358    void setWindowSize(int width, int height);
359
360    int getWindowWidth() const
361    {
362        return _windowWidth;
363    }
364
365    int getWindowHeight() const
366    {
367        return _windowHeight;
368    }
369
370    // Camera
371
372    void saveNamedViewpoint(const char *name);
373
374    bool restoreNamedViewpoint(const char *name, double durationSecs);
375
376    bool removeNamedViewpoint(const char *name);
377
378    osgEarth::Viewpoint getViewpoint();
379
380    void setViewpoint(const osgEarth::Viewpoint& v, double durationSecs = 0.0);
381
382    double getMaxDistanceFromExtent(const osgEarth::GeoExtent& extent);
383
384    void setViewpointFromExtent(const osgEarth::GeoExtent& ext,
385                                double durationSecs = 0.0);
386
387    void setViewpointFromRect(double xmin, double ymin,
388                              double xmax, double ymax,
389                              const osgEarth::SpatialReference *srs = NULL,
390                              double durationSecs = 0.0);
391
392    void resetCamera(bool resetOrientation = true);
393
394    void setCameraOrientation(const double quat[4], bool absolute = true);
395
396    void panCamera(double x, double y);
397
398    void rotateCamera(double x, double y);
399
400    void zoomCamera(double z);
401
402    void setCameraDistance(double dist);
403
404    // Keyboard events
405
406    void keyPress(int key);
407
408    void keyRelease(int key);
409
410    // Mouse events
411
412    void setThrowingEnabled(bool state);
413
414    void mouseClick(int button, double x, double y);
415
416    void mouseDoubleClick(int button, double x, double y);
417
418    void mouseDrag(int button, double x, double y);
419
420    void mouseRelease(int button, double x, double y);
421
422    void mouseMotion(double x, double y);
423
424    void mouseScroll(int direction);
425
426    // Rendering an image
427
428    void setBackgroundColor(float color[3]);
429
430    void eventuallyRender();
431
432    bool render();
433
434    osg::Image *getRenderedFrame();
435
436    bool mapMouseCoords(float mouseX, float mouseY,
437                        osgEarth::GeoPoint &pt, bool invertY = true);
438
439    double computeMapScale();
440
441    const osgEarth::SpatialReference *getMapSRS()
442    {
443        if (_mapNode.valid()) {
444            return _mapNode->getMapSRS();
445        } else {
446            return NULL;
447        }
448    }
449
450    void addPlaceNode(double latitude, double longitude, char *labelText);
451
452    void hoverPlaceNode(int x, int y, bool invertY = true);
453
454    void deletePlaceNode(int x, int y, bool invertY = true);
455
456    bool getMousePoint(double *x, double *y, double *z)
457    {
458        return (_coordsCallback.valid() && _coordsCallback->report(x, y, z));
459    }
460
461    bool mouseToLatLong(int mouseX, int mouseY, double *latitude, double *longitude);
462
463    bool getWorldCoords(const osgEarth::GeoPoint& mapPt, osg::Vec3d *world);
464
465    bool worldToScreen(const osg::Vec3d& world, osg::Vec3d *screen,
466                       bool invertY = true);
467
468    bool worldToScreen(std::vector<osg::Vec3d>& coords, bool invertY = true);
469
470    void setMaximumFrameRateInHertz(double rate)
471    {
472        if (rate > 60.0)
473            rate = 60.0;
474        if (rate < 0.25)
475            rate = 0.25;
476        _minFrameTime = 1.0/rate;
477        if (_viewer.valid()) {
478            osgUtil::IncrementalCompileOperation *op =
479                _viewer->getDatabasePager()->getIncrementalCompileOperation();
480            if (op != NULL) {
481                TRACE("Setting DB Pager target frame rate to %g", rate);
482                op->setTargetFrameRate(rate);
483            }
484        }
485    }
486
487    void setMaximumBitrate(double bitsPerSecond)
488    {
489        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
490        double fps = bitsPerSecond / ((double)bitsPerFrame);
491        setMaximumFrameRateInHertz(fps);
492    }
493
494    double getMaximumFrameRateInHertz()
495    {
496        return (1.0/_minFrameTime);
497    }
498
499    double getMaximumBitrate()
500    {
501        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
502        return ((double)bitsPerFrame * getMaximumFrameRateInHertz());
503    }
504
505    void markFrameStart();
506
507    void markFrameEnd();
508
509    long getTimeout();
510
511    void mapNodeUpdate();
512
513    std::string getCanonicalPath(const std::string& url) const;
514
515    void writeScene(const std::string& file);
516
517    void setPlacardConfig(const Placard& placardConf, const char *layerName);
518
519    void selectFeatures(std::vector<unsigned long>& featureIDs, const char *layerName);
520
521    void addRhumbBox(double latMin, double latMax, double longMin, double longMax);
522
523    void initBoxSelection(int x, int y);
524    void updateBoxSelection(int x, int y);
525    void clearBoxSelection();
526
527    bool select(osgEarth::Annotation::AnnotationNode *node)
528    {
529        if (_selected.find(node) == _selected.end()) {
530            _selected.insert(node);
531            return true;
532        } else {
533            return false;
534        }
535    }
536
537    std::set<osgEarth::Annotation::AnnotationNode*>& getHovered()
538    { return _hovered; }
539    std::set<osgEarth::Annotation::AnnotationNode*>& getSelected()
540    { return _selected; }
541    osg::Group *getSceneRoot()
542    { return _sceneRoot.get(); }
543    osgEarth::MapNode *getMapNode()
544    { return _mapNode.get(); }
545    osg::Group *getAnnotations()
546    {
547        initAnnotations();
548        return _annotations.get();
549    }
550    osg::Group *getPlaceNodes()
551    {
552        initAnnotations();
553        return _placeNodes.get();
554    }
555    Placard getPlacardConfig(const std::string& layerName)
556    {
557        Placard ret;
558        PlacardHashmap::iterator itr = _placardConfigs.find(layerName);
559        if (itr != _placardConfigs.end()) {
560            ret = itr->second;
561        }
562        return ret;
563    }
564
565private:
566    typedef std::tr1::unordered_map<ColorMapId, osg::ref_ptr<osg::TransferFunction1D> > ColorMapHashmap;
567    typedef std::tr1::unordered_map<ViewpointId, osgEarth::Viewpoint> ViewpointHashmap;
568    typedef std::tr1::unordered_map<std::string, Placard> PlacardHashmap;
569
570    void initAnnotations();
571
572    void initViewer();
573
574    void finalizeViewer();
575   
576    void initControls();
577
578    void initEarthManipulator();
579
580    void initMouseCoordsTool(CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
581                             int precision = -1);
582
583    osgEarth::Util::MGRSFormatter::Precision getMGRSPrecision(int precisionInMeters);
584
585    void initColorMaps();
586
587    void initCamera();
588
589    bool isPagerIdle();
590
591    bool checkNeedToDoFrame();
592
593    osgGA::EventQueue *getEventQueue();
594
595    bool _needsRedraw;
596    int _windowWidth, _windowHeight;
597    double _mapScale;
598    float _bgColor[3];
599
600    double _minFrameTime;
601    double _lastFrameTime;
602    double _renderTime;
603    osg::Timer_t _startFrameTime;
604    osg::Timer_t _renderStartTime;
605    osg::Timer_t _renderStopTime;
606
607    ColorMapHashmap _colorMaps;
608
609    std::string _resourcePath;
610    std::string _cacheBaseDir;
611    std::string _cacheDir;
612    std::string _baseURI;
613    std::string _attribution;
614
615    osg::ref_ptr<osg::Group> _sceneRoot;
616    osg::ref_ptr<osg::Group> _graticule;
617    osg::ref_ptr<osg::Group> _annotations;
618    PlacardHashmap _placardConfigs;
619    double _anchorLat, _anchorLong;
620    osg::ref_ptr<osgEarth::Annotation::FeatureNode> _selectionBox;
621#ifdef USE_RTT_PICKER
622    osg::ref_ptr<osgEarth::Util::RTTPicker> _picker;
623#endif
624    osg::ref_ptr<osg::Group> _placeNodes;
625    std::set<osgEarth::Annotation::AnnotationNode *> _hovered;
626    std::set<osgEarth::Annotation::AnnotationNode *> _selected;
627    osg::ref_ptr<osgEarth::MapNode> _mapNode;
628    osg::ref_ptr<osgEarth::Map> _map;
629    osg::ref_ptr<osgEarth::Util::SkyNode> _skyNode;
630    osg::ref_ptr<osgViewer::Viewer> _viewer;
631    osg::ref_ptr<ScreenCaptureCallback> _captureCallback;
632    osg::ref_ptr<osgEarth::Util::AutoClipPlaneCullCallback> _clipPlaneCullCallback;
633    osg::ref_ptr<MouseCoordsTool> _mouseCoordsTool;
634    osg::ref_ptr<MouseCoordsCallback> _coordsCallback;
635    osg::ref_ptr<osgEarth::Util::Controls::HBox> _hbox;
636    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _copyrightLabel;
637    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _scaleLabel;
638    osg::ref_ptr<osgEarth::Util::Controls::Frame> _scaleBar;
639    ScaleBarUnits _scaleBarUnits;
640    osg::ref_ptr<osgEarth::Util::EarthManipulator> _manipulator;
641    osg::ref_ptr<osgGA::StateSetManipulator> _stateManip;
642    osg::ref_ptr<osgEarth::Util::VerticalScale> _verticalScale;
643    ViewpointHashmap _viewpoints;
644};
645
646class MapNodeCallback : public osg::NodeCallback
647{
648public:
649    MapNodeCallback(Renderer *renderer) :
650        _renderer(renderer)
651    {}
652
653    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
654    {
655        _renderer->mapNodeUpdate();
656        traverse(node, nv);
657    }
658private:
659    Renderer *_renderer;
660};
661
662class SelectPlaceNodesVisitor : public osg::NodeVisitor
663{
664public:
665    SelectPlaceNodesVisitor(Renderer *renderer,
666                            double latMin, double latMax,
667                            double longMin, double longMax) :
668        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
669        _renderer(renderer),
670        _latMin(latMin), _latMax(latMax),
671        _longMin(longMin), _longMax(longMax)
672    {}
673
674    virtual void apply(osg::Node& node);
675
676private:
677    Renderer *_renderer;
678    double _latMin, _latMax, _longMin, _longMax;
679};
680
681}
682
683#endif
Note: See TracBrowser for help on using the repository browser.