source: geovis/trunk/Renderer.h @ 4973

Last change on this file since 4973 was 4973, checked in by ldelgass, 10 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.