source: geovis/trunk/Renderer.h @ 4822

Last change on this file since 4822 was 4655, checked in by ldelgass, 10 years ago

More selection testing

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