source: geovis/trunk/Renderer.h @ 6050

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

Add simple on/off select mode

File size: 19.3 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    // Rendering an image
434
435    void setBackgroundColor(float color[3]);
436
437    void eventuallyRender();
438
439    bool render();
440
441    osg::Image *getRenderedFrame();
442
443    bool mapMouseCoords(float mouseX, float mouseY,
444                        osgEarth::GeoPoint &pt, bool invertY = true);
445
446    double computeMapScale();
447
448    const osgEarth::SpatialReference *getMapSRS()
449    {
450        if (_mapNode.valid()) {
451            return _mapNode->getMapSRS();
452        } else {
453            return NULL;
454        }
455    }
456
457    void addPlaceNode(double latitude, double longitude, char *labelText);
458
459    void hoverPlaceNode(int x, int y, bool invertY = true);
460
461    void deletePlaceNode(int x, int y, bool invertY = true);
462
463    bool getMousePoint(double *x, double *y, double *z)
464    {
465        return (_coordsCallback.valid() && _coordsCallback->report(x, y, z));
466    }
467
468    bool mouseToLatLong(int mouseX, int mouseY, double *latitude, double *longitude);
469
470    bool getWorldCoords(const osgEarth::GeoPoint& mapPt, osg::Vec3d *world);
471
472    bool worldToScreen(const osg::Vec3d& world, osg::Vec3d *screen,
473                       bool invertY = true);
474
475    bool worldToScreen(std::vector<osg::Vec3d>& coords, bool invertY = true);
476
477    void setMaximumFrameRateInHertz(double rate)
478    {
479        if (rate > 60.0)
480            rate = 60.0;
481        if (rate < 0.25)
482            rate = 0.25;
483        _minFrameTime = 1.0/rate;
484        if (_viewer.valid()) {
485            osgUtil::IncrementalCompileOperation *op =
486                _viewer->getDatabasePager()->getIncrementalCompileOperation();
487            if (op != NULL) {
488                TRACE("Setting DB Pager target frame rate to %g", rate);
489                op->setTargetFrameRate(rate);
490            }
491        }
492    }
493
494    void setMaximumBitrate(double bitsPerSecond)
495    {
496        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
497        double fps = bitsPerSecond / ((double)bitsPerFrame);
498        setMaximumFrameRateInHertz(fps);
499    }
500
501    double getMaximumFrameRateInHertz()
502    {
503        return (1.0/_minFrameTime);
504    }
505
506    double getMaximumBitrate()
507    {
508        unsigned long bitsPerFrame = (_windowWidth * _windowHeight * 3 + 16) * 8;
509        return ((double)bitsPerFrame * getMaximumFrameRateInHertz());
510    }
511
512    void markFrameStart();
513
514    void markFrameEnd();
515
516    long getTimeout();
517
518    void mapNodeUpdate();
519
520    std::string getCanonicalPath(const std::string& url) const;
521
522    void writeScene(const std::string& file);
523
524    void setPlacardConfig(const Placard& placardConf, const char *layerName);
525
526    void setSelectMode(SelectMode mode);
527
528    void selectFeatures(std::vector<unsigned long>& featureIDs, const char *layerName);
529
530    void addPlacard(const osgEarth::GeoPoint& location,
531                    osgEarth::Features::Feature *feature,
532                    const char *layerName);
533
534    void clearSelection();
535
536    void addRhumbBox(double latMin, double latMax, double longMin, double longMax);
537
538    void initBoxSelection(int x, int y);
539    void updateBoxSelection(int x, int y);
540    void clearBoxSelection();
541
542    bool select(osgEarth::Annotation::AnnotationNode *node)
543    {
544        if (_selected.find(node) == _selected.end()) {
545            _selected.insert(node);
546            return true;
547        } else {
548            return false;
549        }
550    }
551
552    std::set<osgEarth::Annotation::AnnotationNode*>& getHovered()
553    { return _hovered; }
554    std::set<osgEarth::Annotation::AnnotationNode*>& getSelected()
555    { return _selected; }
556    osg::Group *getSceneRoot()
557    { return _sceneRoot.get(); }
558    osgEarth::MapNode *getMapNode()
559    { return _mapNode.get(); }
560    osg::Group *getAnnotations()
561    {
562        initAnnotations();
563        return _annotations.get();
564    }
565    osg::Group *getPlaceNodes()
566    {
567        initAnnotations();
568        return _placeNodes.get();
569    }
570    Placard getPlacardConfig(const char *layerName)
571    {
572        Placard ret;
573        PlacardHashmap::iterator itr = _placardConfigs.find(layerName);
574        if (itr != _placardConfigs.end()) {
575            ret = itr->second;
576        }
577        return ret;
578    }
579
580private:
581    typedef std::tr1::unordered_map<ColorMapId, osg::ref_ptr<osg::TransferFunction1D> > ColorMapHashmap;
582    typedef std::tr1::unordered_map<ViewpointId, osgEarth::Viewpoint> ViewpointHashmap;
583    typedef std::tr1::unordered_map<std::string, Placard> PlacardHashmap;
584
585    void initAnnotations();
586
587    void clearSelectionAnnotationNodes();
588
589    void initViewer();
590
591    void finalizeViewer();
592   
593    void initControls();
594
595    void initEarthManipulator();
596
597    void initMouseCoordsTool(CoordinateDisplayType type = COORDS_LATLONG_DECIMAL_DEGREES,
598                             int precision = -1);
599
600    osgEarth::Util::MGRSFormatter::Precision getMGRSPrecision(int precisionInMeters);
601
602    void initColorMaps();
603
604    void initCamera();
605
606    bool isPagerIdle();
607
608    bool checkNeedToDoFrame();
609
610    osgGA::EventQueue *getEventQueue();
611
612    bool _needsRedraw;
613    int _windowWidth, _windowHeight;
614    double _mapScale;
615    float _bgColor[3];
616
617    double _minFrameTime;
618    double _lastFrameTime;
619    double _renderTime;
620    osg::Timer_t _startFrameTime;
621    osg::Timer_t _renderStartTime;
622    osg::Timer_t _renderStopTime;
623
624    ColorMapHashmap _colorMaps;
625
626    std::string _resourcePath;
627    std::string _cacheBaseDir;
628    std::string _cacheDir;
629    std::string _baseURI;
630    std::string _attribution;
631
632    osg::ref_ptr<osg::Group> _sceneRoot;
633    osg::ref_ptr<osg::Group> _graticule;
634    osg::ref_ptr<osg::Group> _annotations;
635    PlacardHashmap _placardConfigs;
636    double _anchorLat, _anchorLong;
637    SelectMode _selectMode;
638    osg::ref_ptr<osgEarth::Annotation::FeatureNode> _selectionBox;
639#ifdef USE_RTT_PICKER
640    osg::ref_ptr<osgEarth::Util::RTTPicker> _picker;
641#endif
642    osg::ref_ptr<osg::Group> _placeNodes;
643    std::set<osgEarth::Annotation::AnnotationNode *> _hovered;
644    std::set<osgEarth::Annotation::AnnotationNode *> _selected;
645    osg::ref_ptr<osgEarth::MapNode> _mapNode;
646    osg::ref_ptr<osgEarth::Map> _map;
647    osg::ref_ptr<osgEarth::Util::SkyNode> _skyNode;
648    osg::ref_ptr<osgViewer::Viewer> _viewer;
649    osg::ref_ptr<ScreenCaptureCallback> _captureCallback;
650    osg::ref_ptr<osgEarth::Util::AutoClipPlaneCullCallback> _clipPlaneCullCallback;
651    osg::ref_ptr<MouseCoordsTool> _mouseCoordsTool;
652    osg::ref_ptr<MouseCoordsCallback> _coordsCallback;
653    osg::ref_ptr<osgEarth::Util::Controls::HBox> _hbox;
654    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _copyrightLabel;
655    osg::ref_ptr<osgEarth::Util::Controls::LabelControl> _scaleLabel;
656    osg::ref_ptr<osgEarth::Util::Controls::Frame> _scaleBar;
657    ScaleBarUnits _scaleBarUnits;
658    osg::ref_ptr<osgEarth::Util::EarthManipulator> _manipulator;
659    osg::ref_ptr<osgGA::StateSetManipulator> _stateManip;
660    osg::ref_ptr<osgEarth::Util::VerticalScale> _verticalScale;
661    ViewpointHashmap _viewpoints;
662};
663
664class MapNodeCallback : public osg::NodeCallback
665{
666public:
667    MapNodeCallback(Renderer *renderer) :
668        _renderer(renderer)
669    {}
670
671    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
672    {
673        _renderer->mapNodeUpdate();
674        traverse(node, nv);
675    }
676private:
677    Renderer *_renderer;
678};
679
680class SelectPlaceNodesVisitor : public osg::NodeVisitor
681{
682public:
683    SelectPlaceNodesVisitor(Renderer *renderer,
684                            double latMin, double latMax,
685                            double longMin, double longMax) :
686        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
687        _renderer(renderer),
688        _latMin(latMin), _latMax(latMax),
689        _longMin(longMin), _longMax(longMax)
690    {}
691
692    virtual void apply(osg::Node& node);
693
694private:
695    Renderer *_renderer;
696    double _latMin, _latMax, _longMin, _longMax;
697};
698
699}
700
701#endif
Note: See TracBrowser for help on using the repository browser.