source: geovis/trunk/Renderer.h @ 5852

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

Add initial iData client support

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