source: geovis/trunk/Renderer.h @ 5049

Last change on this file since 5049 was 5026, checked in by ldelgass, 9 years ago

Add protocol to set map attribution/copyright

File size: 15.5 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2013  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    // Scene
171
172    void loadEarthFile(const char *path);
173
174    void resetMap(osgEarth::MapOptions::CoordinateSystemType type,
175                  const char *profile = NULL,
176                  double bounds[4] = NULL);
177
178    void clearMap();
179
180    // Map options
181
182    void setCoordinateReadout(bool state,
183                              CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
184                              int precision = -1);
185
186    void setReadout(int mouseX, int mouseY);
187
188    void clearReadout();
189
190    void setScaleBar(bool state);
191
192    void setScaleBarUnits(ScaleBarUnits units);
193
194    void setGraticule(bool enable, GraticuleType type = GRATICULE_GEODETIC);
195
196    void setViewerLightType(osg::View::LightingMode mode);
197
198    void setLighting(bool state);
199
200    void setTerrainLighting(bool state);
201
202    void setTerrainVerticalScale(double scale);
203
204    void setTerrainWireframe(bool state);
205
206    void setEphemerisTime(time_t utcTime);
207
208    void setEphemerisTime(int year, int month, int day, double hours);
209
210    // Image raster layers
211
212    int getNumImageLayers() const
213    {
214        return (_map.valid() ? _map->getNumImageLayers() : 0);
215    }
216
217    void getImageLayerNames(std::vector<std::string>& names)
218    {
219        if (_map.valid()) {
220            osgEarth::ImageLayerVector layerVector;
221            _map->getImageLayers(layerVector);
222            osgEarth::ImageLayerVector::const_iterator itr;
223            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
224                //osgEarth::UID uid = (*itr)->getUID();
225                names.push_back((*itr)->getName());
226            }
227        }
228    }
229
230    bool addImageLayer(const char *name, osgEarth::TileSourceOptions& opts,
231                       bool enableCache = true, bool makeShared = false,
232                       bool visible = true);
233
234    void removeImageLayer(const char *name);
235
236    void moveImageLayer(const char *name, unsigned int pos);
237
238    void setImageLayerOpacity(const char *name, double opacity);
239
240    void setImageLayerVisibility(const char *name, bool state);
241
242    void addColorFilter(const char *name, const char *shader);
243
244    void removeColorFilter(const char *name, int idx = -1);
245
246    // Elevation raster layers
247
248    int getNumElevationLayers() const
249    {
250        return (_map.valid() ? _map->getNumElevationLayers() : 0);
251    }
252
253    void getElevationLayerNames(std::vector<std::string>& names)
254    {
255        if (_map.valid()) {
256            osgEarth::ElevationLayerVector layerVector;
257            _map->getElevationLayers(layerVector);
258            osgEarth::ElevationLayerVector::const_iterator itr;
259            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
260                //osgEarth::UID uid = (*itr)->getUID();
261                names.push_back((*itr)->getName());
262            }
263        }
264    }
265
266    void addElevationLayer(const char *name, osgEarth::TileSourceOptions& opts,
267                           bool enableCache = true, bool visible = true);
268
269    void removeElevationLayer(const char *name);
270
271    void moveElevationLayer(const char *name, unsigned int pos);
272
273    void setElevationLayerVisibility(const char *name, bool state);
274
275    // Model layers
276
277    int getNumModelLayers() const
278    {
279        return (_map.valid() ? _map->getNumModelLayers() : 0);
280    }
281
282    void getModelLayerNames(std::vector<std::string>& names)
283    {
284        if (_map.valid()) {
285            osgEarth::ModelLayerVector layerVector;
286            _map->getModelLayers(layerVector);
287            osgEarth::ModelLayerVector::const_iterator itr;
288            for (itr = layerVector.begin(); itr != layerVector.end(); ++itr) {
289                //osgEarth::UID uid = (*itr)->getUID();
290                names.push_back((*itr)->getName());
291            }
292        }
293    }
294
295    void addModelLayer(const char *name, osgEarth::ModelSourceOptions& opts);
296
297    void removeModelLayer(const char *name);
298
299    void moveModelLayer(const char *name, unsigned int pos);
300
301    void setModelLayerOpacity(const char *name, double opacity);
302
303    void setModelLayerVisibility(const char *name, bool state);
304
305    // Render window
306
307    void setWindowSize(int width, int height);
308
309    int getWindowWidth() const
310    {
311        return _windowWidth;
312    }
313
314    int getWindowHeight() const
315    {
316        return _windowHeight;
317    }
318
319    // Camera
320
321    void saveNamedViewpoint(const char *name);
322
323    bool restoreNamedViewpoint(const char *name, double durationSecs);
324
325    bool removeNamedViewpoint(const char *name);
326
327    osgEarth::Viewpoint getViewpoint();
328
329    void setViewpoint(const osgEarth::Viewpoint& v, double durationSecs = 0.0);
330
331    void resetCamera(bool resetOrientation = true);
332
333    void setCameraOrientation(const double quat[4], bool absolute = true);
334
335    void panCamera(double x, double y);
336
337    void rotateCamera(double x, double y);
338
339    void zoomCamera(double z);
340
341    void setCameraDistance(double dist);
342
343    // Keyboard events
344
345    void keyPress(int key);
346
347    void keyRelease(int key);
348
349    // Mouse events
350
351    void setThrowingEnabled(bool state);
352
353    void mouseClick(int button, double x, double y);
354
355    void mouseDoubleClick(int button, double x, double y);
356
357    void mouseDrag(int button, double x, double y);
358
359    void mouseRelease(int button, double x, double y);
360
361    void mouseMotion(double x, double y);
362
363    void mouseScroll(int direction);
364
365    // Rendering an image
366
367    void setBackgroundColor(float color[3]);
368
369    void eventuallyRender();
370
371    bool render();
372
373    osg::Image *getRenderedFrame();
374
375    bool mapMouseCoords(float mouseX, float mouseY,
376                        osgEarth::GeoPoint &pt, bool invertY = true);
377
378    double computeMapScale();
379
380    const osgEarth::SpatialReference *getMapSRS()
381    {
382        if (_mapNode.valid()) {
383            return _mapNode->getMapSRS();
384        } else {
385            return NULL;
386        }
387    }
388
389    void addPlaceNode(double latitude, double longitude, char *labelText);
390
391    void hoverPlaceNode(int x, int y, bool invertY = true);
392
393    void deletePlaceNode(int x, int y, bool invertY = true);
394
395    bool getMousePoint(double *x, double *y, double *z)
396    {
397        return (_coordsCallback.valid() && _coordsCallback->report(x, y, z));
398    }
399
400    bool mouseToLatLong(int mouseX, int mouseY, double *latitude, double *longitude);
401
402    bool getWorldCoords(const osgEarth::GeoPoint& mapPt, osg::Vec3d *world);
403
404    bool worldToScreen(const osg::Vec3d& world, osg::Vec3d *screen,
405                       bool invertY = true);
406
407    bool worldToScreen(std::vector<osg::Vec3d>& coords, bool invertY = true);
408
409    void setMaximumFrameRateInHertz(double rate)
410    {
411        if (rate > 60.0)
412            rate = 60.0;
413        if (rate < 0.25)
414            rate = 0.25;
415        _minFrameTime = 1.0/rate;
416        if (_viewer.valid()) {
417            osgUtil::IncrementalCompileOperation *op =
418                _viewer->getDatabasePager()->getIncrementalCompileOperation();
419            if (op != NULL) {
420                TRACE("Setting DB Pager target frame rate to %g", rate);
421                op->setTargetFrameRate(rate);
422            }
423        }
424    }
425
426    void setMaximumBitrate(double bitsPerSecond)
427    {
428        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
429        double fps = bitsPerSecond / ((double)bitsPerFrame);
430        setMaximumFrameRateInHertz(fps);
431    }
432
433    double getMaximumFrameRateInHertz()
434    {
435        return (1.0/_minFrameTime);
436    }
437
438    double getMaximumBitrate()
439    {
440        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
441        return ((double)bitsPerFrame * getMaximumFrameRateInHertz());
442    }
443
444    void markFrameStart();
445
446    void markFrameEnd();
447
448    long getTimeout();
449
450    void mapNodeUpdate();
451
452    std::string getCanonicalPath(const std::string& url) const;
453
454    void writeScene(const std::string& file);
455
456    void addRhumbBox(double latMin, double latMax, double longMin, double longMax);
457
458    void initBoxSelection(int x, int y);
459    void updateBoxSelection(int x, int y);
460    void clearBoxSelection();
461
462    bool select(osgEarth::Annotation::AnnotationNode *node)
463    {
464        if (_selected.find(node) == _selected.end()) {
465            _selected.insert(node);
466            return true;
467        } else {
468            return false;
469        }
470    }
471
472private:
473    typedef std::tr1::unordered_map<ColorMapId, osg::ref_ptr<osg::TransferFunction1D> > ColorMapHashmap;
474    typedef std::tr1::unordered_map<ViewpointId, osgEarth::Viewpoint> ViewpointHashmap;
475
476    void setupCache();
477
478    void initAnnotations();
479
480    void initViewer();
481
482    void finalizeViewer();
483   
484    void initControls();
485
486    void initEarthManipulator();
487
488    void initMouseCoordsTool(CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
489                             int precision = -1);
490
491    osgEarth::Util::MGRSFormatter::Precision getMGRSPrecision(int precisionInMeters);
492
493    void initColorMaps();
494
495    void initCamera();
496
497    bool isPagerIdle();
498
499    bool checkNeedToDoFrame();
500
501    osgGA::EventQueue *getEventQueue();
502
503    bool _needsRedraw;
504    int _windowWidth, _windowHeight;
505    double _mapScale;
506    float _bgColor[3];
507
508    double _minFrameTime;
509    double _lastFrameTime;
510    double _renderTime;
511    osg::Timer_t _startFrameTime;
512    osg::Timer_t _renderStartTime;
513    osg::Timer_t _renderStopTime;
514
515    ColorMapHashmap _colorMaps;
516
517    std::string _resourcePath;
518    std::string _cacheBaseDir;
519    std::string _cacheDir;
520    std::string _baseURI;
521    std::string _attribution;
522
523    osg::ref_ptr<osg::Group> _sceneRoot;
524    osg::ref_ptr<osg::Group> _graticule;
525    osg::ref_ptr<osg::Group> _annotations;
526    double _anchorLat, _anchorLong;
527    osg::ref_ptr<osgEarth::Annotation::FeatureNode> _selectionBox;
528    osg::ref_ptr<osg::Group> _placeNodes;
529    std::set<osgEarth::Annotation::AnnotationNode *> _hovered;
530    std::set<osgEarth::Annotation::AnnotationNode *> _selected;
531    osg::ref_ptr<osgEarth::MapNode> _mapNode;
532    osg::ref_ptr<osgEarth::Map> _map;
533    osg::ref_ptr<osgEarth::Util::SkyNode> _skyNode;
534    osg::ref_ptr<osgViewer::Viewer> _viewer;
535    osg::ref_ptr<ScreenCaptureCallback> _captureCallback;
536    osg::ref_ptr<osgEarth::Util::AutoClipPlaneCullCallback> _clipPlaneCullCallback;
537    osg::ref_ptr<MouseCoordsTool> _mouseCoordsTool;
538    osg::ref_ptr<MouseCoordsCallback> _coordsCallback;
539    osg::ref_ptr<osgEarth::Util::Controls::HBox> _hbox;
540    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _copyrightLabel;
541    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _scaleLabel;
542    osg::ref_ptr<osgEarth::Util::Controls::Frame> _scaleBar;
543    ScaleBarUnits _scaleBarUnits;
544    osg::ref_ptr<osgEarth::Util::EarthManipulator> _manipulator;
545    osg::ref_ptr<osgGA::StateSetManipulator> _stateManip;
546    osg::ref_ptr<osgEarth::Util::VerticalScale> _verticalScale;
547    ViewpointHashmap _viewpoints;
548};
549
550class MapNodeCallback : public osg::NodeCallback
551{
552public:
553    MapNodeCallback(Renderer *renderer) :
554        _renderer(renderer)
555    {}
556
557    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
558    {
559        _renderer->mapNodeUpdate();
560        traverse(node, nv);
561    }
562private:
563    Renderer *_renderer;
564};
565
566class SelectPlaceNodesVisitor : public osg::NodeVisitor
567{
568public:
569    SelectPlaceNodesVisitor(Renderer *renderer,
570                            double latMin, double latMax,
571                            double longMin, double longMax) :
572        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
573        _renderer(renderer),
574        _latMin(latMin), _latMax(latMax),
575        _longMin(longMin), _longMax(longMax)
576    {}
577
578    virtual void apply(osg::Node& node);
579
580private:
581    Renderer *_renderer;
582    double _latMin, _latMax, _longMin, _longMax;
583};
584
585}
586
587#endif
Note: See TracBrowser for help on using the repository browser.