1/* -*-c++-*- */
2/* osgEarth - Geospatial SDK for OpenSceneGraph
3* Copyright 2008-2014 Pelican Mapping
4* http://osgearth.org
5*
6* osgEarth is free software; you can redistribute it and/or modify
7* it under the terms of the GNU Lesser General Public License as published by
8* the Free Software Foundation; either version 2 of the License, or
9* (at your option) any later version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14* GNU Lesser General Public License for more details.
15*
16* You should have received a copy of the GNU Lesser General Public License
17* along with this program.  If not, see <http://www.gnu.org/licenses/>
18*/
19#ifndef OSGEARTH_DRIVERS_REX_SURFACE_NODE
20#define OSGEARTH_DRIVERS_REX_SURFACE_NODE 1
21
22#include "Common"
23#include "GeometryPool"
24#include "RenderBindings"
25#include "TileDrawable"
26#include "TileRenderModel"
27
28#include <osgEarth/MapInfo>
29#include <osgEarth/Horizon>
30#include <osg/MatrixTransform>
31#include <osg/BoundingBox>
32#include <osg/Drawable>
33#include <osg/Geode>
34#include <osgText/Text>
35#include <osgUtil/CullVisitor>
36#include <OpenThreads/Atomic>
37#include <vector>
38
39namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
40{
41    using namespace osgEarth;
42
43    /**
44     * Like cluster culling
45     */
46    struct HorizonTileCuller
47    {
48        osg::Vec3d  _points[4];
49        osg::ref_ptr<Horizon> _horizon;
50
51        void set(const SpatialReference* srs, const osg::Matrix& local2world, const osg::BoundingBox& bbox);
52
53        bool isVisible(const osg::Vec3d& from) const;
54    };
55
56
57    /**
58     * SurfaceNode holds the geometry and transform information
59     * for one terrain tile surface.
60     */
61    class SurfaceNode : public osg::MatrixTransform
62    {
63    public:
64        SurfaceNode(
65            const TileKey&        tilekey,
66            const MapInfo&        mapinfo,
67            const RenderBindings& bindings,
68            TileDrawable*         drawable);
69
70        void setElevationRaster(const osg::Image* raster, const osg::Matrixf& scaleBias);
71        const osg::Image* getElevationRaster() const;
72        const osg::Matrixf& getElevationMatrix() const;
73
74        const osg::BoundingBox& getAlignedBoundingBox() const;
75
76        TileDrawable* getDrawable() const { return _drawable.get(); }
77
78        inline bool isVisibleFrom(const osg::Vec3& viewpoint) const {
79            return _horizonCuller.isVisible(viewpoint);
80        }
81
82        // A box can have 4 children.
83        // Returns true if any child box intersects the sphere of radius centered around point
84        inline bool anyChildBoxIntersectsSphere(const osg::Vec3& point, float radiusSquared) {
85            for(int c=0; c<4; ++c) {
86                for(int j=0; j<8; ++j) {
87                    if ( (_childrenCorners[c][j]-point).length2() < radiusSquared )
88                        return true;
89                }
90            }
91            return false;
92        }
93
94        bool anyChildBoxWithinRange(float range, osg::NodeVisitor& nv) const {
95            for(int c=0; c<4; ++c) {
96                for(int j=0; j<8; ++j) {
97                    if (nv.getDistanceToViewPoint(_childrenCorners[c][j], true) < range)
98                        return true;
99                }
100            }
101            return false;
102        }
103
104        void setDebugText(const std::string& strText);
105
106        osg::BoundingSphere computeBound() const;
107
108        osg::Node* getDebugNode() const { return _debugNode.get(); }
109
110        void setLastFramePassedCull(unsigned fn);
111
112        unsigned getLastFramePassedCull() const { return _lastFramePassedCull; }
113
114        float getPixelSizeOnScreen(osg::CullStack* cull) const;
115
116    protected:
117        virtual ~SurfaceNode() { }
118
119        TileKey                     _tileKey;
120        osg::ref_ptr<TileDrawable>  _drawable;
121        osg::ref_ptr<osg::Node>     _debugNode;
122        osg::ref_ptr<osgText::Text> _debugText;
123        static const bool           _enableDebugNodes;
124        OpenThreads::Atomic         _lastFramePassedCull;
125        HorizonTileCuller           _horizonCuller;
126
127        typedef osg::Vec3 VectorPoints[8];
128
129
130        void addDebugNode(const osg::BoundingBox& box);
131        void removeDebugNode(void);
132
133        VectorPoints _worldCorners;
134
135        typedef VectorPoints (ChildrenCorners) [4];
136        ChildrenCorners _childrenCorners;
137    };
138
139} } } // namespace osgEarth::Drivers::RexTerrainEngine
140
141#endif // OSGEARTH_DRIVERS_REX_SURFACE_NODE
142