source: geovis/trunk/Renderer.h @ 4635

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

Add resources directory command line option, preliminary testing of new map
coords syntax

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