source: geovis/trunk/Renderer.h @ 6307

Last change on this file since 6307 was 6276, checked in by ldelgass, 8 years ago

Add server response to notify clients of selection box region

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