source: geovis/trunk/Renderer.h @ 4957

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

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

File size: 15.1 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 <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>
19#include <osg/TransferFunction>
20#include <osgViewer/Viewer>
21#include <osgGA/StateSetManipulator>
22#include <osgUtil/IncrementalCompileOperation>
23
24#include <osgEarth/StringUtils>
25#include <osgEarth/Map>
26#include <osgEarth/Viewpoint>
27#include <osgEarth/ImageLayer>
28#include <osgEarth/ElevationLayer>
29#include <osgEarth/ModelLayer>
30#include <osgEarth/TileSource>
31#include <osgEarth/ModelSource>
32#include <osgEarth/GeoData>
33#include <osgEarthAnnotation/AnnotationNode>
34#include <osgEarthAnnotation/FeatureNode>
35#include <osgEarthUtil/EarthManipulator>
36#include <osgEarthUtil/MouseCoordsTool>
37#include <osgEarthUtil/Controls>
38#include <osgEarthUtil/Formatter>
39#include <osgEarthUtil/MGRSFormatter>
40#include <osgEarthUtil/AutoClipPlaneHandler>
41#include <osgEarthUtil/VerticalScale>
42
43#include "Types.h"
44#include "Trace.h"
45#include "MouseCoordsTool.h"
46#include "ScaleBar.h"
47
48// Controls if TGA format is sent to client
49//#define RENDER_TARGA
50#define TARGA_BYTES_PER_PIXEL 3
51
52namespace GeoVis {
53
54class ScreenCaptureCallback : public osg::Camera::DrawCallback
55{
56public:
57    ScreenCaptureCallback(osg::Texture2D *texture = NULL) :
58        osg::Camera::DrawCallback(),
59        _texture(texture)
60    {
61        _image = new osg::Image;
62    }
63
64    virtual void operator()(osg::RenderInfo &renderInfo) const
65    {
66        TRACE("Enter ScreenCaptureCallback");
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);
79#if 0 //USE_OFFSCREEN_FRAMEBUFFER
80        _image = _texture->getImage();
81#else
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
89#endif
90    }
91
92    osg::Image *getImage()
93    {
94        return _image.get();
95    }
96
97    osg::Texture2D *getTexture()
98    {
99        return _texture.get();
100    }
101
102private:
103    osg::ref_ptr<osg::Texture2D> _texture;
104    osg::ref_ptr<osg::Image> _image;
105};
106
107/**
108 * \brief GIS Renderer
109 */
110class Renderer
111{
112public:
113    typedef std::string ColorMapId;
114    typedef std::string ViewpointId;
115
116    enum GraticuleType {
117        GRATICULE_UTM,
118        GRATICULE_MGRS,
119        GRATICULE_GEODETIC
120    };
121
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
129    Renderer();
130    virtual ~Renderer();
131
132    void setResourcePath(const std::string& path)
133    {
134        TRACE("Set resource path to %s", path.c_str());
135        _resourcePath = path;
136    }
137
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
149    std::string getBaseImage();
150
151    std::string getPinIcon();
152
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
161    // Scene
162
163    void loadEarthFile(const char *path);
164
165    void resetMap(osgEarth::MapOptions::CoordinateSystemType type,
166                  const char *profile = NULL,
167                  double bounds[4] = NULL);
168
169    void clearMap();
170
171    // Map options
172
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
185    void setGraticule(bool enable, GraticuleType type = GRATICULE_GEODETIC);
186
187    void setViewerLightType(osg::View::LightingMode mode);
188
189    void setLighting(bool state);
190
191    void setTerrainLighting(bool state);
192
193    void setTerrainVerticalScale(double scale);
194
195    void setTerrainWireframe(bool state);
196
197    // Image raster layers
198
199    int getNumImageLayers() const
200    {
201        return (_map.valid() ? _map->getNumImageLayers() : 0);
202    }
203
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
217    bool addImageLayer(const char *name, osgEarth::TileSourceOptions& opts,
218                       bool enableCache = true, bool makeShared = false,
219                       bool visible = true);
220
221    void removeImageLayer(const char *name);
222
223    void moveImageLayer(const char *name, unsigned int pos);
224
225    void setImageLayerOpacity(const char *name, double opacity);
226
227    void setImageLayerVisibility(const char *name, bool state);
228
229    void addColorFilter(const char *name, const char *shader);
230
231    void removeColorFilter(const char *name, int idx = -1);
232
233    // Elevation raster layers
234
235    int getNumElevationLayers() const
236    {
237        return (_map.valid() ? _map->getNumElevationLayers() : 0);
238    }
239
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
253    void addElevationLayer(const char *name, osgEarth::TileSourceOptions& opts,
254                           bool enableCache = true, bool visible = true);
255
256    void removeElevationLayer(const char *name);
257
258    void moveElevationLayer(const char *name, unsigned int pos);
259
260    void setElevationLayerVisibility(const char *name, bool state);
261
262    // Model layers
263
264    int getNumModelLayers() const
265    {
266        return (_map.valid() ? _map->getNumModelLayers() : 0);
267    }
268
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
282    void addModelLayer(const char *name, osgEarth::ModelSourceOptions& opts);
283
284    void removeModelLayer(const char *name);
285
286    void moveModelLayer(const char *name, unsigned int pos);
287
288    void setModelLayerOpacity(const char *name, double opacity);
289
290    void setModelLayerVisibility(const char *name, bool state);
291
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
306    // Camera
307
308    void saveNamedViewpoint(const char *name);
309
310    bool restoreNamedViewpoint(const char *name, double durationSecs);
311
312    bool removeNamedViewpoint(const char *name);
313
314    osgEarth::Viewpoint getViewpoint();
315
316    void setViewpoint(const osgEarth::Viewpoint& v, double durationSecs = 0.0);
317
318    void resetCamera(bool resetOrientation = true);
319
320    void setCameraOrientation(const double quat[4], bool absolute = true);
321
322    void panCamera(double x, double y);
323
324    void rotateCamera(double x, double y);
325
326    void zoomCamera(double z);
327
328    void setCameraDistance(double dist);
329
330    // Keyboard events
331
332    void keyPress(int key);
333
334    void keyRelease(int key);
335
336    // Mouse events
337
338    void setThrowingEnabled(bool state);
339
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
352    // Rendering an image
353
354    void setBackgroundColor(float color[3]);
355
356    void eventuallyRender();
357
358    bool render();
359
360    osg::Image *getRenderedFrame();
361
362    bool mapMouseCoords(float mouseX, float mouseY,
363                        osgEarth::GeoPoint &pt, bool invertY = true);
364
365    double computeMapScale();
366
367    const osgEarth::SpatialReference *getMapSRS()
368    {
369        if (_mapNode.valid()) {
370            return _mapNode->getMapSRS();
371        } else {
372            return NULL;
373        }
374    }
375
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
382    bool getMousePoint(double *x, double *y, double *z)
383    {
384        return (_coordsCallback.valid() && _coordsCallback->report(x, y, z));
385    }
386
387    bool mouseToLatLong(int mouseX, int mouseY, double *latitude, double *longitude);
388
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
394    bool worldToScreen(std::vector<osg::Vec3d>& coords, bool invertY = true);
395
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;
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        }
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
435    long getTimeout();
436
437    void mapNodeUpdate();
438
439    std::string getCanonicalPath(const std::string& url) const;
440
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
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
459private:
460    typedef std::tr1::unordered_map<ColorMapId, osg::ref_ptr<osg::TransferFunction1D> > ColorMapHashmap;
461    typedef std::tr1::unordered_map<ViewpointId, osgEarth::Viewpoint> ViewpointHashmap;
462
463    void setupCache();
464
465    void initAnnotations();
466
467    void initViewer();
468
469    void finalizeViewer();
470   
471    void initControls();
472
473    void initEarthManipulator();
474
475    void initMouseCoordsTool(CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
476                             int precision = -1);
477
478    osgEarth::Util::MGRSFormatter::Precision getMGRSPrecision(int precisionInMeters);
479
480    void initColorMaps();
481
482    void initCamera();
483
484    bool isPagerIdle();
485
486    bool checkNeedToDoFrame();
487
488    osgGA::EventQueue *getEventQueue();
489
490    bool _needsRedraw;
491    int _windowWidth, _windowHeight;
492    double _mapScale;
493    float _bgColor[3];
494
495    double _minFrameTime;
496    double _lastFrameTime;
497    double _renderTime;
498    osg::Timer_t _startFrameTime;
499    osg::Timer_t _renderStartTime;
500    osg::Timer_t _renderStopTime;
501
502    ColorMapHashmap _colorMaps;
503
504    std::string _resourcePath;
505    std::string _cacheBaseDir;
506    std::string _cacheDir;
507    std::string _baseURI;
508
509    osg::ref_ptr<osg::Group> _sceneRoot;
510    osg::ref_ptr<osg::Group> _graticule;
511    osg::ref_ptr<osg::Group> _annotations;
512    double _anchorLat, _anchorLong;
513    osg::ref_ptr<osgEarth::Annotation::FeatureNode> _selectionBox;
514    osg::ref_ptr<osg::Group> _placeNodes;
515    std::set<osgEarth::Annotation::AnnotationNode *> _hovered;
516    std::set<osgEarth::Annotation::AnnotationNode *> _selected;
517    osg::ref_ptr<osgEarth::MapNode> _mapNode;
518    osg::ref_ptr<osgEarth::Map> _map;
519    osg::ref_ptr<osgViewer::Viewer> _viewer;
520    osg::ref_ptr<ScreenCaptureCallback> _captureCallback;
521    osg::ref_ptr<osgEarth::Util::AutoClipPlaneCullCallback> _clipPlaneCullCallback;
522    osg::ref_ptr<MouseCoordsTool> _mouseCoordsTool;
523    osg::ref_ptr<MouseCoordsCallback> _coordsCallback;
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;
528    ScaleBarUnits _scaleBarUnits;
529    osg::ref_ptr<osgEarth::Util::EarthManipulator> _manipulator;
530    osg::ref_ptr<osgGA::StateSetManipulator> _stateManip;
531    osg::ref_ptr<osgEarth::Util::VerticalScale> _verticalScale;
532    ViewpointHashmap _viewpoints;
533};
534
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
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
570}
571
572#endif
Note: See TracBrowser for help on using the repository browser.