source: geovis/trunk/Renderer.h @ 4957

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

Add protocol option to enable/disable disk caching of image layers

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