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_REX_TILE_RENDER_MODEL
20#define OSGEARTH_REX_TILE_RENDER_MODEL 1
21
22#include "Common"
23#include "RenderBindings"
24#include <osgEarth/Common>
25#include <osgEarth/Containers> // for AutoArray
26#include <osgEarth/Layer>
27#include <osgEarth/ImageLayer>
28#include <osgEarth/PatchLayer>
29#include <osg/Texture>
30#include <osg/Matrix>
31#include <vector>
32
33namespace osgEarth { namespace Drivers { namespace RexTerrainEngine
34{
35    /**
36     * A single texture and its matrix. This corresponds to a
37     * single SamplerBinding (above).
38     */
39    struct Sampler
40    {
41        osg::ref_ptr<osg::Texture> _texture;
42        osg::Matrixf _matrix;
43    };
44    typedef AutoArray<Sampler> Samplers;
45
46    /**
47     * Samplers (one per RenderBinding) specific to one rendering pass of a tile.
48     * Typically this is just the color and color parent samplers.
49     */
50    struct RenderingPass
51    {
52    public:
53        RenderingPass() :
54            _sourceUID(-1),
55            _samplers(SamplerBinding::COLOR_PARENT+1),
56            _visibleLayer(0L),
57            _terrainLayer(0L)
58            { }
59
60        UID sourceUID() const { return _sourceUID; }
61        Samplers& samplers() { return _samplers; }
62        const Samplers& samplers() const  { return _samplers; }
63        const Layer* layer() const { return _layer.get(); }
64        const VisibleLayer* visibleLayer() const { return _visibleLayer; }
65        const TerrainLayer* terrainLayer() const { return _terrainLayer; }
66
67        void releaseGLObjects(osg::State* state) const
68        {
69            for (unsigned s = 0; s<_samplers.size(); ++s)
70                if (_samplers[s]._texture.valid() && _samplers[s]._matrix.isIdentity())
71                    _samplers[s]._texture->releaseGLObjects(state);
72        }
73
74        void resizeGLObjectBuffers(unsigned size)
75        {
76            for (unsigned s = 0; s<_samplers.size(); ++s)
77                if (_samplers[s]._texture.valid() && _samplers[s]._matrix.isIdentity())
78                    _samplers[s]._texture->resizeGLObjectBuffers(size);
79        }
80
81        void setLayer(const Layer* layer) {
82            _layer = layer;
83            if (layer) {
84                _visibleLayer = dynamic_cast<const VisibleLayer*>(layer);
85                _terrainLayer = dynamic_cast<const TerrainLayer*>(layer);
86                _sourceUID = layer->getUID();
87            }
88        }
89
90    private:
91        /** UID of the layer responsible for this rendering pass (usually an ImageLayer) */
92        UID _sourceUID;
93
94        /** Samplers specific to this rendering pass (COLOR, COLOR_PARENT) */
95        Samplers _samplers;
96
97        /** Layer respsonible for this rendering pass */
98        osg::ref_ptr<const Layer> _layer;
99
100        /** VisibleLayer responsible for this rendering pass (is _layer is a VisibleLayer) */
101        const VisibleLayer* _visibleLayer;
102
103        /** VisibleLayer responsible for this rendering pass (is _layer is a TerrainLayer) */
104        const TerrainLayer* _terrainLayer;
105
106
107    };
108
109    /**
110     * Unordered collection of rendering passes.
111     */
112    typedef std::vector<RenderingPass> RenderingPasses;
113
114    /**
115     * Everything necessary to render a single terrain tile.
116     * REX renders the terrain in multiple passes, one pass for each visible layer.
117     */
118    struct TileRenderModel
119    {
120        /** Samplers that are bound for every rendering pass (elevation, normal map, etc.) */
121        Samplers _sharedSamplers;
122
123        /** Samplers bound for each visible layer (color) */
124        RenderingPasses _passes;
125
126        /** Add a new rendering pass to the end of the list. */
127        RenderingPass& addPass()
128        {
129            _passes.resize(_passes.size()+1);
130            return _passes.back();
131        }
132
133        /** Look up a rendering pass by the corresponding layer ID */
134        const RenderingPass* getPass(UID uid) const
135        {
136            for (unsigned i = 0; i < _passes.size(); ++i) {
137                if (_passes[i].sourceUID() == uid)
138                    return &_passes[i];
139            }
140            return 0L;
141        }
142
143        /** Look up a rendering pass by the corresponding layer ID */
144        RenderingPass* getPass(UID uid)
145        {
146            for (unsigned i = 0; i < _passes.size(); ++i) {
147                if (_passes[i].sourceUID() == uid)
148                    return &_passes[i];
149            }
150            return 0L;
151        }
152
153        /** Deallocate GPU objects associated with this model */
154        void releaseGLObjects(osg::State* state) const
155        {
156            for (unsigned s = 0; s<_sharedSamplers.size(); ++s)
157                if (_sharedSamplers[s]._texture.valid() && _sharedSamplers[s]._matrix.isIdentity())
158                    _sharedSamplers[s]._texture->releaseGLObjects(state);
159
160            for (unsigned p = 0; p<_passes.size(); ++p)
161                _passes[p].releaseGLObjects(state);
162        }
163
164        /** Resize GL buffers associated with this model */
165        void resizeGLObjectBuffers(unsigned size)
166        {
167            for (unsigned s = 0; s<_sharedSamplers.size(); ++s)
168                if (_sharedSamplers[s]._texture.valid() && _sharedSamplers[s]._matrix.isIdentity())
169                    _sharedSamplers[s]._texture->resizeGLObjectBuffers(size);
170
171            for (unsigned p = 0; p<_passes.size(); ++p)
172                _passes[p].resizeGLObjectBuffers(size);
173        }
174    };
175
176} } } // namespace osgEarth::Drivers::RexTerrainEngine
177
178#endif // OSGEARTH_REX_TILE_RENDER_MODEL
179