source: geovis/trunk/Renderer.h @ 5152

Last change on this file since 5152 was 5118, checked in by ldelgass, 10 years ago

Fix legend rendering: use colormap min/max to interpolate values (OSG transfer
functions aren't normalized)

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