source: geovis/trunk/Renderer.h @ 4973

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

First pass at protocol to set ephemeris time (currently uses server local time)

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