[SCM] osgearth branch, master, updated. debian/1.4.1-1-39-g6366f59
Pirmin Kalberer
pka at sourcepole.ch
Tue Jul 9 21:18:50 UTC 2013
The following commit has been merged in the master branch:
commit e6d23c997ba785478683405f0306c3dd0901105c
Author: Pirmin Kalberer <pka at sourcepole.ch>
Date: Sat Mar 30 20:40:49 2013 +0100
Upstream release 2.3
diff --git a/src/applications/CMakeLists.txt b/src/applications/CMakeLists.txt
index d12f3ad..f82b456 100644
--- a/src/applications/CMakeLists.txt
+++ b/src/applications/CMakeLists.txt
@@ -23,17 +23,28 @@ SET(TARGET_COMMON_LIBRARIES
)
SET(TARGET_DEFAULT_PREFIX "application_")
-SET(TARGET_DEFAULT_LABEL_PREFIX "Sample")
+SET(TARGET_DEFAULT_APPLICATION_FOLDER "Applications")
+SET(TARGET_DEFAULT_LABEL_PREFIX "Tool")
+SET(TARGET_DEFAULT_APPLICATION_FOLDER "Tools")
ADD_SUBDIRECTORY(osgearth_viewer)
+ADD_SUBDIRECTORY(osgearth_seed)
+ADD_SUBDIRECTORY(osgearth_featureinfo)
+ADD_SUBDIRECTORY(osgearth_package)
+ADD_SUBDIRECTORY(osgearth_tfs)
+ADD_SUBDIRECTORY(osgearth_boundarygen)
+ADD_SUBDIRECTORY(osgearth_overlayviewer)
+ADD_SUBDIRECTORY(osgearth_version)
+
+
+SET(TARGET_DEFAULT_LABEL_PREFIX "Sample")
+SET(TARGET_DEFAULT_APPLICATION_FOLDER "Samples")
ADD_SUBDIRECTORY(osgearth_clamp)
ADD_SUBDIRECTORY(osgearth_manip)
-ADD_SUBDIRECTORY(osgearth_seed)
ADD_SUBDIRECTORY(osgearth_toc)
ADD_SUBDIRECTORY(osgearth_elevation)
ADD_SUBDIRECTORY(osgearth_features)
ADD_SUBDIRECTORY(osgearth_featurefilter)
-ADD_SUBDIRECTORY(osgearth_featureinfo)
ADD_SUBDIRECTORY(osgearth_los)
ADD_SUBDIRECTORY(osgearth_terrainprofile)
ADD_SUBDIRECTORY(osgearth_map)
@@ -45,20 +56,16 @@ IF(NOT ${OPENSCENEGRAPH_VERSION} VERSION_LESS "2.9.6")
ENDIF()
ADD_SUBDIRECTORY(osgearth_measure)
-ADD_SUBDIRECTORY(osgearth_version)
ADD_SUBDIRECTORY(osgearth_controls)
ADD_SUBDIRECTORY(osgearth_shadercomp)
ADD_SUBDIRECTORY(osgearth_tilesource)
ADD_SUBDIRECTORY(osgearth_imageoverlay)
ADD_SUBDIRECTORY(osgearth_city)
-ADD_SUBDIRECTORY(osgearth_package)
ADD_SUBDIRECTORY(osgearth_graticule)
ADD_SUBDIRECTORY(osgearth_featuremanip)
ADD_SUBDIRECTORY(osgearth_featurequery)
-ADD_SUBDIRECTORY(osgearth_overlayviewer)
ADD_SUBDIRECTORY(osgearth_occlusionculling)
ADD_SUBDIRECTORY(osgearth_colorfilter)
-ADD_SUBDIRECTORY(osgearth_tfs)
ADD_SUBDIRECTORY(osgearth_contour)
ADD_SUBDIRECTORY(osgearth_verticalscale)
@@ -70,5 +77,3 @@ IF (QT4_FOUND AND NOT ANDROID AND OSGEARTH_USE_QT)
ADD_SUBDIRECTORY(osgearth_qt)
ADD_SUBDIRECTORY(osgearth_qt_simple)
ENDIF()
-
-#ADD_SUBDIRECTORY(osgearth_test_srs)
diff --git a/src/applications/osgearth_boundarygen/BoundaryUtil b/src/applications/osgearth_boundarygen/BoundaryUtil
new file mode 100644
index 0000000..3a66bee
--- /dev/null
+++ b/src/applications/osgearth_boundarygen/BoundaryUtil
@@ -0,0 +1,59 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef BOUNDARY_UTIL
+#define BOUNDARY_UTIL 1
+
+#include <osg/Node>
+
+class BoundaryUtil
+{
+public:
+ /* Use the vertices of the given node to calculate a boundary via the
+ * findHull() method.
+ */
+ static osg::Vec3dArray* getBoundary(osg::Node* modelNode, bool geocentric=true, bool convexHull=false);
+
+ /* Finds the convex hull for the given points using the Andrew's monotone
+ * chain algorithm. Returns an ordered set of points defining the hull
+ */
+ static osg::Vec3dArray* findHull(osg::Vec3dArray& points);
+
+ static osg::Vec3dArray* findMeshBoundary(osg::Node* modelNode, bool geocentric=true);
+
+ static bool simpleBoundaryTest(const osg::Vec3dArray& boundary);
+
+protected:
+ /* Returns an array containing the points sorted first by x and then by y */
+ static osg::Vec3dArray* hullPresortPoints(osg::Vec3dArray& points);
+
+ /* Tests if a point is Left|On|Right of an infinite line
+ * Returns: >0 for P2 left of the line through P0 and P1
+ * 0 for P2 on the line
+ * <0 for P2 right of the line
+ *
+ * Implementation based on method from softSurfer (www.softsurfer.com)
+ */
+ static inline float isLeft(osg::Vec3d P0, osg::Vec3d P1, osg::Vec3d P2)
+ {
+ return (P1.x() - P0.x())*(P2.y() - P0.y()) - (P2.x() - P0.x())*(P1.y() - P0.y());
+ }
+};
+
+#endif // BOUNDARY_UTIL
diff --git a/src/applications/osgearth_boundarygen/BoundaryUtil.cpp b/src/applications/osgearth_boundarygen/BoundaryUtil.cpp
new file mode 100644
index 0000000..f49e671
--- /dev/null
+++ b/src/applications/osgearth_boundarygen/BoundaryUtil.cpp
@@ -0,0 +1,519 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include "BoundaryUtil"
+#include "VertexCollectionVisitor"
+#include <algorithm>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/TriangleIndexFunctor>
+#include <osgEarthSymbology/Geometry>
+#include <map>
+#include <vector>
+#include <set>
+
+/* Comparator used to sort osg::Vec3d's first by x and then by y */
+bool presortCompare (osg::Vec3d i, osg::Vec3d j)
+{
+ if (i.x() == j.x())
+ return i.y() < j.y();
+
+ return i.x() < j.x();
+}
+
+/* Use the vertices of the given node to calculate a boundary via the
+ * findHull() method.
+ */
+osg::Vec3dArray* BoundaryUtil::getBoundary(osg::Node* modelNode, bool geocentric, bool convexHull)
+{
+ if (!modelNode)
+ return 0;
+
+ if ( convexHull )
+ {
+ VertexCollectionVisitor v(geocentric);
+ modelNode->accept(v);
+
+ osg::ref_ptr<osg::Vec3dArray> verts = v.getVertices();
+ verts = findHull(*verts);
+
+ osg::EllipsoidModel em;
+ for( osg::Vec3dArray::iterator i = verts->begin(); i != verts->end(); ++i )
+ {
+ em.convertLatLongHeightToXYZ( osg::DegreesToRadians(i->y()), osg::DegreesToRadians(i->x()), i->z(),
+ i->x(), i->y(), i->z() );
+ }
+
+ return verts.release();
+ }
+ else
+ {
+ return findMeshBoundary( modelNode, geocentric );
+ }
+}
+
+/* Finds the convex hull for the given points using the Andrew's monotone
+ * chian algorithm. Returns an ordered set of points defining the hull
+ *
+ * Implementation based on chainHull_2D() method from
+ * softSurfer (www.softsurfer.com)
+ */
+osg::Vec3dArray* BoundaryUtil::findHull(osg::Vec3dArray& points)
+{
+ if (points.size() == 0)
+ return 0;
+
+ // the output array hull will be used as the stack
+ osg::Vec3dArray* hull = new osg::Vec3dArray(points.size());
+
+ // Presort the points as required by the algorithm
+ osg::ref_ptr<osg::Vec3dArray> sorted = hullPresortPoints(points);
+
+ int bot=0, top=(-1); // indices for bottom and top of the stack
+ int i; // array scan index
+ int n = sorted->size();
+
+ // Get the indices of points with min x-coord and min|max y-coord
+ int minmin = 0, minmax;
+ double xmin = (*sorted)[0].x();
+ for (i=1; i<n; i++)
+ if ((*sorted)[i].x() != xmin) break;
+ minmax = i-1;
+
+ //if the points at minmin and minmax have the same value, shift minmin
+ //to ignore the duplicate points
+ if ((*sorted)[minmin] == (*sorted)[minmax])
+ minmin = minmax;
+
+ // degenerate case: all x-coords == xmin
+ if (minmax == n-1)
+ {
+ (*hull)[++top] = (*sorted)[minmin];
+ if ((*sorted)[minmax].y() != (*sorted)[minmin].y()) // a nontrivial segment
+ (*hull)[++top] = (*sorted)[minmax];
+ (*hull)[++top] = (*sorted)[minmin]; // add polygon endpoint
+
+ hull->resize(top + 1);
+ return hull;
+ }
+
+ // Get the indices of points with max x-coord and min|max y-coord
+ int maxmin, maxmax = n-1;
+ double xmax = (*sorted)[n-1].x();
+ for (i=n-2; i>=0; i--)
+ if ((*sorted)[i].x() != xmax) break;
+ maxmin = i+1;
+
+ // Compute the lower hull on the stack
+ (*hull)[++top] = (*sorted)[minmin]; // push minmin point onto stack
+ i = minmax;
+ while (++i <= maxmin)
+ {
+ // the lower line joins (*sorted)[minmin] with (*sorted)[maxmin]
+
+ // if multiple points have the same x/y values, go with the lowest z value
+ if ((*hull)[top].x() == (*sorted)[i].x() && (*hull)[top].y() == (*sorted)[i].y())
+ {
+ if ((*sorted)[i].z() < (*hull)[top].z())
+ (*hull)[top].z() = (*sorted)[i].z();
+
+ continue;
+ }
+
+ if (isLeft((*sorted)[minmin], (*sorted)[maxmin], (*sorted)[i]) > 0 && i < maxmin)
+ continue; // ignore (*sorted)[i] above the lower line. NOTE: Differs from original CH algorithm in that it keeps collinear points
+
+ while (top > 0) // there are at least 2 points on the stack
+ {
+ // test if (*sorted)[i] is left of or on the line at the stack top. NOTE: Differs from original CH algorithm in that it keeps collinear points
+ if (isLeft((*hull)[top-1], (*hull)[top], (*sorted)[i]) >= 0)
+ break; // (*sorted)[i] is a new hull vertex
+ else
+ top--; // pop top point off stack
+ }
+ (*hull)[++top] = (*sorted)[i]; // push (*sorted)[i] onto stack
+ }
+
+ if (maxmax != maxmin) // if distinct xmax points
+ {
+ // Push all points between maxmin and maxmax onto stack. NOTE: Differs from original CH algorithm in that it keeps collinear points
+ while (i <= maxmax)
+ {
+ if ((*hull)[top].x() == (*sorted)[i].x() && (*hull)[top].y() == (*hull)[top].y())
+ {
+ if ((*sorted)[i].z() < (*hull)[top].z())
+ (*hull)[top].z() = (*sorted)[i].z();
+ }
+ else
+ {
+ (*hull)[++top] = (*sorted)[i];
+ }
+
+ i++;
+ }
+ }
+
+ // Next, compute the upper hull on the stack H above the bottom hull
+
+ bot = top; // the bottom point of the upper hull stack
+ i = maxmin;
+ while (--i >= minmax)
+ {
+ // the upper line joins (*sorted)[maxmax] with (*sorted)[minmax]
+
+ // if multiple points have the same x/y values, go with the lowest z value
+ if ((*hull)[top].x() == (*sorted)[i].x() && (*hull)[top].y() == (*sorted)[i].y())
+ {
+ if ((*sorted)[i].z() < (*hull)[top].z())
+ (*hull)[top].z() = (*sorted)[i].z();
+
+ continue;
+ }
+
+ if (isLeft((*sorted)[maxmax], (*sorted)[minmax], (*sorted)[i]) > 0 && i > minmax)
+ continue; // ignore (*sorted)[i] below the upper line. NOTE: Differs from original CH algorithm in that it keeps collinear points
+
+ while (top > bot) // at least 2 points on the upper stack
+ {
+ // test if (*sorted)[i] is left of or on the line at the stack top. NOTE: Differs from original CH algorithm in that it keeps collinear points
+ if (isLeft((*hull)[top-1], (*hull)[top], (*sorted)[i]) >= 0)
+ break; // (*sorted)[i] is a new hull vertex
+ else
+ top--; // pop top point off stack
+ }
+ (*hull)[++top] = (*sorted)[i]; // push (*sorted)[i] onto stack
+ }
+
+ // If minmax and minmin are the same, remove the duplicate point
+ if (minmax == minmin)
+ {
+ top--;
+ }
+ else
+ {
+ // Push all points between minmax and minmin onto stack. NOTE: Differs from original CH algorithm in that it keeps collinear points
+ while (i > minmin)
+ {
+ if ((*hull)[top].x() == (*sorted)[i].x() && (*hull)[top].y() == (*hull)[top].y())
+ {
+ if ((*sorted)[i].z() < (*hull)[top].z())
+ (*hull)[top].z() = (*sorted)[i].z();
+ }
+ else
+ {
+ (*hull)[++top] = (*sorted)[i];
+ }
+
+ i--;
+ }
+ }
+
+ hull->resize(top + 1);
+ return hull;
+}
+
+/* Returns an array containing the points sorted first by x and then by y */
+osg::Vec3dArray* BoundaryUtil::hullPresortPoints(osg::Vec3dArray& points)
+{
+ osg::Vec3dArray* sorted = new osg::Vec3dArray(points.begin(), points.end());
+ std::sort(sorted->begin(), sorted->end(), presortCompare);
+
+ return sorted;
+}
+
+//---------------------------------------------------------------------------
+
+namespace
+{
+ typedef std::set<osg::Vec3d> VertexSet;
+ typedef VertexSet::iterator Index;
+
+ // custom comparator for Index so we can use it at a std::map key
+ struct IndexLess : public std::less<Index> {
+ bool operator()(const Index& lhs, const Index& rhs ) const {
+ return (*lhs) < (*rhs);
+ }
+ };
+
+ typedef std::set<Index, IndexLess> IndexSet;
+ typedef std::map<Index, IndexSet, IndexLess> EdgeMap;
+
+ // Stores the noded topology of a model with unique verticies and edge definitions.
+ // The verticies are stored rotated into the XY plane so that we can properly find
+ // the "bottom-most" vert and walk the boundary.
+ struct TopologyGraph
+ {
+ TopologyGraph()
+ : _minY( _verts.end() ) { }
+
+ VertexSet _verts; // set of unique verts in the topology (rotated into XY plane)
+ osg::Quat _rot; // rotates a geocentric vert into the XY plane
+ EdgeMap _edgeMap; // maps each vert to all the verts with which it shares an edge
+ Index _minY; // points to the vert with the minimum Y coordinate (in XY plane)
+ };
+
+ typedef std::map<unsigned,Index> UniqueMap;
+
+ // A TriangleIndexFunctor that traverses a stream of triangles and builds a
+ // topology graph from their points and edges.
+ struct TopologyBuilder
+ {
+ TopologyGraph* _topology; // topology to which to append point and edge data
+ osg::Vec3Array* _vertexList; // source vertex list
+ osg::Matrixd _local2world; // transforms source verts into world coordinates
+ UniqueMap _uniqueMap; // prevents duplicates
+
+ void operator()( unsigned v0, unsigned v1, unsigned v2 )
+ {
+ Index i0 = add( v0 );
+ Index i1 = add( v1 );
+ Index i2 = add( v2 );
+
+ // add to the edge list for each of these verts
+ _topology->_edgeMap[i0].insert( i1 );
+ _topology->_edgeMap[i0].insert( i2 );
+ _topology->_edgeMap[i1].insert( i0 );
+ _topology->_edgeMap[i1].insert( i2 );
+ _topology->_edgeMap[i2].insert( i0 );
+ _topology->_edgeMap[i2].insert( i1 );
+ }
+
+ Index add( unsigned v )
+ {
+ // first see if we already added this vert:
+ UniqueMap::iterator i = _uniqueMap.find( v );
+ if ( i == _uniqueMap.end() )
+ {
+ // no, so transform it into world coordinates, and rotate it into the XY plane
+ osg::Vec3d spVert = (*_vertexList)[v];
+ osg::Vec3d local = _topology->_rot * (spVert * _local2world);
+
+ // insert it into the unique vert list
+ std::pair<VertexSet::iterator,bool> f = _topology->_verts.insert( local );
+ if ( f.second )
+ {
+ // this is a new location, so check it to see if it is the new "lowest" point:
+ if ( _topology->_minY == _topology->_verts.end() || local.y() < _topology->_minY->y() )
+ _topology->_minY = f.first;
+
+ // store in the uniqueness map to prevent duplication
+ _uniqueMap[ v ] = f.first;
+ }
+
+ // return the index of the vert.
+ return f.first;
+ }
+ else
+ {
+ // return the index of the vert.
+ return i->second;
+ }
+ }
+ };
+
+ // Visits a scene graph and builds a topology graph from the verts and edges
+ // found within.
+ struct BuildTopologyVisitor : public osg::NodeVisitor
+ {
+ BuildTopologyVisitor( TopologyGraph& topology )
+ : osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),
+ _topology( topology )
+ {
+ //nop
+ }
+
+ // track local transforms so we can build a topology in world coords
+ void apply( osg::Transform& xform )
+ {
+ osg::Matrix matrix;
+ if ( !_matrixStack.empty() ) matrix = _matrixStack.back();
+ xform.computeLocalToWorldMatrix( matrix, this );
+ _matrixStack.push_back( matrix );
+ traverse( xform );
+ _matrixStack.pop_back();
+ }
+
+ // add the contents of a geode to the topology
+ void apply( osg::Geode& geode )
+ {
+ for( unsigned i=0; i<geode.getNumDrawables(); ++i )
+ {
+ osg::Drawable* drawable = geode.getDrawable( i );
+ if ( drawable->asGeometry() )
+ {
+ apply( drawable->asGeometry() );
+ }
+ }
+ }
+
+ // add the contents of a Geometry to the topology
+ void apply( osg::Geometry* geometry )
+ {
+ osg::Vec3Array* vertexList = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
+ if ( vertexList )
+ {
+ osg::TriangleIndexFunctor<TopologyBuilder> _builder;
+ _builder._topology = &_topology;
+ _builder._vertexList = vertexList;
+ if ( !_matrixStack.empty() )
+ _builder._local2world = _matrixStack.back();
+ geometry->accept( _builder );
+ }
+ }
+
+ std::vector<osg::Matrixd> _matrixStack;
+ TopologyGraph& _topology;
+ };
+}
+
+//------------------------------------------------------------------------
+
+osg::Vec3dArray*
+BoundaryUtil::findMeshBoundary( osg::Node* node, bool geocentric )
+{
+ // the normal defines the XY plane in which to search for a boundary
+ osg::Vec3d normal(0,0,1);
+
+ if ( geocentric )
+ {
+ // define the XY plane based on the normal to the center of the dataset:
+ osg::BoundingSphere bs = node->getBound();
+ normal = bs.center();
+ normal.normalize();
+ }
+
+ osg::ref_ptr<osg::Vec3dArray> _result = new osg::Vec3dArray();
+
+ // first build a topology graph from the node.
+ TopologyGraph topology;
+
+ // set up a quat that will rotate geometry into our XY plane
+ if ( normal != osg::Vec3(0,0,1) )
+ topology._rot.makeRotate( normal, osg::Vec3d(0,0,1) );
+
+ // build the topology
+ BuildTopologyVisitor buildTopoVisitor(topology);
+ node->accept( buildTopoVisitor );
+
+ // starting with the minimum-Y vertex (which is guaranteed to be in the boundary)
+ // traverse the outside of the point set. Do this by sorting all the edges by
+ // their angle relative to the vector to the previous point. The vector with the
+ // smallest angle represents the edge connecting the current point to the next
+ // boundary point. Walk the edge until we return to the beginning.
+
+ Index vptr = topology._minY;
+ Index vptr_prev = topology._verts.end();
+
+ while( true )
+ {
+ // store this vertex in the result set:
+ _result->push_back( *vptr );
+
+ // pull up the next 2D vertex (XY plane):
+ osg::Vec2d vert( vptr->x(), vptr->y() );
+
+ // construct the "base" vector that points from the current point back
+ // to the previous point; or to -X in the initial case
+ osg::Vec2d base;
+ if ( vptr_prev == topology._verts.end() )
+ base.set( -1, 0 );
+ else
+ base = osg::Vec2d( vptr_prev->x(), vptr_prev->y() ) - vert;
+
+ // pull up the edge set for this vertex:
+ IndexSet& edges = topology._edgeMap[vptr];
+
+ // find the edge with the minimun delta angle to the base vector
+ double minAngle = DBL_MAX;
+ Index minEdge = topology._verts.end();
+
+ for( IndexSet::iterator e = edges.begin(); e != edges.end(); ++e )
+ {
+ // don't go back from whence we just came
+ if ( *e == vptr_prev )
+ continue;
+
+ // calculate the angle between the base vector and the current edge:
+ osg::Vec2d edgeVert( (*e)->x(), (*e)->y() );
+ osg::Vec2d edge = edgeVert - vert;
+
+ double baseAngle = atan2(base.y(), base.x());
+ double edgeAngle = atan2(edge.y(), edge.x());
+
+ double outsideAngle = baseAngle - edgeAngle;
+
+ // normalize it to [0..360)
+ if ( outsideAngle < 0.0 )
+ outsideAngle += 2.0*osg::PI;
+
+ // see it is qualifies as the new minimum angle
+ if ( outsideAngle < minAngle )
+ {
+ minAngle = outsideAngle;
+ minEdge = *e;
+ }
+ }
+
+ if ( minEdge == topology._verts.end() )
+ {
+ // this will probably never happen
+ osg::notify(osg::WARN) << "Illegal state - bailing" << std::endl;
+ return 0L;
+ }
+
+ vptr_prev = vptr;
+
+ // follow the chosen edge around the outside of the geometry:
+ vptr = minEdge;
+
+ // once we make it all the way around, we're done:
+ if ( vptr == topology._minY )
+ break;
+ }
+
+ // un-rotate the results from the XY plane back to their original frame:
+ osg::Quat invRot = topology._rot.inverse();
+ for( osg::Vec3dArray::iterator i = _result->begin(); i != _result->end(); ++i )
+ {
+ (*i) = invRot * (*i);
+ }
+
+ return _result.release();
+}
+
+//------------------------------------------------------------------------
+
+bool
+BoundaryUtil::simpleBoundaryTest(const osg::Vec3dArray& boundary)
+{
+ osg::ref_ptr<osgEarth::Symbology::Polygon> boundsPoly = new osgEarth::Symbology::Polygon();
+ for (int i=0; i < (int)boundary.size(); i++)
+ boundsPoly->push_back(boundary[i]);
+
+ osgEarth::Bounds boundsBounds = boundsPoly->getBounds();
+
+ osg::ref_ptr<osgEarth::Symbology::Polygon> outterPoly = new osgEarth::Symbology::Polygon();
+ outterPoly->push_back(osg::Vec3d(boundsBounds.xMin() - 10.0, boundsBounds.yMin() - 10.0, boundsBounds.zMin()));
+ outterPoly->push_back(osg::Vec3d(boundsBounds.xMax() + 10.0, boundsBounds.yMin() - 10.0, boundsBounds.zMin()));
+ outterPoly->push_back(osg::Vec3d(boundsBounds.xMax() + 10.0, boundsBounds.yMax() + 10.0, boundsBounds.zMin()));
+ outterPoly->push_back(osg::Vec3d(boundsBounds.xMin() - 10.0, boundsBounds.yMax() + 10.0, boundsBounds.zMin()));
+
+ osg::ref_ptr<osgEarth::Symbology::Geometry> outPoly;
+ return outterPoly->difference(boundsPoly, outPoly);
+}
diff --git a/src/applications/osgearth_boundarygen/CMakeLists.txt b/src/applications/osgearth_boundarygen/CMakeLists.txt
new file mode 100644
index 0000000..fe9ec6b
--- /dev/null
+++ b/src/applications/osgearth_boundarygen/CMakeLists.txt
@@ -0,0 +1,16 @@
+INCLUDE_DIRECTORIES(${OSG_INCLUDE_DIRS} )
+SET(TARGET_LIBRARIES_VARS OSG_LIBRARY OSGDB_LIBRARY OSGUTIL_LIBRARY OSGVIEWER_LIBRARY OPENTHREADS_LIBRARY)
+
+SET(TARGET_H
+ BoundaryUtil
+ VertexCollectionVisitor
+)
+
+SET(TARGET_SRC
+ BoundaryUtil.cpp
+ VertexCollectionVisitor.cpp
+ boundarygen.cpp
+)
+
+#### end var setup ###
+SETUP_APPLICATION(osgearth_boundarygen)
diff --git a/src/applications/osgearth_boundarygen/VertexCollectionVisitor b/src/applications/osgearth_boundarygen/VertexCollectionVisitor
new file mode 100644
index 0000000..7f7fcc3
--- /dev/null
+++ b/src/applications/osgearth_boundarygen/VertexCollectionVisitor
@@ -0,0 +1,60 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef VERTEX_COLLECTION_VISITOR
+#define VERTEX_COLLECTION_VISITOR 1
+
+#include <osg/CoordinateSystemNode>
+#include <osg/NodeVisitor>
+
+class VertexCollectionVisitor : public osg::NodeVisitor
+{
+public:
+
+ VertexCollectionVisitor(bool geocentric = false, TraversalMode traversalMode = TRAVERSE_ALL_CHILDREN);
+
+ virtual void reset();
+
+ osg::Vec3dArray* getVertices() { return _vertices.get(); }
+
+ void apply(osg::Node& node);
+
+ void apply(osg::Transform& transform);
+
+ void apply(osg::Geode& geode);
+
+ inline void pushMatrix(osg::Matrix& matrix) { _matrixStack.push_back(matrix); }
+
+ inline void popMatrix() { _matrixStack.pop_back(); }
+
+ void applyDrawable(osg::Drawable* drawable);
+
+protected:
+
+ typedef std::vector<osg::Matrix> MatrixStack;
+
+ osg::ref_ptr<osg::Vec3dArray> _vertices;
+ MatrixStack _matrixStack;
+ bool _geocentric;
+ osg::ref_ptr<osg::EllipsoidModel> _ellipsoidModel;
+
+ void addVertex(osg::Vec3 vertex);
+};
+
+#endif //VERTEX_COLLECTION_VISITOR
diff --git a/src/applications/osgearth_boundarygen/VertexCollectionVisitor.cpp b/src/applications/osgearth_boundarygen/VertexCollectionVisitor.cpp
new file mode 100644
index 0000000..138c701
--- /dev/null
+++ b/src/applications/osgearth_boundarygen/VertexCollectionVisitor.cpp
@@ -0,0 +1,100 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include "VertexCollectionVisitor"
+#include <osg/CoordinateSystemNode>
+#include <osg/Drawable>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/Transform>
+
+VertexCollectionVisitor::VertexCollectionVisitor(bool geocentric, TraversalMode traversalMode):
+ _geocentric(geocentric), osg::NodeVisitor(traversalMode)
+{
+ _vertices = new osg::Vec3dArray();
+ _ellipsoidModel = new osg::EllipsoidModel();
+}
+
+void VertexCollectionVisitor::reset()
+{
+ _matrixStack.clear();
+ _vertices->clear();
+}
+
+void VertexCollectionVisitor::apply(osg::Node& node)
+{
+ traverse(node);
+}
+
+void VertexCollectionVisitor::apply(osg::Transform& transform)
+{
+ osg::Matrix matrix;
+ if (!_matrixStack.empty()) matrix = _matrixStack.back();
+
+ transform.computeLocalToWorldMatrix(matrix,this);
+
+ pushMatrix(matrix);
+
+ traverse(transform);
+
+ popMatrix();
+}
+
+void VertexCollectionVisitor::apply(osg::Geode& geode)
+{
+ for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
+ applyDrawable(geode.getDrawable(i));
+}
+
+void VertexCollectionVisitor::applyDrawable(osg::Drawable* drawable)
+{
+ osg::Geometry* geometry = drawable->asGeometry();
+ if (geometry)
+ {
+ osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
+ if (verts)
+ {
+ if (_matrixStack.empty())
+ {
+ for (osg::Vec3Array::iterator it=verts->begin(); it != verts->end(); ++it)
+ addVertex(*it);
+ }
+ else
+ {
+ osg::Matrix& matrix = _matrixStack.back();
+ for (osg::Vec3Array::iterator it=verts->begin(); it != verts->end(); ++it)
+ addVertex((*it) * matrix);
+ }
+ }
+ }
+}
+
+void VertexCollectionVisitor::addVertex(osg::Vec3 vertex)
+{
+ if (_geocentric)
+ {
+ double lat, lon, height;
+ _ellipsoidModel->convertXYZToLatLongHeight(vertex.x(), vertex.y(), vertex.z(), lat, lon, height);
+ _vertices->push_back(osg::Vec3d(osg::RadiansToDegrees(lon), osg::RadiansToDegrees(lat), height));
+ }
+ else
+ {
+ _vertices->push_back(vertex);
+ }
+}
diff --git a/src/applications/osgearth_boundarygen/boundarygen.cpp b/src/applications/osgearth_boundarygen/boundarygen.cpp
new file mode 100644
index 0000000..3c4dbd9
--- /dev/null
+++ b/src/applications/osgearth_boundarygen/boundarygen.cpp
@@ -0,0 +1,178 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>
+*/
+
+#include "BoundaryUtil"
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <osg/Notify>
+#include <osg/LineWidth>
+#include <osg/Point>
+#include <osg/PolygonOffset>
+#include <osg/MatrixTransform>
+#include <osgDB/ReadFile>
+#include <osgDB/WriteFile>
+#include <osgGA/StateSetManipulator>
+#include <osgGA/GUIEventHandler>
+#include <osgViewer/Viewer>
+#include <osgViewer/ViewerEventHandlers>
+
+
+int usage( char** argv, const std::string& msg )
+{
+ OSG_NOTICE << msg << "\n\n";
+ OSG_NOTICE
+ << "osgEarth Boundary Generator Tool\n\n"
+ << "Generates boundary geometry that you can use with an osgEarth <mask> layer in order\n"
+ << "to stitch an external model into the terrain.\n\n"
+ << "USAGE: " << argv[0] << " [options] model_file\n"
+ << " --out file_name : output file for boundary geometry (default is boundary.txt)\n"
+ << " --no-geocentric : skip geocentric reprojection (for flat databases)\n"
+ << " --convex-hull : calculate a convex hull instead of a full boundary\n"
+ << " --verbose : print progress to console\n"
+ << " --view : show result in 3D window\n"
+ << std::endl;
+
+
+ return -1;
+}
+
+int main(int argc, char** argv)
+{
+ osg::ArgumentParser arguments(&argc,argv);
+
+ std::string outFile;
+ if (!arguments.read("--out", outFile))
+ outFile = "boundary.txt";
+
+ bool geocentric = !arguments.read("--no-geocentric");
+ bool verbose = arguments.read("--verbose");
+ bool convexOnly = arguments.read("--convex-hull");
+ bool view = arguments.read("--view");
+
+ osg::Node* modelNode = osgDB::readNodeFiles( arguments );
+ if (!modelNode)
+ return usage( argv, "Unable to load model." );
+
+ osg::ref_ptr<osg::Vec3dArray> hull = BoundaryUtil::getBoundary(modelNode, geocentric, convexOnly);
+
+ if ( !outFile.empty() )
+ {
+ if (hull.valid())
+ {
+ if (verbose)
+ std::cout << std::endl << "hull.size() == " << hull->size() << std::endl;
+
+ std::ofstream outStream;
+ outStream.open(outFile.c_str());
+ if (outStream.fail())
+ {
+ std::cout << "Unable to open " << outFile << " for writing." << std::endl;
+ }
+ else
+ {
+ outStream << "POLYGON((";
+
+ osg::ref_ptr<osg::EllipsoidModel> em = new osg::EllipsoidModel();
+
+ for (int i=0; i < (int)hull->size(); i++)
+ {
+ const osg::Vec3d& vert = (*hull.get())[i];
+
+ double lat, lon, height;
+ em->convertXYZToLatLongHeight( vert.x(), vert.y(), vert.z(), lat, lon, height );
+ lat = osg::RadiansToDegrees(lat);
+ lon = osg::RadiansToDegrees(lon);
+
+ if (verbose)
+ std::cout << " hull[" << i << "] == " << lon << ", " << lat << ", " << height << std::endl;
+
+ outStream << std::setiosflags(std::ios_base::fixed) << (i > 0 ? ", " : "") << lon << " " << lat << " " << height;
+ }
+
+ outStream << "))";
+ outStream.close();
+
+ std::cout << "Boundary data written to " << outFile << std::endl;
+
+ if (!convexOnly)
+ std::cout << "Boundary: " << (BoundaryUtil::simpleBoundaryTest(*hull) ? "VALID" : "INVALID") << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << "Could not find boundary." << std::endl;
+ }
+ }
+
+ if (view)
+ {
+ osgViewer::Viewer viewer(arguments);
+
+ osg::BoundingSphered bs;
+ for( osg::Vec3dArray::iterator i = hull->begin(); i != hull->end(); ++i )
+ bs.expandBy( *i );
+
+ osg::MatrixTransform* xform = new osg::MatrixTransform();
+ xform->setMatrix( osg::Matrix::translate( bs.center() ) );
+
+ osg::Vec3Array* drawHull = new osg::Vec3Array();
+ for( osg::Vec3dArray::iterator i = hull->begin(); i != hull->end(); ++i )
+ drawHull->push_back( (*i) - bs.center() );
+
+ osg::Group* root = new osg::Group();
+ root->addChild( modelNode );
+ root->addChild( xform );
+ modelNode->getOrCreateStateSet()->setAttributeAndModes( new osg::PolygonOffset(1,1), 1 );
+
+ osg::Geometry* boundaryGeometry = new osg::Geometry();
+ boundaryGeometry->setVertexArray( drawHull );
+
+ osg::Vec4Array* colors = new osg::Vec4Array;
+ colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
+ boundaryGeometry->setColorArray(colors);
+ boundaryGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ osg::StateSet* ss = boundaryGeometry->getOrCreateStateSet();
+ ss->setAttributeAndModes( new osg::LineWidth(1.0), 1 );
+ ss->setAttributeAndModes( new osg::Point(3.5), 1 );
+ ss->setMode( GL_LIGHTING, 0 );
+
+ boundaryGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,drawHull->size()));
+ boundaryGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,0,drawHull->size()));
+
+ osg::Geode* boundaryGeode = new osg::Geode();
+ boundaryGeode->addDrawable(boundaryGeometry);
+ xform->addChild(boundaryGeode);
+
+ viewer.setSceneData( root );
+
+ // add some stock OSG handlers:
+ viewer.addEventHandler(new osgViewer::StatsHandler());
+ viewer.addEventHandler(new osgViewer::WindowSizeHandler());
+ viewer.addEventHandler(new osgViewer::ThreadingHandler());
+ viewer.addEventHandler(new osgViewer::LODScaleHandler());
+ viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
+ viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
+
+ return viewer.run();
+ }
+
+ return 0;
+}
diff --git a/src/applications/osgearth_contour/osgearth_contour.cpp b/src/applications/osgearth_contour/osgearth_contour.cpp
index 81d333d..1d1479d 100644
--- a/src/applications/osgearth_contour/osgearth_contour.cpp
+++ b/src/applications/osgearth_contour/osgearth_contour.cpp
@@ -23,7 +23,7 @@
*/
#include <osg/Notify>
#include <osgViewer/Viewer>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/Registry>
#include <osgEarth/TerrainEngineNode>
#include <osgEarthUtil/EarthManipulator>
diff --git a/src/applications/osgearth_controls/osgearth_controls.cpp b/src/applications/osgearth_controls/osgearth_controls.cpp
index adfadd4..70e1264 100644
--- a/src/applications/osgearth_controls/osgearth_controls.cpp
+++ b/src/applications/osgearth_controls/osgearth_controls.cpp
@@ -23,6 +23,7 @@
#include <osgDB/ReadFile>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
+#include <osgEarth/Registry>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/Controls>
#include <osgEarthSymbology/Color>
@@ -115,7 +116,7 @@ createControls( ControlCanvas* cs )
// Add a text label:
LabelControl* label = new LabelControl( "osgEarth Controls Toolkit" );
- label->setFont( osgText::readFontFile( "arialbd.ttf" ) );
+ label->setFont( osgEarth::Registry::instance()->getDefaultFont() );
label->setFontSize( 24.0f );
label->setHorizAlign( Control::ALIGN_CENTER );
label->setMargin( 5 );
diff --git a/src/applications/osgearth_measure/osgearth_measure.cpp b/src/applications/osgearth_measure/osgearth_measure.cpp
index 21999dd..83a659d 100644
--- a/src/applications/osgearth_measure/osgearth_measure.cpp
+++ b/src/applications/osgearth_measure/osgearth_measure.cpp
@@ -24,6 +24,7 @@
#include <osgViewer/ViewerEventHandlers>
#include <osgEarth/MapNode>
#include <osgEarth/XmlUtils>
+#include <osgEarth/Registry>
#include <osgEarth/Viewpoint>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/AutoClipPlaneHandler>
@@ -150,7 +151,7 @@ main(int argc, char** argv)
// Add a text label:
grid->setControl( 0, 0, new LabelControl("Distance:") );
LabelControl* label = new LabelControl();
- label->setFont( osgText::readFontFile( "arialbd.ttf" ) );
+ label->setFont( osgEarth::Registry::instance()->getDefaultFont() );
label->setFontSize( 24.0f );
label->setHorizAlign( Control::ALIGN_LEFT );
label->setText("click to measure");
diff --git a/src/applications/osgearth_package/osgearth_package.cpp b/src/applications/osgearth_package/osgearth_package.cpp
index 15723ec..9ee48bd 100644
--- a/src/applications/osgearth_package/osgearth_package.cpp
+++ b/src/applications/osgearth_package/osgearth_package.cpp
@@ -59,18 +59,12 @@ usage( const std::string& msg = "" )
<< " <earth_file> : earth file defining layers to export (requied)\n"
<< " --out <path> : root output folder of the TMS repo (required)\n"
<< " [--bounds xmin ymin xmax ymax]* : bounds to package (in map coordinates; default=entire map)\n"
- << " [--max-level <num>] : max LOD level for tiles (all layers; default=5)\n"
+ << " [--max-level <num>] : max LOD level for tiles (all layers; default=inf)\n"
<< " [--out-earth <earthfile>] : export an earth file referencing the new repo\n"
<< " [--ext <extension>] : overrides the image file extension (e.g. jpg)\n"
<< " [--overwrite] : overwrite existing tiles\n"
<< " [--keep-empties] : writes out fully transparent image tiles (normally discarded)\n"
-#if 0
- << std::endl
- << " --tfs : make a TFS repo" << std::endl
- << " [--out <path>] : root output folder of the TFS repo" << std::endl
- << " [--sort <attr>] : name of attribute by which to sort features" << std::endl
- << " [--max <num> ] : target maximum # of features per tile" << std::endl
-#endif
+ << " [--db-options] : db options string to pass to the image writer in quotes (e.g., \"JPEG_QUALITY 60\")\n"
<< std::endl
<< " [--quiet] : suppress progress output" << std::endl;
@@ -117,9 +111,9 @@ makeTMS( osg::ArgumentParser& args )
// find a .earth file on the command line
std::string earthFile = findArgumentWithExtension(args, ".earth");
- if ( earthFile.empty() )
+ /* if ( earthFile.empty() )
return usage( "Missing required .earth file" );
-
+ */
// folder to which to write the TMS archive.
std::string rootFolder;
if ( !args.read( "--out", rootFolder ) )
@@ -134,6 +128,17 @@ makeTMS( osg::ArgumentParser& args )
std::string outEarth;
args.read("--out-earth", outEarth);
+ std::string dbOptions;
+ args.read("--db-options", dbOptions);
+ std::string::size_type n = 0;
+ while ((n=dbOptions.find('"', n))!=dbOptions.npos)
+ {
+ dbOptions.erase(n,1);
+ }
+
+ osg::ref_ptr<osgDB::Options> options = new osgDB::Options(dbOptions);
+
+
std::vector< Bounds > bounds;
// restrict packaging to user-specified bounds.
double xmin=DBL_MAX, ymin=DBL_MAX, xmax=DBL_MIN, ymax=DBL_MIN;
@@ -164,7 +169,7 @@ makeTMS( osg::ArgumentParser& args )
Map* map = mapNode->getMap();
// fire up a packager:
- TMSPackager packager( map->getProfile() );
+ TMSPackager packager( map->getProfile(), options);
packager.setVerbose( verbose );
packager.setOverwrite( overwrite );
diff --git a/src/applications/osgearth_seed/osgearth_seed.cpp b/src/applications/osgearth_seed/osgearth_seed.cpp
index 20cb33b..318a030 100644
--- a/src/applications/osgearth_seed/osgearth_seed.cpp
+++ b/src/applications/osgearth_seed/osgearth_seed.cpp
@@ -24,6 +24,7 @@
#include <osgEarth/Common>
#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
#include <osgEarth/Cache>
#include <osgEarth/CacheSeed>
#include <osgEarth/MapNode>
diff --git a/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp b/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp
index 6cc22bd..92b0c21 100644
--- a/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp
+++ b/src/applications/osgearth_shadercomp/osgearth_shadercomp.cpp
@@ -31,7 +31,7 @@
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgEarthUtil/EarthManipulator>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/Registry>
#include <osgEarthUtil/Controls>
@@ -46,9 +46,6 @@ int usage( const std::string& msg )
<< msg << "\n\n"
<< "USAGE: osgearth_shadercomp <earthfile> \n"
<< " [--test1] : Run the function injection test \n"
- << " [--test2] : Run the shader nesting test \n"
- << " [--test3] : Run the OVERRIDE mode test \n"
- << " [--test4] : Run the PROTECTED mode test \n"
<< " [--test5] : Run the Program state set text \n"
<< std::endl;
@@ -97,110 +94,6 @@ namespace TEST_1
//-------------------------------------------------------------------------
-// TESTS natual VP shader nesting. Even though a reddening shader is applied,
-// the built-in applyLighting shader should override it and take precedence.
-// Normal lighting should be used.
-namespace TEST_2
-{
- char s_source[] =
- "#version " GLSL_VERSION_STR "\n"
- "void osgearth_frag_applyColoring( inout vec4 color ) { \n"
- " color.r = 1.0; \n"
- "} \n";
-
- osg::Group* run( osg::Node* earth )
- {
- osg::Group* g1 = new osg::Group();
- g1->addChild( earth );
-
- osgEarth::VirtualProgram* vp = new osgEarth::VirtualProgram();
- vp->setShader( "osgearth_frag_applyColoring", new osg::Shader(osg::Shader::FRAGMENT, s_source) );
- g1->getOrCreateStateSet()->setAttributeAndModes( vp, osg::StateAttribute::ON );
-
- return g1;
- }
-}
-
-//-------------------------------------------------------------------------
-
-// TESTS the use of the OVERRIDE qualifier. Same as TEST_2 shader, but the "reddening"
-// shader should pre-empty the built-in shader because of the OVERRIDE mode.
-namespace TEST_3
-{
- char s_source[] =
- "#version " GLSL_VERSION_STR "\n"
- "void osgearth_frag_applyColoring( inout vec4 color ) { \n"
- " color = vec4(1.0, 0.0, 0.0, 1.0); \n"
- "} \n";
-
- osg::Group* run( osg::Node* earth )
- {
- osg::Group* g1 = new osg::Group();
- g1->addChild( earth );
-
- osgEarth::VirtualProgram* vp = new osgEarth::VirtualProgram();
-
- // NOTE the use of OVERRIDE; this prevents subordinate VPs from replacing the
- // function (unless marked as PROTECTED).
- vp->setShader(
- "osgearth_frag_applyColoring",
- new osg::Shader(osg::Shader::FRAGMENT, s_source),
- osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
-
- g1->getOrCreateStateSet()->setAttributeAndModes( vp, osg::StateAttribute::ON );
-
- return g1;
- }
-}
-
-//-------------------------------------------------------------------------
-
-// TESTS the use of the PROTECTED qualifier. Same as TEST_3 shader, but the "reddening"
-// shader (which has its OVERRIDE mode set) has a subordinate shader with its PROTECTED
-// mode set, which nullifies the effect of the OVERRIDE.
-namespace TEST_4
-{
- char s_source_1[] =
- "#version " GLSL_VERSION_STR "\n"
- "void osgearth_frag_applyColoring( inout vec4 color ) { \n"
- " color = vec4(1.0, 0.0, 0.0, 1.0); \n"
- "} \n";
-
- char s_source_2[] =
- "#version " GLSL_VERSION_STR "\n"
- "void osgearth_frag_applyColoring( inout vec4 color ) { \n"
- " color = vec4(0.0, 0.0, 1.0, 1.0); \n"
- "} \n";
-
- osg::Group* run( osg::Node* earth )
- {
- // Insert a Shader in OVERRIDE mode:
- osg::Group* g1 = new osg::Group();
- osgEarth::VirtualProgram* vp1 = new osgEarth::VirtualProgram();
- vp1->setShader(
- "osgearth_frag_applyColoring",
- new osg::Shader(osg::Shader::FRAGMENT, s_source_1),
- osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
- g1->getOrCreateStateSet()->setAttributeAndModes( vp1, osg::StateAttribute::ON );
-
- // Insert a subordinate shader in PROTECTED mode:
- osg::Group* g2 = new osg::Group();
- osgEarth::VirtualProgram* vp2 = new osgEarth::VirtualProgram();
- vp2->setShader(
- "osgearth_frag_applyColoring",
- new osg::Shader(osg::Shader::FRAGMENT, s_source_2),
- osg::StateAttribute::ON | osg::StateAttribute::PROTECTED | osg::StateAttribute::OVERRIDE );
- g2->getOrCreateStateSet()->setAttributeAndModes( vp2, osg::StateAttribute::ON );
-
- g1->addChild( g2 );
- g2->addChild( earth );
- return g1;
- }
-}
-
-//-------------------------------------------------------------------------
-
-//
namespace TEST_5
{
char s_vert[] =
@@ -256,8 +149,6 @@ namespace TEST_5
osg::Group* root = new osg::Group();
root->getOrCreateStateSet()->setRenderBinDetails( 0, "TraversalOrderBin" );
- //n1->getOrCreateStateSet()->setRenderBinDetails( 2, "RenderBin" );
- //n2->getOrCreateStateSet()->setRenderBinDetails( 1, "RenderBin" );
root->getOrCreateStateSet()->setMode(GL_LIGHTING,0);
root->addChild( n1 );
@@ -276,10 +167,13 @@ int main(int argc, char** argv)
osgViewer::Viewer viewer(arguments);
bool test1 = arguments.read("--test1");
- bool test2 = arguments.read("--test2");
- bool test3 = arguments.read("--test3");
- bool test4 = arguments.read("--test4");
bool test5 = arguments.read("--test5");
+ bool ok = test1 || test5;
+
+ if ( !ok )
+ {
+ return usage("");
+ }
if ( !test5 )
{
@@ -300,21 +194,6 @@ int main(int argc, char** argv)
viewer.setSceneData( TEST_1::run(earthNode) );
label->setText( "Function injection test: the map should appear hazy." );
}
- else if ( test2 )
- {
- viewer.setSceneData( TEST_2::run(earthNode) );
- label->setText( "Shader nesting test: the map should appear normally." );
- }
- else if ( test3 )
- {
- viewer.setSceneData( TEST_3::run(earthNode) );
- label->setText( "Shader override test: the map should appear red." );
- }
- else if ( test4 )
- {
- viewer.setSceneData( TEST_4::run(earthNode) );
- label->setText( "Shader protected test: the map should appear blue." );
- }
}
else // if ( test5 )
{
diff --git a/src/applications/osgearth_shadow/osgearth_shadow.cpp b/src/applications/osgearth_shadow/osgearth_shadow.cpp
index 9488f9c..6b1d188 100644
--- a/src/applications/osgearth_shadow/osgearth_shadow.cpp
+++ b/src/applications/osgearth_shadow/osgearth_shadow.cpp
@@ -124,7 +124,7 @@ int main(int argc, char** argv)
if (!skyNode)
{
OE_NOTICE << "Please run with options --sky to enable the SkyNode" << std::endl;
- exit(1);
+ //exit(1);
}
// Prevent terrain skirts (or other "secondary geometry") from casting shadows
diff --git a/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp b/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp
index 932f85f..09a61b8 100644
--- a/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp
+++ b/src/applications/osgearth_terrainprofile/osgearth_terrainprofile.cpp
@@ -28,6 +28,7 @@
#include <osgEarthUtil/AutoClipPlaneHandler>
#include <osgEarthUtil/TerrainProfile>
#include <osgEarth/GeoMath>
+#include <osgEarth/Registry>
#include <osgEarthFeatures/Feature>
#include <osgEarthAnnotation/FeatureNode>
#include <osgText/Text>
@@ -93,7 +94,7 @@ public:
_profileCalculator->addChangedCallback( _graphChangedCallback.get() );
float textSize = 8;
- osg::ref_ptr< osgText::Font> font = osgText::readFontFile( "arialbd.ttf" );
+ osg::ref_ptr< osgText::Font> font = osgEarth::Registry::instance()->getDefaultFont();
osg::Vec4 textColor = osg::Vec4f(1,0,0,1);
diff --git a/src/applications/osgearth_toc/osgearth_toc.cpp b/src/applications/osgearth_toc/osgearth_toc.cpp
index 7addf24..5a881fe 100644
--- a/src/applications/osgearth_toc/osgearth_toc.cpp
+++ b/src/applications/osgearth_toc/osgearth_toc.cpp
@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
#include <osgEarth/MapNode>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/Controls>
diff --git a/src/applications/osgearth_verticalscale/osgearth_verticalscale.cpp b/src/applications/osgearth_verticalscale/osgearth_verticalscale.cpp
index 23af1de..779cf9e 100644
--- a/src/applications/osgearth_verticalscale/osgearth_verticalscale.cpp
+++ b/src/applications/osgearth_verticalscale/osgearth_verticalscale.cpp
@@ -23,7 +23,7 @@
*/
#include <osg/Notify>
#include <osgViewer/Viewer>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/Registry>
#include <osgEarth/TerrainEngineNode>
#include <osgEarthUtil/EarthManipulator>
diff --git a/src/applications/osgearth_viewerIOS/osgEarthViewerIOS.xcodeproj/project.pbxproj b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..23e708c
--- /dev/null
+++ b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS.xcodeproj/project.pbxproj
@@ -0,0 +1,1044 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 90283E5615C6FB3E00620EEF /* tests in Resources */ = {isa = PBXBuildFile; fileRef = 90283E5415C6FB3E00620EEF /* tests */; };
+ 90283E5715C6FB3E00620EEF /* data in Resources */ = {isa = PBXBuildFile; fileRef = 90283E5515C6FB3E00620EEF /* data */; };
+ 90283E5D15C7091A00620EEF /* libosgdb_osgearth_engine_quadtree.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90283E5C15C7091A00620EEF /* libosgdb_osgearth_engine_quadtree.a */; };
+ 903B45DB15C0DE9F00F7702B /* EarthMultiTouchManipulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 903B45D915C0DE9F00F7702B /* EarthMultiTouchManipulator.cpp */; };
+ 9048FB2415FA9DE50012C900 /* libosgdb_tiff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9048FB2315FA9DE50012C900 /* libosgdb_tiff.a */; };
+ 9051000115B1EDFD00D9ABD3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9051000015B1EDFD00D9ABD3 /* Foundation.framework */; };
+ 9051000315B1EDFD00D9ABD3 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9051000215B1EDFD00D9ABD3 /* CoreGraphics.framework */; };
+ 9051000715B1EDFD00D9ABD3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9051000615B1EDFD00D9ABD3 /* OpenGLES.framework */; };
+ 9051000D15B1EDFD00D9ABD3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9051000B15B1EDFD00D9ABD3 /* InfoPlist.strings */; };
+ 9051000F15B1EDFD00D9ABD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9051000E15B1EDFD00D9ABD3 /* main.m */; };
+ 9051001315B1EDFD00D9ABD3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9051001215B1EDFD00D9ABD3 /* AppDelegate.m */; };
+ 9051001A15B1EDFD00D9ABD3 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9051001915B1EDFD00D9ABD3 /* ViewController.m */; };
+ 9051001D15B1EDFD00D9ABD3 /* ViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9051001B15B1EDFD00D9ABD3 /* ViewController_iPhone.xib */; };
+ 9051002015B1EDFD00D9ABD3 /* ViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9051001E15B1EDFD00D9ABD3 /* ViewController_iPad.xib */; };
+ 905100C315B20AC600D9ABD3 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 905100C215B20AC600D9ABD3 /* ImageIO.framework */; };
+ 905100C515B20AD100D9ABD3 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 905100C415B20AD100D9ABD3 /* CoreImage.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+ 905100CB15B2101E00D9ABD3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 905100CA15B2101E00D9ABD3 /* QuartzCore.framework */; };
+ 905100CD15B217A800D9ABD3 /* libc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 905100CC15B217A800D9ABD3 /* libc++.dylib */; };
+ 905100CF15B217B500D9ABD3 /* libz.1.1.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 905100CE15B217B500D9ABD3 /* libz.1.1.3.dylib */; };
+ 905100D115B2185000D9ABD3 /* libiconv.2.4.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 905100D015B2185000D9ABD3 /* libiconv.2.4.0.dylib */; };
+ 9051FFFF15B1EDFD00D9ABD3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9051FFFE15B1EDFD00D9ABD3 /* UIKit.framework */; };
+ 907D033915B86F8700575110 /* libOpenThreads.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02DC15B86F8700575110 /* libOpenThreads.a */; };
+ 907D033A15B86F8700575110 /* libosg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02DD15B86F8700575110 /* libosg.a */; };
+ 907D033B15B86F8700575110 /* libosgAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02DE15B86F8700575110 /* libosgAnimation.a */; };
+ 907D033C15B86F8700575110 /* libosgdb_3dc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02DF15B86F8700575110 /* libosgdb_3dc.a */; };
+ 907D033D15B86F8700575110 /* libosgdb_3ds.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E015B86F8700575110 /* libosgdb_3ds.a */; };
+ 907D033E15B86F8700575110 /* libosgdb_ac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E115B86F8700575110 /* libosgdb_ac.a */; };
+ 907D033F15B86F8700575110 /* libosgdb_bmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E215B86F8700575110 /* libosgdb_bmp.a */; };
+ 907D034015B86F8700575110 /* libosgdb_bsp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E315B86F8700575110 /* libosgdb_bsp.a */; };
+ 907D034115B86F8700575110 /* libosgdb_bvh.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E415B86F8700575110 /* libosgdb_bvh.a */; };
+ 907D034215B86F8700575110 /* libosgdb_cfg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E515B86F8700575110 /* libosgdb_cfg.a */; };
+ 907D034315B86F8700575110 /* libosgdb_curl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E615B86F8700575110 /* libosgdb_curl.a */; };
+ 907D034415B86F8700575110 /* libosgdb_dds.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E715B86F8700575110 /* libosgdb_dds.a */; };
+ 907D034515B86F8700575110 /* libosgdb_deprecated_osg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E815B86F8700575110 /* libosgdb_deprecated_osg.a */; };
+ 907D034615B86F8700575110 /* libosgdb_deprecated_osganimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02E915B86F8700575110 /* libosgdb_deprecated_osganimation.a */; };
+ 907D034715B86F8700575110 /* libosgdb_deprecated_osgfx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02EA15B86F8700575110 /* libosgdb_deprecated_osgfx.a */; };
+ 907D034815B86F8700575110 /* libosgdb_deprecated_osgparticle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02EB15B86F8700575110 /* libosgdb_deprecated_osgparticle.a */; };
+ 907D034915B86F8700575110 /* libosgdb_deprecated_osgshadow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02EC15B86F8700575110 /* libosgdb_deprecated_osgshadow.a */; };
+ 907D034A15B86F8700575110 /* libosgdb_deprecated_osgsim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02ED15B86F8700575110 /* libosgdb_deprecated_osgsim.a */; };
+ 907D034B15B86F8700575110 /* libosgdb_deprecated_osgterrain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02EE15B86F8700575110 /* libosgdb_deprecated_osgterrain.a */; };
+ 907D034C15B86F8700575110 /* libosgdb_deprecated_osgtext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02EF15B86F8700575110 /* libosgdb_deprecated_osgtext.a */; };
+ 907D034D15B86F8700575110 /* libosgdb_deprecated_osgviewer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F015B86F8700575110 /* libosgdb_deprecated_osgviewer.a */; };
+ 907D034E15B86F8700575110 /* libosgdb_deprecated_osgvolume.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F115B86F8700575110 /* libosgdb_deprecated_osgvolume.a */; };
+ 907D034F15B86F8700575110 /* libosgdb_deprecated_osgwidget.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F215B86F8700575110 /* libosgdb_deprecated_osgwidget.a */; };
+ 907D035015B86F8700575110 /* libosgdb_dot.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F315B86F8700575110 /* libosgdb_dot.a */; };
+ 907D035115B86F8700575110 /* libosgdb_dw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F415B86F8700575110 /* libosgdb_dw.a */; };
+ 907D035215B86F8700575110 /* libosgdb_dxf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F515B86F8700575110 /* libosgdb_dxf.a */; };
+ 907D035315B86F8700575110 /* libosgdb_freetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F615B86F8700575110 /* libosgdb_freetype.a */; };
+ 907D035415B86F8700575110 /* libosgdb_gdal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F715B86F8700575110 /* libosgdb_gdal.a */; };
+ 907D035515B86F8700575110 /* libosgdb_geo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F815B86F8700575110 /* libosgdb_geo.a */; };
+ 907D035615B86F8700575110 /* libosgdb_glsl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02F915B86F8700575110 /* libosgdb_glsl.a */; };
+ 907D035715B86F8700575110 /* libosgdb_gz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02FA15B86F8700575110 /* libosgdb_gz.a */; };
+ 907D035815B86F8700575110 /* libosgdb_hdr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02FB15B86F8700575110 /* libosgdb_hdr.a */; };
+ 907D035915B86F8700575110 /* libosgdb_imageio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02FC15B86F8700575110 /* libosgdb_imageio.a */; };
+ 907D035A15B86F8700575110 /* libosgdb_ive.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02FD15B86F8700575110 /* libosgdb_ive.a */; };
+ 907D035B15B86F8700575110 /* libosgdb_logo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02FE15B86F8700575110 /* libosgdb_logo.a */; };
+ 907D035C15B86F8700575110 /* libosgdb_lwo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D02FF15B86F8700575110 /* libosgdb_lwo.a */; };
+ 907D035D15B86F8700575110 /* libosgdb_lws.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030015B86F8700575110 /* libosgdb_lws.a */; };
+ 907D035E15B86F8700575110 /* libosgdb_md2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030115B86F8700575110 /* libosgdb_md2.a */; };
+ 907D035F15B86F8700575110 /* libosgdb_mdl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030215B86F8700575110 /* libosgdb_mdl.a */; };
+ 907D036015B86F8700575110 /* libosgdb_normals.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030315B86F8700575110 /* libosgdb_normals.a */; };
+ 907D036115B86F8700575110 /* libosgdb_obj.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030415B86F8700575110 /* libosgdb_obj.a */; };
+ 907D036215B86F8700575110 /* libosgdb_ogr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030515B86F8700575110 /* libosgdb_ogr.a */; };
+ 907D036315B86F8700575110 /* libosgdb_openflight.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030615B86F8700575110 /* libosgdb_openflight.a */; };
+ 907D036415B86F8700575110 /* libosgdb_osg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030715B86F8700575110 /* libosgdb_osg.a */; };
+ 907D036515B86F8700575110 /* libosgdb_osga.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030815B86F8700575110 /* libosgdb_osga.a */; };
+ 907D036615B86F8700575110 /* libosgdb_osgshadow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030915B86F8700575110 /* libosgdb_osgshadow.a */; };
+ 907D036715B86F8700575110 /* libosgdb_osgterrain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030A15B86F8700575110 /* libosgdb_osgterrain.a */; };
+ 907D036815B86F8700575110 /* libosgdb_osgtgz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030B15B86F8700575110 /* libosgdb_osgtgz.a */; };
+ 907D036915B86F8700575110 /* libosgdb_osgviewer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030C15B86F8700575110 /* libosgdb_osgviewer.a */; };
+ 907D036A15B86F8700575110 /* libosgdb_p3d.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030D15B86F8700575110 /* libosgdb_p3d.a */; };
+ 907D036B15B86F8700575110 /* libosgdb_pic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030E15B86F8700575110 /* libosgdb_pic.a */; };
+ 907D036C15B86F8700575110 /* libosgdb_ply.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D030F15B86F8700575110 /* libosgdb_ply.a */; };
+ 907D036D15B86F8700575110 /* libosgdb_pnm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031015B86F8700575110 /* libosgdb_pnm.a */; };
+ 907D036E15B86F8700575110 /* libosgdb_pov.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031115B86F8700575110 /* libosgdb_pov.a */; };
+ 907D036F15B86F8700575110 /* libosgdb_pvr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031215B86F8700575110 /* libosgdb_pvr.a */; };
+ 907D037015B86F8700575110 /* libosgdb_revisions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031315B86F8700575110 /* libosgdb_revisions.a */; };
+ 907D037115B86F8700575110 /* libosgdb_rgb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031415B86F8700575110 /* libosgdb_rgb.a */; };
+ 907D037215B86F8700575110 /* libosgdb_rot.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031515B86F8700575110 /* libosgdb_rot.a */; };
+ 907D037315B86F8700575110 /* libosgdb_scale.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031615B86F8700575110 /* libosgdb_scale.a */; };
+ 907D037415B86F8700575110 /* libosgdb_serializers_osg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031715B86F8700575110 /* libosgdb_serializers_osg.a */; };
+ 907D037515B86F8700575110 /* libosgdb_serializers_osganimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031815B86F8700575110 /* libosgdb_serializers_osganimation.a */; };
+ 907D037615B86F8700575110 /* libosgdb_serializers_osgfx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031915B86F8700575110 /* libosgdb_serializers_osgfx.a */; };
+ 907D037715B86F8700575110 /* libosgdb_serializers_osgmanipulator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031A15B86F8700575110 /* libosgdb_serializers_osgmanipulator.a */; };
+ 907D037815B86F8700575110 /* libosgdb_serializers_osgparticle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031B15B86F8700575110 /* libosgdb_serializers_osgparticle.a */; };
+ 907D037915B86F8700575110 /* libosgdb_serializers_osgshadow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031C15B86F8700575110 /* libosgdb_serializers_osgshadow.a */; };
+ 907D037A15B86F8700575110 /* libosgdb_serializers_osgsim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031D15B86F8700575110 /* libosgdb_serializers_osgsim.a */; };
+ 907D037B15B86F8700575110 /* libosgdb_serializers_osgterrain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031E15B86F8700575110 /* libosgdb_serializers_osgterrain.a */; };
+ 907D037C15B86F8700575110 /* libosgdb_serializers_osgtext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D031F15B86F8700575110 /* libosgdb_serializers_osgtext.a */; };
+ 907D037D15B86F8700575110 /* libosgdb_serializers_osgvolume.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032015B86F8700575110 /* libosgdb_serializers_osgvolume.a */; };
+ 907D037E15B86F8700575110 /* libosgdb_shp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032115B86F8700575110 /* libosgdb_shp.a */; };
+ 907D037F15B86F8700575110 /* libosgdb_stl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032215B86F8700575110 /* libosgdb_stl.a */; };
+ 907D038015B86F8700575110 /* libosgdb_tga.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032315B86F8700575110 /* libosgdb_tga.a */; };
+ 907D038115B86F8700575110 /* libosgdb_tgz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032415B86F8700575110 /* libosgdb_tgz.a */; };
+ 907D038215B86F8700575110 /* libosgdb_trans.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032515B86F8700575110 /* libosgdb_trans.a */; };
+ 907D038315B86F8700575110 /* libosgdb_txf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032615B86F8700575110 /* libosgdb_txf.a */; };
+ 907D038415B86F8700575110 /* libosgdb_txp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032715B86F8700575110 /* libosgdb_txp.a */; };
+ 907D038515B86F8700575110 /* libosgdb_vtf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032815B86F8700575110 /* libosgdb_vtf.a */; };
+ 907D038615B86F8700575110 /* libosgdb_x.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032915B86F8700575110 /* libosgdb_x.a */; };
+ 907D038715B86F8700575110 /* libosgdb_zip.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032A15B86F8700575110 /* libosgdb_zip.a */; };
+ 907D038815B86F8700575110 /* libosgDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032B15B86F8700575110 /* libosgDB.a */; };
+ 907D038915B86F8700575110 /* libosgFX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032C15B86F8700575110 /* libosgFX.a */; };
+ 907D038A15B86F8700575110 /* libosgGA.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032D15B86F8700575110 /* libosgGA.a */; };
+ 907D038B15B86F8700575110 /* libosgManipulator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032E15B86F8700575110 /* libosgManipulator.a */; };
+ 907D038C15B86F8700575110 /* libosgParticle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D032F15B86F8700575110 /* libosgParticle.a */; };
+ 907D038D15B86F8700575110 /* libosgPresentation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033015B86F8700575110 /* libosgPresentation.a */; };
+ 907D038E15B86F8700575110 /* libosgShadow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033115B86F8700575110 /* libosgShadow.a */; };
+ 907D038F15B86F8700575110 /* libosgSim.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033215B86F8700575110 /* libosgSim.a */; };
+ 907D039015B86F8700575110 /* libosgTerrain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033315B86F8700575110 /* libosgTerrain.a */; };
+ 907D039115B86F8700575110 /* libosgText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033415B86F8700575110 /* libosgText.a */; };
+ 907D039215B86F8700575110 /* libosgUtil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033515B86F8700575110 /* libosgUtil.a */; };
+ 907D039315B86F8700575110 /* libosgViewer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033615B86F8700575110 /* libosgViewer.a */; };
+ 907D039415B86F8700575110 /* libosgVolume.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033715B86F8700575110 /* libosgVolume.a */; };
+ 907D039515B86F8700575110 /* libosgWidget.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D033815B86F8700575110 /* libosgWidget.a */; };
+ 907D03BD15B86F9E00575110 /* libosgdb_kml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039715B86F9E00575110 /* libosgdb_kml.a */; };
+ 907D03BE15B86F9E00575110 /* libosgdb_osgearth_feature_wfs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039815B86F9E00575110 /* libosgdb_osgearth_feature_wfs.a */; };
+ 907D03BF15B86F9E00575110 /* libosgdb_osgearth_feature_tfs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039915B86F9E00575110 /* libosgdb_osgearth_feature_tfs.a */; };
+ 907D03C015B86F9E00575110 /* libosgdb_osgearth_tms.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039A15B86F9E00575110 /* libosgdb_osgearth_tms.a */; };
+ 907D03C115B86F9E00575110 /* libosgdb_osgearth_wms.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039B15B86F9E00575110 /* libosgdb_osgearth_wms.a */; };
+ 907D03C215B86F9E00575110 /* libosgdb_osgearth_label_overlay.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039C15B86F9E00575110 /* libosgdb_osgearth_label_overlay.a */; };
+ 907D03C315B86F9E00575110 /* libosgdb_osgearth_xyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039D15B86F9E00575110 /* libosgdb_osgearth_xyz.a */; };
+ 907D03C415B86F9E00575110 /* libosgEarthUtil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039E15B86F9E00575110 /* libosgEarthUtil.a */; };
+ 907D03C515B86F9E00575110 /* libosgdb_osgearth_label_annotation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D039F15B86F9E00575110 /* libosgdb_osgearth_label_annotation.a */; };
+ 907D03C615B86F9E00575110 /* libosgdb_osgearth_mask_feature.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A015B86F9E00575110 /* libosgdb_osgearth_mask_feature.a */; };
+ 907D03C715B86F9E00575110 /* libosgdb_osgearth_model_feature_geom.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A115B86F9E00575110 /* libosgdb_osgearth_model_feature_geom.a */; };
+ 907D03C815B86F9E00575110 /* libosgEarthAnnotation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A215B86F9E00575110 /* libosgEarthAnnotation.a */; };
+ 907D03C915B86F9E00575110 /* libosgdb_osgearth_agglite.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A315B86F9E00575110 /* libosgdb_osgearth_agglite.a */; };
+ 907D03CA15B86F9E00575110 /* libosgdb_osgearth_feature_ogr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A415B86F9E00575110 /* libosgdb_osgearth_feature_ogr.a */; };
+ 907D03CB15B86F9E00575110 /* libosgdb_osgearth_model_feature_stencil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A515B86F9E00575110 /* libosgdb_osgearth_model_feature_stencil.a */; };
+ 907D03CC15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm2008.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A615B86F9E00575110 /* libosgdb_osgearth_vdatum_egm2008.a */; };
+ 907D03CD15B86F9E00575110 /* libosgdb_osgearth_model_simple.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A715B86F9E00575110 /* libosgdb_osgearth_model_simple.a */; };
+ 907D03CE15B86F9E00575110 /* libosgdb_osgearth_engine_osgterrain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A815B86F9E00575110 /* libosgdb_osgearth_engine_osgterrain.a */; };
+ 907D03CF15B86F9E00575110 /* libosgEarthFeatures.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03A915B86F9E00575110 /* libosgEarthFeatures.a */; };
+ 907D03D015B86F9E00575110 /* libosgdb_osgearth_vdatum_egm96.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03AA15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm96.a */; };
+ 907D03D115B86F9E00575110 /* libosgdb_osgearth_ocean_surface.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03AB15B86F9E00575110 /* libosgdb_osgearth_ocean_surface.a */; };
+ 907D03D215B86F9E00575110 /* libosgdb_osgearth_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03AC15B86F9E00575110 /* libosgdb_osgearth_debug.a */; };
+ 907D03D315B86F9E00575110 /* libosgdb_osgearth_mbtiles.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03AD15B86F9E00575110 /* libosgdb_osgearth_mbtiles.a */; };
+ 907D03D415B86F9E00575110 /* libosgdb_osgearth_vdatum_egm84.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03AE15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm84.a */; };
+ 907D03D515B86F9E00575110 /* libosgdb_osgearth_tileservice.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03AF15B86F9E00575110 /* libosgdb_osgearth_tileservice.a */; };
+ 907D03D615B86F9E00575110 /* libosgdb_osgearth_yahoo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B015B86F9E00575110 /* libosgdb_osgearth_yahoo.a */; };
+ 907D03D715B86F9E00575110 /* libosgdb_osgearth_arcgis_map_cache.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B115B86F9E00575110 /* libosgdb_osgearth_arcgis_map_cache.a */; };
+ 907D03D815B86F9E00575110 /* libosgdb_osgearth_tilecache.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B215B86F9E00575110 /* libosgdb_osgearth_tilecache.a */; };
+ 907D03D915B86F9E00575110 /* libosgdb_osgearth_wcs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B315B86F9E00575110 /* libosgdb_osgearth_wcs.a */; };
+ 907D03DA15B86F9E00575110 /* libosgEarthSymbology.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B415B86F9E00575110 /* libosgEarthSymbology.a */; };
+ 907D03DB15B86F9F00575110 /* libosgdb_osgearth_gdal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B515B86F9E00575110 /* libosgdb_osgearth_gdal.a */; };
+ 907D03DC15B86F9F00575110 /* libosgdb_osgearth_refresh.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B615B86F9E00575110 /* libosgdb_osgearth_refresh.a */; };
+ 907D03DD15B86F9F00575110 /* libosgdb_osgearth_vpb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B715B86F9E00575110 /* libosgdb_osgearth_vpb.a */; };
+ 907D03DE15B86F9F00575110 /* libosgdb_earth.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B815B86F9E00575110 /* libosgdb_earth.a */; };
+ 907D03DF15B86F9F00575110 /* libosgdb_osgearth_cache_filesystem.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03B915B86F9E00575110 /* libosgdb_osgearth_cache_filesystem.a */; };
+ 907D03E015B86F9F00575110 /* libosgdb_osgearth_arcgis.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03BA15B86F9E00575110 /* libosgdb_osgearth_arcgis.a */; };
+ 907D03E115B86F9F00575110 /* libosgdb_osgearth_osg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03BB15B86F9E00575110 /* libosgdb_osgearth_osg.a */; };
+ 907D03E215B86F9F00575110 /* libosgEarth.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03BC15B86F9E00575110 /* libosgEarth.a */; };
+ 907D03FA15B8C31A00575110 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D03F915B8C31A00575110 /* libsqlite3.dylib */; };
+ 907D0A8E15B8CEBE00575110 /* libGEOS_3.2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 907D0A8D15B8CEBE00575110 /* libGEOS_3.2.a */; };
+ 907D0A9115B8DDAA00575110 /* GLES2ShaderGenVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 907D0A8F15B8DDAA00575110 /* GLES2ShaderGenVisitor.cpp */; };
+ 90A0DD6D15B7BAF9004FACEE /* libFreeType_iphone_universal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90A0DD6C15B7BAF9004FACEE /* libFreeType_iphone_universal.a */; };
+ 90A0DD6F15B7BB50004FACEE /* libproj.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90A0DD6E15B7BB50004FACEE /* libproj.a */; };
+ 90A0DD7115B7BB64004FACEE /* libgdal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90A0DD7015B7BB64004FACEE /* libgdal.a */; };
+ 90A0DD7615B7BBA4004FACEE /* libcurl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90A0DD7515B7BBA4004FACEE /* libcurl.a */; };
+ 90B8676615C8894900F5CDC3 /* StartViewerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90B8676415C8894900F5CDC3 /* StartViewerController.m */; };
+ 90B8676715C8894900F5CDC3 /* StartViewerController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 90B8676515C8894900F5CDC3 /* StartViewerController.xib */; };
+ 90DABDDC15CEFF9700D0F609 /* moon_1024x512.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 90DABDDB15CEFF9700D0F609 /* moon_1024x512.jpg */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 90283E5415C6FB3E00620EEF /* tests */ = {isa = PBXFileReference; lastKnownFileType = folder; name = tests; path = ../../../../tests; sourceTree = "<group>"; };
+ 90283E5515C6FB3E00620EEF /* data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = data; path = ../../../../data; sourceTree = "<group>"; };
+ 90283E5C15C7091A00620EEF /* libosgdb_osgearth_engine_quadtree.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_engine_quadtree.a; path = ../../../lib/Release/libosgdb_osgearth_engine_quadtree.a; sourceTree = "<group>"; };
+ 903B45D915C0DE9F00F7702B /* EarthMultiTouchManipulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EarthMultiTouchManipulator.cpp; sourceTree = "<group>"; };
+ 903B45DA15C0DE9F00F7702B /* EarthMultiTouchManipulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EarthMultiTouchManipulator.h; sourceTree = "<group>"; };
+ 9048FB2315FA9DE50012C900 /* libosgdb_tiff.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_tiff.a; path = "../../../../osg-ios-gles2/lib/libosgdb_tiff.a"; sourceTree = "<group>"; };
+ 9051000015B1EDFD00D9ABD3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 9051000215B1EDFD00D9ABD3 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 9051000615B1EDFD00D9ABD3 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
+ 9051000A15B1EDFD00D9ABD3 /* osgEarthViewerIOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "osgEarthViewerIOS-Info.plist"; sourceTree = "<group>"; };
+ 9051000C15B1EDFD00D9ABD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 9051000E15B1EDFD00D9ABD3 /* main.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = main.m; sourceTree = "<group>"; };
+ 9051001015B1EDFD00D9ABD3 /* osgEarthViewerIOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "osgEarthViewerIOS-Prefix.pch"; sourceTree = "<group>"; };
+ 9051001115B1EDFD00D9ABD3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+ 9051001215B1EDFD00D9ABD3 /* AppDelegate.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = AppDelegate.m; sourceTree = "<group>"; };
+ 9051001815B1EDFD00D9ABD3 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
+ 9051001915B1EDFD00D9ABD3 /* ViewController.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = ViewController.m; sourceTree = "<group>"; };
+ 9051001C15B1EDFD00D9ABD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController_iPhone.xib; sourceTree = "<group>"; };
+ 9051001F15B1EDFD00D9ABD3 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController_iPad.xib; sourceTree = "<group>"; };
+ 905100C215B20AC600D9ABD3 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; };
+ 905100C415B20AD100D9ABD3 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; };
+ 905100C615B20B1D00D9ABD3 /* osgPlugins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = osgPlugins.h; sourceTree = "<group>"; };
+ 905100CA15B2101E00D9ABD3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ 905100CC15B217A800D9ABD3 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "usr/lib/libc++.dylib"; sourceTree = SDKROOT; };
+ 905100CE15B217B500D9ABD3 /* libz.1.1.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.1.3.dylib; path = usr/lib/libz.1.1.3.dylib; sourceTree = SDKROOT; };
+ 905100D015B2185000D9ABD3 /* libiconv.2.4.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.2.4.0.dylib; path = usr/lib/libiconv.2.4.0.dylib; sourceTree = SDKROOT; };
+ 9051FFFA15B1EDFD00D9ABD3 /* osgEarth.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = osgEarth.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 9051FFFE15B1EDFD00D9ABD3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 907D02DC15B86F8700575110 /* libOpenThreads.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libOpenThreads.a; path = "../../../../osg-ios-gles2/lib/libOpenThreads.a"; sourceTree = "<group>"; };
+ 907D02DD15B86F8700575110 /* libosg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosg.a; path = "../../../../osg-ios-gles2/lib/libosg.a"; sourceTree = "<group>"; };
+ 907D02DE15B86F8700575110 /* libosgAnimation.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgAnimation.a; path = "../../../../osg-ios-gles2/lib/libosgAnimation.a"; sourceTree = "<group>"; };
+ 907D02DF15B86F8700575110 /* libosgdb_3dc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_3dc.a; path = "../../../../osg-ios-gles2/lib/libosgdb_3dc.a"; sourceTree = "<group>"; };
+ 907D02E015B86F8700575110 /* libosgdb_3ds.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_3ds.a; path = "../../../../osg-ios-gles2/lib/libosgdb_3ds.a"; sourceTree = "<group>"; };
+ 907D02E115B86F8700575110 /* libosgdb_ac.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_ac.a; path = "../../../../osg-ios-gles2/lib/libosgdb_ac.a"; sourceTree = "<group>"; };
+ 907D02E215B86F8700575110 /* libosgdb_bmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_bmp.a; path = "../../../../osg-ios-gles2/lib/libosgdb_bmp.a"; sourceTree = "<group>"; };
+ 907D02E315B86F8700575110 /* libosgdb_bsp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_bsp.a; path = "../../../../osg-ios-gles2/lib/libosgdb_bsp.a"; sourceTree = "<group>"; };
+ 907D02E415B86F8700575110 /* libosgdb_bvh.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_bvh.a; path = "../../../../osg-ios-gles2/lib/libosgdb_bvh.a"; sourceTree = "<group>"; };
+ 907D02E515B86F8700575110 /* libosgdb_cfg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_cfg.a; path = "../../../../osg-ios-gles2/lib/libosgdb_cfg.a"; sourceTree = "<group>"; };
+ 907D02E615B86F8700575110 /* libosgdb_curl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_curl.a; path = "../../../../osg-ios-gles2/lib/libosgdb_curl.a"; sourceTree = "<group>"; };
+ 907D02E715B86F8700575110 /* libosgdb_dds.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_dds.a; path = "../../../../osg-ios-gles2/lib/libosgdb_dds.a"; sourceTree = "<group>"; };
+ 907D02E815B86F8700575110 /* libosgdb_deprecated_osg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osg.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osg.a"; sourceTree = "<group>"; };
+ 907D02E915B86F8700575110 /* libosgdb_deprecated_osganimation.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osganimation.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osganimation.a"; sourceTree = "<group>"; };
+ 907D02EA15B86F8700575110 /* libosgdb_deprecated_osgfx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgfx.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgfx.a"; sourceTree = "<group>"; };
+ 907D02EB15B86F8700575110 /* libosgdb_deprecated_osgparticle.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgparticle.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgparticle.a"; sourceTree = "<group>"; };
+ 907D02EC15B86F8700575110 /* libosgdb_deprecated_osgshadow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgshadow.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgshadow.a"; sourceTree = "<group>"; };
+ 907D02ED15B86F8700575110 /* libosgdb_deprecated_osgsim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgsim.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgsim.a"; sourceTree = "<group>"; };
+ 907D02EE15B86F8700575110 /* libosgdb_deprecated_osgterrain.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgterrain.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgterrain.a"; sourceTree = "<group>"; };
+ 907D02EF15B86F8700575110 /* libosgdb_deprecated_osgtext.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgtext.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgtext.a"; sourceTree = "<group>"; };
+ 907D02F015B86F8700575110 /* libosgdb_deprecated_osgviewer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgviewer.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgviewer.a"; sourceTree = "<group>"; };
+ 907D02F115B86F8700575110 /* libosgdb_deprecated_osgvolume.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgvolume.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgvolume.a"; sourceTree = "<group>"; };
+ 907D02F215B86F8700575110 /* libosgdb_deprecated_osgwidget.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_deprecated_osgwidget.a; path = "../../../../osg-ios-gles2/lib/libosgdb_deprecated_osgwidget.a"; sourceTree = "<group>"; };
+ 907D02F315B86F8700575110 /* libosgdb_dot.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_dot.a; path = "../../../../osg-ios-gles2/lib/libosgdb_dot.a"; sourceTree = "<group>"; };
+ 907D02F415B86F8700575110 /* libosgdb_dw.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_dw.a; path = "../../../../osg-ios-gles2/lib/libosgdb_dw.a"; sourceTree = "<group>"; };
+ 907D02F515B86F8700575110 /* libosgdb_dxf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_dxf.a; path = "../../../../osg-ios-gles2/lib/libosgdb_dxf.a"; sourceTree = "<group>"; };
+ 907D02F615B86F8700575110 /* libosgdb_freetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_freetype.a; path = "../../../../osg-ios-gles2/lib/libosgdb_freetype.a"; sourceTree = "<group>"; };
+ 907D02F715B86F8700575110 /* libosgdb_gdal.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_gdal.a; path = "../../../../osg-ios-gles2/lib/libosgdb_gdal.a"; sourceTree = "<group>"; };
+ 907D02F815B86F8700575110 /* libosgdb_geo.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_geo.a; path = "../../../../osg-ios-gles2/lib/libosgdb_geo.a"; sourceTree = "<group>"; };
+ 907D02F915B86F8700575110 /* libosgdb_glsl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_glsl.a; path = "../../../../osg-ios-gles2/lib/libosgdb_glsl.a"; sourceTree = "<group>"; };
+ 907D02FA15B86F8700575110 /* libosgdb_gz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_gz.a; path = "../../../../osg-ios-gles2/lib/libosgdb_gz.a"; sourceTree = "<group>"; };
+ 907D02FB15B86F8700575110 /* libosgdb_hdr.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_hdr.a; path = "../../../../osg-ios-gles2/lib/libosgdb_hdr.a"; sourceTree = "<group>"; };
+ 907D02FC15B86F8700575110 /* libosgdb_imageio.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_imageio.a; path = "../../../../osg-ios-gles2/lib/libosgdb_imageio.a"; sourceTree = "<group>"; };
+ 907D02FD15B86F8700575110 /* libosgdb_ive.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_ive.a; path = "../../../../osg-ios-gles2/lib/libosgdb_ive.a"; sourceTree = "<group>"; };
+ 907D02FE15B86F8700575110 /* libosgdb_logo.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_logo.a; path = "../../../../osg-ios-gles2/lib/libosgdb_logo.a"; sourceTree = "<group>"; };
+ 907D02FF15B86F8700575110 /* libosgdb_lwo.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_lwo.a; path = "../../../../osg-ios-gles2/lib/libosgdb_lwo.a"; sourceTree = "<group>"; };
+ 907D030015B86F8700575110 /* libosgdb_lws.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_lws.a; path = "../../../../osg-ios-gles2/lib/libosgdb_lws.a"; sourceTree = "<group>"; };
+ 907D030115B86F8700575110 /* libosgdb_md2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_md2.a; path = "../../../../osg-ios-gles2/lib/libosgdb_md2.a"; sourceTree = "<group>"; };
+ 907D030215B86F8700575110 /* libosgdb_mdl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_mdl.a; path = "../../../../osg-ios-gles2/lib/libosgdb_mdl.a"; sourceTree = "<group>"; };
+ 907D030315B86F8700575110 /* libosgdb_normals.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_normals.a; path = "../../../../osg-ios-gles2/lib/libosgdb_normals.a"; sourceTree = "<group>"; };
+ 907D030415B86F8700575110 /* libosgdb_obj.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_obj.a; path = "../../../../osg-ios-gles2/lib/libosgdb_obj.a"; sourceTree = "<group>"; };
+ 907D030515B86F8700575110 /* libosgdb_ogr.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_ogr.a; path = "../../../../osg-ios-gles2/lib/libosgdb_ogr.a"; sourceTree = "<group>"; };
+ 907D030615B86F8700575110 /* libosgdb_openflight.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_openflight.a; path = "../../../../osg-ios-gles2/lib/libosgdb_openflight.a"; sourceTree = "<group>"; };
+ 907D030715B86F8700575110 /* libosgdb_osg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osg.a; path = "../../../../osg-ios-gles2/lib/libosgdb_osg.a"; sourceTree = "<group>"; };
+ 907D030815B86F8700575110 /* libosgdb_osga.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osga.a; path = "../../../../osg-ios-gles2/lib/libosgdb_osga.a"; sourceTree = "<group>"; };
+ 907D030915B86F8700575110 /* libosgdb_osgshadow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgshadow.a; path = "../../../../osg-ios-gles2/lib/libosgdb_osgshadow.a"; sourceTree = "<group>"; };
+ 907D030A15B86F8700575110 /* libosgdb_osgterrain.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgterrain.a; path = "../../../../osg-ios-gles2/lib/libosgdb_osgterrain.a"; sourceTree = "<group>"; };
+ 907D030B15B86F8700575110 /* libosgdb_osgtgz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgtgz.a; path = "../../../../osg-ios-gles2/lib/libosgdb_osgtgz.a"; sourceTree = "<group>"; };
+ 907D030C15B86F8700575110 /* libosgdb_osgviewer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgviewer.a; path = "../../../../osg-ios-gles2/lib/libosgdb_osgviewer.a"; sourceTree = "<group>"; };
+ 907D030D15B86F8700575110 /* libosgdb_p3d.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_p3d.a; path = "../../../../osg-ios-gles2/lib/libosgdb_p3d.a"; sourceTree = "<group>"; };
+ 907D030E15B86F8700575110 /* libosgdb_pic.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_pic.a; path = "../../../../osg-ios-gles2/lib/libosgdb_pic.a"; sourceTree = "<group>"; };
+ 907D030F15B86F8700575110 /* libosgdb_ply.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_ply.a; path = "../../../../osg-ios-gles2/lib/libosgdb_ply.a"; sourceTree = "<group>"; };
+ 907D031015B86F8700575110 /* libosgdb_pnm.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_pnm.a; path = "../../../../osg-ios-gles2/lib/libosgdb_pnm.a"; sourceTree = "<group>"; };
+ 907D031115B86F8700575110 /* libosgdb_pov.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_pov.a; path = "../../../../osg-ios-gles2/lib/libosgdb_pov.a"; sourceTree = "<group>"; };
+ 907D031215B86F8700575110 /* libosgdb_pvr.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_pvr.a; path = "../../../../osg-ios-gles2/lib/libosgdb_pvr.a"; sourceTree = "<group>"; };
+ 907D031315B86F8700575110 /* libosgdb_revisions.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_revisions.a; path = "../../../../osg-ios-gles2/lib/libosgdb_revisions.a"; sourceTree = "<group>"; };
+ 907D031415B86F8700575110 /* libosgdb_rgb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_rgb.a; path = "../../../../osg-ios-gles2/lib/libosgdb_rgb.a"; sourceTree = "<group>"; };
+ 907D031515B86F8700575110 /* libosgdb_rot.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_rot.a; path = "../../../../osg-ios-gles2/lib/libosgdb_rot.a"; sourceTree = "<group>"; };
+ 907D031615B86F8700575110 /* libosgdb_scale.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_scale.a; path = "../../../../osg-ios-gles2/lib/libosgdb_scale.a"; sourceTree = "<group>"; };
+ 907D031715B86F8700575110 /* libosgdb_serializers_osg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osg.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osg.a"; sourceTree = "<group>"; };
+ 907D031815B86F8700575110 /* libosgdb_serializers_osganimation.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osganimation.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osganimation.a"; sourceTree = "<group>"; };
+ 907D031915B86F8700575110 /* libosgdb_serializers_osgfx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgfx.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgfx.a"; sourceTree = "<group>"; };
+ 907D031A15B86F8700575110 /* libosgdb_serializers_osgmanipulator.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgmanipulator.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgmanipulator.a"; sourceTree = "<group>"; };
+ 907D031B15B86F8700575110 /* libosgdb_serializers_osgparticle.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgparticle.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgparticle.a"; sourceTree = "<group>"; };
+ 907D031C15B86F8700575110 /* libosgdb_serializers_osgshadow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgshadow.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgshadow.a"; sourceTree = "<group>"; };
+ 907D031D15B86F8700575110 /* libosgdb_serializers_osgsim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgsim.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgsim.a"; sourceTree = "<group>"; };
+ 907D031E15B86F8700575110 /* libosgdb_serializers_osgterrain.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgterrain.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgterrain.a"; sourceTree = "<group>"; };
+ 907D031F15B86F8700575110 /* libosgdb_serializers_osgtext.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgtext.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgtext.a"; sourceTree = "<group>"; };
+ 907D032015B86F8700575110 /* libosgdb_serializers_osgvolume.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_serializers_osgvolume.a; path = "../../../../osg-ios-gles2/lib/libosgdb_serializers_osgvolume.a"; sourceTree = "<group>"; };
+ 907D032115B86F8700575110 /* libosgdb_shp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_shp.a; path = "../../../../osg-ios-gles2/lib/libosgdb_shp.a"; sourceTree = "<group>"; };
+ 907D032215B86F8700575110 /* libosgdb_stl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_stl.a; path = "../../../../osg-ios-gles2/lib/libosgdb_stl.a"; sourceTree = "<group>"; };
+ 907D032315B86F8700575110 /* libosgdb_tga.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_tga.a; path = "../../../../osg-ios-gles2/lib/libosgdb_tga.a"; sourceTree = "<group>"; };
+ 907D032415B86F8700575110 /* libosgdb_tgz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_tgz.a; path = "../../../../osg-ios-gles2/lib/libosgdb_tgz.a"; sourceTree = "<group>"; };
+ 907D032515B86F8700575110 /* libosgdb_trans.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_trans.a; path = "../../../../osg-ios-gles2/lib/libosgdb_trans.a"; sourceTree = "<group>"; };
+ 907D032615B86F8700575110 /* libosgdb_txf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_txf.a; path = "../../../../osg-ios-gles2/lib/libosgdb_txf.a"; sourceTree = "<group>"; };
+ 907D032715B86F8700575110 /* libosgdb_txp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_txp.a; path = "../../../../osg-ios-gles2/lib/libosgdb_txp.a"; sourceTree = "<group>"; };
+ 907D032815B86F8700575110 /* libosgdb_vtf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_vtf.a; path = "../../../../osg-ios-gles2/lib/libosgdb_vtf.a"; sourceTree = "<group>"; };
+ 907D032915B86F8700575110 /* libosgdb_x.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_x.a; path = "../../../../osg-ios-gles2/lib/libosgdb_x.a"; sourceTree = "<group>"; };
+ 907D032A15B86F8700575110 /* libosgdb_zip.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_zip.a; path = "../../../../osg-ios-gles2/lib/libosgdb_zip.a"; sourceTree = "<group>"; };
+ 907D032B15B86F8700575110 /* libosgDB.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgDB.a; path = "../../../../osg-ios-gles2/lib/libosgDB.a"; sourceTree = "<group>"; };
+ 907D032C15B86F8700575110 /* libosgFX.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgFX.a; path = "../../../../osg-ios-gles2/lib/libosgFX.a"; sourceTree = "<group>"; };
+ 907D032D15B86F8700575110 /* libosgGA.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgGA.a; path = "../../../../osg-ios-gles2/lib/libosgGA.a"; sourceTree = "<group>"; };
+ 907D032E15B86F8700575110 /* libosgManipulator.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgManipulator.a; path = "../../../../osg-ios-gles2/lib/libosgManipulator.a"; sourceTree = "<group>"; };
+ 907D032F15B86F8700575110 /* libosgParticle.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgParticle.a; path = "../../../../osg-ios-gles2/lib/libosgParticle.a"; sourceTree = "<group>"; };
+ 907D033015B86F8700575110 /* libosgPresentation.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgPresentation.a; path = "../../../../osg-ios-gles2/lib/libosgPresentation.a"; sourceTree = "<group>"; };
+ 907D033115B86F8700575110 /* libosgShadow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgShadow.a; path = "../../../../osg-ios-gles2/lib/libosgShadow.a"; sourceTree = "<group>"; };
+ 907D033215B86F8700575110 /* libosgSim.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgSim.a; path = "../../../../osg-ios-gles2/lib/libosgSim.a"; sourceTree = "<group>"; };
+ 907D033315B86F8700575110 /* libosgTerrain.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgTerrain.a; path = "../../../../osg-ios-gles2/lib/libosgTerrain.a"; sourceTree = "<group>"; };
+ 907D033415B86F8700575110 /* libosgText.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgText.a; path = "../../../../osg-ios-gles2/lib/libosgText.a"; sourceTree = "<group>"; };
+ 907D033515B86F8700575110 /* libosgUtil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgUtil.a; path = "../../../../osg-ios-gles2/lib/libosgUtil.a"; sourceTree = "<group>"; };
+ 907D033615B86F8700575110 /* libosgViewer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgViewer.a; path = "../../../../osg-ios-gles2/lib/libosgViewer.a"; sourceTree = "<group>"; };
+ 907D033715B86F8700575110 /* libosgVolume.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgVolume.a; path = "../../../../osg-ios-gles2/lib/libosgVolume.a"; sourceTree = "<group>"; };
+ 907D033815B86F8700575110 /* libosgWidget.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgWidget.a; path = "../../../../osg-ios-gles2/lib/libosgWidget.a"; sourceTree = "<group>"; };
+ 907D039715B86F9E00575110 /* libosgdb_kml.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_kml.a; path = ../../../lib/Release/libosgdb_kml.a; sourceTree = "<group>"; };
+ 907D039815B86F9E00575110 /* libosgdb_osgearth_feature_wfs.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_feature_wfs.a; path = ../../../lib/Release/libosgdb_osgearth_feature_wfs.a; sourceTree = "<group>"; };
+ 907D039915B86F9E00575110 /* libosgdb_osgearth_feature_tfs.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_feature_tfs.a; path = ../../../lib/Release/libosgdb_osgearth_feature_tfs.a; sourceTree = "<group>"; };
+ 907D039A15B86F9E00575110 /* libosgdb_osgearth_tms.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_tms.a; path = ../../../lib/Release/libosgdb_osgearth_tms.a; sourceTree = "<group>"; };
+ 907D039B15B86F9E00575110 /* libosgdb_osgearth_wms.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_wms.a; path = ../../../lib/Release/libosgdb_osgearth_wms.a; sourceTree = "<group>"; };
+ 907D039C15B86F9E00575110 /* libosgdb_osgearth_label_overlay.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_label_overlay.a; path = ../../../lib/Release/libosgdb_osgearth_label_overlay.a; sourceTree = "<group>"; };
+ 907D039D15B86F9E00575110 /* libosgdb_osgearth_xyz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_xyz.a; path = ../../../lib/Release/libosgdb_osgearth_xyz.a; sourceTree = "<group>"; };
+ 907D039E15B86F9E00575110 /* libosgEarthUtil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgEarthUtil.a; path = ../../../lib/Release/libosgEarthUtil.a; sourceTree = "<group>"; };
+ 907D039F15B86F9E00575110 /* libosgdb_osgearth_label_annotation.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_label_annotation.a; path = ../../../lib/Release/libosgdb_osgearth_label_annotation.a; sourceTree = "<group>"; };
+ 907D03A015B86F9E00575110 /* libosgdb_osgearth_mask_feature.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_mask_feature.a; path = ../../../lib/Release/libosgdb_osgearth_mask_feature.a; sourceTree = "<group>"; };
+ 907D03A115B86F9E00575110 /* libosgdb_osgearth_model_feature_geom.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_model_feature_geom.a; path = ../../../lib/Release/libosgdb_osgearth_model_feature_geom.a; sourceTree = "<group>"; };
+ 907D03A215B86F9E00575110 /* libosgEarthAnnotation.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgEarthAnnotation.a; path = ../../../lib/Release/libosgEarthAnnotation.a; sourceTree = "<group>"; };
+ 907D03A315B86F9E00575110 /* libosgdb_osgearth_agglite.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_agglite.a; path = ../../../lib/Release/libosgdb_osgearth_agglite.a; sourceTree = "<group>"; };
+ 907D03A415B86F9E00575110 /* libosgdb_osgearth_feature_ogr.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_feature_ogr.a; path = ../../../lib/Release/libosgdb_osgearth_feature_ogr.a; sourceTree = "<group>"; };
+ 907D03A515B86F9E00575110 /* libosgdb_osgearth_model_feature_stencil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_model_feature_stencil.a; path = ../../../lib/Release/libosgdb_osgearth_model_feature_stencil.a; sourceTree = "<group>"; };
+ 907D03A615B86F9E00575110 /* libosgdb_osgearth_vdatum_egm2008.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_vdatum_egm2008.a; path = ../../../lib/Release/libosgdb_osgearth_vdatum_egm2008.a; sourceTree = "<group>"; };
+ 907D03A715B86F9E00575110 /* libosgdb_osgearth_model_simple.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_model_simple.a; path = ../../../lib/Release/libosgdb_osgearth_model_simple.a; sourceTree = "<group>"; };
+ 907D03A815B86F9E00575110 /* libosgdb_osgearth_engine_osgterrain.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_engine_osgterrain.a; path = ../../../lib/Release/libosgdb_osgearth_engine_osgterrain.a; sourceTree = "<group>"; };
+ 907D03A915B86F9E00575110 /* libosgEarthFeatures.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgEarthFeatures.a; path = ../../../lib/Release/libosgEarthFeatures.a; sourceTree = "<group>"; };
+ 907D03AA15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm96.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_vdatum_egm96.a; path = ../../../lib/Release/libosgdb_osgearth_vdatum_egm96.a; sourceTree = "<group>"; };
+ 907D03AB15B86F9E00575110 /* libosgdb_osgearth_ocean_surface.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_ocean_surface.a; path = ../../../lib/Release/libosgdb_osgearth_ocean_surface.a; sourceTree = "<group>"; };
+ 907D03AC15B86F9E00575110 /* libosgdb_osgearth_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_debug.a; path = ../../../lib/Release/libosgdb_osgearth_debug.a; sourceTree = "<group>"; };
+ 907D03AD15B86F9E00575110 /* libosgdb_osgearth_mbtiles.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_mbtiles.a; path = ../../../lib/Release/libosgdb_osgearth_mbtiles.a; sourceTree = "<group>"; };
+ 907D03AE15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm84.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_vdatum_egm84.a; path = ../../../lib/Release/libosgdb_osgearth_vdatum_egm84.a; sourceTree = "<group>"; };
+ 907D03AF15B86F9E00575110 /* libosgdb_osgearth_tileservice.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_tileservice.a; path = ../../../lib/Release/libosgdb_osgearth_tileservice.a; sourceTree = "<group>"; };
+ 907D03B015B86F9E00575110 /* libosgdb_osgearth_yahoo.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_yahoo.a; path = ../../../lib/Release/libosgdb_osgearth_yahoo.a; sourceTree = "<group>"; };
+ 907D03B115B86F9E00575110 /* libosgdb_osgearth_arcgis_map_cache.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_arcgis_map_cache.a; path = ../../../lib/Release/libosgdb_osgearth_arcgis_map_cache.a; sourceTree = "<group>"; };
+ 907D03B215B86F9E00575110 /* libosgdb_osgearth_tilecache.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_tilecache.a; path = ../../../lib/Release/libosgdb_osgearth_tilecache.a; sourceTree = "<group>"; };
+ 907D03B315B86F9E00575110 /* libosgdb_osgearth_wcs.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_wcs.a; path = ../../../lib/Release/libosgdb_osgearth_wcs.a; sourceTree = "<group>"; };
+ 907D03B415B86F9E00575110 /* libosgEarthSymbology.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgEarthSymbology.a; path = ../../../lib/Release/libosgEarthSymbology.a; sourceTree = "<group>"; };
+ 907D03B515B86F9E00575110 /* libosgdb_osgearth_gdal.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_gdal.a; path = ../../../lib/Release/libosgdb_osgearth_gdal.a; sourceTree = "<group>"; };
+ 907D03B615B86F9E00575110 /* libosgdb_osgearth_refresh.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_refresh.a; path = ../../../lib/Release/libosgdb_osgearth_refresh.a; sourceTree = "<group>"; };
+ 907D03B715B86F9E00575110 /* libosgdb_osgearth_vpb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_vpb.a; path = ../../../lib/Release/libosgdb_osgearth_vpb.a; sourceTree = "<group>"; };
+ 907D03B815B86F9E00575110 /* libosgdb_earth.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_earth.a; path = ../../../lib/Release/libosgdb_earth.a; sourceTree = "<group>"; };
+ 907D03B915B86F9E00575110 /* libosgdb_osgearth_cache_filesystem.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_cache_filesystem.a; path = ../../../lib/Release/libosgdb_osgearth_cache_filesystem.a; sourceTree = "<group>"; };
+ 907D03BA15B86F9E00575110 /* libosgdb_osgearth_arcgis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_arcgis.a; path = ../../../lib/Release/libosgdb_osgearth_arcgis.a; sourceTree = "<group>"; };
+ 907D03BB15B86F9E00575110 /* libosgdb_osgearth_osg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgdb_osgearth_osg.a; path = ../../../lib/Release/libosgdb_osgearth_osg.a; sourceTree = "<group>"; };
+ 907D03BC15B86F9E00575110 /* libosgEarth.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libosgEarth.a; path = ../../../lib/Release/libosgEarth.a; sourceTree = "<group>"; };
+ 907D03F915B8C31A00575110 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
+ 907D0A8D15B8CEBE00575110 /* libGEOS_3.2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libGEOS_3.2.a; path = "../../../../3rdParty/geos-ios-device/lib/libGEOS_3.2.a"; sourceTree = "<group>"; };
+ 907D0A8F15B8DDAA00575110 /* GLES2ShaderGenVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GLES2ShaderGenVisitor.cpp; path = ShaderGen/GLES2ShaderGenVisitor.cpp; sourceTree = "<group>"; };
+ 907D0A9015B8DDAA00575110 /* GLES2ShaderGenVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLES2ShaderGenVisitor.h; path = ShaderGen/GLES2ShaderGenVisitor.h; sourceTree = "<group>"; };
+ 90A0DD6C15B7BAF9004FACEE /* libFreeType_iphone_universal.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libFreeType_iphone_universal.a; sourceTree = "<group>"; };
+ 90A0DD6E15B7BB50004FACEE /* libproj.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libproj.a; sourceTree = "<group>"; };
+ 90A0DD7015B7BB64004FACEE /* libgdal.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgdal.a; sourceTree = "<group>"; };
+ 90A0DD7515B7BBA4004FACEE /* libcurl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libcurl.a; sourceTree = "<group>"; };
+ 90B8676315C8894900F5CDC3 /* StartViewerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StartViewerController.h; sourceTree = "<group>"; };
+ 90B8676415C8894900F5CDC3 /* StartViewerController.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = StartViewerController.m; sourceTree = "<group>"; };
+ 90B8676515C8894900F5CDC3 /* StartViewerController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StartViewerController.xib; sourceTree = "<group>"; };
+ 90DABDDB15CEFF9700D0F609 /* moon_1024x512.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = moon_1024x512.jpg; path = ../../../../data/moon_1024x512.jpg; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 9051FFF715B1EDFD00D9ABD3 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 907D037E15B86F8700575110 /* libosgdb_shp.a in Frameworks */,
+ 9048FB2415FA9DE50012C900 /* libosgdb_tiff.a in Frameworks */,
+ 907D03FA15B8C31A00575110 /* libsqlite3.dylib in Frameworks */,
+ 90A0DD7615B7BBA4004FACEE /* libcurl.a in Frameworks */,
+ 90A0DD7115B7BB64004FACEE /* libgdal.a in Frameworks */,
+ 90A0DD6F15B7BB50004FACEE /* libproj.a in Frameworks */,
+ 90A0DD6D15B7BAF9004FACEE /* libFreeType_iphone_universal.a in Frameworks */,
+ 905100D115B2185000D9ABD3 /* libiconv.2.4.0.dylib in Frameworks */,
+ 905100CF15B217B500D9ABD3 /* libz.1.1.3.dylib in Frameworks */,
+ 905100CD15B217A800D9ABD3 /* libc++.dylib in Frameworks */,
+ 905100CB15B2101E00D9ABD3 /* QuartzCore.framework in Frameworks */,
+ 905100C515B20AD100D9ABD3 /* CoreImage.framework in Frameworks */,
+ 905100C315B20AC600D9ABD3 /* ImageIO.framework in Frameworks */,
+ 9051FFFF15B1EDFD00D9ABD3 /* UIKit.framework in Frameworks */,
+ 9051000115B1EDFD00D9ABD3 /* Foundation.framework in Frameworks */,
+ 9051000315B1EDFD00D9ABD3 /* CoreGraphics.framework in Frameworks */,
+ 9051000715B1EDFD00D9ABD3 /* OpenGLES.framework in Frameworks */,
+ 907D033915B86F8700575110 /* libOpenThreads.a in Frameworks */,
+ 907D033A15B86F8700575110 /* libosg.a in Frameworks */,
+ 907D033B15B86F8700575110 /* libosgAnimation.a in Frameworks */,
+ 907D033C15B86F8700575110 /* libosgdb_3dc.a in Frameworks */,
+ 907D033D15B86F8700575110 /* libosgdb_3ds.a in Frameworks */,
+ 907D033E15B86F8700575110 /* libosgdb_ac.a in Frameworks */,
+ 907D033F15B86F8700575110 /* libosgdb_bmp.a in Frameworks */,
+ 907D034015B86F8700575110 /* libosgdb_bsp.a in Frameworks */,
+ 907D034115B86F8700575110 /* libosgdb_bvh.a in Frameworks */,
+ 907D034215B86F8700575110 /* libosgdb_cfg.a in Frameworks */,
+ 907D034315B86F8700575110 /* libosgdb_curl.a in Frameworks */,
+ 907D034415B86F8700575110 /* libosgdb_dds.a in Frameworks */,
+ 907D034515B86F8700575110 /* libosgdb_deprecated_osg.a in Frameworks */,
+ 907D034615B86F8700575110 /* libosgdb_deprecated_osganimation.a in Frameworks */,
+ 907D034715B86F8700575110 /* libosgdb_deprecated_osgfx.a in Frameworks */,
+ 907D034815B86F8700575110 /* libosgdb_deprecated_osgparticle.a in Frameworks */,
+ 907D034915B86F8700575110 /* libosgdb_deprecated_osgshadow.a in Frameworks */,
+ 907D034A15B86F8700575110 /* libosgdb_deprecated_osgsim.a in Frameworks */,
+ 907D034B15B86F8700575110 /* libosgdb_deprecated_osgterrain.a in Frameworks */,
+ 907D034C15B86F8700575110 /* libosgdb_deprecated_osgtext.a in Frameworks */,
+ 907D034D15B86F8700575110 /* libosgdb_deprecated_osgviewer.a in Frameworks */,
+ 907D034E15B86F8700575110 /* libosgdb_deprecated_osgvolume.a in Frameworks */,
+ 907D034F15B86F8700575110 /* libosgdb_deprecated_osgwidget.a in Frameworks */,
+ 907D035015B86F8700575110 /* libosgdb_dot.a in Frameworks */,
+ 907D035115B86F8700575110 /* libosgdb_dw.a in Frameworks */,
+ 907D035215B86F8700575110 /* libosgdb_dxf.a in Frameworks */,
+ 907D035315B86F8700575110 /* libosgdb_freetype.a in Frameworks */,
+ 907D035415B86F8700575110 /* libosgdb_gdal.a in Frameworks */,
+ 907D035515B86F8700575110 /* libosgdb_geo.a in Frameworks */,
+ 907D035615B86F8700575110 /* libosgdb_glsl.a in Frameworks */,
+ 907D035715B86F8700575110 /* libosgdb_gz.a in Frameworks */,
+ 907D035815B86F8700575110 /* libosgdb_hdr.a in Frameworks */,
+ 907D035915B86F8700575110 /* libosgdb_imageio.a in Frameworks */,
+ 907D035A15B86F8700575110 /* libosgdb_ive.a in Frameworks */,
+ 907D035B15B86F8700575110 /* libosgdb_logo.a in Frameworks */,
+ 907D035C15B86F8700575110 /* libosgdb_lwo.a in Frameworks */,
+ 907D035D15B86F8700575110 /* libosgdb_lws.a in Frameworks */,
+ 907D035E15B86F8700575110 /* libosgdb_md2.a in Frameworks */,
+ 907D035F15B86F8700575110 /* libosgdb_mdl.a in Frameworks */,
+ 907D036015B86F8700575110 /* libosgdb_normals.a in Frameworks */,
+ 907D036115B86F8700575110 /* libosgdb_obj.a in Frameworks */,
+ 907D036215B86F8700575110 /* libosgdb_ogr.a in Frameworks */,
+ 907D036315B86F8700575110 /* libosgdb_openflight.a in Frameworks */,
+ 907D036415B86F8700575110 /* libosgdb_osg.a in Frameworks */,
+ 907D036515B86F8700575110 /* libosgdb_osga.a in Frameworks */,
+ 907D036615B86F8700575110 /* libosgdb_osgshadow.a in Frameworks */,
+ 907D036715B86F8700575110 /* libosgdb_osgterrain.a in Frameworks */,
+ 907D036815B86F8700575110 /* libosgdb_osgtgz.a in Frameworks */,
+ 907D036915B86F8700575110 /* libosgdb_osgviewer.a in Frameworks */,
+ 907D036A15B86F8700575110 /* libosgdb_p3d.a in Frameworks */,
+ 907D036B15B86F8700575110 /* libosgdb_pic.a in Frameworks */,
+ 907D036C15B86F8700575110 /* libosgdb_ply.a in Frameworks */,
+ 907D036D15B86F8700575110 /* libosgdb_pnm.a in Frameworks */,
+ 907D036E15B86F8700575110 /* libosgdb_pov.a in Frameworks */,
+ 907D036F15B86F8700575110 /* libosgdb_pvr.a in Frameworks */,
+ 907D037015B86F8700575110 /* libosgdb_revisions.a in Frameworks */,
+ 907D037115B86F8700575110 /* libosgdb_rgb.a in Frameworks */,
+ 907D037215B86F8700575110 /* libosgdb_rot.a in Frameworks */,
+ 907D037315B86F8700575110 /* libosgdb_scale.a in Frameworks */,
+ 907D037415B86F8700575110 /* libosgdb_serializers_osg.a in Frameworks */,
+ 907D037515B86F8700575110 /* libosgdb_serializers_osganimation.a in Frameworks */,
+ 907D037615B86F8700575110 /* libosgdb_serializers_osgfx.a in Frameworks */,
+ 907D037715B86F8700575110 /* libosgdb_serializers_osgmanipulator.a in Frameworks */,
+ 907D037815B86F8700575110 /* libosgdb_serializers_osgparticle.a in Frameworks */,
+ 907D037915B86F8700575110 /* libosgdb_serializers_osgshadow.a in Frameworks */,
+ 907D037A15B86F8700575110 /* libosgdb_serializers_osgsim.a in Frameworks */,
+ 907D037B15B86F8700575110 /* libosgdb_serializers_osgterrain.a in Frameworks */,
+ 907D037C15B86F8700575110 /* libosgdb_serializers_osgtext.a in Frameworks */,
+ 907D037D15B86F8700575110 /* libosgdb_serializers_osgvolume.a in Frameworks */,
+ 907D037F15B86F8700575110 /* libosgdb_stl.a in Frameworks */,
+ 907D038015B86F8700575110 /* libosgdb_tga.a in Frameworks */,
+ 907D038115B86F8700575110 /* libosgdb_tgz.a in Frameworks */,
+ 907D038215B86F8700575110 /* libosgdb_trans.a in Frameworks */,
+ 907D038315B86F8700575110 /* libosgdb_txf.a in Frameworks */,
+ 907D038415B86F8700575110 /* libosgdb_txp.a in Frameworks */,
+ 907D038515B86F8700575110 /* libosgdb_vtf.a in Frameworks */,
+ 907D038615B86F8700575110 /* libosgdb_x.a in Frameworks */,
+ 907D038715B86F8700575110 /* libosgdb_zip.a in Frameworks */,
+ 907D038815B86F8700575110 /* libosgDB.a in Frameworks */,
+ 907D038915B86F8700575110 /* libosgFX.a in Frameworks */,
+ 907D038A15B86F8700575110 /* libosgGA.a in Frameworks */,
+ 907D038B15B86F8700575110 /* libosgManipulator.a in Frameworks */,
+ 907D038C15B86F8700575110 /* libosgParticle.a in Frameworks */,
+ 907D038D15B86F8700575110 /* libosgPresentation.a in Frameworks */,
+ 907D038E15B86F8700575110 /* libosgShadow.a in Frameworks */,
+ 907D038F15B86F8700575110 /* libosgSim.a in Frameworks */,
+ 907D039015B86F8700575110 /* libosgTerrain.a in Frameworks */,
+ 907D039115B86F8700575110 /* libosgText.a in Frameworks */,
+ 907D039215B86F8700575110 /* libosgUtil.a in Frameworks */,
+ 907D039315B86F8700575110 /* libosgViewer.a in Frameworks */,
+ 907D039415B86F8700575110 /* libosgVolume.a in Frameworks */,
+ 907D039515B86F8700575110 /* libosgWidget.a in Frameworks */,
+ 907D03BD15B86F9E00575110 /* libosgdb_kml.a in Frameworks */,
+ 907D03BE15B86F9E00575110 /* libosgdb_osgearth_feature_wfs.a in Frameworks */,
+ 907D03BF15B86F9E00575110 /* libosgdb_osgearth_feature_tfs.a in Frameworks */,
+ 907D03C015B86F9E00575110 /* libosgdb_osgearth_tms.a in Frameworks */,
+ 907D03C115B86F9E00575110 /* libosgdb_osgearth_wms.a in Frameworks */,
+ 907D03C215B86F9E00575110 /* libosgdb_osgearth_label_overlay.a in Frameworks */,
+ 907D03C315B86F9E00575110 /* libosgdb_osgearth_xyz.a in Frameworks */,
+ 907D03C415B86F9E00575110 /* libosgEarthUtil.a in Frameworks */,
+ 907D03C515B86F9E00575110 /* libosgdb_osgearth_label_annotation.a in Frameworks */,
+ 907D03C615B86F9E00575110 /* libosgdb_osgearth_mask_feature.a in Frameworks */,
+ 907D03C715B86F9E00575110 /* libosgdb_osgearth_model_feature_geom.a in Frameworks */,
+ 907D03C815B86F9E00575110 /* libosgEarthAnnotation.a in Frameworks */,
+ 907D03C915B86F9E00575110 /* libosgdb_osgearth_agglite.a in Frameworks */,
+ 907D03CA15B86F9E00575110 /* libosgdb_osgearth_feature_ogr.a in Frameworks */,
+ 907D03CB15B86F9E00575110 /* libosgdb_osgearth_model_feature_stencil.a in Frameworks */,
+ 907D03CC15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm2008.a in Frameworks */,
+ 907D03CD15B86F9E00575110 /* libosgdb_osgearth_model_simple.a in Frameworks */,
+ 907D03CE15B86F9E00575110 /* libosgdb_osgearth_engine_osgterrain.a in Frameworks */,
+ 907D03CF15B86F9E00575110 /* libosgEarthFeatures.a in Frameworks */,
+ 907D03D015B86F9E00575110 /* libosgdb_osgearth_vdatum_egm96.a in Frameworks */,
+ 907D03D115B86F9E00575110 /* libosgdb_osgearth_ocean_surface.a in Frameworks */,
+ 907D03D215B86F9E00575110 /* libosgdb_osgearth_debug.a in Frameworks */,
+ 907D03D315B86F9E00575110 /* libosgdb_osgearth_mbtiles.a in Frameworks */,
+ 907D03D415B86F9E00575110 /* libosgdb_osgearth_vdatum_egm84.a in Frameworks */,
+ 907D03D515B86F9E00575110 /* libosgdb_osgearth_tileservice.a in Frameworks */,
+ 907D03D615B86F9E00575110 /* libosgdb_osgearth_yahoo.a in Frameworks */,
+ 907D03D715B86F9E00575110 /* libosgdb_osgearth_arcgis_map_cache.a in Frameworks */,
+ 907D03D815B86F9E00575110 /* libosgdb_osgearth_tilecache.a in Frameworks */,
+ 907D03D915B86F9E00575110 /* libosgdb_osgearth_wcs.a in Frameworks */,
+ 907D03DA15B86F9E00575110 /* libosgEarthSymbology.a in Frameworks */,
+ 907D03DB15B86F9F00575110 /* libosgdb_osgearth_gdal.a in Frameworks */,
+ 907D03DC15B86F9F00575110 /* libosgdb_osgearth_refresh.a in Frameworks */,
+ 907D03DD15B86F9F00575110 /* libosgdb_osgearth_vpb.a in Frameworks */,
+ 907D03DE15B86F9F00575110 /* libosgdb_earth.a in Frameworks */,
+ 907D03DF15B86F9F00575110 /* libosgdb_osgearth_cache_filesystem.a in Frameworks */,
+ 907D03E015B86F9F00575110 /* libosgdb_osgearth_arcgis.a in Frameworks */,
+ 907D03E115B86F9F00575110 /* libosgdb_osgearth_osg.a in Frameworks */,
+ 907D03E215B86F9F00575110 /* libosgEarth.a in Frameworks */,
+ 907D0A8E15B8CEBE00575110 /* libGEOS_3.2.a in Frameworks */,
+ 90283E5D15C7091A00620EEF /* libosgdb_osgearth_engine_quadtree.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 9051000815B1EDFD00D9ABD3 /* osgEarthViewerIOS */ = {
+ isa = PBXGroup;
+ children = (
+ 90B8676915C8895100F5CDC3 /* StartView */,
+ 908C793D15BB0B4E001CFA5E /* MultiTouchManipulator */,
+ 907D0A9215B8DDAF00575110 /* ShaderGen */,
+ 905100C615B20B1D00D9ABD3 /* osgPlugins.h */,
+ 9051001115B1EDFD00D9ABD3 /* AppDelegate.h */,
+ 9051001215B1EDFD00D9ABD3 /* AppDelegate.m */,
+ 9051001815B1EDFD00D9ABD3 /* ViewController.h */,
+ 9051001915B1EDFD00D9ABD3 /* ViewController.m */,
+ 9051001B15B1EDFD00D9ABD3 /* ViewController_iPhone.xib */,
+ 9051001E15B1EDFD00D9ABD3 /* ViewController_iPad.xib */,
+ 9051000915B1EDFD00D9ABD3 /* Supporting Files */,
+ );
+ path = osgEarthViewerIOS;
+ sourceTree = "<group>";
+ };
+ 9051000915B1EDFD00D9ABD3 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 9051000A15B1EDFD00D9ABD3 /* osgEarthViewerIOS-Info.plist */,
+ 9051000B15B1EDFD00D9ABD3 /* InfoPlist.strings */,
+ 9051000E15B1EDFD00D9ABD3 /* main.m */,
+ 9051001015B1EDFD00D9ABD3 /* osgEarthViewerIOS-Prefix.pch */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 905100D215B21FFD00D9ABD3 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 90DABDDB15CEFF9700D0F609 /* moon_1024x512.jpg */,
+ 90283E5415C6FB3E00620EEF /* tests */,
+ 90283E5515C6FB3E00620EEF /* data */,
+ );
+ name = Resources;
+ path = osgEarthViewerIOS;
+ sourceTree = "<group>";
+ };
+ 9051FFEF15B1EDFD00D9ABD3 = {
+ isa = PBXGroup;
+ children = (
+ 9051000815B1EDFD00D9ABD3 /* osgEarthViewerIOS */,
+ 905100D215B21FFD00D9ABD3 /* Resources */,
+ 90A0DD7715B7BBAB004FACEE /* Libs */,
+ 9051FFFB15B1EDFD00D9ABD3 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 9051FFFB15B1EDFD00D9ABD3 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 9051FFFA15B1EDFD00D9ABD3 /* osgEarth.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 9051FFFD15B1EDFD00D9ABD3 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 905100CA15B2101E00D9ABD3 /* QuartzCore.framework */,
+ 905100C415B20AD100D9ABD3 /* CoreImage.framework */,
+ 905100C215B20AC600D9ABD3 /* ImageIO.framework */,
+ 9051FFFE15B1EDFD00D9ABD3 /* UIKit.framework */,
+ 9051000015B1EDFD00D9ABD3 /* Foundation.framework */,
+ 9051000215B1EDFD00D9ABD3 /* CoreGraphics.framework */,
+ 9051000615B1EDFD00D9ABD3 /* OpenGLES.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 907D02DB15B86F7100575110 /* osg */ = {
+ isa = PBXGroup;
+ children = (
+ 907D02DC15B86F8700575110 /* libOpenThreads.a */,
+ 907D02DD15B86F8700575110 /* libosg.a */,
+ 907D02DE15B86F8700575110 /* libosgAnimation.a */,
+ 907D02DF15B86F8700575110 /* libosgdb_3dc.a */,
+ 907D02E015B86F8700575110 /* libosgdb_3ds.a */,
+ 907D02E115B86F8700575110 /* libosgdb_ac.a */,
+ 907D02E215B86F8700575110 /* libosgdb_bmp.a */,
+ 907D02E315B86F8700575110 /* libosgdb_bsp.a */,
+ 907D02E415B86F8700575110 /* libosgdb_bvh.a */,
+ 907D02E515B86F8700575110 /* libosgdb_cfg.a */,
+ 907D02E615B86F8700575110 /* libosgdb_curl.a */,
+ 907D02E715B86F8700575110 /* libosgdb_dds.a */,
+ 9048FB2315FA9DE50012C900 /* libosgdb_tiff.a */,
+ 907D02E815B86F8700575110 /* libosgdb_deprecated_osg.a */,
+ 907D02E915B86F8700575110 /* libosgdb_deprecated_osganimation.a */,
+ 907D02EA15B86F8700575110 /* libosgdb_deprecated_osgfx.a */,
+ 907D02EB15B86F8700575110 /* libosgdb_deprecated_osgparticle.a */,
+ 907D02EC15B86F8700575110 /* libosgdb_deprecated_osgshadow.a */,
+ 907D02ED15B86F8700575110 /* libosgdb_deprecated_osgsim.a */,
+ 907D02EE15B86F8700575110 /* libosgdb_deprecated_osgterrain.a */,
+ 907D02EF15B86F8700575110 /* libosgdb_deprecated_osgtext.a */,
+ 907D02F015B86F8700575110 /* libosgdb_deprecated_osgviewer.a */,
+ 907D02F115B86F8700575110 /* libosgdb_deprecated_osgvolume.a */,
+ 907D02F215B86F8700575110 /* libosgdb_deprecated_osgwidget.a */,
+ 907D02F315B86F8700575110 /* libosgdb_dot.a */,
+ 907D02F415B86F8700575110 /* libosgdb_dw.a */,
+ 907D02F515B86F8700575110 /* libosgdb_dxf.a */,
+ 907D02F615B86F8700575110 /* libosgdb_freetype.a */,
+ 907D02F715B86F8700575110 /* libosgdb_gdal.a */,
+ 907D02F815B86F8700575110 /* libosgdb_geo.a */,
+ 907D02F915B86F8700575110 /* libosgdb_glsl.a */,
+ 907D02FA15B86F8700575110 /* libosgdb_gz.a */,
+ 907D02FB15B86F8700575110 /* libosgdb_hdr.a */,
+ 907D02FC15B86F8700575110 /* libosgdb_imageio.a */,
+ 907D02FD15B86F8700575110 /* libosgdb_ive.a */,
+ 907D02FE15B86F8700575110 /* libosgdb_logo.a */,
+ 907D02FF15B86F8700575110 /* libosgdb_lwo.a */,
+ 907D030015B86F8700575110 /* libosgdb_lws.a */,
+ 907D030115B86F8700575110 /* libosgdb_md2.a */,
+ 907D030215B86F8700575110 /* libosgdb_mdl.a */,
+ 907D030315B86F8700575110 /* libosgdb_normals.a */,
+ 907D030415B86F8700575110 /* libosgdb_obj.a */,
+ 907D030515B86F8700575110 /* libosgdb_ogr.a */,
+ 907D030615B86F8700575110 /* libosgdb_openflight.a */,
+ 907D030715B86F8700575110 /* libosgdb_osg.a */,
+ 907D030815B86F8700575110 /* libosgdb_osga.a */,
+ 907D030915B86F8700575110 /* libosgdb_osgshadow.a */,
+ 907D030A15B86F8700575110 /* libosgdb_osgterrain.a */,
+ 907D030B15B86F8700575110 /* libosgdb_osgtgz.a */,
+ 907D030C15B86F8700575110 /* libosgdb_osgviewer.a */,
+ 907D030D15B86F8700575110 /* libosgdb_p3d.a */,
+ 907D030E15B86F8700575110 /* libosgdb_pic.a */,
+ 907D030F15B86F8700575110 /* libosgdb_ply.a */,
+ 907D031015B86F8700575110 /* libosgdb_pnm.a */,
+ 907D031115B86F8700575110 /* libosgdb_pov.a */,
+ 907D031215B86F8700575110 /* libosgdb_pvr.a */,
+ 907D031315B86F8700575110 /* libosgdb_revisions.a */,
+ 907D031415B86F8700575110 /* libosgdb_rgb.a */,
+ 907D031515B86F8700575110 /* libosgdb_rot.a */,
+ 907D031615B86F8700575110 /* libosgdb_scale.a */,
+ 907D031715B86F8700575110 /* libosgdb_serializers_osg.a */,
+ 907D031815B86F8700575110 /* libosgdb_serializers_osganimation.a */,
+ 907D031915B86F8700575110 /* libosgdb_serializers_osgfx.a */,
+ 907D031A15B86F8700575110 /* libosgdb_serializers_osgmanipulator.a */,
+ 907D031B15B86F8700575110 /* libosgdb_serializers_osgparticle.a */,
+ 907D031C15B86F8700575110 /* libosgdb_serializers_osgshadow.a */,
+ 907D031D15B86F8700575110 /* libosgdb_serializers_osgsim.a */,
+ 907D031E15B86F8700575110 /* libosgdb_serializers_osgterrain.a */,
+ 907D031F15B86F8700575110 /* libosgdb_serializers_osgtext.a */,
+ 907D032015B86F8700575110 /* libosgdb_serializers_osgvolume.a */,
+ 907D032115B86F8700575110 /* libosgdb_shp.a */,
+ 907D032215B86F8700575110 /* libosgdb_stl.a */,
+ 907D032315B86F8700575110 /* libosgdb_tga.a */,
+ 907D032415B86F8700575110 /* libosgdb_tgz.a */,
+ 907D032515B86F8700575110 /* libosgdb_trans.a */,
+ 907D032615B86F8700575110 /* libosgdb_txf.a */,
+ 907D032715B86F8700575110 /* libosgdb_txp.a */,
+ 907D032815B86F8700575110 /* libosgdb_vtf.a */,
+ 907D032915B86F8700575110 /* libosgdb_x.a */,
+ 907D032A15B86F8700575110 /* libosgdb_zip.a */,
+ 907D032B15B86F8700575110 /* libosgDB.a */,
+ 907D032C15B86F8700575110 /* libosgFX.a */,
+ 907D032D15B86F8700575110 /* libosgGA.a */,
+ 907D032E15B86F8700575110 /* libosgManipulator.a */,
+ 907D032F15B86F8700575110 /* libosgParticle.a */,
+ 907D033015B86F8700575110 /* libosgPresentation.a */,
+ 907D033115B86F8700575110 /* libosgShadow.a */,
+ 907D033215B86F8700575110 /* libosgSim.a */,
+ 907D033315B86F8700575110 /* libosgTerrain.a */,
+ 907D033415B86F8700575110 /* libosgText.a */,
+ 907D033515B86F8700575110 /* libosgUtil.a */,
+ 907D033615B86F8700575110 /* libosgViewer.a */,
+ 907D033715B86F8700575110 /* libosgVolume.a */,
+ 907D033815B86F8700575110 /* libosgWidget.a */,
+ );
+ name = osg;
+ sourceTree = "<group>";
+ };
+ 907D039615B86F8C00575110 /* osgEarth */ = {
+ isa = PBXGroup;
+ children = (
+ 907D039715B86F9E00575110 /* libosgdb_kml.a */,
+ 907D039815B86F9E00575110 /* libosgdb_osgearth_feature_wfs.a */,
+ 907D039915B86F9E00575110 /* libosgdb_osgearth_feature_tfs.a */,
+ 907D039A15B86F9E00575110 /* libosgdb_osgearth_tms.a */,
+ 907D039B15B86F9E00575110 /* libosgdb_osgearth_wms.a */,
+ 907D039C15B86F9E00575110 /* libosgdb_osgearth_label_overlay.a */,
+ 907D039D15B86F9E00575110 /* libosgdb_osgearth_xyz.a */,
+ 907D039E15B86F9E00575110 /* libosgEarthUtil.a */,
+ 907D039F15B86F9E00575110 /* libosgdb_osgearth_label_annotation.a */,
+ 907D03A015B86F9E00575110 /* libosgdb_osgearth_mask_feature.a */,
+ 907D03A115B86F9E00575110 /* libosgdb_osgearth_model_feature_geom.a */,
+ 907D03A215B86F9E00575110 /* libosgEarthAnnotation.a */,
+ 907D03A315B86F9E00575110 /* libosgdb_osgearth_agglite.a */,
+ 907D03A415B86F9E00575110 /* libosgdb_osgearth_feature_ogr.a */,
+ 907D03A515B86F9E00575110 /* libosgdb_osgearth_model_feature_stencil.a */,
+ 907D03A615B86F9E00575110 /* libosgdb_osgearth_vdatum_egm2008.a */,
+ 907D03A715B86F9E00575110 /* libosgdb_osgearth_model_simple.a */,
+ 907D03A815B86F9E00575110 /* libosgdb_osgearth_engine_osgterrain.a */,
+ 90283E5C15C7091A00620EEF /* libosgdb_osgearth_engine_quadtree.a */,
+ 907D03A915B86F9E00575110 /* libosgEarthFeatures.a */,
+ 907D03AA15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm96.a */,
+ 907D03AB15B86F9E00575110 /* libosgdb_osgearth_ocean_surface.a */,
+ 907D03AC15B86F9E00575110 /* libosgdb_osgearth_debug.a */,
+ 907D03AD15B86F9E00575110 /* libosgdb_osgearth_mbtiles.a */,
+ 907D03AE15B86F9E00575110 /* libosgdb_osgearth_vdatum_egm84.a */,
+ 907D03AF15B86F9E00575110 /* libosgdb_osgearth_tileservice.a */,
+ 907D03B015B86F9E00575110 /* libosgdb_osgearth_yahoo.a */,
+ 907D03B115B86F9E00575110 /* libosgdb_osgearth_arcgis_map_cache.a */,
+ 907D03B215B86F9E00575110 /* libosgdb_osgearth_tilecache.a */,
+ 907D03B315B86F9E00575110 /* libosgdb_osgearth_wcs.a */,
+ 907D03B415B86F9E00575110 /* libosgEarthSymbology.a */,
+ 907D03B515B86F9E00575110 /* libosgdb_osgearth_gdal.a */,
+ 907D03B615B86F9E00575110 /* libosgdb_osgearth_refresh.a */,
+ 907D03B715B86F9E00575110 /* libosgdb_osgearth_vpb.a */,
+ 907D03B815B86F9E00575110 /* libosgdb_earth.a */,
+ 907D03B915B86F9E00575110 /* libosgdb_osgearth_cache_filesystem.a */,
+ 907D03BA15B86F9E00575110 /* libosgdb_osgearth_arcgis.a */,
+ 907D03BB15B86F9E00575110 /* libosgdb_osgearth_osg.a */,
+ 907D03BC15B86F9E00575110 /* libosgEarth.a */,
+ );
+ name = osgEarth;
+ sourceTree = "<group>";
+ };
+ 907D0A9215B8DDAF00575110 /* ShaderGen */ = {
+ isa = PBXGroup;
+ children = (
+ 907D0A8F15B8DDAA00575110 /* GLES2ShaderGenVisitor.cpp */,
+ 907D0A9015B8DDAA00575110 /* GLES2ShaderGenVisitor.h */,
+ );
+ name = ShaderGen;
+ sourceTree = "<group>";
+ };
+ 908C793D15BB0B4E001CFA5E /* MultiTouchManipulator */ = {
+ isa = PBXGroup;
+ children = (
+ 903B45D915C0DE9F00F7702B /* EarthMultiTouchManipulator.cpp */,
+ 903B45DA15C0DE9F00F7702B /* EarthMultiTouchManipulator.h */,
+ );
+ path = MultiTouchManipulator;
+ sourceTree = "<group>";
+ };
+ 90A0DD7215B7BB68004FACEE /* gdal */ = {
+ isa = PBXGroup;
+ children = (
+ 90A0DD7015B7BB64004FACEE /* libgdal.a */,
+ );
+ name = gdal;
+ path = "../../../../3rdParty/gdal-ios-device/lib";
+ sourceTree = "<group>";
+ };
+ 90A0DD7315B7BB72004FACEE /* freetype */ = {
+ isa = PBXGroup;
+ children = (
+ 90A0DD6C15B7BAF9004FACEE /* libFreeType_iphone_universal.a */,
+ );
+ name = freetype;
+ path = "../../../../3rdParty/freetype-ios-universal/lib";
+ sourceTree = "<group>";
+ };
+ 90A0DD7415B7BB7C004FACEE /* proj4 */ = {
+ isa = PBXGroup;
+ children = (
+ 90A0DD6E15B7BB50004FACEE /* libproj.a */,
+ );
+ name = proj4;
+ path = "../../../../3rdParty/proj4-ios-device/lib";
+ sourceTree = "<group>";
+ };
+ 90A0DD7715B7BBAB004FACEE /* Libs */ = {
+ isa = PBXGroup;
+ children = (
+ 907D0A8D15B8CEBE00575110 /* libGEOS_3.2.a */,
+ 907D039615B86F8C00575110 /* osgEarth */,
+ 907D02DB15B86F7100575110 /* osg */,
+ 90A0DD7815B7BBCE004FACEE /* curl */,
+ 90A0DD7415B7BB7C004FACEE /* proj4 */,
+ 90A0DD7315B7BB72004FACEE /* freetype */,
+ 90A0DD7215B7BB68004FACEE /* gdal */,
+ 905100D015B2185000D9ABD3 /* libiconv.2.4.0.dylib */,
+ 905100CE15B217B500D9ABD3 /* libz.1.1.3.dylib */,
+ 905100CC15B217A800D9ABD3 /* libc++.dylib */,
+ 907D03F915B8C31A00575110 /* libsqlite3.dylib */,
+ 9051FFFD15B1EDFD00D9ABD3 /* Frameworks */,
+ );
+ name = Libs;
+ sourceTree = "<group>";
+ };
+ 90A0DD7815B7BBCE004FACEE /* curl */ = {
+ isa = PBXGroup;
+ children = (
+ 90A0DD7515B7BBA4004FACEE /* libcurl.a */,
+ );
+ name = curl;
+ path = "../../../../3rdParty/curl-ios-device/lib";
+ sourceTree = "<group>";
+ };
+ 90B8676915C8895100F5CDC3 /* StartView */ = {
+ isa = PBXGroup;
+ children = (
+ 90B8676315C8894900F5CDC3 /* StartViewerController.h */,
+ 90B8676415C8894900F5CDC3 /* StartViewerController.m */,
+ 90B8676515C8894900F5CDC3 /* StartViewerController.xib */,
+ );
+ name = StartView;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 9051FFF915B1EDFD00D9ABD3 /* osgEarthViewerIOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 9051002315B1EDFD00D9ABD3 /* Build configuration list for PBXNativeTarget "osgEarthViewerIOS" */;
+ buildPhases = (
+ 9051FFF615B1EDFD00D9ABD3 /* Sources */,
+ 9051FFF715B1EDFD00D9ABD3 /* Frameworks */,
+ 9051FFF815B1EDFD00D9ABD3 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = osgEarthViewerIOS;
+ productName = osgEarthViewerIOS;
+ productReference = 9051FFFA15B1EDFD00D9ABD3 /* osgEarth.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 9051FFF115B1EDFD00D9ABD3 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0430;
+ };
+ buildConfigurationList = 9051FFF415B1EDFD00D9ABD3 /* Build configuration list for PBXProject "osgEarthViewerIOS" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ English,
+ );
+ mainGroup = 9051FFEF15B1EDFD00D9ABD3;
+ productRefGroup = 9051FFFB15B1EDFD00D9ABD3 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 9051FFF915B1EDFD00D9ABD3 /* osgEarthViewerIOS */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 9051FFF815B1EDFD00D9ABD3 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9051000D15B1EDFD00D9ABD3 /* InfoPlist.strings in Resources */,
+ 9051001D15B1EDFD00D9ABD3 /* ViewController_iPhone.xib in Resources */,
+ 9051002015B1EDFD00D9ABD3 /* ViewController_iPad.xib in Resources */,
+ 90283E5615C6FB3E00620EEF /* tests in Resources */,
+ 90283E5715C6FB3E00620EEF /* data in Resources */,
+ 90B8676715C8894900F5CDC3 /* StartViewerController.xib in Resources */,
+ 90DABDDC15CEFF9700D0F609 /* moon_1024x512.jpg in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 9051FFF615B1EDFD00D9ABD3 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 9051000F15B1EDFD00D9ABD3 /* main.m in Sources */,
+ 9051001315B1EDFD00D9ABD3 /* AppDelegate.m in Sources */,
+ 9051001A15B1EDFD00D9ABD3 /* ViewController.m in Sources */,
+ 907D0A9115B8DDAA00575110 /* GLES2ShaderGenVisitor.cpp in Sources */,
+ 903B45DB15C0DE9F00F7702B /* EarthMultiTouchManipulator.cpp in Sources */,
+ 90B8676615C8894900F5CDC3 /* StartViewerController.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 9051000B15B1EDFD00D9ABD3 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 9051000C15B1EDFD00D9ABD3 /* en */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+ 9051001B15B1EDFD00D9ABD3 /* ViewController_iPhone.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 9051001C15B1EDFD00D9ABD3 /* en */,
+ );
+ name = ViewController_iPhone.xib;
+ sourceTree = "<group>";
+ };
+ 9051001E15B1EDFD00D9ABD3 /* ViewController_iPad.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 9051001F15B1EDFD00D9ABD3 /* en */,
+ );
+ name = ViewController_iPad.xib;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 9051002115B1EDFD00D9ABD3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 9051002215B1EDFD00D9ABD3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.1;
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 9051002415B1EDFD00D9ABD3 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Thomas Hogarth (35UD7TG27V)";
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "osgEarthViewerIOS/osgEarthViewerIOS-Prefix.pch";
+ "GCC_THUMB_SUPPORT[arch=armv6]" = "";
+ HEADER_SEARCH_PATHS = (
+ /Users/hogbox/Documents/AlphaPixel/osgEarthPort/osgearth/src,
+ "/Users/hogbox/Documents/AlphaPixel/osgEarthPort/osg-ios-gles2/include",
+ );
+ INFOPLIST_FILE = "osgEarthViewerIOS/osgEarthViewerIOS-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SRCROOT)/../../../../osg-ios-gles2/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/freetype-ios-universal/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/proj4-ios-device/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/gdal-ios-device/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/curl-ios-device/lib\"",
+ "\"$(SRCROOT)/../../../lib/Release\"",
+ "\"$(SRCROOT)/../../../../3rdParty/geos-ios-device/lib\"",
+ );
+ PRODUCT_NAME = osgEarth;
+ "PROVISIONING_PROFILE[sdk=iphoneos*]" = "C5A8E349-91DB-4E98-9612-789DB499534E";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 9051002515B1EDFD00D9ABD3 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Thomas Hogarth (35UD7TG27V)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "osgEarthViewerIOS/osgEarthViewerIOS-Prefix.pch";
+ "GCC_THUMB_SUPPORT[arch=armv6]" = "";
+ HEADER_SEARCH_PATHS = (
+ /Users/hogbox/Documents/AlphaPixel/osgEarthPort/osgearth/src,
+ "/Users/hogbox/Documents/AlphaPixel/osgEarthPort/osg-ios-gles2/include",
+ );
+ INFOPLIST_FILE = "osgEarthViewerIOS/osgEarthViewerIOS-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 4.3;
+ LIBRARY_SEARCH_PATHS = (
+ "\"$(SRCROOT)/../../../../osg-ios-gles2/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/freetype-ios-universal/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/proj4-ios-device/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/gdal-ios-device/lib\"",
+ "\"$(SRCROOT)/../../../../3rdParty/curl-ios-device/lib\"",
+ "\"$(SRCROOT)/../../../lib/Release\"",
+ "\"$(SRCROOT)/../../../../3rdParty/geos-ios-device/lib\"",
+ );
+ PRODUCT_NAME = osgEarth;
+ "PROVISIONING_PROFILE[sdk=iphoneos*]" = "C5A8E349-91DB-4E98-9612-789DB499534E";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 9051002315B1EDFD00D9ABD3 /* Build configuration list for PBXNativeTarget "osgEarthViewerIOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9051002415B1EDFD00D9ABD3 /* Debug */,
+ 9051002515B1EDFD00D9ABD3 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 9051FFF415B1EDFD00D9ABD3 /* Build configuration list for PBXProject "osgEarthViewerIOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 9051002115B1EDFD00D9ABD3 /* Debug */,
+ 9051002215B1EDFD00D9ABD3 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 9051FFF115B1EDFD00D9ABD3 /* Project object */;
+}
diff --git a/src/applications/osgearth_viewerIOS/osgEarthViewerIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..0901c6b
--- /dev/null
+++ b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:osgEarthViewerIOS.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/ViewController.m b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/ViewController.m
index fe08880..a30011f 100644
--- a/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/ViewController.m
+++ b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/ViewController.m
@@ -175,8 +175,8 @@ public:
osgEarth::Util::SkyNode* sky = new osgEarth::Util::SkyNode( mapNode->getMap() );
sky->setAmbientBrightness( ambientBrightness );
sky->setDateTime( 1984, 11, 8, hours );
- sky->attach( _viewer, 0 );
- root->addChild( sky );
+ //sky->attach( _viewer, 0 );
+ //root->addChild( sky );
//for some reason we have to do this as global stateset doesn't
@@ -185,7 +185,7 @@ public:
//add model
- unsigned int numObjects = 2;
+ /*unsigned int numObjects = 2;
osg::Group* treeGroup = new osg::Group();
root->addChild(treeGroup);
osg::Node* tree = osgDB::readNodeFile("./data/boxman.osg");
@@ -212,16 +212,16 @@ public:
locator->addChild( mt );
treeGroup->addChild( locator );
mapNode->getTerrain()->addTerrainCallback( new ClampObjectLocatorCallback(locator) );
- }
+ }*/
//manip->setHomeViewpoint(Viewpoint( "Mt Rainier", osg::Vec3d( centerLon, centerLat, 0.0 ), 0.0, -90, 45000 ));
//attach a UpdateLightingUniformsHelper to the model
UpdateLightingUniformsHelper* updateLightInfo = new UpdateLightingUniformsHelper();
- treeGroup->setCullCallback(updateLightInfo);
+ //treeGroup->setCullCallback(updateLightInfo);
osgUtil::GLES2ShaderGenVisitor shaderGen;
- treeGroup->accept(shaderGen);
+ //treeGroup->accept(shaderGen);
_viewer->setSceneData( root );
}
@@ -250,10 +250,6 @@ public:
//create the viewer
_viewer = new osgViewer::Viewer();
- //_viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
- _viewer->getDatabasePager()->setTargetMaximumNumberOfPageLOD(0);
- _viewer->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true,true);
-
// Setup the traits parameters
traits->x = 0;
traits->y = 0;
@@ -263,7 +259,7 @@ public:
traits->alpha = 8;
//traits->samples = 4;
//traits->sampleBuffers = 2;
- //traits->stencil = 1;
+ traits->stencil = 1;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;
@@ -281,8 +277,9 @@ public:
}
_viewer->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
- _viewer->getCamera()->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ _viewer->getCamera()->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
_viewer->getCamera()->setClearColor(osg::Vec4(1.0f,0.0f,0.0f,0.0f));
+ _viewer->getCamera()->setClearStencil(0);
_viewer->getCamera()->setProjectionMatrixAsPerspective(45.0f,(float)w/h,
0.1f, 10000.0f);
@@ -293,9 +290,15 @@ public:
// configure the near/far so we don't clip things that are up close
_viewer->getCamera()->setNearFarRatio(0.00002);
+ //optimize viewer and db pager
+ _viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
+ _viewer->getCamera()->setLODScale(_viewer->getCamera()->getLODScale()/2.0);
+
// osgEarth benefits from pre-compilation of GL objects in the pager. In newer versions of
// OSG, this activates OSG's IncrementalCompileOpeartion in order to avoid frame breaks.
_viewer->getDatabasePager()->setDoPreCompile( true );
+ _viewer->getDatabasePager()->setTargetMaximumNumberOfPageLOD(0);
+ _viewer->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true,true);
_isAnimating=false;
diff --git a/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/osgPlugins.h b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/osgPlugins.h
index 486ab1a..5329526 100755
--- a/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/osgPlugins.h
+++ b/src/applications/osgearth_viewerIOS/osgEarthViewerIOS/osgPlugins.h
@@ -17,6 +17,7 @@ USE_GRAPICSWINDOW_IMPLEMENTATION(IOS)
USE_OSGPLUGIN(OpenFlight)
USE_OSGPLUGIN(obj)
+USE_OSGPLUGIN(shp)
USE_OSGPLUGIN(ive)
//depreceated osg format
diff --git a/src/osgEarth/CMakeLists.txt b/src/osgEarth/CMakeLists.txt
index 25e0e0c..2175736 100644
--- a/src/osgEarth/CMakeLists.txt
+++ b/src/osgEarth/CMakeLists.txt
@@ -7,6 +7,8 @@ ENDIF(DYNAMIC_OSGEARTH)
OPTION(CURL_IS_STATIC "on if curl is a static lib " ON)
MARK_AS_ADVANCED(CURL_IS_STATIC)
+ADD_DEFINITIONS(-DTIXML_USE_STL)
+
IF(WIN32)
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
IF(CURL_IS_STATIC)
@@ -61,6 +63,10 @@ SET(LIB_PUBLIC_HEADERS
Locators
LocalTangentPlane
Map
+ MapCallback
+ MapFrame
+ MapInfo
+ MapModelChange
MapNode
MapNodeObserver
MapNodeOptions
@@ -81,7 +87,7 @@ SET(LIB_PUBLIC_HEADERS
Random
Registry
Revisioning
- ShaderComposition
+ ShaderFactory
ShaderGenerator
ShaderUtils
SparseTexture2DArray
@@ -105,6 +111,7 @@ SET(LIB_PUBLIC_HEADERS
Version
VerticalDatum
Viewpoint
+ VirtualProgram
XmlUtils
)
@@ -165,6 +172,9 @@ ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
Locators.cpp
LocalTangentPlane.cpp
Map.cpp
+ MapCallback.cpp
+ MapFrame.cpp
+ MapInfo.cpp
MapNode.cpp
MapNodeOptions.cpp
MapOptions.cpp
@@ -184,7 +194,7 @@ ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
Random.cpp
Registry.cpp
Revisioning.cpp
- ShaderComposition.cpp
+ ShaderFactory.cpp
ShaderGenerator.cpp
ShaderUtils.cpp
SparseTexture2DArray.cpp
@@ -208,6 +218,7 @@ ADD_LIBRARY(${LIB_NAME} ${OSGEARTH_USER_DEFINED_DYNAMIC_OR_STATIC}
Version.cpp
VerticalDatum.cpp
Viewpoint.cpp
+ VirtualProgram.cpp
XmlUtils.cpp
)
diff --git a/src/osgEarth/Cache.cpp b/src/osgEarth/Cache.cpp
index 06c26b2..d96a8bf 100644
--- a/src/osgEarth/Cache.cpp
+++ b/src/osgEarth/Cache.cpp
@@ -69,7 +69,7 @@ Cache*
CacheFactory::create( const CacheOptions& options )
{
osg::ref_ptr<Cache> result =0L;
- OE_INFO << LC << "Initializing cache of type \"" << options.getDriver() << "\"" << std::endl;
+ OE_DEBUG << LC << "Initializing cache of type \"" << options.getDriver() << "\"" << std::endl;
if ( options.getDriver().empty() )
{
diff --git a/src/osgEarth/CacheSeed.cpp b/src/osgEarth/CacheSeed.cpp
index b3d2759..4cfeb9b 100644
--- a/src/osgEarth/CacheSeed.cpp
+++ b/src/osgEarth/CacheSeed.cpp
@@ -18,6 +18,7 @@
*/
#include <osgEarth/CacheSeed>
+#include <osgEarth/MapFrame>
#include <OpenThreads/ScopedLock>
#include <limits.h>
@@ -27,12 +28,12 @@ using namespace osgEarth;
using namespace OpenThreads;
CacheSeed::CacheSeed():
- _minLevel(0),
- _maxLevel(12),
- _total(0),
- _completed(0)
- {
- }
+_minLevel (0),
+_maxLevel (12),
+_total (0),
+_completed(0)
+{
+}
void CacheSeed::seed( Map* map )
{
@@ -60,7 +61,7 @@ void CacheSeed::seed( Map* map )
//Assumes the the TileSource will perform the caching for us when we call createImage
for( ImageLayerVector::const_iterator i = mapf.imageLayers().begin(); i != mapf.imageLayers().end(); i++ )
{
- ImageLayer* layer = i->get();
+ ImageLayer* layer = i->get();
TileSource* src = layer->getTileSource();
const ImageLayerOptions& opt = layer->getImageLayerOptions();
@@ -85,16 +86,16 @@ void CacheSeed::seed( Map* map )
{
hasCaches = true;
- if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
+ if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
src_min_level = opt.minLevel().get();
- if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
+ if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
src_max_level = opt.maxLevel().get();
}
}
for( ElevationLayerVector::const_iterator i = mapf.elevationLayers().begin(); i != mapf.elevationLayers().end(); i++ )
{
- ElevationLayer* layer = i->get();
+ ElevationLayer* layer = i->get();
TileSource* src = layer->getTileSource();
const ElevationLayerOptions& opt = layer->getElevationLayerOptions();
@@ -118,11 +119,11 @@ void CacheSeed::seed( Map* map )
{
hasCaches = true;
- if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
+ if (opt.minLevel().isSet() && (int)opt.minLevel().get() < src_min_level)
src_min_level = opt.minLevel().get();
- if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
+ if (opt.maxLevel().isSet() && opt.maxLevel().get() > src_max_level)
src_max_level = opt.maxLevel().get();
- }
+ }
}
if ( !hasCaches )
@@ -267,7 +268,7 @@ void CacheSeed::seed( Map* map )
_total = _completed;
- if ( _progress.valid()) _progress->reportProgress(_completed, _total, "Finished");
+ if ( _progress.valid()) _progress->reportProgress(_completed, _total, 0, 1, "Finished");
}
void CacheSeed::incrementCompleted( unsigned int total ) const
@@ -293,8 +294,8 @@ CacheSeed::processKey(const MapFrame& mapf, const TileKey& key ) const
incrementCompleted( 1 );
}
- if ( _progress.valid() && _progress->isCanceled() )
- return; // Task has been cancelled by user
+ if ( _progress.valid() && _progress->isCanceled() )
+ return; // Task has been cancelled by user
if ( _progress.valid() && gotData && _progress->reportProgress(_completed, _total, std::string("Cached tile: ") + key.str()) )
return; // Canceled
diff --git a/src/osgEarth/Capabilities.cpp b/src/osgEarth/Capabilities.cpp
index fe42b5d..8e331fb 100644
--- a/src/osgEarth/Capabilities.cpp
+++ b/src/osgEarth/Capabilities.cpp
@@ -189,7 +189,11 @@ _maxUniformBlockSize ( 0 )
#endif
OE_INFO << LC << " Max lights = " << _maxLights << std::endl;
- _supportsGLSL = GL2->isGlslSupported();
+
+ if ( ::getenv("OSGEARTH_NO_GLSL") )
+ _supportsGLSL = false;
+ else
+ _supportsGLSL = GL2->isGlslSupported();
OE_INFO << LC << " GLSL = " << SAYBOOL(_supportsGLSL) << std::endl;
if ( _supportsGLSL )
@@ -219,7 +223,8 @@ _maxUniformBlockSize ( 0 )
_supportsTwoSidedStencil = osg::isGLExtensionSupported( id, "GL_EXT_stencil_two_side" );
OE_INFO << LC << " 2-sided stencils = " << SAYBOOL(_supportsTwoSidedStencil) << std::endl;
- _supportsDepthPackedStencilBuffer = osg::isGLExtensionSupported( id, "GL_EXT_packed_depth_stencil" );
+ _supportsDepthPackedStencilBuffer = osg::isGLExtensionSupported( id, "GL_EXT_packed_depth_stencil" ) ||
+ osg::isGLExtensionSupported( id, "GL_OES_packed_depth_stencil" );
OE_INFO << LC << " depth-packed stencil = " << SAYBOOL(_supportsDepthPackedStencilBuffer) << std::endl;
_supportsOcclusionQuery = osg::isGLExtensionSupported( id, "GL_ARB_occlusion_query" );
@@ -228,11 +233,17 @@ _maxUniformBlockSize ( 0 )
_supportsDrawInstanced = osg::isGLExtensionOrVersionSupported( id, "GL_EXT_draw_instanced", 3.1f );
OE_INFO << LC << " draw instanced = " << SAYBOOL(_supportsDrawInstanced) << std::endl;
+ glGetIntegerv( GL_MAX_UNIFORM_BLOCK_SIZE, &_maxUniformBlockSize );
+ OE_INFO << LC << " max uniform block size = " << _maxUniformBlockSize << std::endl;
+
_supportsUniformBufferObjects = osg::isGLExtensionOrVersionSupported( id, "GL_ARB_uniform_buffer_object", 2.0f );
OE_INFO << LC << " uniform buffer objects = " << SAYBOOL(_supportsUniformBufferObjects) << std::endl;
- glGetIntegerv( GL_MAX_UNIFORM_BLOCK_SIZE, &_maxUniformBlockSize );
- OE_INFO << LC << " max uniform block size = " << _maxUniformBlockSize << std::endl;
+ if ( _supportsUniformBufferObjects && _maxUniformBlockSize == 0 )
+ {
+ OE_INFO << LC << " ...but disabled, since UBO block size reports zero" << std::endl;
+ _supportsUniformBufferObjects = false;
+ }
//_supportsTexture2DLod = osg::isGLExtensionSupported( id, "GL_ARB_shader_texture_lod" );
diff --git a/src/osgEarth/CompositeTileSource.cpp b/src/osgEarth/CompositeTileSource.cpp
index 6918b1d..8c7ab12 100644
--- a/src/osgEarth/CompositeTileSource.cpp
+++ b/src/osgEarth/CompositeTileSource.cpp
@@ -302,7 +302,7 @@ CompositeTileSource::createImage(const TileKey& key,
{
//We got an image, but now we need to crop it to match the incoming key's extents
GeoImage geoImage( image.get(), parentKey.getExtent());
- GeoImage cropped = geoImage.crop( key.getExtent(), true, textureSize.x(), textureSize.y());
+ GeoImage cropped = geoImage.crop( key.getExtent(), true, textureSize.x(), textureSize.y(), *source->_options.bilinearReprojection());
image = cropped.getImage();
}
diff --git a/src/osgEarth/Containers b/src/osgEarth/Containers
index d53ec2f..b40b40b 100644
--- a/src/osgEarth/Containers
+++ b/src/osgEarth/Containers
@@ -22,6 +22,7 @@
#include <osgEarth/Common>
#include <osgEarth/ThreadingUtils>
#include <list>
+#include <vector>
namespace osgEarth
{
diff --git a/src/osgEarth/CullingUtils.cpp b/src/osgEarth/CullingUtils.cpp
index f8341c9..a30ec69 100644
--- a/src/osgEarth/CullingUtils.cpp
+++ b/src/osgEarth/CullingUtils.cpp
@@ -591,4 +591,4 @@ void OcclusionCullingCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
traverse( node, nv );
}
-}
\ No newline at end of file
+}
diff --git a/src/osgEarth/DrapeableNode.cpp b/src/osgEarth/DrapeableNode.cpp
index 6dee4fd..1d59d5f 100644
--- a/src/osgEarth/DrapeableNode.cpp
+++ b/src/osgEarth/DrapeableNode.cpp
@@ -30,20 +30,12 @@ using namespace osgEarth;
namespace
{
-#if 0
- // Custom group that limits traversals to CULL and any visitor internal to
- // the operation of the OverlayDecorator.
- struct OverlayTraversalGroup : public osg::Group {
- virtual void traverse(osg::NodeVisitor& nv) {
- if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR ||
- dynamic_cast<OverlayDecorator::InternalNodeVisitor*>(&nv) )
- {
- osg::Group::traverse(nv);
- }
- }
- };
-#endif
-
+ /**
+ * When draping is enabled, the actual draped graph goes under an OverlayProxy
+ * group. It tracks the accumulated stateset and nodemask of the Drapeable
+ * itself and applies it to the draped geometry (which is installed under the
+ * MapNode's OverlayDecorator).
+ */
struct OverlayProxy : public osg::Group
{
OverlayProxy( osg::Node* owner )
@@ -75,7 +67,7 @@ namespace
// first check the owner's traversal mask.
bool visible = true;
- for( int k = 0; visible && k < ownerPath.size(); ++k )
+ for( int k = 0; visible && k < (int)ownerPath.size(); ++k )
{
visible = nv.validNodeMask(*ownerPath[k]);
}
@@ -85,12 +77,12 @@ namespace
// find the intersection point:
int i = findIndexOfNodePathConvergence( visitorPath, ownerPath );
- if ( i >= 0 && i < ownerPath.size()-1 )
+ if ( i >= 0 && i < (int)ownerPath.size()-1 )
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
int pushes = 0;
- for( int k = i+1; k < ownerPath.size(); ++k )
+ for( int k = i+1; k < (int)ownerPath.size(); ++k )
{
osg::Node* node = ownerPath[k];
osg::StateSet* ss = ownerPath[k]->getStateSet();
diff --git a/src/osgEarth/DrawInstanced b/src/osgEarth/DrawInstanced
index e74d3f4..08b60da 100644
--- a/src/osgEarth/DrawInstanced
+++ b/src/osgEarth/DrawInstanced
@@ -21,7 +21,7 @@
#define OSGEARTH_DRAW_INSTANCED_H 1
#include <osgEarth/Common>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osg/NodeVisitor>
#include <osg/Geode>
diff --git a/src/osgEarth/DrawInstanced.cpp b/src/osgEarth/DrawInstanced.cpp
index b51c301..2cf5b9f 100644
--- a/src/osgEarth/DrawInstanced.cpp
+++ b/src/osgEarth/DrawInstanced.cpp
@@ -113,29 +113,28 @@ DrawInstanced::createDrawInstancedProgram()
if ( Registry::capabilities().supportsUniformBufferObjects() )
{
+ // note: no newlines in the layout() line, please
buf << "#extension GL_ARB_uniform_buffer_object : enable\n"
- << "layout(std140) uniform osgearth_InstanceModelData\n"
- << "{\n"
- << "mat4 osgearth_instanceModelMatrix[ " << MAX_COUNT_UBO << "];\n"
- << "};\n";
+ << "layout(std140) uniform oe_di_modelData { "
+ << "mat4 oe_di_modelMatrix[" << MAX_COUNT_UBO << "]; } ;\n";
- vp->getTemplate()->addBindUniformBlock( "osgearth_InstanceModelData", 0 );
+ vp->getTemplate()->addBindUniformBlock( "oe_di_modelData", 0 );
}
else
{
- buf << "uniform mat4 osgearth_instanceModelMatrix[" << MAX_COUNT_ARRAY << "];\n";
+ buf << "uniform mat4 oe_di_modelMatrix[" << MAX_COUNT_ARRAY << "];\n";
}
- buf << "void osgearth_setInstancePosition()\n"
+ buf << "void oe_di_setPosition()\n"
<< "{\n"
- << " gl_Position = gl_ModelViewProjectionMatrix * osgearth_instanceModelMatrix[gl_InstanceID] * gl_Vertex; \n"
+ << " gl_Position = gl_ModelViewProjectionMatrix * oe_di_modelMatrix[gl_InstanceID] * gl_Vertex; \n"
<< "}\n";
std::string src;
src = buf.str();
vp->setFunction(
- "osgearth_setInstancePosition",
+ "oe_di_setPosition",
src,
ShaderComp::LOCATION_VERTEX_PRE_COLORING );
@@ -260,7 +259,7 @@ DrawInstanced::convertGraphToUseDrawInstanced( osg::Group* parent )
{
// assign the matrices to the uniform array:
ArrayUniform uniform(
- "osgearth_instanceModelMatrix",
+ "oe_di_modelMatrix",
osg::Uniform::FLOAT_MAT4,
sliceGroup->getOrCreateStateSet(),
currentSize );
diff --git a/src/osgEarth/ElevationLayer b/src/osgEarth/ElevationLayer
index f2cb239..8cf71fc 100644
--- a/src/osgEarth/ElevationLayer
+++ b/src/osgEarth/ElevationLayer
@@ -21,6 +21,7 @@
#define OSGEARTH_ELEVATION_TERRAIN_LAYER_H 1
#include <osgEarth/TerrainLayer>
+#include <osg/MixinVector>
namespace osgEarth
{
@@ -45,7 +46,7 @@ namespace osgEarth
virtual void mergeConfig( const Config& conf );
private:
- void fromConfig( const Config& conf );
+ void fromConfig( const Config& conf );
void setDefaults();
};
@@ -143,7 +144,26 @@ namespace osgEarth
void init();
};
- typedef std::vector< osg::ref_ptr<ElevationLayer> > ElevationLayerVector;
+
+ /**
+ * Vector of elevation layers, with added methods.
+ */
+ class OSGEARTH_EXPORT ElevationLayerVector : public osg::MixinVector< osg::ref_ptr<ElevationLayer> >
+ {
+ public:
+ /**
+ * Creates a heightfield object by sampling this elevation layer vector.
+ */
+ bool createHeightField(
+ const TileKey& key,
+ bool fallback,
+ const Profile* haeProfile,
+ ElevationInterpolation interpolation,
+ ElevationSamplePolicy samplePolicy,
+ osg::ref_ptr<osg::HeightField>& out_result,
+ bool* out_isFallback,
+ ProgressCallback* progress ) const;
+ };
} // namespace osgEarth
diff --git a/src/osgEarth/ElevationLayer.cpp b/src/osgEarth/ElevationLayer.cpp
index a9dc133..e51dbfb 100644
--- a/src/osgEarth/ElevationLayer.cpp
+++ b/src/osgEarth/ElevationLayer.cpp
@@ -439,3 +439,248 @@ ElevationLayer::createHeightField(const TileKey& key,
GeoHeightField( result, key.getExtent() ) :
GeoHeightField::INVALID;
}
+
+
+//------------------------------------------------------------------------
+
+
+bool
+ElevationLayerVector::createHeightField(const TileKey& key,
+ bool fallback,
+ const Profile* haeProfile,
+ ElevationInterpolation interpolation,
+ ElevationSamplePolicy samplePolicy,
+ osg::ref_ptr<osg::HeightField>& out_result,
+ bool* out_isFallback,
+ ProgressCallback* progress ) const
+{
+ unsigned lowestLOD = key.getLevelOfDetail();
+ bool hfInitialized = false;
+
+ //Get a HeightField for each of the enabled layers
+ GeoHeightFieldVector heightFields;
+
+ //The number of fallback heightfields we have
+ int numFallbacks = 0;
+
+ //Default to being fallback data.
+ if ( out_isFallback )
+ {
+ *out_isFallback = true;
+ }
+
+ // if the caller provided an "HAE map profile", he wants an HAE elevation grid even if
+ // the map profile has a vertical datum. This is the usual case when building the 3D
+ // terrain, for example. Construct a temporary key that doesn't have the vertical
+ // datum info and use that to query the elevation data.
+ TileKey keyToUse = key;
+ if ( haeProfile )
+ {
+ keyToUse = TileKey(key.getLevelOfDetail(), key.getTileX(), key.getTileY(), haeProfile );
+ }
+
+ // Generate a heightfield for each elevation layer.
+
+ unsigned defElevSize = 8;
+
+ for( ElevationLayerVector::const_iterator i = this->begin(); i != this->end(); i++ )
+ {
+ ElevationLayer* layer = i->get();
+ if ( layer->getVisible() )
+ {
+ GeoHeightField geoHF = layer->createHeightField( keyToUse, progress );
+
+ // if "fallback" is set, try to fall back on lower LODs.
+ if ( !geoHF.valid() && fallback )
+ {
+ TileKey hf_key = keyToUse.createParentKey();
+
+ while ( hf_key.valid() && !geoHF.valid() )
+ {
+ geoHF = layer->createHeightField( hf_key, progress );
+ if ( !geoHF.valid() )
+ hf_key = hf_key.createParentKey();
+ }
+
+ if ( geoHF.valid() )
+ {
+ if ( hf_key.getLevelOfDetail() < lowestLOD )
+ lowestLOD = hf_key.getLevelOfDetail();
+
+ //This HeightField is fallback data, so increment the count.
+ numFallbacks++;
+ }
+ }
+
+ if ( geoHF.valid() )
+ {
+ heightFields.push_back( geoHF );
+ }
+ }
+ }
+
+ //If any of the layers produced valid data then it's not considered a fallback
+ if ( out_isFallback )
+ {
+ *out_isFallback = (numFallbacks == heightFields.size());
+ //OE_NOTICE << "Num fallbacks=" << numFallbacks << " numHeightFields=" << heightFields.size() << " is fallback " << *out_isFallback << std::endl;
+ }
+
+ if ( heightFields.size() == 0 )
+ {
+ //If we got no heightfields but were requested to fallback, create an empty heightfield.
+ if ( fallback )
+ {
+ out_result = HeightFieldUtils::createReferenceHeightField( keyToUse.getExtent(), defElevSize, defElevSize );
+ return true;
+ }
+ else
+ {
+ //We weren't requested to fallback so just return.
+ return false;
+ }
+ }
+
+ else if (heightFields.size() == 1)
+ {
+ if ( lowestLOD == key.getLevelOfDetail() )
+ {
+ //If we only have on heightfield, just return it.
+ out_result = heightFields[0].takeHeightField();
+ }
+ else
+ {
+ GeoHeightField geoHF = heightFields[0].createSubSample( key.getExtent(), interpolation);
+ out_result = geoHF.takeHeightField();
+ hfInitialized = true;
+ }
+ }
+
+ else
+ {
+ //If we have multiple heightfields, we need to composite them together.
+ unsigned int width = 0;
+ unsigned int height = 0;
+
+ for (GeoHeightFieldVector::const_iterator i = heightFields.begin(); i < heightFields.end(); ++i)
+ {
+ if (i->getHeightField()->getNumColumns() > width)
+ width = i->getHeightField()->getNumColumns();
+ if (i->getHeightField()->getNumRows() > height)
+ height = i->getHeightField()->getNumRows();
+ }
+ out_result = new osg::HeightField();
+ out_result->allocate( width, height );
+
+ //Go ahead and set up the heightfield so we don't have to worry about it later
+ double minx, miny, maxx, maxy;
+ key.getExtent().getBounds(minx, miny, maxx, maxy);
+ double dx = (maxx - minx)/(double)(out_result->getNumColumns()-1);
+ double dy = (maxy - miny)/(double)(out_result->getNumRows()-1);
+
+ const SpatialReference* keySRS = keyToUse.getProfile()->getSRS();
+
+ //Create the new heightfield by sampling all of them.
+ for (unsigned int c = 0; c < width; ++c)
+ {
+ double x = minx + (dx * (double)c);
+ for (unsigned r = 0; r < height; ++r)
+ {
+ double y = miny + (dy * (double)r);
+
+ //Collect elevations from all of the layers. Iterate BACKWARDS because the last layer
+ // is the highest priority.
+ std::vector<float> elevations;
+ for( GeoHeightFieldVector::reverse_iterator itr = heightFields.rbegin(); itr != heightFields.rend(); ++itr )
+ {
+ const GeoHeightField& geoHF = *itr;
+
+ float elevation = 0.0f;
+ if ( geoHF.getElevation(keySRS, x, y, interpolation, keySRS, elevation) )
+ {
+ if (elevation != NO_DATA_VALUE)
+ {
+ elevations.push_back(elevation);
+ }
+ }
+ }
+
+ float elevation = NO_DATA_VALUE;
+
+ //The list of elevations only contains valid values
+ if (elevations.size() > 0)
+ {
+ if (samplePolicy == SAMPLE_FIRST_VALID)
+ {
+ elevation = elevations[0];
+ }
+ else if (samplePolicy == SAMPLE_HIGHEST)
+ {
+ elevation = -FLT_MAX;
+ for (unsigned int i = 0; i < elevations.size(); ++i)
+ {
+ if (elevation < elevations[i]) elevation = elevations[i];
+ }
+ }
+ else if (samplePolicy == SAMPLE_LOWEST)
+ {
+ elevation = FLT_MAX;
+ for (unsigned i = 0; i < elevations.size(); ++i)
+ {
+ if (elevation > elevations[i]) elevation = elevations[i];
+ }
+ }
+ else if (samplePolicy == SAMPLE_AVERAGE)
+ {
+ elevation = 0.0;
+ for (unsigned i = 0; i < elevations.size(); ++i)
+ {
+ elevation += elevations[i];
+ }
+ elevation /= (float)elevations.size();
+ }
+ }
+ out_result->setHeight(c, r, elevation);
+ }
+ }
+ }
+
+ // Replace any NoData areas with the reference value. This is zero for HAE datums,
+ // and some geoid height for orthometric datums.
+ if (out_result.valid())
+ {
+ const Geoid* geoid = 0L;
+ const VerticalDatum* vdatum = key.getProfile()->getSRS()->getVerticalDatum();
+
+ if ( haeProfile && vdatum )
+ {
+ geoid = vdatum->getGeoid();
+ }
+
+ HeightFieldUtils::resolveInvalidHeights(
+ out_result.get(),
+ key.getExtent(),
+ NO_DATA_VALUE,
+ geoid );
+
+ //ReplaceInvalidDataOperator o;
+ //o.setValidDataOperator(new osgTerrain::NoDataValue(NO_DATA_VALUE));
+ //o( out_result.get() );
+ }
+
+ //Initialize the HF values for osgTerrain
+ if (out_result.valid() && !hfInitialized )
+ {
+ //Go ahead and set up the heightfield so we don't have to worry about it later
+ double minx, miny, maxx, maxy;
+ key.getExtent().getBounds(minx, miny, maxx, maxy);
+ out_result->setOrigin( osg::Vec3d( minx, miny, 0.0 ) );
+ double dx = (maxx - minx)/(double)(out_result->getNumColumns()-1);
+ double dy = (maxy - miny)/(double)(out_result->getNumRows()-1);
+ out_result->setXInterval( dx );
+ out_result->setYInterval( dy );
+ out_result->setBorderWidth( 0 );
+ }
+
+ return out_result.valid();
+}
diff --git a/src/osgEarth/ElevationQuery b/src/osgEarth/ElevationQuery
index 06bc752..c4082d4 100644
--- a/src/osgEarth/ElevationQuery
+++ b/src/osgEarth/ElevationQuery
@@ -19,7 +19,7 @@
#ifndef OSGEARTH_ELEVATION_QUERY_H
#define OSGEARTH_ELEVATION_QUERY_H 1
-#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
#include <osgEarth/Containers>
namespace osgEarth
diff --git a/src/osgEarth/FadeEffect.cpp b/src/osgEarth/FadeEffect.cpp
index 923e0ff..fae0b9e 100644
--- a/src/osgEarth/FadeEffect.cpp
+++ b/src/osgEarth/FadeEffect.cpp
@@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <osgEarth/FadeEffect>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
#include <osgUtil/CullVisitor>
using namespace osgEarth;
@@ -28,24 +30,30 @@ namespace
{
char* FadeEffectVertexShader =
"#version " GLSL_VERSION_STR "\n"
- "uniform float osgearth_FadeEffect_duration; \n"
- "uniform float osgearth_FadeEffect_startTime; \n"
+#ifdef OSG_GLES2_AVAILABLE
+ "precision mediump float; \n"
+#endif
+ "uniform float oe_FadeEffect_duration; \n"
+ "uniform float oe_FadeEffect_startTime; \n"
"uniform float osg_FrameTime; \n"
- "varying float osgearth_FadeEffect_opacity; \n"
+ "varying float oe_FadeEffect_opacity; \n"
- "void vertFadeEffect() \n"
+ "void oe_vertFadeEffect() \n"
"{ \n"
- " float t = (osg_FrameTime-osgearth_FadeEffect_startTime)/osgearth_FadeEffect_duration; \n"
- " osgearth_FadeEffect_opacity = clamp( t, 0.0, 1.0 ); \n"
+ " float t = (osg_FrameTime-oe_FadeEffect_startTime)/oe_FadeEffect_duration; \n"
+ " oe_FadeEffect_opacity = clamp( t, 0.0, 1.0 ); \n"
"} \n";
char* FadeEffectFragmentShader =
"#version " GLSL_VERSION_STR "\n"
- "varying float osgearth_FadeEffect_opacity; \n"
+#ifdef OSG_GLES2_AVAILABLE
+ "precision mediump float; \n"
+#endif
+ "varying float oe_FadeEffect_opacity; \n"
- "void fragFadeEffect( inout vec4 color ) \n"
+ "void oe_fragFadeEffect( inout vec4 color ) \n"
"{ \n"
- " color.a *= osgearth_FadeEffect_opacity; \n"
+ " color.a *= oe_FadeEffect_opacity; \n"
"} \n";
}
@@ -54,21 +62,24 @@ namespace
osg::Uniform*
FadeEffect::createStartTimeUniform()
{
- return new osg::Uniform( osg::Uniform::FLOAT, "osgearth_FadeEffect_startTime" );
+ return new osg::Uniform( osg::Uniform::FLOAT, "oe_FadeEffect_startTime" );
}
FadeEffect::FadeEffect()
{
osg::StateSet* ss = this->getOrCreateStateSet();
- VirtualProgram* vp = new VirtualProgram();
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ VirtualProgram* vp = new VirtualProgram();
- vp->setFunction( "vertFadeEffect", FadeEffectVertexShader, ShaderComp::LOCATION_VERTEX_POST_LIGHTING );
- vp->setFunction( "fragFadeEffect", FadeEffectFragmentShader, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
+ vp->setFunction( "oe_vertFadeEffect", FadeEffectVertexShader, ShaderComp::LOCATION_VERTEX_POST_LIGHTING );
+ vp->setFunction( "oe_fragFadeEffect", FadeEffectFragmentShader, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
- ss->setAttributeAndModes( vp, osg::StateAttribute::ON );
+ ss->setAttributeAndModes( vp, osg::StateAttribute::ON );
+ }
- _fadeDuration = new osg::Uniform( osg::Uniform::FLOAT, "osgearth_FadeEffect_duration" );
+ _fadeDuration = new osg::Uniform( osg::Uniform::FLOAT, "oe_FadeEffect_duration" );
_fadeDuration->set( 1.0f );
ss->addUniform( _fadeDuration );
@@ -95,10 +106,13 @@ namespace
{
char* FadeLODFragmentShader =
"#version " GLSL_VERSION_STR "\n"
- "varying float osgearth_FadeLOD_opacity; \n"
- "void fragFadeLOD( inout vec4 color ) \n"
+#ifdef OSG_GLES_AVAILABLE
+ "precision mediump float; \n"
+#endif
+ "varying float oe_FadeLOD_opacity; \n"
+ "void oe_fragFadeLOD( inout vec4 color ) \n"
"{ \n"
- " color.a *= osgearth_FadeLOD_opacity; \n"
+ " color.a *= oe_FadeLOD_opacity; \n"
"} \n";
}
@@ -113,16 +127,19 @@ _maxPixelExtent( FLT_MAX ),
_minFadeExtent ( 0.0f ),
_maxFadeExtent ( 0.0f )
{
- VirtualProgram* vp = new VirtualProgram();
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ VirtualProgram* vp = new VirtualProgram();
- vp->setFunction(
- "fragFadeLOD",
- FadeLODFragmentShader,
- ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
+ vp->setFunction(
+ "oe_fragFadeLOD",
+ FadeLODFragmentShader,
+ ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
- osg::StateSet* ss = getOrCreateStateSet();
+ osg::StateSet* ss = getOrCreateStateSet();
- ss->setAttributeAndModes( vp, osg::StateAttribute::ON );
+ ss->setAttributeAndModes( vp, osg::StateAttribute::ON );
+ }
}
@@ -135,7 +152,7 @@ FadeLOD::traverse( osg::NodeVisitor& nv )
PerViewData& data = _perViewData.get(cv);
if ( !data._opacity.valid() )
{
- data._opacity = new osg::Uniform(osg::Uniform::FLOAT, "osgearth_FadeLOD_opacity");
+ data._opacity = new osg::Uniform(osg::Uniform::FLOAT, "oe_FadeLOD_opacity");
data._stateSet = new osg::StateSet();
data._stateSet->addUniform( data._opacity.get() );
}
diff --git a/src/osgEarth/GeoData b/src/osgEarth/GeoData
index b1386d2..9d62116 100644
--- a/src/osgEarth/GeoData
+++ b/src/osgEarth/GeoData
@@ -558,7 +558,8 @@ namespace osgEarth
const GeoExtent& extent,
bool exact = false,
unsigned int width = 0,
- unsigned int height = 0) const;
+ unsigned int height = 0,
+ bool useBilinearInterpolation = true) const;
/**
* Warps the image into a new spatial reference system.
@@ -576,7 +577,8 @@ namespace osgEarth
const SpatialReference* to_srs,
const GeoExtent* to_extent = 0,
unsigned int width = 0,
- unsigned int height = 0) const;
+ unsigned int height = 0,
+ bool useBilinearInterpolation = true) const;
/**
* Adds a one-pixel transparent border around an image.
diff --git a/src/osgEarth/GeoData.cpp b/src/osgEarth/GeoData.cpp
index 13b4714..26ef307 100644
--- a/src/osgEarth/GeoData.cpp
+++ b/src/osgEarth/GeoData.cpp
@@ -1193,7 +1193,7 @@ GeoImage::getUnitsPerPixel() const {
}
GeoImage
-GeoImage::crop( const GeoExtent& extent, bool exact, unsigned int width, unsigned int height ) const
+GeoImage::crop( const GeoExtent& extent, bool exact, unsigned int width, unsigned int height, bool useBilinearInterpolation) const
{
//Check for equivalence
if ( extent.getSRS()->isEquivalentTo( getSRS() ) )
@@ -1218,7 +1218,7 @@ GeoImage::crop( const GeoExtent& extent, bool exact, unsigned int width, unsigne
}
//Note: Passing in the current SRS simply forces GDAL to not do any warping
- return reproject( getSRS(), &extent, width, height);
+ return reproject( getSRS(), &extent, width, height, useBilinearInterpolation);
}
else
{
@@ -1377,7 +1377,7 @@ createDataSetFromImage(const osg::Image* image, double minX, double minY, double
static osg::Image*
reprojectImage(osg::Image* srcImage, const std::string srcWKT, double srcMinX, double srcMinY, double srcMaxX, double srcMaxY,
const std::string destWKT, double destMinX, double destMinY, double destMaxX, double destMaxY,
- int width = 0, int height = 0)
+ int width = 0, int height = 0, bool useBilinearInterpolation = true)
{
GDAL_SCOPED_LOCK;
osg::Timer_t start = osg::Timer::instance()->tick();
@@ -1406,11 +1406,20 @@ reprojectImage(osg::Image* srcImage, const std::string srcWKT, double srcMinX, d
GDALDataset* destDS = createMemDS(width, height, destMinX, destMinY, destMaxX, destMaxY, destWKT);
- GDALReprojectImage(srcDS, NULL,
- destDS, NULL,
- //GDALResampleAlg::GRA_NearestNeighbour,
- GRA_Bilinear,
- 0,0,0,0,0);
+ if (useBilinearInterpolation == true)
+ {
+ GDALReprojectImage(srcDS, NULL,
+ destDS, NULL,
+ GRA_Bilinear,
+ 0,0,0,0,0);
+ }
+ else
+ {
+ GDALReprojectImage(srcDS, NULL,
+ destDS, NULL,
+ GRA_NearestNeighbour,
+ 0,0,0,0,0);
+ }
osg::Image* result = createImageFromDataset(destDS);
@@ -1617,7 +1626,7 @@ namespace
GeoImage
-GeoImage::reproject(const SpatialReference* to_srs, const GeoExtent* to_extent, unsigned int width, unsigned int height) const
+GeoImage::reproject(const SpatialReference* to_srs, const GeoExtent* to_extent, unsigned int width, unsigned int height, bool useBilinearInterpolation) const
{
GeoExtent destExtent;
if (to_extent)
@@ -1650,7 +1659,7 @@ GeoImage::reproject(const SpatialReference* to_srs, const GeoExtent* to_extent,
getExtent().xMin(), getExtent().yMin(), getExtent().xMax(), getExtent().yMax(),
to_srs->getWKT(),
destExtent.xMin(), destExtent.yMin(), destExtent.xMax(), destExtent.yMax(),
- width, height);
+ width, height, useBilinearInterpolation);
}
return GeoImage(resultImage, destExtent);
}
diff --git a/src/osgEarth/HTTPClient b/src/osgEarth/HTTPClient
index bac1527..85f7ece 100644
--- a/src/osgEarth/HTTPClient
+++ b/src/osgEarth/HTTPClient
@@ -210,6 +210,15 @@ namespace osgEarth
TODO: This should probably move into the Registry */
static void setProxySettings( const ProxySettings &proxySettings );
+ /**
+ Gets the timeout in seconds to use for HTTP requests.*/
+ static long getTimeout();
+
+ /**
+ Sets the timeout in seconds to use for HTTP requests.
+ Setting to 0 (default) is infinite timeout */
+ void setTimeout( long timeout );
+
public:
/**
diff --git a/src/osgEarth/HTTPClient.cpp b/src/osgEarth/HTTPClient.cpp
index 8e5f149..b3e3316 100644
--- a/src/osgEarth/HTTPClient.cpp
+++ b/src/osgEarth/HTTPClient.cpp
@@ -293,13 +293,19 @@ HTTPResponse::getHeadersAsConfig() const
#define USER_AGENT "osgearth" QUOTE(OSGEARTH_MAJOR_VERSION) "." QUOTE(OSGEARTH_MINOR_VERSION)
-static optional<ProxySettings> _proxySettings;
-static std::string _userAgent = USER_AGENT;
-
namespace
{
// per-thread client map (must be global scope)
static Threading::PerThread<HTTPClient> s_clientPerThread;
+
+ static optional<ProxySettings> s_proxySettings;
+
+ static std::string s_userAgent = USER_AGENT;
+
+ static long s_timeout = 0;
+
+ // HTTP debugging.
+ static bool s_HTTP_DEBUG = false;
}
HTTPClient&
@@ -333,7 +339,7 @@ HTTPClient::initializeImpl()
_curl_handle = curl_easy_init();
//Get the user agent
- std::string userAgent = _userAgent;
+ std::string userAgent = s_userAgent;
const char* userAgentEnv = getenv("OSGEARTH_USERAGENT");
if (userAgentEnv)
{
@@ -348,6 +354,13 @@ HTTPClient::initializeImpl()
OE_WARN << LC << "Simulating a network error with Response Code = " << _simResponseCode << std::endl;
}
+ // Dumps out HTTP request/response info
+ if ( ::getenv("OSGEARTH_HTTP_DEBUG") )
+ {
+ s_HTTP_DEBUG = true;
+ OE_WARN << LC << "HTTP debugging enabled" << std::endl;
+ }
+
OE_DEBUG << LC << "HTTPClient setting userAgent=" << userAgent << std::endl;
curl_easy_setopt( _curl_handle, CURLOPT_USERAGENT, userAgent.c_str() );
@@ -355,8 +368,15 @@ HTTPClient::initializeImpl()
curl_easy_setopt( _curl_handle, CURLOPT_FOLLOWLOCATION, (void*)1 );
curl_easy_setopt( _curl_handle, CURLOPT_MAXREDIRS, (void*)5 );
curl_easy_setopt( _curl_handle, CURLOPT_PROGRESSFUNCTION, &CurlProgressCallback);
- curl_easy_setopt( _curl_handle, CURLOPT_NOPROGRESS, (void*)0 ); //FALSE);
- //curl_easy_setopt( _curl_handle, CURLOPT_TIMEOUT, 1L );
+ curl_easy_setopt( _curl_handle, CURLOPT_NOPROGRESS, (void*)0 ); //FALSE);
+ long timeout = s_timeout;
+ const char* timeoutEnv = getenv("OSGEARTH_HTTP_TIMEOUT");
+ if (timeoutEnv)
+ {
+ timeout = osgEarth::as<long>(std::string(timeoutEnv), 0);
+ }
+ OE_DEBUG << LC << "Setting timeout to " << timeout << std::endl;
+ curl_easy_setopt( _curl_handle, CURLOPT_TIMEOUT, timeout );
_initialized = true;
}
@@ -370,17 +390,27 @@ HTTPClient::~HTTPClient()
void
HTTPClient::setProxySettings( const ProxySettings& proxySettings )
{
- _proxySettings = proxySettings;
+ s_proxySettings = proxySettings;
}
const std::string& HTTPClient::getUserAgent()
{
- return _userAgent;
+ return s_userAgent;
}
void HTTPClient::setUserAgent(const std::string& userAgent)
{
- _userAgent = userAgent;
+ s_userAgent = userAgent;
+}
+
+long HTTPClient::getTimeout()
+{
+ return s_timeout;
+}
+
+void HTTPClient::setTimeout( long timeout )
+{
+ s_timeout = timeout;
}
void
@@ -580,8 +610,6 @@ HTTPClient::doGet( const HTTPRequest& request, const osgDB::Options* options, Pr
{
initialize();
- OE_TEST << LC << "doGet " << request.getURL() << std::endl;
-
const osgDB::AuthenticationMap* authenticationMap = (options && options->getAuthenticationMap()) ?
options->getAuthenticationMap() :
osgDB::Registry::instance()->getAuthenticationMap();
@@ -595,15 +623,15 @@ HTTPClient::doGet( const HTTPRequest& request, const osgDB::Options* options, Pr
// the proxy information changes.
//Try to get the proxy settings from the global settings
- if (_proxySettings.isSet())
+ if (s_proxySettings.isSet())
{
- proxy_host = _proxySettings.get().hostName();
+ proxy_host = s_proxySettings.get().hostName();
std::stringstream buf;
- buf << _proxySettings.get().port();
+ buf << s_proxySettings.get().port();
proxy_port = buf.str();
- std::string proxy_username = _proxySettings.get().userName();
- std::string proxy_password = _proxySettings.get().password();
+ std::string proxy_username = s_proxySettings.get().userName();
+ std::string proxy_password = s_proxySettings.get().password();
if (!proxy_username.empty() && !proxy_password.empty())
{
proxy_auth = proxy_username + std::string(":") + proxy_password;
@@ -651,14 +679,18 @@ HTTPClient::doGet( const HTTPRequest& request, const osgDB::Options* options, Pr
bufStr = buf.str();
proxy_addr = bufStr;
- OE_DEBUG << LC << "setting proxy: " << proxy_addr << std::endl;
+ if ( s_HTTP_DEBUG )
+ OE_NOTICE << LC << "Using proxy: " << proxy_addr << std::endl;
+
//curl_easy_setopt( _curl_handle, CURLOPT_HTTPPROXYTUNNEL, 1 );
curl_easy_setopt( _curl_handle, CURLOPT_PROXY, proxy_addr.c_str() );
//Setup the proxy authentication if setup
if (!proxy_auth.empty())
{
- OE_DEBUG << LC << "Setting up proxy authentication " << proxy_auth << std::endl;
+ if ( s_HTTP_DEBUG )
+ OE_NOTICE << LC << "Using proxy authentication " << proxy_auth << std::endl;
+
curl_easy_setopt( _curl_handle, CURLOPT_PROXYUSERPWD, proxy_auth.c_str());
}
}
@@ -740,8 +772,12 @@ HTTPClient::doGet( const HTTPRequest& request, const osgDB::Options* options, Pr
if (!proxy_addr.empty())
{
long connect_code = 0L;
- curl_easy_getinfo( _curl_handle, CURLINFO_HTTP_CONNECTCODE, &connect_code );
- OE_DEBUG << LC << "proxy connect code " << connect_code << std::endl;
+ CURLcode r = curl_easy_getinfo(_curl_handle, CURLINFO_HTTP_CONNECTCODE, &connect_code);
+ if ( r != CURLE_OK )
+ {
+ OE_WARN << LC << "Proxy connect error: " << curl_easy_strerror(r) << std::endl;
+ return HTTPResponse(0);
+ }
}
curl_easy_getinfo( _curl_handle, CURLINFO_RESPONSE_CODE, &response_code );
@@ -753,21 +789,24 @@ HTTPClient::doGet( const HTTPRequest& request, const osgDB::Options* options, Pr
res = response_code == 408 ? CURLE_OPERATION_TIMEDOUT : CURLE_COULDNT_CONNECT;
}
- //OE_DEBUG << LC << "got response, code = " << response_code << std::endl;
+ if ( s_HTTP_DEBUG )
+ {
+ OE_NOTICE << LC << "GET(" << response_code << "): \"" << request.getURL() << "\"" << std::endl;
+ }
HTTPResponse response( response_code );
- if ( response_code == 200L && res != CURLE_ABORTED_BY_CALLBACK && res != CURLE_OPERATION_TIMEDOUT ) //res == 0 )
+ if ( response_code == 200L && res != CURLE_ABORTED_BY_CALLBACK && res != CURLE_OPERATION_TIMEDOUT )
{
// check for multipart content:
char* content_type_cp;
curl_easy_getinfo( _curl_handle, CURLINFO_CONTENT_TYPE, &content_type_cp );
if ( content_type_cp == NULL )
{
- OE_NOTICE << LC
+ OE_WARN << LC
<< "NULL Content-Type (protocol violation) "
<< "URL=" << request.getURL() << std::endl;
- return NULL;
+ return HTTPResponse(0L);
}
// NOTE:
@@ -795,7 +834,7 @@ HTTPClient::doGet( const HTTPRequest& request, const osgDB::Options* options, Pr
}
}
else if (res == CURLE_ABORTED_BY_CALLBACK || res == CURLE_OPERATION_TIMEDOUT)
- {
+ {
//If we were aborted by a callback, then it was cancelled by a user
response._cancelled = true;
}
@@ -929,7 +968,7 @@ HTTPClient::doReadImage(const std::string& location,
//If we have an error but it's recoverable, like a server error or timeout then set the callback to retry.
if (HTTPClient::isRecoverable( result.code() ) )
- {
+ {
if (callback)
{
OE_DEBUG << "Error in HTTPClient for " << location << " but it's recoverable" << std::endl;
@@ -1090,7 +1129,7 @@ HTTPClient::doReadString(const std::string& location,
//If we have an error but it's recoverable, like a server error or timeout then set the callback to retry.
if (HTTPClient::isRecoverable( result.code() ) )
- {
+ {
if (callback)
{
OE_DEBUG << "Error in HTTPClient for " << location << " but it's recoverable" << std::endl;
diff --git a/src/osgEarth/ImageLayer.cpp b/src/osgEarth/ImageLayer.cpp
index d4d036f..bbf36a3 100644
--- a/src/osgEarth/ImageLayer.cpp
+++ b/src/osgEarth/ImageLayer.cpp
@@ -451,7 +451,7 @@ ImageLayer::createImageInNativeProfile( const TileKey& key, ProgressCallback* pr
GeoExtent tightExtent = nativeProfile->clampAndTransformExtent( key.getExtent() );
// a non-exact crop is critical here to avoid resampling the data
- return result.crop( tightExtent, false );
+ return result.crop( tightExtent, false, 0, 0, *_runtimeOptions.driver()->bilinearReprojection() );
}
else // all fallback data
@@ -670,7 +670,7 @@ ImageLayer::createImageFromTileSource(const TileKey& key,
// same pixel size; because chances are if we're requesting a fallback that we're
// planning to mosaic it later, and the mosaicer requires same-size images.
GeoImage raw( result.get(), finalKey.getExtent() );
- GeoImage cropped = raw.crop( key.getExtent(), true, raw.getImage()->s(), raw.getImage()->t() );
+ GeoImage cropped = raw.crop( key.getExtent(), true, raw.getImage()->s(), raw.getImage()->t(), *_runtimeOptions.driver()->bilinearReprojection() );
result = cropped.takeImage();
fellBack = true;
}
@@ -811,7 +811,8 @@ ImageLayer::assembleImageFromTileSource(const TileKey& key,
key.getProfile()->getSRS(),
&key.getExtent(),
*_runtimeOptions.reprojectedTileSize(),
- *_runtimeOptions.reprojectedTileSize() );
+ *_runtimeOptions.reprojectedTileSize(),
+ *_runtimeOptions.driver()->bilinearReprojection());
}
return result;
diff --git a/src/osgEarth/Locators.cpp b/src/osgEarth/Locators.cpp
index 8138970..b5116f3 100644
--- a/src/osgEarth/Locators.cpp
+++ b/src/osgEarth/Locators.cpp
@@ -19,7 +19,7 @@
#include <osgEarth/Locators>
#include <osgEarth/TileKey>
#include <osgEarth/Registry>
-#include <osgEarth/Map>
+#include <osgEarth/MapInfo>
#include <osg/Notify>
using namespace osgEarth;
diff --git a/src/osgEarth/Map b/src/osgEarth/Map
index d1b1bfd..db46ef8 100644
--- a/src/osgEarth/Map
+++ b/src/osgEarth/Map
@@ -24,6 +24,7 @@
#include <osgEarth/GeoData>
#include <osgEarth/Profile>
#include <osgEarth/MapOptions>
+#include <osgEarth/MapCallback>
#include <osgEarth/ImageLayer>
#include <osgEarth/ElevationLayer>
#include <osgEarth/ModelLayer>
@@ -33,80 +34,10 @@
#include <osgDB/ReaderWriter>
namespace osgEarth
-{
+{
class MapInfo;
/**
- * Conveys atomic change actions to the map data model.
- */
- struct MapModelChange
- {
- enum ActionType {
- ADD_IMAGE_LAYER,
- REMOVE_IMAGE_LAYER,
- MOVE_IMAGE_LAYER,
- ADD_ELEVATION_LAYER,
- REMOVE_ELEVATION_LAYER,
- MOVE_ELEVATION_LAYER,
- ADD_MODEL_LAYER,
- REMOVE_MODEL_LAYER,
- MOVE_MODEL_LAYER,
- ADD_MASK_LAYER,
- REMOVE_MASK_LAYER,
- UNSPECIFIED
- };
-
- MapModelChange( ActionType action, Revision mapModeRev, Layer* layer, int firstIndex =-1, int secondIndex =-1 )
- : _action(action), _layer(layer), _modelRevision(mapModeRev), _firstIndex(firstIndex), _secondIndex(secondIndex) { }
-
- const ActionType& getAction() const { return _action; }
- const Revision& getRevision() const { return _modelRevision; }
- int getFirstIndex() const { return _firstIndex; }
- int getSecondIndex() const { return _secondIndex; }
- Layer* getLayer() const { return _layer.get(); }
- ImageLayer* getImageLayer() const { return dynamic_cast<ImageLayer*>(_layer.get()); }
- ElevationLayer* getElevationLayer() const { return dynamic_cast<ElevationLayer*>(_layer.get()); }
- ModelLayer* getModelLayer() const { return dynamic_cast<ModelLayer*>(_layer.get()); }
- MaskLayer* getMaskLayer() const { return dynamic_cast<MaskLayer*>(_layer.get()); }
-
- private:
- ActionType _action;
- osg::ref_ptr<Layer> _layer;
- Revision _modelRevision;
- int _firstIndex, _secondIndex;
- };
-
- /**
- * Callback that the Map object uses to notify listeners of map data model changes.
- */
- struct OSGEARTH_EXPORT MapCallback : public osg::Referenced
- {
- virtual void onMapInfoEstablished( const MapInfo& mapInfo ) { }
-
- virtual void onMapModelChanged( const MapModelChange& change );
-
- virtual void onImageLayerAdded( ImageLayer* layer, unsigned int index ) { }
- virtual void onImageLayerRemoved( ImageLayer* layer, unsigned int index ) { }
- virtual void onImageLayerMoved( ImageLayer* layer, unsigned int oldIndex, unsigned int newIndex ) { }
-
- virtual void onElevationLayerAdded( ElevationLayer* layer, unsigned int index ) { }
- virtual void onElevationLayerRemoved( ElevationLayer* layer, unsigned int index ) { }
- virtual void onElevationLayerMoved( ElevationLayer* layer, unsigned int oldIndex, unsigned int newIndex ) { }
-
- virtual void onModelLayerAdded( ModelLayer* layer, unsigned int index ) { }
- virtual void onModelLayerRemoved( ModelLayer* layer ) { }
- virtual void onModelLayerMoved( ModelLayer* layer, unsigned int oldIndex, unsigned int newIndex ) { }
-
- virtual void onMaskLayerAdded( MaskLayer* mask ) { }
- virtual void onMaskLayerRemoved( MaskLayer* mask ) { }
-
- /** dtor */
- virtual ~MapCallback() { }
- };
-
- typedef std::list< osg::ref_ptr<MapCallback> > MapCallbackList;
-
- /**
* Map is the main data model that the MapNode will render. It is a
* container for all Layer objects (that contain the actual data) and
* the rendering options.
@@ -442,133 +373,6 @@ namespace osgEarth
friend class MapInfo;
};
-
-
- /**
- * A convenience class that combines a general geospatial profile and additional
- * information about the map itself.
- */
- class OSGEARTH_EXPORT MapInfo
- {
- public:
- MapInfo( const Map* map );
-
- MapInfo( const MapInfo& rhs );
-
- /** dtor */
- virtual ~MapInfo() { }
-
- const Profile* getProfile() const { return _profile.get(); }
- const SpatialReference* getSRS() const { return _profile->getSRS(); }
-
- bool isGeocentric() const { return _isGeocentric; }
- bool isCube() const { return _isCube; }
- bool isPlateCarre() const { return _profile->getSRS()->isPlateCarre(); }
-
- bool isProjectedSRS() const { return !isGeographicSRS(); }
- bool isGeographicSRS() const { return _profile->getSRS()->isGeographic(); }
-
- ElevationInterpolation getElevationInterpolation() const { return _elevationInterpolation;}
-
- private:
- osg::ref_ptr<const Profile> _profile;
- bool _isGeocentric, _isCube;
- ElevationInterpolation _elevationInterpolation;
- };
-
-
- /**
- * A "snapshot in time" of a Map model revision. Use this class to get a safe "copy" of
- * the map model lists that you can use without worrying about the model changing underneath
- * you from another thread.
- */
- class OSGEARTH_EXPORT MapFrame
- {
- public:
- /**
- * Constructs a new map frame.
- */
- MapFrame( const Map* map, Map::ModelParts parts =Map::TERRAIN_LAYERS, const std::string& name ="" );
-
- /**
- * A copy constructor with a new name (no sync happens)
- */
- MapFrame( const MapFrame& frame, const std::string& name ="" );
-
- /** dtor */
- virtual ~MapFrame() { }
-
- /**
- * Synchronizes this frame with the source map model (only if necessary). Returns
- * true is new data was synced; false if nothing changed.
- */
- bool sync();
-
- /** Accesses the profile/rendering info about the source map. */
- const MapInfo& getMapInfo() const { return _mapInfo; }
-
- /** Convenience method to access the map's profile */
- const Profile* getProfile() const { return _mapInfo.getProfile(); }
-
-
- /** The image layer stack snapshot */
- const ImageLayerVector& imageLayers() const { return _imageLayers; }
- ImageLayer* getImageLayerAt( int index ) const { return _imageLayers[index].get(); }
- ImageLayer* getImageLayerByUID( UID uid ) const;
- ImageLayer* getImageLayerByName( const std::string& name ) const;
-
- /** The elevation layer stack snapshot */
- const ElevationLayerVector& elevationLayers() const { return _elevationLayers; }
- ElevationLayer* getElevationLayerAt( int index ) const { return _elevationLayers[index].get(); }
- ElevationLayer* getElevationLayerByUID( UID uid ) const;
- ElevationLayer* getElevationLayerByName( const std::string& name ) const;
-
- /** The model layer set snapshot */
- const ModelLayerVector& modelLayers() const { return _modelLayers; }
- ModelLayer* getModelLayerAt(int index) const { return _modelLayers[index].get(); }
-
- /** The mask layer set snapshot */
- const MaskLayerVector& terrainMaskLayers() const { return _maskLayers; }
-
- /** Gets the index of the layer in the layer stack snapshot. */
- int indexOf( ImageLayer* layer ) const;
- int indexOf( ElevationLayer* layer ) const;
- int indexOf( ModelLayer* layer ) const;
-
- /** Gets the map data model revision with which this frame is currently sync'd */
- Revision getRevision() const { return _mapDataModelRevision; }
-
- /** Checks whether all the data for the specified key is cached. */
- bool isCached( const TileKey& key ) const;
-
- /**
- * Equivalent to the Map::createHeightField() method, but operates on the elevation stack
- * snapshot in this MapFrame.
- */
- bool getHeightField(
- const TileKey& key,
- bool fallback,
- osg::ref_ptr<osg::HeightField>& out_hf,
- bool* out_isFallback =0L,
- bool convertToHAE =true,
- ElevationSamplePolicy samplePolicy =SAMPLE_FIRST_VALID,
- ProgressCallback* progress =0L ) const;
-
- private:
- bool _initialized;
- osg::observer_ptr<const Map> _map;
- //osg::ref_ptr<const Map> _map;
- std::string _name;
- MapInfo _mapInfo;
- Map::ModelParts _parts;
- Revision _mapDataModelRevision;
- ImageLayerVector _imageLayers;
- ElevationLayerVector _elevationLayers;
- ModelLayerVector _modelLayers;
- MaskLayerVector _maskLayers;
- friend class Map;
- };
-
}
#endif // OSGEARTH_MAP_H
diff --git a/src/osgEarth/Map.cpp b/src/osgEarth/Map.cpp
index 1165ac4..217e2cb 100644
--- a/src/osgEarth/Map.cpp
+++ b/src/osgEarth/Map.cpp
@@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
+#include <osgEarth/MapModelChange>
#include <osgEarth/Registry>
#include <osgEarth/TileSource>
#include <osgEarth/HeightFieldUtils>
@@ -29,40 +31,6 @@ using namespace osgEarth;
//------------------------------------------------------------------------
-void
-MapCallback::onMapModelChanged( const MapModelChange& change )
-{
- switch( change.getAction() )
- {
- case MapModelChange::ADD_ELEVATION_LAYER:
- onElevationLayerAdded( change.getElevationLayer(), change.getFirstIndex() ); break;
- case MapModelChange::ADD_IMAGE_LAYER:
- onImageLayerAdded( change.getImageLayer(), change.getFirstIndex() ); break;
- case MapModelChange::ADD_MASK_LAYER:
- onMaskLayerAdded( change.getMaskLayer() ); break;
- case MapModelChange::ADD_MODEL_LAYER:
- onModelLayerAdded( change.getModelLayer(), change.getFirstIndex() ); break;
- case MapModelChange::REMOVE_ELEVATION_LAYER:
- onElevationLayerRemoved( change.getElevationLayer(), change.getFirstIndex() ); break;
- case MapModelChange::REMOVE_IMAGE_LAYER:
- onImageLayerRemoved( change.getImageLayer(), change.getFirstIndex() ); break;
- case MapModelChange::REMOVE_MASK_LAYER:
- onMaskLayerRemoved( change.getMaskLayer() ); break;
- case MapModelChange::REMOVE_MODEL_LAYER:
- onModelLayerRemoved( change.getModelLayer() ); break;
- case MapModelChange::MOVE_ELEVATION_LAYER:
- onElevationLayerMoved( change.getElevationLayer(), change.getFirstIndex(), change.getSecondIndex() ); break;
- case MapModelChange::MOVE_IMAGE_LAYER:
- onImageLayerMoved( change.getImageLayer(), change.getFirstIndex(), change.getSecondIndex() ); break;
- case MapModelChange::MOVE_MODEL_LAYER:
- onModelLayerMoved( change.getModelLayer(), change.getFirstIndex(), change.getSecondIndex() ); break;
- case MapModelChange::UNSPECIFIED: break;
- default: break;
- }
-}
-
-//------------------------------------------------------------------------
-
Map::Map( const MapOptions& options ) :
osg::Referenced ( true ),
_mapOptions ( options ),
@@ -77,7 +45,8 @@ _dataModelRevision ( 0 )
// if the map was a cache policy set, make this the system-wide default, UNLESS
// there ALREADY IS a registry default, in which case THAT will override THIS one.
- // (In other words, whichever one is set first wins.)
+ // (In other words, whichever one is set first wins. And of course, if the registry
+ // has an override set, that will cancel out all of this.)
const optional<CachePolicy> regCachePolicy = Registry::instance()->defaultCachePolicy();
if ( _mapOptions.cachePolicy().isSet() )
@@ -1050,257 +1019,6 @@ Map::calculateProfile()
}
}
-namespace
-{
- /**
- * Returns a heightfield corresponding to the input key by compositing
- * elevation data for a vector of elevation layers. The resulting
- * heightfield's height values will be expressed relative to the vertical
- * datum in the requesting key (which is usually that of the Map itself).
- */
- bool
- s_getHeightField(const TileKey& key,
- const ElevationLayerVector& elevLayers,
- bool fallback,
- const Profile* haeProfile,
- ElevationInterpolation interpolation,
- ElevationSamplePolicy samplePolicy,
- osg::ref_ptr<osg::HeightField>& out_result,
- bool* out_isFallback,
- ProgressCallback* progress )
- {
- unsigned lowestLOD = key.getLevelOfDetail();
- bool hfInitialized = false;
-
- //Get a HeightField for each of the enabled layers
- GeoHeightFieldVector heightFields;
-
- //The number of fallback heightfields we have
- int numFallbacks = 0;
-
- //Default to being fallback data.
- if ( out_isFallback )
- {
- *out_isFallback = true;
- }
-
- // if the caller provided an "HAE map profile", he wants an HAE elevation grid even if
- // the map profile has a vertical datum. This is the usual case when building the 3D
- // terrain, for example. Construct a temporary key that doesn't have the vertical
- // datum info and use that to query the elevation data.
- TileKey keyToUse = key;
- if ( haeProfile )
- {
- keyToUse = TileKey(key.getLevelOfDetail(), key.getTileX(), key.getTileY(), haeProfile );
- }
-
- // Generate a heightfield for each elevation layer.
-
- unsigned defElevSize = 8;
-
- for( ElevationLayerVector::const_iterator i = elevLayers.begin(); i != elevLayers.end(); i++ )
- {
- ElevationLayer* layer = i->get();
- if ( layer->getVisible() )
- {
- GeoHeightField geoHF = layer->createHeightField( keyToUse, progress );
-
- // if "fallback" is set, try to fall back on lower LODs.
- if ( !geoHF.valid() && fallback )
- {
- TileKey hf_key = keyToUse.createParentKey();
-
- while ( hf_key.valid() && !geoHF.valid() )
- {
- geoHF = layer->createHeightField( hf_key, progress );
- if ( !geoHF.valid() )
- hf_key = hf_key.createParentKey();
- }
-
- if ( geoHF.valid() )
- {
- if ( hf_key.getLevelOfDetail() < lowestLOD )
- lowestLOD = hf_key.getLevelOfDetail();
-
- //This HeightField is fallback data, so increment the count.
- numFallbacks++;
- }
- }
-
- if ( geoHF.valid() )
- {
- heightFields.push_back( geoHF );
- }
- }
- }
-
- //If any of the layers produced valid data then it's not considered a fallback
- if ( out_isFallback )
- {
- *out_isFallback = (numFallbacks == heightFields.size());
- //OE_NOTICE << "Num fallbacks=" << numFallbacks << " numHeightFields=" << heightFields.size() << " is fallback " << *out_isFallback << std::endl;
- }
-
- if ( heightFields.size() == 0 )
- {
- //If we got no heightfields but were requested to fallback, create an empty heightfield.
- if ( fallback )
- {
- out_result = HeightFieldUtils::createReferenceHeightField( keyToUse.getExtent(), defElevSize, defElevSize );
- return true;
- }
- else
- {
- //We weren't requested to fallback so just return.
- return false;
- }
- }
-
- else if (heightFields.size() == 1)
- {
- if ( lowestLOD == key.getLevelOfDetail() )
- {
- //If we only have on heightfield, just return it.
- out_result = heightFields[0].takeHeightField();
- }
- else
- {
- GeoHeightField geoHF = heightFields[0].createSubSample( key.getExtent(), interpolation);
- out_result = geoHF.takeHeightField();
- hfInitialized = true;
- }
- }
-
- else
- {
- //If we have multiple heightfields, we need to composite them together.
- unsigned int width = 0;
- unsigned int height = 0;
-
- for (GeoHeightFieldVector::const_iterator i = heightFields.begin(); i < heightFields.end(); ++i)
- {
- if (i->getHeightField()->getNumColumns() > width)
- width = i->getHeightField()->getNumColumns();
- if (i->getHeightField()->getNumRows() > height)
- height = i->getHeightField()->getNumRows();
- }
- out_result = new osg::HeightField();
- out_result->allocate( width, height );
-
- //Go ahead and set up the heightfield so we don't have to worry about it later
- double minx, miny, maxx, maxy;
- key.getExtent().getBounds(minx, miny, maxx, maxy);
- double dx = (maxx - minx)/(double)(out_result->getNumColumns()-1);
- double dy = (maxy - miny)/(double)(out_result->getNumRows()-1);
-
- const SpatialReference* keySRS = keyToUse.getProfile()->getSRS();
-
- //Create the new heightfield by sampling all of them.
- for (unsigned int c = 0; c < width; ++c)
- {
- double x = minx + (dx * (double)c);
- for (unsigned r = 0; r < height; ++r)
- {
- double y = miny + (dy * (double)r);
-
- //Collect elevations from all of the layers. Iterate BACKWARDS because the last layer
- // is the highest priority.
- std::vector<float> elevations;
- for( GeoHeightFieldVector::reverse_iterator itr = heightFields.rbegin(); itr != heightFields.rend(); ++itr )
- {
- const GeoHeightField& geoHF = *itr;
-
- float elevation = 0.0f;
- if ( geoHF.getElevation(keySRS, x, y, interpolation, keySRS, elevation) )
- {
- if (elevation != NO_DATA_VALUE)
- {
- elevations.push_back(elevation);
- }
- }
- }
-
- float elevation = NO_DATA_VALUE;
-
- //The list of elevations only contains valid values
- if (elevations.size() > 0)
- {
- if (samplePolicy == SAMPLE_FIRST_VALID)
- {
- elevation = elevations[0];
- }
- else if (samplePolicy == SAMPLE_HIGHEST)
- {
- elevation = -FLT_MAX;
- for (unsigned int i = 0; i < elevations.size(); ++i)
- {
- if (elevation < elevations[i]) elevation = elevations[i];
- }
- }
- else if (samplePolicy == SAMPLE_LOWEST)
- {
- elevation = FLT_MAX;
- for (unsigned i = 0; i < elevations.size(); ++i)
- {
- if (elevation > elevations[i]) elevation = elevations[i];
- }
- }
- else if (samplePolicy == SAMPLE_AVERAGE)
- {
- elevation = 0.0;
- for (unsigned i = 0; i < elevations.size(); ++i)
- {
- elevation += elevations[i];
- }
- elevation /= (float)elevations.size();
- }
- }
- out_result->setHeight(c, r, elevation);
- }
- }
- }
-
- // Replace any NoData areas with the reference value. This is zero for HAE datums,
- // and some geoid height for orthometric datums.
- if (out_result.valid())
- {
- const Geoid* geoid = 0L;
- const VerticalDatum* vdatum = key.getProfile()->getSRS()->getVerticalDatum();
-
- if ( haeProfile && vdatum )
- {
- geoid = vdatum->getGeoid();
- }
-
- HeightFieldUtils::resolveInvalidHeights(
- out_result.get(),
- key.getExtent(),
- NO_DATA_VALUE,
- geoid );
-
- //ReplaceInvalidDataOperator o;
- //o.setValidDataOperator(new osgTerrain::NoDataValue(NO_DATA_VALUE));
- //o( out_result.get() );
- }
-
- //Initialize the HF values for osgTerrain
- if (out_result.valid() && !hfInitialized )
- {
- //Go ahead and set up the heightfield so we don't have to worry about it later
- double minx, miny, maxx, maxy;
- key.getExtent().getBounds(minx, miny, maxx, maxy);
- out_result->setOrigin( osg::Vec3d( minx, miny, 0.0 ) );
- double dx = (maxx - minx)/(double)(out_result->getNumColumns()-1);
- double dy = (maxy - miny)/(double)(out_result->getNumRows()-1);
- out_result->setXInterval( dx );
- out_result->setYInterval( dy );
- out_result->setBorderWidth( 0 );
- }
-
- return out_result.valid();
- }
-}
-
bool
Map::getHeightField(const TileKey& key,
@@ -1315,9 +1033,8 @@ Map::getHeightField(const TileKey& key,
ElevationInterpolation interp = getMapOptions().elevationInterpolation().get();
- return s_getHeightField(
+ return _elevationLayers.createHeightField(
key,
- _elevationLayers,
fallback,
convertToHAE ? _profileNoVDatum.get() : 0L,
interp,
@@ -1377,176 +1094,3 @@ Map::sync( MapFrame& frame ) const
}
return result;
}
-
-//------------------------------------------------------------------------
-
-MapInfo::MapInfo( const Map* map ) :
-_profile ( 0L ),
-_isGeocentric ( true ),
-_isCube ( false ),
-_elevationInterpolation( INTERP_BILINEAR )
-{
- if ( map )
- {
- _profile = map->getProfile();
- _isGeocentric = map->isGeocentric();
- _isCube = map->getMapOptions().coordSysType() == MapOptions::CSTYPE_GEOCENTRIC_CUBE;
- _elevationInterpolation = *map->getMapOptions().elevationInterpolation();
- }
-}
-
-MapInfo::MapInfo( const MapInfo& rhs ) :
-_profile ( rhs._profile ),
-_isGeocentric ( rhs._isGeocentric ),
-_isCube ( rhs._isCube ),
-_elevationInterpolation( rhs._elevationInterpolation )
-{
- //nop
-}
-
-//------------------------------------------------------------------------
-
-MapFrame::MapFrame( const Map* map, Map::ModelParts parts, const std::string& name ) :
-_initialized( false ),
-_map ( map ),
-_name ( name ),
-_mapInfo ( map ),
-_parts ( parts )
-{
- sync();
-}
-
-MapFrame::MapFrame( const MapFrame& src, const std::string& name ) :
-_initialized ( src._initialized ),
-_map ( src._map.get() ),
-_name ( name ),
-_mapInfo ( src._mapInfo ),
-_parts ( src._parts ),
-_mapDataModelRevision( src._mapDataModelRevision ),
-_imageLayers ( src._imageLayers ),
-_elevationLayers ( src._elevationLayers ),
-_modelLayers ( src._modelLayers ),
-_maskLayers ( src._maskLayers )
-{
- //no sync required here; we copied the arrays etc
-}
-
-bool
-MapFrame::sync()
-{
- if ( _map.valid() )
- {
- return _map->sync( *this );
- }
- else
- {
- _imageLayers.clear();
- _elevationLayers.clear();
- _modelLayers.clear();
- _maskLayers.clear();
- return false;
- }
-}
-
-bool
-MapFrame::getHeightField(const TileKey& key,
- bool fallback,
- osg::ref_ptr<osg::HeightField>& out_hf,
- bool* out_isFallback,
- bool convertToHAE,
- ElevationSamplePolicy samplePolicy,
- ProgressCallback* progress) const
-{
- if ( !_map.valid() ) return false;
-
- return s_getHeightField(
- key,
- _elevationLayers,
- fallback,
- convertToHAE ? _map->getProfileNoVDatum() : 0L,
- _mapInfo.getElevationInterpolation(),
- samplePolicy,
- out_hf,
- out_isFallback,
- progress );
-}
-
-int
-MapFrame::indexOf( ImageLayer* layer ) const
-{
- ImageLayerVector::const_iterator i = std::find( _imageLayers.begin(), _imageLayers.end(), layer );
- return i != _imageLayers.end() ? i - _imageLayers.begin() : -1;
-}
-
-int
-MapFrame::indexOf( ElevationLayer* layer ) const
-{
- ElevationLayerVector::const_iterator i = std::find( _elevationLayers.begin(), _elevationLayers.end(), layer );
- return i != _elevationLayers.end() ? i - _elevationLayers.begin() : -1;
-}
-
-int
-MapFrame::indexOf( ModelLayer* layer ) const
-{
- ModelLayerVector::const_iterator i = std::find( _modelLayers.begin(), _modelLayers.end(), layer );
- return i != _modelLayers.end() ? i - _modelLayers.begin() : -1;
-}
-
-ImageLayer*
-MapFrame::getImageLayerByUID( UID uid ) const
-{
- for(ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
- if ( i->get()->getUID() == uid )
- return i->get();
- return 0L;
-}
-
-ImageLayer*
-MapFrame::getImageLayerByName( const std::string& name ) const
-{
- for(ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
- if ( i->get()->getName() == name )
- return i->get();
- return 0L;
-}
-
-bool
-MapFrame::isCached( const TileKey& key ) const
-{
- //Check to see if the tile will load fast
- // Check the imagery layers
- for( ImageLayerVector::const_iterator i = imageLayers().begin(); i != imageLayers().end(); i++ )
- {
- //If we're cache only we should be fast
- if (i->get()->isCacheOnly()) continue;
-
- osg::ref_ptr< TileSource > source = i->get()->getTileSource();
- if (!source.valid()) continue;
-
- //If the tile is blacklisted, it should also be fast.
- if ( source->getBlacklist()->contains( key.getTileId() ) ) continue;
- //If no data is available on this tile, we'll be fast
- if ( !source->hasData( key ) ) continue;
-
- if ( !i->get()->isCached( key ) ) return false;
- }
-
- for( ElevationLayerVector::const_iterator i = elevationLayers().begin(); i != elevationLayers().end(); ++i )
- {
- //If we're cache only we should be fast
- if (i->get()->isCacheOnly()) continue;
-
- osg::ref_ptr< TileSource > source = i->get()->getTileSource();
- if (!source.valid()) continue;
-
- //If the tile is blacklisted, it should also be fast.
- if ( source->getBlacklist()->contains( key.getTileId() ) ) continue;
- if ( !source->hasData( key ) ) continue;
- if ( !i->get()->isCached( key ) )
- {
- return false;
- }
- }
-
- return true;
-}
diff --git a/src/osgEarth/MapCallback b/src/osgEarth/MapCallback
new file mode 100644
index 0000000..21ad4b3
--- /dev/null
+++ b/src/osgEarth/MapCallback
@@ -0,0 +1,67 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2012 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_MAP_CALLBACK_H
+#define OSGEARTH_MAP_CALLBACK_H 1
+
+#include <osgEarth/Common>
+#include <osg/ref_ptr>
+#include <list>
+
+namespace osgEarth
+{
+ class MapInfo;
+ class ImageLayer;
+ class ElevationLayer;
+ class ModelLayer;
+ class MaskLayer;
+ struct MapModelChange;
+
+ /**
+ * Callback that the Map object uses to notify listeners of map data model changes.
+ */
+ struct OSGEARTH_EXPORT MapCallback : public osg::Referenced
+ {
+ virtual void onMapInfoEstablished( const MapInfo& mapInfo ) { }
+
+ virtual void onMapModelChanged( const MapModelChange& change );
+
+ virtual void onImageLayerAdded( ImageLayer* layer, unsigned int index ) { }
+ virtual void onImageLayerRemoved( ImageLayer* layer, unsigned int index ) { }
+ virtual void onImageLayerMoved( ImageLayer* layer, unsigned int oldIndex, unsigned int newIndex ) { }
+
+ virtual void onElevationLayerAdded( ElevationLayer* layer, unsigned int index ) { }
+ virtual void onElevationLayerRemoved( ElevationLayer* layer, unsigned int index ) { }
+ virtual void onElevationLayerMoved( ElevationLayer* layer, unsigned int oldIndex, unsigned int newIndex ) { }
+
+ virtual void onModelLayerAdded( ModelLayer* layer, unsigned int index ) { }
+ virtual void onModelLayerRemoved( ModelLayer* layer ) { }
+ virtual void onModelLayerMoved( ModelLayer* layer, unsigned int oldIndex, unsigned int newIndex ) { }
+
+ virtual void onMaskLayerAdded( MaskLayer* mask ) { }
+ virtual void onMaskLayerRemoved( MaskLayer* mask ) { }
+
+ /** dtor */
+ virtual ~MapCallback() { }
+ };
+
+ typedef std::list< osg::ref_ptr<MapCallback> > MapCallbackList;
+}
+
+#endif // OSGEARTH_MAP_CALLBACK_H
diff --git a/src/osgEarth/MapCallback.cpp b/src/osgEarth/MapCallback.cpp
new file mode 100644
index 0000000..bd44174
--- /dev/null
+++ b/src/osgEarth/MapCallback.cpp
@@ -0,0 +1,73 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2012 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/MapCallback>
+#include <osgEarth/MapModelChange>
+#include <osgEarth/ImageLayer>
+#include <osgEarth/ElevationLayer>
+#include <osgEarth/ModelLayer>
+#include <osgEarth/MaskLayer>
+
+#define LC "[MapCallback] "
+
+using namespace osgEarth;
+
+void
+MapCallback::onMapModelChanged( const MapModelChange& change )
+{
+ switch( change.getAction() )
+ {
+ case MapModelChange::ADD_ELEVATION_LAYER:
+ onElevationLayerAdded( change.getElevationLayer(), change.getFirstIndex() );
+ break;
+ case MapModelChange::ADD_IMAGE_LAYER:
+ onImageLayerAdded( change.getImageLayer(), change.getFirstIndex() );
+ break;
+ case MapModelChange::ADD_MASK_LAYER:
+ onMaskLayerAdded( change.getMaskLayer() );
+ break;
+ case MapModelChange::ADD_MODEL_LAYER:
+ onModelLayerAdded( change.getModelLayer(), change.getFirstIndex() );
+ break;
+ case MapModelChange::REMOVE_ELEVATION_LAYER:
+ onElevationLayerRemoved( change.getElevationLayer(), change.getFirstIndex() );
+ break;
+ case MapModelChange::REMOVE_IMAGE_LAYER:
+ onImageLayerRemoved( change.getImageLayer(), change.getFirstIndex() );
+ break;
+ case MapModelChange::REMOVE_MASK_LAYER:
+ onMaskLayerRemoved( change.getMaskLayer() );
+ break;
+ case MapModelChange::REMOVE_MODEL_LAYER:
+ onModelLayerRemoved( change.getModelLayer() );
+ break;
+ case MapModelChange::MOVE_ELEVATION_LAYER:
+ onElevationLayerMoved( change.getElevationLayer(), change.getFirstIndex(), change.getSecondIndex() );
+ break;
+ case MapModelChange::MOVE_IMAGE_LAYER:
+ onImageLayerMoved( change.getImageLayer(), change.getFirstIndex(), change.getSecondIndex() );
+ break;
+ case MapModelChange::MOVE_MODEL_LAYER:
+ onModelLayerMoved( change.getModelLayer(), change.getFirstIndex(), change.getSecondIndex() );
+ break;
+ case MapModelChange::UNSPECIFIED:
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/osgEarth/MapFrame b/src/osgEarth/MapFrame
new file mode 100644
index 0000000..650a8ed
--- /dev/null
+++ b/src/osgEarth/MapFrame
@@ -0,0 +1,124 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2012 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_MAP_FRAME_H
+#define OSGEARTH_MAP_FRAME_H 1
+
+#include <osgEarth/Common>
+#include <osgEarth/Containers>
+#include <osgEarth/Map>
+#include <osgEarth/MapInfo>
+
+namespace osgEarth
+{
+ /**
+ * A "snapshot in time" of a Map model revision. Use this class to get a safe "copy" of
+ * the map model lists that you can use without worrying about the model changing underneath
+ * you from another thread.
+ */
+ class OSGEARTH_EXPORT MapFrame
+ {
+ public:
+ /**
+ * Constructs a new map frame.
+ */
+ MapFrame( const Map* map, Map::ModelParts parts =Map::TERRAIN_LAYERS, const std::string& name ="" );
+
+ /**
+ * A copy constructor with a new name (no sync happens)
+ */
+ MapFrame( const MapFrame& frame, const std::string& name ="" );
+
+ /** dtor */
+ virtual ~MapFrame() { }
+
+ /**
+ * Synchronizes this frame with the source map model (only if necessary). Returns
+ * true is new data was synced; false if nothing changed.
+ */
+ bool sync();
+
+ /** Accesses the profile/rendering info about the source map. */
+ const MapInfo& getMapInfo() const { return _mapInfo; }
+
+ /** Convenience method to access the map's profile */
+ const Profile* getProfile() const { return _mapInfo.getProfile(); }
+
+
+ /** The image layer stack snapshot */
+ const ImageLayerVector& imageLayers() const { return _imageLayers; }
+ ImageLayer* getImageLayerAt( int index ) const { return _imageLayers[index].get(); }
+ ImageLayer* getImageLayerByUID( UID uid ) const;
+ ImageLayer* getImageLayerByName( const std::string& name ) const;
+
+ /** The elevation layer stack snapshot */
+ const ElevationLayerVector& elevationLayers() const { return _elevationLayers; }
+ ElevationLayer* getElevationLayerAt( int index ) const { return _elevationLayers[index].get(); }
+ ElevationLayer* getElevationLayerByUID( UID uid ) const;
+ ElevationLayer* getElevationLayerByName( const std::string& name ) const;
+
+ /** The model layer set snapshot */
+ const ModelLayerVector& modelLayers() const { return _modelLayers; }
+ ModelLayer* getModelLayerAt(int index) const { return _modelLayers[index].get(); }
+
+ /** The mask layer set snapshot */
+ const MaskLayerVector& terrainMaskLayers() const { return _maskLayers; }
+
+ /** Gets the index of the layer in the layer stack snapshot. */
+ int indexOf( ImageLayer* layer ) const;
+ int indexOf( ElevationLayer* layer ) const;
+ int indexOf( ModelLayer* layer ) const;
+
+ /** Gets the map data model revision with which this frame is currently sync'd */
+ Revision getRevision() const { return _mapDataModelRevision; }
+
+ /** Checks whether all the data for the specified key is cached. */
+ bool isCached( const TileKey& key ) const;
+
+ /**
+ * Equivalent to the Map::createHeightField() method, but operates on the elevation stack
+ * snapshot in this MapFrame.
+ */
+ bool getHeightField(
+ const TileKey& key,
+ bool fallback,
+ osg::ref_ptr<osg::HeightField>& out_hf,
+ bool* out_isFallback =0L,
+ bool convertToHAE =true,
+ ElevationSamplePolicy samplePolicy =SAMPLE_FIRST_VALID,
+ ProgressCallback* progress =0L ) const;
+
+ private:
+ bool _initialized;
+ osg::observer_ptr<const Map> _map;
+ std::string _name;
+ MapInfo _mapInfo;
+ Map::ModelParts _parts;
+ Revision _mapDataModelRevision;
+ ImageLayerVector _imageLayers;
+ ElevationLayerVector _elevationLayers;
+ ModelLayerVector _modelLayers;
+ MaskLayerVector _maskLayers;
+
+ friend class Map;
+ };
+
+}
+
+#endif // OSGEARTH_MAP_FRAME_H
diff --git a/src/osgEarth/MapFrame.cpp b/src/osgEarth/MapFrame.cpp
new file mode 100644
index 0000000..a39a9a8
--- /dev/null
+++ b/src/osgEarth/MapFrame.cpp
@@ -0,0 +1,183 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2012 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/MapFrame>
+
+using namespace osgEarth;
+
+#define LC "[MapFrame] "
+
+
+MapFrame::MapFrame( const Map* map, Map::ModelParts parts, const std::string& name ) :
+_initialized( false ),
+_map ( map ),
+_name ( name ),
+_mapInfo ( map ),
+_parts ( parts )
+{
+ sync();
+}
+
+
+MapFrame::MapFrame( const MapFrame& src, const std::string& name ) :
+_initialized ( src._initialized ),
+_map ( src._map.get() ),
+_name ( name ),
+_mapInfo ( src._mapInfo ),
+_parts ( src._parts ),
+_mapDataModelRevision( src._mapDataModelRevision ),
+_imageLayers ( src._imageLayers ),
+_elevationLayers ( src._elevationLayers ),
+_modelLayers ( src._modelLayers ),
+_maskLayers ( src._maskLayers )
+{
+ //no sync required here; we copied the arrays etc
+}
+
+
+bool
+MapFrame::sync()
+{
+ bool changed = false;
+
+ if ( _map.valid() )
+ {
+ changed = _map->sync( *this );
+ }
+ else
+ {
+ _imageLayers.clear();
+ _elevationLayers.clear();
+ _modelLayers.clear();
+ _maskLayers.clear();
+ }
+
+ return changed;
+}
+
+
+bool
+MapFrame::getHeightField(const TileKey& key,
+ bool fallback,
+ osg::ref_ptr<osg::HeightField>& out_hf,
+ bool* out_isFallback,
+ bool convertToHAE,
+ ElevationSamplePolicy samplePolicy,
+ ProgressCallback* progress) const
+{
+ if ( !_map.valid() )
+ return false;
+
+
+
+ return _elevationLayers.createHeightField(
+ key,
+ fallback,
+ convertToHAE ? _map->getProfileNoVDatum() : 0L,
+ _mapInfo.getElevationInterpolation(),
+ samplePolicy,
+ out_hf,
+ out_isFallback,
+ progress );
+}
+
+
+int
+MapFrame::indexOf( ImageLayer* layer ) const
+{
+ ImageLayerVector::const_iterator i = std::find( _imageLayers.begin(), _imageLayers.end(), layer );
+ return i != _imageLayers.end() ? i - _imageLayers.begin() : -1;
+}
+
+
+int
+MapFrame::indexOf( ElevationLayer* layer ) const
+{
+ ElevationLayerVector::const_iterator i = std::find( _elevationLayers.begin(), _elevationLayers.end(), layer );
+ return i != _elevationLayers.end() ? i - _elevationLayers.begin() : -1;
+}
+
+
+int
+MapFrame::indexOf( ModelLayer* layer ) const
+{
+ ModelLayerVector::const_iterator i = std::find( _modelLayers.begin(), _modelLayers.end(), layer );
+ return i != _modelLayers.end() ? i - _modelLayers.begin() : -1;
+}
+
+
+ImageLayer*
+MapFrame::getImageLayerByUID( UID uid ) const
+{
+ for(ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
+ if ( i->get()->getUID() == uid )
+ return i->get();
+ return 0L;
+}
+
+
+ImageLayer*
+MapFrame::getImageLayerByName( const std::string& name ) const
+{
+ for(ImageLayerVector::const_iterator i = _imageLayers.begin(); i != _imageLayers.end(); ++i )
+ if ( i->get()->getName() == name )
+ return i->get();
+ return 0L;
+}
+
+
+bool
+MapFrame::isCached( const TileKey& key ) const
+{
+ //Check to see if the tile will load fast
+ // Check the imagery layers
+ for( ImageLayerVector::const_iterator i = imageLayers().begin(); i != imageLayers().end(); i++ )
+ {
+ //If we're cache only we should be fast
+ if (i->get()->isCacheOnly()) continue;
+
+ osg::ref_ptr< TileSource > source = i->get()->getTileSource();
+ if (!source.valid()) continue;
+
+ //If the tile is blacklisted, it should also be fast.
+ if ( source->getBlacklist()->contains( key.getTileId() ) ) continue;
+ //If no data is available on this tile, we'll be fast
+ if ( !source->hasData( key ) ) continue;
+
+ if ( !i->get()->isCached( key ) ) return false;
+ }
+
+ for( ElevationLayerVector::const_iterator i = elevationLayers().begin(); i != elevationLayers().end(); ++i )
+ {
+ //If we're cache only we should be fast
+ if (i->get()->isCacheOnly()) continue;
+
+ osg::ref_ptr< TileSource > source = i->get()->getTileSource();
+ if (!source.valid()) continue;
+
+ //If the tile is blacklisted, it should also be fast.
+ if ( source->getBlacklist()->contains( key.getTileId() ) ) continue;
+ if ( !source->hasData( key ) ) continue;
+ if ( !i->get()->isCached( key ) )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/src/osgEarth/MapInfo b/src/osgEarth/MapInfo
new file mode 100644
index 0000000..b045e89
--- /dev/null
+++ b/src/osgEarth/MapInfo
@@ -0,0 +1,64 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2012 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_MAP_INFO_H
+#define OSGEARTH_MAP_INFO_H 1
+
+#include <osgEarth/Common>
+#include <osgEarth/GeoCommon>
+#include <osgEarth/Profile>
+
+namespace osgEarth
+{
+ class Map;
+
+ /**
+ * A convenience class that combines a general geospatial profile and additional
+ * information about the map itself.
+ */
+ class OSGEARTH_EXPORT MapInfo
+ {
+ public:
+ MapInfo( const Map* map );
+
+ MapInfo( const MapInfo& rhs );
+
+ /** dtor */
+ virtual ~MapInfo() { }
+
+ const Profile* getProfile() const { return _profile.get(); }
+ const SpatialReference* getSRS() const { return _profile->getSRS(); }
+
+ bool isGeocentric() const { return _isGeocentric; }
+ bool isCube() const { return _isCube; }
+ bool isPlateCarre() const { return _profile->getSRS()->isPlateCarre(); }
+
+ bool isProjectedSRS() const { return !isGeographicSRS(); }
+ bool isGeographicSRS() const { return _profile->getSRS()->isGeographic(); }
+
+ ElevationInterpolation getElevationInterpolation() const { return _elevationInterpolation;}
+
+ private:
+ osg::ref_ptr<const Profile> _profile;
+ bool _isGeocentric, _isCube;
+ ElevationInterpolation _elevationInterpolation;
+ };
+}
+
+#endif // OSGEARTH_MAP_CALLBACK_H
diff --git a/src/osgEarthFeatures/CentroidFilter.cpp b/src/osgEarth/MapInfo.cpp
similarity index 52%
copy from src/osgEarthFeatures/CentroidFilter.cpp
copy to src/osgEarth/MapInfo.cpp
index 0b89bd1..9284072 100644
--- a/src/osgEarthFeatures/CentroidFilter.cpp
+++ b/src/osgEarth/MapInfo.cpp
@@ -16,36 +16,34 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
-#include <osgEarthFeatures/CentroidFilter>
-
-#define LC "[CentroidFilter] "
+#include <osgEarth/MapInfo>
+#include <osgEarth/Map>
using namespace osgEarth;
-using namespace osgEarth::Features;
-//------------------------------------------------------------------------
+#define LC "[MapInfo] "
-CentroidFilter::CentroidFilter()
-{
- //NOP
-}
-FilterContext
-CentroidFilter::push(FeatureList& features, FilterContext& context )
-{
- for( FeatureList::iterator i = features.begin(); i != features.end(); ++i )
+MapInfo::MapInfo( const Map* map ) :
+_profile ( 0L ),
+_isGeocentric ( true ),
+_isCube ( false ),
+_elevationInterpolation( INTERP_BILINEAR )
+{
+ if ( map )
{
- Feature* f = i->get();
-
- Geometry* geom = f->getGeometry();
- if ( !geom )
- continue;
-
- PointSet* newGeom = new PointSet();
- newGeom->push_back( geom->getBounds().center() );
-
- f->setGeometry( newGeom );
+ _profile = map->getProfile();
+ _isGeocentric = map->isGeocentric();
+ _isCube = map->getMapOptions().coordSysType() == MapOptions::CSTYPE_GEOCENTRIC_CUBE;
+ _elevationInterpolation = *map->getMapOptions().elevationInterpolation();
}
+}
- return context;
+MapInfo::MapInfo( const MapInfo& rhs ) :
+_profile ( rhs._profile ),
+_isGeocentric ( rhs._isGeocentric ),
+_isCube ( rhs._isCube ),
+_elevationInterpolation( rhs._elevationInterpolation )
+{
+ //nop
}
diff --git a/src/osgEarth/MapModelChange b/src/osgEarth/MapModelChange
new file mode 100644
index 0000000..5b92462
--- /dev/null
+++ b/src/osgEarth/MapModelChange
@@ -0,0 +1,74 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2012 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifndef OSGEARTH_MAP_MODEL_CHANGE_H
+#define OSGEARTH_MAP_MODEL_CHANGE_H 1
+
+#include <osgEarth/Common>
+#include <osgEarth/Revisioning>
+#include <osgEarth/ImageLayer>
+#include <osgEarth/ElevationLayer>
+#include <osgEarth/ModelLayer>
+#include <osgEarth/MaskLayer>
+
+namespace osgEarth
+{
+ /**
+ * Conveys atomic change actions to the map data model.
+ */
+ struct MapModelChange /* no export, header-only */
+ {
+ enum ActionType
+ {
+ ADD_IMAGE_LAYER,
+ REMOVE_IMAGE_LAYER,
+ MOVE_IMAGE_LAYER,
+ ADD_ELEVATION_LAYER,
+ REMOVE_ELEVATION_LAYER,
+ MOVE_ELEVATION_LAYER,
+ ADD_MODEL_LAYER,
+ REMOVE_MODEL_LAYER,
+ MOVE_MODEL_LAYER,
+ ADD_MASK_LAYER,
+ REMOVE_MASK_LAYER,
+ UNSPECIFIED
+ };
+
+ MapModelChange( ActionType action, Revision mapModeRev, Layer* layer, int firstIndex =-1, int secondIndex =-1 )
+ : _action(action), _layer(layer), _modelRevision(mapModeRev), _firstIndex(firstIndex), _secondIndex(secondIndex) { }
+
+ const ActionType& getAction() const { return _action; }
+ const Revision& getRevision() const { return _modelRevision; }
+ int getFirstIndex() const { return _firstIndex; }
+ int getSecondIndex() const { return _secondIndex; }
+ Layer* getLayer() const { return _layer.get(); }
+ ImageLayer* getImageLayer() const { return dynamic_cast<ImageLayer*>(_layer.get()); }
+ ElevationLayer* getElevationLayer() const { return dynamic_cast<ElevationLayer*>(_layer.get()); }
+ ModelLayer* getModelLayer() const { return dynamic_cast<ModelLayer*>(_layer.get()); }
+ MaskLayer* getMaskLayer() const { return dynamic_cast<MaskLayer*>(_layer.get()); }
+
+ private:
+ ActionType _action;
+ osg::ref_ptr<Layer> _layer;
+ Revision _modelRevision;
+ int _firstIndex, _secondIndex;
+ };
+}
+
+#endif // OSGEARTH_MAP_MODEL_CHANGE_H
diff --git a/src/osgEarth/MapNode.cpp b/src/osgEarth/MapNode.cpp
index 3fbe086..ff75556 100644
--- a/src/osgEarth/MapNode.cpp
+++ b/src/osgEarth/MapNode.cpp
@@ -22,7 +22,7 @@
#include <osgEarth/MaskNode>
#include <osgEarth/NodeUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/OverlayDecorator>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/TextureCompositor>
@@ -315,6 +315,8 @@ MapNode::init()
_overlayDecorator->setTextureSize( *_mapNodeOptions.overlayTextureSize() );
if ( _mapNodeOptions.overlayMipMapping().isSet() )
_overlayDecorator->setMipMapping( *_mapNodeOptions.overlayMipMapping() );
+ if ( _mapNodeOptions.overlayAttachStencil().isSet() )
+ _overlayDecorator->setAttachStencil( *_mapNodeOptions.overlayAttachStencil() );
addTerrainDecorator( _overlayDecorator );
@@ -345,9 +347,14 @@ MapNode::init()
// Install top-level shader programs:
if ( Registry::capabilities().supportsGLSL() )
{
+ // Note. We use OVERRIDE here so that child object that use the ShaderGenerator
+ // don't have to worry about installing default shaders. The usage pattern is
+ // to use PROTECTED mode if you want to override the defaults in (say) a ModelLayer
+ // or in a TextureCompositor.
+
VirtualProgram* vp = new VirtualProgram();
vp->setName( "MapNode" );
- vp->installDefaultColoringAndLightingShaders();
+ vp->installDefaultColoringAndLightingShaders( 0, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
ss->setAttributeAndModes( vp, osg::StateAttribute::ON );
}
@@ -367,7 +374,7 @@ MapNode::~MapNode()
//Remove our model callback from any of the model layers in the map
for (osgEarth::ModelLayerVector::iterator itr = modelLayers.begin(); itr != modelLayers.end(); ++itr)
{
- this->onModelLayerRemoved( itr->get() );
+ this->onModelLayerRemoved( itr->get() );
}
}
diff --git a/src/osgEarth/MapNodeObserver b/src/osgEarth/MapNodeObserver
index 10faab3..2e71ff0 100644
--- a/src/osgEarth/MapNodeObserver
+++ b/src/osgEarth/MapNodeObserver
@@ -47,6 +47,11 @@ namespace osgEarth
* Gets the map node from its observer reference
*/
virtual MapNode* getMapNode() =0;
+
+ /**
+ * dtor
+ */
+ virtual ~MapNodeObserver() { }
};
diff --git a/src/osgEarth/MapNodeOptions b/src/osgEarth/MapNodeOptions
index 1c0d71d..5915971 100644
--- a/src/osgEarth/MapNodeOptions
+++ b/src/osgEarth/MapNodeOptions
@@ -77,6 +77,12 @@ namespace osgEarth
const optional<bool>& overlayMipMapping() const { return _overlayMipMapping; }
/**
+ * Whether to attach the RTT camera to the stencil buffer
+ */
+ optional<bool>& overlayAttachStencil() { return _overlayAttachStencil; }
+ const optional<bool>& overlayAttachStencil() const { return _overlayAttachStencil; }
+
+ /**
* Options to conigure the terrain engine (the component that renders the
* terrain surface).
*/
@@ -98,6 +104,7 @@ namespace osgEarth
optional<bool> _overlayBlending;
optional<unsigned> _overlayTextureSize;
optional<bool> _overlayMipMapping;
+ optional<bool> _overlayAttachStencil;
optional<Config> _terrainOptionsConf;
TerrainOptions* _terrainOptions;
diff --git a/src/osgEarth/MapNodeOptions.cpp b/src/osgEarth/MapNodeOptions.cpp
index 6374747..00e48e3 100644
--- a/src/osgEarth/MapNodeOptions.cpp
+++ b/src/osgEarth/MapNodeOptions.cpp
@@ -39,7 +39,8 @@ _overlayVertexWarping( false ),
_overlayBlending ( true ),
_overlayMipMapping ( false ),
_overlayTextureSize ( 4096 ),
-_terrainOptions ( 0L )
+_terrainOptions ( 0L ),
+_overlayAttachStencil( true )
{
mergeConfig( conf );
}
@@ -52,6 +53,7 @@ _overlayVertexWarping( false ),
_overlayBlending ( true ),
_overlayTextureSize ( 4096 ),
_overlayMipMapping ( false ),
+_overlayAttachStencil( true ),
_terrainOptions ( 0L )
{
setTerrainOptions( to );
@@ -65,7 +67,8 @@ _overlayVertexWarping( false ),
_overlayBlending ( true ),
_overlayTextureSize ( 4096 ),
_overlayMipMapping ( false ),
-_terrainOptions ( 0L )
+_terrainOptions ( 0L ),
+_overlayAttachStencil( true )
{
mergeConfig( rhs.getConfig() );
}
@@ -86,14 +89,15 @@ MapNodeOptions::getConfig() const
Config conf; // start with a fresh one since this is a FINAL object // = ConfigOptions::getConfig();
conf.key() = "options";
- conf.updateObjIfSet( "proxy", _proxySettings );
- conf.updateIfSet ( "cache_only", _cacheOnly );
- conf.updateIfSet ( "lighting", _enableLighting );
- conf.updateIfSet ( "terrain", _terrainOptionsConf );
- conf.updateIfSet ( "overlay_warping", _overlayVertexWarping );
- conf.updateIfSet ( "overlay_blending", _overlayBlending );
- conf.updateIfSet ( "overlay_texture_size", _overlayTextureSize );
- conf.updateIfSet ( "overlay_mipmapping", _overlayMipMapping );
+ conf.updateObjIfSet( "proxy", _proxySettings );
+ conf.updateIfSet ( "cache_only", _cacheOnly );
+ conf.updateIfSet ( "lighting", _enableLighting );
+ conf.updateIfSet ( "terrain", _terrainOptionsConf );
+ conf.updateIfSet ( "overlay_warping", _overlayVertexWarping );
+ conf.updateIfSet ( "overlay_blending", _overlayBlending );
+ conf.updateIfSet ( "overlay_texture_size", _overlayTextureSize );
+ conf.updateIfSet ( "overlay_mipmapping", _overlayMipMapping );
+ conf.updateIfSet ( "overlay_attach_stencil", _overlayAttachStencil );
return conf;
}
@@ -103,13 +107,14 @@ MapNodeOptions::mergeConfig( const Config& conf )
{
ConfigOptions::mergeConfig( conf );
- conf.getObjIfSet( "proxy", _proxySettings );
- conf.getIfSet ( "cache_only", _cacheOnly );
- conf.getIfSet ( "lighting", _enableLighting );
- conf.getIfSet ( "overlay_warping", _overlayVertexWarping );
- conf.getIfSet ( "overlay_blending", _overlayBlending );
- conf.getIfSet ( "overlay_texture_size", _overlayTextureSize );
- conf.getIfSet ( "overlay_mipmapping", _overlayMipMapping );
+ conf.getObjIfSet( "proxy", _proxySettings );
+ conf.getIfSet ( "cache_only", _cacheOnly );
+ conf.getIfSet ( "lighting", _enableLighting );
+ conf.getIfSet ( "overlay_warping", _overlayVertexWarping );
+ conf.getIfSet ( "overlay_blending", _overlayBlending );
+ conf.getIfSet ( "overlay_texture_size", _overlayTextureSize );
+ conf.getIfSet ( "overlay_mipmapping", _overlayMipMapping );
+ conf.getIfSet ( "overlay_attach_stencil", _overlayAttachStencil );
if ( conf.hasChild( "terrain" ) )
{
diff --git a/src/osgEarth/ModelLayer b/src/osgEarth/ModelLayer
index ab55805..be797d1 100644
--- a/src/osgEarth/ModelLayer
+++ b/src/osgEarth/ModelLayer
@@ -82,14 +82,6 @@ namespace osgEarth
optional<bool>& overlay() { return _overlay; }
const optional<bool>& overlay() const { return _overlay; }
- /**
- * TEMPORARY option that will turn off all shader program composition
- * on the model layer. Need this temporarily to support external model
- * references until we get a proper shader gen working
- */
- optional<bool>& disableShaders() { return _disableShaderComp; }
- const optional<bool>& disableShaders() const { return _disableShaderComp; }
-
public:
virtual Config getConfig() const;
virtual void mergeConfig( const Config& conf );
@@ -98,13 +90,12 @@ namespace osgEarth
void fromConfig( const Config& conf );
void setDefaults();
- optional<std::string> _name;
- optional<bool> _overlay;
+ optional<std::string> _name;
+ optional<bool> _overlay;
optional<ModelSourceOptions> _driver;
- optional<bool> _enabled;
- optional<bool> _visible;
- optional<bool> _lighting;
- optional<bool> _disableShaderComp;
+ optional<bool> _enabled;
+ optional<bool> _visible;
+ optional<bool> _lighting;
};
/**
@@ -209,8 +200,6 @@ namespace osgEarth
osg::ref_ptr<ModelSource> _modelSource;
const ModelLayerOptions _initOptions;
ModelLayerOptions _runtimeOptions;
- //osg::ref_ptr< osg::Node > _node;
- //osg::ref_ptr<osgDB::Options> _dbOptions;
Revision _modelSourceRev;
ModelLayerCallbackList _callbacks;
UpdateLightingUniformsHelper _updateLightingUniformsHelper;
diff --git a/src/osgEarth/ModelLayer.cpp b/src/osgEarth/ModelLayer.cpp
index 8f90eca..fc798e7 100644
--- a/src/osgEarth/ModelLayer.cpp
+++ b/src/osgEarth/ModelLayer.cpp
@@ -20,7 +20,6 @@
#include <osgEarth/Map>
#include <osgEarth/Registry>
#include <osgEarth/Capabilities>
-#include <osgEarth/ShaderComposition>
#include <osg/Depth>
#define LC "[ModelLayer] "
@@ -67,11 +66,10 @@ ConfigOptions()
void
ModelLayerOptions::setDefaults()
{
- _overlay.init( false );
- _enabled.init( true );
- _visible.init( true );
- _lighting.init( true );
- _disableShaderComp.init( false );
+ _overlay.init ( false );
+ _enabled.init ( true );
+ _visible.init ( true );
+ _lighting.init ( true );
}
Config
@@ -86,9 +84,6 @@ ModelLayerOptions::getConfig() const
conf.updateIfSet( "visible", _visible );
conf.updateIfSet( "lighting", _lighting );
- // temporary.
- conf.updateIfSet( "disable_shaders", _disableShaderComp );
-
// Merge the ModelSource options
if ( driver().isSet() )
conf.merge( driver()->getConfig() );
@@ -105,9 +100,6 @@ ModelLayerOptions::fromConfig( const Config& conf )
conf.getIfSet( "visible", _visible );
conf.getIfSet( "lighting", _lighting );
- // temporary.
- conf.getIfSet( "disable_shaders", _disableShaderComp );
-
if ( conf.hasValue("driver") )
driver() = ModelSourceOptions(conf);
}
@@ -181,12 +173,6 @@ ModelLayer::createSceneGraph(const Map* map,
if ( _modelSource.valid() )
{
- //// if the model source has changed, regenerate the node.
- //if ( _node.valid() && !_modelSource->inSyncWith(_modelSourceRev) )
- //{
- // _node = 0L;
- //}
-
node = _modelSource->createNode( map, dbOptions, progress );
if ( node )
@@ -201,19 +187,6 @@ ModelLayer::createSceneGraph(const Map* map,
setLightingEnabled( *_runtimeOptions.lightingEnabled() );
}
- if ( Registry::instance()->getCapabilities().supportsGLSL() )
- {
- node->addCullCallback( new UpdateLightingUniformsHelper() );
-
- if ( _runtimeOptions.disableShaders() == true )
- {
- osg::StateSet* ss = node->getOrCreateStateSet();
- ss->setAttributeAndModes(
- new osg::Program(),
- osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE );
- }
- }
-
if ( _modelSource->getOptions().depthTestEnabled() == false )
{
osg::StateSet* ss = node->getOrCreateStateSet();
@@ -221,6 +194,12 @@ ModelLayer::createSceneGraph(const Map* map,
ss->setRenderBinDetails( 99999, "RenderBin" ); //TODO: configure this bin ...
}
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ // install a callback that keeps the shader uniforms up to date
+ node->addCullCallback( new UpdateLightingUniformsHelper() );
+ }
+
_modelSource->sync( _modelSourceRev );
// save an observer reference to the node so we can change the visibility/lighting/etc.
@@ -279,14 +258,6 @@ ModelLayer::setLightingEnabled( bool value )
(osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED) );
}
}
-
- //if ( _node.valid() )
- //{
- // _node->getOrCreateStateSet()->setMode(
- // GL_LIGHTING, value ? osg::StateAttribute::ON :
- // (osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED) );
-
- //}
}
bool
diff --git a/src/osgEarth/OverlayDecorator b/src/osgEarth/OverlayDecorator
index cd0f064..c0b7023 100644
--- a/src/osgEarth/OverlayDecorator
+++ b/src/osgEarth/OverlayDecorator
@@ -103,6 +103,14 @@ namespace osgEarth
void setOverlayBlending( bool value );
bool getOverlayBlending() const { return _rttBlending; }
+
+ /**
+ * Whether to attach the RTT to camera to the stencil buffer. Default = true.
+ * Some older cards don't have very good support
+ */
+ void setAttachStencil( bool value );
+ bool getAttachStencil() const;
+
void setOverlayGraphTraversalMask( unsigned mask );
public: // TerrainDecorator
@@ -127,6 +135,7 @@ namespace osgEarth
unsigned _rttTraversalMask;
double _maxHorizonDistance;
+ bool _attachStencil;
osg::ref_ptr<const SpatialReference> _srs;
osg::ref_ptr<const osg::EllipsoidModel> _ellipsoid;
@@ -136,14 +145,14 @@ namespace osgEarth
{
osg::ref_ptr<osg::Camera> _rttCamera;
osg::ref_ptr<osg::Uniform> _texGenUniform;
- osg::ref_ptr<osg::TexGenNode> _texGenNode;
+ osg::ref_ptr<osg::TexGen> _texGen;
osg::Matrixd _rttViewMatrix;
osg::Matrixd _rttProjMatrix;
osg::ref_ptr<osg::StateSet> _subgraphStateSet;
};
- //typedef std::map<osg::Camera*, PerViewData> PerViewDataMap;
- typedef std::map<osg::NodeVisitor*, PerViewData> PerViewDataMap;
+ typedef std::map<osg::Camera*, PerViewData> PerViewDataMap;
+ //typedef std::map<osg::NodeVisitor*, PerViewData> PerViewDataMap;
PerViewDataMap _perViewData;
Threading::ReadWriteMutex _perViewDataMutex;
@@ -155,7 +164,8 @@ namespace osgEarth
void initializePerViewData( PerViewData& );
void initSubgraphShaders( PerViewData& );
bool checkNeedsUpdate( PerViewData& );
- PerViewData& getPerViewData( osg::NodeVisitor* key );
+ PerViewData& getPerViewData( osg::Camera* key );
+ //PerViewData& getPerViewData( osg::NodeVisitor* key );
public:
// marker class for DrapeableNode support.
diff --git a/src/osgEarth/OverlayDecorator.cpp b/src/osgEarth/OverlayDecorator.cpp
index b95f06e..1c4759f 100644
--- a/src/osgEarth/OverlayDecorator.cpp
+++ b/src/osgEarth/OverlayDecorator.cpp
@@ -17,10 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <osgEarth/OverlayDecorator>
+#include <osgEarth/MapInfo>
#include <osgEarth/NodeUtils>
#include <osgEarth/Registry>
#include <osgEarth/TextureCompositor>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/Capabilities>
#include <osg/Texture2D>
#include <osg/TexEnv>
@@ -45,166 +46,6 @@ using namespace osgEarth;
namespace
{
-#if 0
- /**
- * Creates a polytope that minimally bounds a bounding sphere
- * in world space.
- */
- void computeWorldBoundingPolytope(const osg::BoundingSphere& bs,
- const SpatialReference* srs,
- bool geocentric,
- osg::Polytope& out_polytope)
- {
- out_polytope.clear();
- const osg::EllipsoidModel* ellipsoid = srs->getEllipsoid();
-
- // add planes for the four sides of the BS. Normals point inwards.
- out_polytope.add( osg::Plane(osg::Vec3d( 1, 0,0), osg::Vec3d(-bs.radius(),0,0)) );
- out_polytope.add( osg::Plane(osg::Vec3d(-1, 0,0), osg::Vec3d( bs.radius(),0,0)) );
- out_polytope.add( osg::Plane(osg::Vec3d( 0, 1,0), osg::Vec3d(0, -bs.radius(),0)) );
- out_polytope.add( osg::Plane(osg::Vec3d( 0,-1,0), osg::Vec3d(0, bs.radius(),0)) );
-
- // for a projected map, we're done. For a geocentric one, add a bottom cap.
- if ( geocentric )
- {
- // add a bottom cap, unless the bounds are sufficiently large.
- double minRad = std::min(ellipsoid->getRadiusPolar(), ellipsoid->getRadiusEquator());
- double maxRad = std::max(ellipsoid->getRadiusPolar(), ellipsoid->getRadiusEquator());
- double zeroOffset = bs.center().length();
- if ( zeroOffset > minRad * 0.1 )
- {
- out_polytope.add( osg::Plane(osg::Vec3d(0,0,1), osg::Vec3d(0,0,-maxRad+zeroOffset)) );
- }
- }
-
- // transform the clipping planes ito world space localized about the center point
- GeoPoint refPoint;
- refPoint.fromWorld( srs, bs.center() );
- osg::Matrix local2world;
- refPoint.createLocalToWorld( local2world );
-
- out_polytope.transform( local2world );
- }
-
-
- /**
- * Tests whether a "cohesive" point set intersects a polytope. This differs from
- * Polytope::contains(verts); that function tests each point individually, whereas
- * this method tests the point set as a whole (i.e. as the border points of a solid --
- * we are testing whether this solid intersects the polytope.)
- */
- bool pointSetIntersectsClippingPolytope(const std::vector<osg::Vec3>& points, osg::Polytope& pt)
- {
- osg::Polytope::PlaneList& planes = pt.getPlaneList();
- for( osg::Polytope::PlaneList::iterator plane = planes.begin(); plane != planes.end(); ++plane )
- {
- unsigned outsides = 0;
- for( std::vector<osg::Vec3>::const_iterator point = points.begin(); point != points.end(); ++point )
- {
- bool outside = plane->distance( *point ) < 0.0f;
- if ( outside ) outsides++;
- else break;
- }
- if ( outsides == points.size() )
- return false;
- }
- return true;
- }
-
-
- /**
- * Visitor that computes a bounding sphere for the geometry that intersects
- * a frustum polyhedron. Since this is used to project geometry on to the
- * terrain surface, it has to account for geometry that is not clamped --
- * so instead of using the normal bounding sphere it computes a world-space
- * polytope for each geometry and interests that with the frustum.
- */
- struct ComputeBoundsWithinFrustum : public OverlayDecorator::InternalNodeVisitor
- {
- std::vector<osg::Vec3> _frustumVerts;
-
- ComputeBoundsWithinFrustum(const osgShadow::ConvexPolyhedron& frustumPH,
- const SpatialReference* srs,
- bool geocentric,
- osg::BoundingSphere& out_bs)
- : InternalNodeVisitor(),
- _srs ( srs ),
- _geocentric( geocentric ),
- _bs ( out_bs )
- {
- frustumPH.getPolytope( _originalPT );
-
- _polytopeStack.push( _originalPT );
- _local2worldStack.push( osg::Matrix::identity() );
- _world2localStack.push( osg::Matrix::identity() );
-
- // extract the corner verts from the frustum polyhedron; we will use those to
- // test for intersection.
- std::vector<osg::Vec3d> temp;
- temp.reserve( 8 );
- frustumPH.getPoints( temp );
- for( unsigned i=0; i<temp.size(); ++i )
- _frustumVerts.push_back(temp[i]);
- }
-
- bool contains( const osg::BoundingSphere& bs )
- {
- osg::BoundingSphere worldBS( bs.center() * _local2worldStack.top(), bs.radius() );
- osg::Polytope bsWorldPT;
- computeWorldBoundingPolytope( worldBS, _srs, _geocentric, bsWorldPT );
- return pointSetIntersectsClippingPolytope( _frustumVerts, bsWorldPT );
- }
-
- void apply( osg::Node& node )
- {
- const osg::BoundingSphere& bs = node.getBound();
- if ( contains(bs) )
- {
- traverse( node );
- }
- }
-
- void apply( osg::Geode& node )
- {
- const osg::BoundingSphere& bs = node.getBound();
- if ( contains(bs) )
- {
- _bs.expandBy( osg::BoundingSphere(
- bs.center() * _local2worldStack.top(),
- bs.radius() ) );
- }
- }
-
- void apply( osg::Transform& transform )
- {
- osg::Matrixd local2world;
- transform.computeLocalToWorldMatrix( local2world, this );
-
- _local2worldStack.push( local2world );
-
- _polytopeStack.push( _originalPT );
- _polytopeStack.top().transformProvidingInverse( local2world );
-
- osg::Matrix world2local;
- world2local.invert( local2world );
- _world2localStack.push( world2local );
-
- traverse(transform);
-
- _local2worldStack.pop();
- _polytopeStack.pop();
- }
-
- osg::BoundingSphere& _bs;
- const SpatialReference* _srs;
- bool _geocentric;
- osg::Polytope _originalPT;
- std::stack<osg::Polytope> _polytopeStack;
- std::stack<osg::Matrixd> _local2worldStack, _world2localStack;
- };
-#endif
-
-
/**
* This method takes a set of verts and finds the nearest and farthest distances from
* the points to the camera. It does this calculation in the plane defined by the
@@ -275,7 +116,8 @@ _rttBlending ( true ),
_updatePending ( false ),
_dumpRequested ( false ),
_rttTraversalMask( ~0 ),
-_maxHorizonDistance( DBL_MAX )
+_maxHorizonDistance( DBL_MAX ),
+_attachStencil ( true )
{
// nop
}
@@ -323,14 +165,14 @@ OverlayDecorator::initializePerViewData( PerViewData& pvd )
// create the projected texture:
osg::Texture2D* projTexture = new osg::Texture2D();
projTexture->setTextureSize( *_textureSize, *_textureSize );
- projTexture->setInternalFormat( GL_RGBA8 );
+ projTexture->setInternalFormat( GL_RGBA );
projTexture->setSourceFormat( GL_RGBA );
projTexture->setSourceType( GL_UNSIGNED_BYTE );
projTexture->setFilter( osg::Texture::MIN_FILTER, _mipmapping? osg::Texture::LINEAR_MIPMAP_LINEAR: osg::Texture::LINEAR );
projTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
- projTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER );
- projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER );
- projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_BORDER );
+ projTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); //CLAMP_TO_BORDER );
+ projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
+ projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE );
projTexture->setBorderColor( osg::Vec4(0,0,0,0) );
// set up the RTT camera:
@@ -348,30 +190,40 @@ OverlayDecorator::initializePerViewData( PerViewData& pvd )
pvd._rttCamera->attach( osg::Camera::COLOR_BUFFER, projTexture, 0, 0, _mipmapping );
- // try a depth-packed buffer. failing that, try a normal one.. if the FBO doesn't support
- // that (which is doesn't on some GPUs like Intel), it will automatically fall back on
- // a PBUFFER_RTT impl
- if ( Registry::instance()->getCapabilities().supportsDepthPackedStencilBuffer() )
- pvd._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT );
- else
- pvd._rttCamera->attach( osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX );
+ if (_attachStencil) {
+ // try a depth-packed buffer. failing that, try a normal one.. if the FBO doesn't support
+ // that (which is doesn't on some GPUs like Intel), it will automatically fall back on
+ // a PBUFFER_RTT impl
+ if ( Registry::instance()->getCapabilities().supportsDepthPackedStencilBuffer() )
+ {
+#ifdef OSG_GLES2_AVAILABLE
+ pvd._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8_EXT );
+#else
+ pvd._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT );
+#endif
+ }
+ else
+ {
+ pvd._rttCamera->attach( osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX );
+ }
+ }
osg::StateSet* rttStateSet = pvd._rttCamera->getOrCreateStateSet();
rttStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
// install a new default shader program that replaces anything from above.
- VirtualProgram* vp = new VirtualProgram();
- vp->setName( "overlay rtt" );
- vp->installDefaultColoringAndLightingShaders();
- vp->setInheritShaders( false );
- rttStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
+ if ( _useShaders )
+ {
+ VirtualProgram* vp = new VirtualProgram();
+ vp->setName( "overlay rtt" );
+ vp->installDefaultColoringAndLightingShaders();
+ vp->setInheritShaders( false );
+ rttStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
+ }
if ( _rttBlending )
{
- //osg::BlendFunc* blendFunc = new osg::BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- //osg::BlendFunc* blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
//Setup a separate blend function for the alpha components and the RGB components.
//Because the destination alpha is initialized to 0 instead of 1
osg::BlendFunc* blendFunc = 0;
@@ -410,23 +262,23 @@ OverlayDecorator::initializePerViewData( PerViewData& pvd )
// assemble the subgraph stateset:
pvd._subgraphStateSet = new osg::StateSet();
- // set up the subgraph to receive the projected texture:
- pvd._subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_S, osg::StateAttribute::ON );
- pvd._subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_T, osg::StateAttribute::ON );
- pvd._subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_R, osg::StateAttribute::ON );
- pvd._subgraphStateSet->setTextureMode( *_textureUnit, GL_TEXTURE_GEN_Q, osg::StateAttribute::ON );
pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, projTexture, osg::StateAttribute::ON );
if ( _useShaders )
{
- // set up the shaders
+ // GPU path
initSubgraphShaders( pvd );
}
else
{
- // FFP path:
- pvd._texGenNode = new osg::TexGenNode();
- pvd._texGenNode->setTexGen( new osg::TexGen() );
+ // FFP path
+ pvd._texGen = new osg::TexGen();
+ pvd._texGen->setMode( osg::TexGen::EYE_LINEAR );
+ pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, pvd._texGen.get(), 1 );
+
+ osg::TexEnv* env = new osg::TexEnv();
+ env->setMode( osg::TexEnv::DECAL );
+ pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, env, 1 );
}
}
@@ -440,10 +292,10 @@ OverlayDecorator::initSubgraphShaders( PerViewData& pvd )
set->setAttributeAndModes( vp, osg::StateAttribute::ON );
// sampler for projected texture:
- set->getOrCreateUniform( "osgearth_overlay_ProjTex", osg::Uniform::SAMPLER_2D )->set( *_textureUnit );
+ set->getOrCreateUniform( "oe_overlay_ProjTex", osg::Uniform::SAMPLER_2D )->set( *_textureUnit );
// the texture projection matrix uniform.
- pvd._texGenUniform = set->getOrCreateUniform( "osgearth_overlay_TexGenMatrix", osg::Uniform::FLOAT_MAT4 );
+ pvd._texGenUniform = set->getOrCreateUniform( "oe_overlay_TexGenMatrix", osg::Uniform::FLOAT_MAT4 );
// vertex shader - subgraph
std::string vertexSource = Stringify()
@@ -451,16 +303,16 @@ OverlayDecorator::initSubgraphShaders( PerViewData& pvd )
#ifdef OSG_GLES2_AVAILABLE
<< "precision mediump float;\n"
#endif
- << "uniform mat4 osgearth_overlay_TexGenMatrix; \n"
+ << "uniform mat4 oe_overlay_TexGenMatrix; \n"
<< "uniform mat4 osg_ViewMatrixInverse; \n"
<< "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n"
- << "void osgearth_overlay_vertex(void) \n"
+ << "void oe_overlay_vertex(void) \n"
<< "{ \n"
- << " osg_TexCoord["<< *_textureUnit << "] = osgearth_overlay_TexGenMatrix * osg_ViewMatrixInverse * gl_ModelViewMatrix * gl_Vertex; \n"
+ << " osg_TexCoord["<< *_textureUnit << "] = oe_overlay_TexGenMatrix * osg_ViewMatrixInverse * gl_ModelViewMatrix * gl_Vertex; \n"
<< "} \n";
- vp->setFunction( "osgearth_overlay_vertex", vertexSource, ShaderComp::LOCATION_VERTEX_POST_LIGHTING );
+ vp->setFunction( "oe_overlay_vertex", vertexSource, ShaderComp::LOCATION_VERTEX_POST_LIGHTING );
// fragment shader - subgraph
std::string fragmentSource = Stringify()
@@ -468,16 +320,16 @@ OverlayDecorator::initSubgraphShaders( PerViewData& pvd )
#ifdef OSG_GLES2_AVAILABLE
<< "precision mediump float;\n"
#endif
- << "uniform sampler2D osgearth_overlay_ProjTex; \n"
+ << "uniform sampler2D oe_overlay_ProjTex; \n"
<< "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n"
- << "void osgearth_overlay_fragment( inout vec4 color ) \n"
+ << "void oe_overlay_fragment( inout vec4 color ) \n"
<< "{ \n"
<< " vec2 texCoord = osg_TexCoord["<< *_textureUnit << "].xy / osg_TexCoord["<< *_textureUnit << "].q; \n"
- << " vec4 texel = texture2D(osgearth_overlay_ProjTex, texCoord); \n"
+ << " vec4 texel = texture2D(oe_overlay_ProjTex, texCoord); \n"
<< " color = vec4( mix( color.rgb, texel.rgb, texel.a ), color.a); \n"
<< "} \n";
- vp->setFunction( "osgearth_overlay_fragment", fragmentSource, ShaderComp::LOCATION_FRAGMENT_POST_LIGHTING );
+ vp->setFunction( "oe_overlay_fragment", fragmentSource, ShaderComp::LOCATION_FRAGMENT_POST_LIGHTING );
}
void
@@ -575,6 +427,18 @@ OverlayDecorator::setOverlayBlending( bool value )
}
}
+bool
+OverlayDecorator::getAttachStencil() const
+{
+ return _attachStencil;
+}
+
+void
+OverlayDecorator::setAttachStencil( bool value )
+{
+ _attachStencil = value;
+}
+
void
OverlayDecorator::onInstall( TerrainEngineNode* engine )
{
@@ -596,11 +460,13 @@ OverlayDecorator::onInstall( TerrainEngineNode* engine )
// see whether we want shader support:
// TODO: this is not stricty correct; you might still want to use shader overlays
// in multipass mode, AND you might want FFP overlays in multitexture-FFP mode.
- _useShaders = engine->getTextureCompositor()->usesShaderComposition();
+ _useShaders =
+ Registry::capabilities().supportsGLSL() &&
+ engine->getTextureCompositor()->usesShaderComposition();
if ( !_textureSize.isSet() )
{
- unsigned maxSize = Registry::instance()->getCapabilities().getMaxFastTextureSize();
+ unsigned maxSize = Registry::capabilities().getMaxFastTextureSize();
_textureSize.init( osg::minimum( 4096u, maxSize ) );
OE_INFO << LC << "Using texture size = " << *_textureSize << std::endl;
@@ -639,7 +505,7 @@ OverlayDecorator::updateRTTCamera( OverlayDecorator::PerViewData& pvd )
}
else
{
- pvd._texGenNode->getTexGen()->setPlanesFromMatrix( MVPT );
+ pvd._texGen->setPlanesFromMatrix( MVPT );
}
}
@@ -933,7 +799,8 @@ OverlayDecorator::cull( osgUtil::CullVisitor* cv, OverlayDecorator::PerViewData&
}
OverlayDecorator::PerViewData&
-OverlayDecorator::getPerViewData(osg::NodeVisitor* key)
+OverlayDecorator::getPerViewData(osg::Camera* key)
+//OverlayDecorator::getPerViewData(osg::NodeVisitor* key)
{
// first check for it:
{
@@ -967,54 +834,47 @@ OverlayDecorator::getPerViewData(osg::NodeVisitor* key)
void
OverlayDecorator::traverse( osg::NodeVisitor& nv )
{
- bool isCull = nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR;
-
if ( _overlayGraph.valid() && _textureUnit.isSet() )
{
// in the CULL traversal, find the per-view data associated with the
// cull visitor's current camera view and work with that:
- if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
+ if ( nv.getVisitorType() == nv.CULL_VISITOR )
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( &nv );
- PerViewData& pvd = getPerViewData( cv );
- if ( cv->getCurrentCamera() )
+ osg::Camera* camera = cv->getCurrentCamera();
+ if ( camera != 0L && (_rttTraversalMask & nv.getTraversalMask()) != 0 )
{
- if ( (_rttTraversalMask & nv.getTraversalMask()) != 0 )
- {
- if (checkNeedsUpdate(pvd))
- {
- updateRTTCamera(pvd);
- }
+ PerViewData& pvd = getPerViewData( camera );
- if ( pvd._texGenNode.valid() ) // FFP only
- pvd._texGenNode->accept( nv );
-
- cull( cv, pvd );
- pvd._rttCamera->accept( nv );
+ if (checkNeedsUpdate(pvd))
+ {
+ updateRTTCamera(pvd);
}
- else
+
+ if ( pvd._texGen.valid() )
{
- osg::Group::traverse(nv);
+ // FFP path only
+ cv->getCurrentRenderBin()->getStage()->addPositionedTextureAttribute(
+ *_textureUnit, cv->getModelViewMatrix(), pvd._texGen.get() );
}
- }
- // debug-- (draws the overlay at its native location as well)
- //_overlayGraph->accept(nv);
- }
+ cull( cv, pvd );
- else if ( nv.getVisitorType() == nv.UPDATE_VISITOR )
- {
- if ( _overlayGraph.valid() )
+ pvd._rttCamera->accept( nv );
+ }
+ else
{
- _overlayGraph->accept( nv );
+ osg::Group::traverse(nv);
}
- osg::Group::traverse( nv );
+
+ // debug-- (draws the overlay at its native location as well)
+ //_overlayGraph->accept(nv);
}
else
{
- // Some other type of visitor (like an intersection). Skip the RTT camera and
- // traverse the overlay graph directly.
+ // Some other type of visitor (like update or intersection). Skip the RTT camera
+ // and traverse the overlay graph directly.
if ( _overlayGraph.valid() )
{
_overlayGraph->accept( nv );
diff --git a/src/osgEarth/Progress b/src/osgEarth/Progress
index 2c3bc68..767be74 100644
--- a/src/osgEarth/Progress
+++ b/src/osgEarth/Progress
@@ -39,23 +39,53 @@ namespace osgEarth
/**
* Callback function that will be called.
* @param current
- * The current amount of work to be done.
+ * The amount of work done in the current stage
* @param total
- * The total amount of work to be done.
+ * The total amount of work to be done in the current stage
+ * @param stage
+ * Stage of the operation we're currently in
+ * @param totalStages
+ * Total number of stages in the operation
* @param msg
* Description of what is being done. Useful when total is unknown.
* @param returns
* Returns true if the current task should be cancelled, false otherwise.
*/
- virtual bool reportProgress(double current, double total, const std::string& msg = std::string());
+ virtual bool reportProgress(
+ double current,
+ double total,
+ unsigned currentStage,
+ unsigned totalStages,
+ const std::string& msg );
- // called when the process starts
+ /**
+ * Convenience functions
+ */
+ bool reportProgress( double current, double total, const std::string& msg ) {
+ return reportProgress(current, total, 0, 1, msg );
+ }
+ bool reportProgress( double current, double total ) {
+ return reportProgress(current, total, 0, 1, "" );
+ }
+
+ /**
+ * called when the process starts
+ */
virtual void onStarted() { }
- // called when the process completed
+ /**
+ * called when the process completed
+ */
virtual void onCompleted() { }
+ /**
+ * Sets the cancelation flag
+ */
void cancel() { _canceled = true; }
+
+ /**
+ * Whether cancelation was requested
+ */
bool isCanceled() const { return _canceled; }
std::string& message() { return _message; }
@@ -63,18 +93,21 @@ namespace osgEarth
/**
*Whether or not the task should be retried.
*/
- bool needsRetry() const { return _needsRetry;}
+ bool needsRetry() const { return _needsRetry; }
+
/**
- *Sets whether or not the task should be retried
- */
+ * Sets whether or not the task should be retried
+ */
void setNeedsRetry( bool needsRetry ) { _needsRetry = needsRetry; }
protected:
- volatile bool _canceled;
- std::string _message;
- volatile bool _needsRetry;
+ volatile unsigned _numStages;
+ volatile bool _canceled;
+ std::string _message;
+ volatile bool _needsRetry;
};
+
/**
* ConsoleProgressCallback is a simple ProgressCallback that reports progress to the console
*/
@@ -90,13 +123,24 @@ namespace osgEarth
/**
* Callback function that will be called.
* @param current
- * The current amount of work to be done.
+ * The amount of work done in the current stage
* @param total
- * The total amount of work to be done.
+ * The total amount of work to be done in the current stage
+ * @param stage
+ * Stage of the operation we're currently in
+ * @param totalStages
+ * Total number of stages in the operation
+ * @param msg
+ * Description of what is being done. Useful when total is unknown.
* @param returns
* Returns true if the current task should be cancelled, false otherwise.
*/
- virtual bool reportProgress(double current, double total, const std::string& msg = std::string());
+ virtual bool reportProgress(
+ double current,
+ double total,
+ unsigned currentStage,
+ unsigned totalStages,
+ const std::string& msg );
};
}
diff --git a/src/osgEarth/Progress.cpp b/src/osgEarth/Progress.cpp
index 197ef62..5dcf059 100644
--- a/src/osgEarth/Progress.cpp
+++ b/src/osgEarth/Progress.cpp
@@ -24,13 +24,17 @@ using namespace osgEarth;
ProgressCallback::ProgressCallback() :
osg::Referenced( true ),
-_canceled(false),
-_needsRetry(false)
+_canceled ( false ),
+_needsRetry ( false )
{
//NOP
}
-bool ProgressCallback::reportProgress(double /*current*/, double /*total*/, const std::string& /*msg*/)
+bool ProgressCallback::reportProgress(double current,
+ double total,
+ unsigned stage,
+ unsigned numStages,
+ const std::string& msg )
{
return false;
}
@@ -43,12 +47,17 @@ ProgressCallback()
}
bool
-ConsoleProgressCallback::reportProgress(double current, double total, const std::string& msg)
+ConsoleProgressCallback::reportProgress(double current, double total,
+ unsigned stage, unsigned numStages,
+ const std::string& msg)
{
if (total > 0)
{
double percentComplete = (current / total) * 100.0;
- OE_NOTICE << "Completed " << percentComplete << "% " << current << " of " << total << std::endl;
+ OE_NOTICE
+ << "Stage " << (stage+1) << "/" << numStages
+ << "; completed " << percentComplete << "% " << current << " of " << total
+ << std::endl;
}
else
{
diff --git a/src/osgEarth/Registry b/src/osgEarth/Registry
index ebc0a6d..d691ec1 100644
--- a/src/osgEarth/Registry
+++ b/src/osgEarth/Registry
@@ -43,6 +43,7 @@ namespace osgEarth
class TaskServiceManager;
class URIReadCallback;
class ColorFilterRegistry;
+ class StateSetCache;
/**
* Application-wide global repository.
@@ -75,9 +76,20 @@ namespace osgEarth
Cache* getCache() const;
void setCache( Cache* cache );
- /** The system-wide default cache policy */
+ /** The override cache policy (overrides all others if set) */
+ const optional<CachePolicy>& overrideCachePolicy() const { return _overrideCachePolicy; }
+ void setOverrideCachePolicy( const CachePolicy& policy );
+
+ /** The default cache policy (used when no policy is set) */
const optional<CachePolicy>& defaultCachePolicy() const { return _defaultCachePolicy; }
- void setDefaultCachePolicy( const CachePolicy& policy ) { _defaultCachePolicy = policy; }
+ void setDefaultCachePolicy( const CachePolicy& policy );
+
+ /**
+ * Gets the cache policy.
+ * First checks for an override policy; then looks in the DB::Options for one,
+ * then checks for the default policy; then returns false as a last resort.
+ */
+ bool getCachePolicy( optional<CachePolicy>& cp, const osgDB::Options* options =0L ) const;
/**
* Whether the given filename is blacklisted
@@ -121,6 +133,14 @@ namespace osgEarth
void setShaderFactory( ShaderFactory* lib );
/**
+ * A default StateSetCache to use by any process that uses one.
+ * A StateSetCache assist in stateset sharing across multiple nodes.
+ */
+ StateSetCache* getStateSetCache() const;
+ void setStateSetCache( StateSetCache* cache );
+ static StateSetCache* stateSetCache() { return instance()->getStateSetCache(); }
+
+ /**
* Gets a reference to the global task service manager.
*/
TaskServiceManager* getTaskServiceManager() {
@@ -188,6 +208,7 @@ namespace osgEarth
osg::ref_ptr<Cache> _cache;
optional<CachePolicy> _defaultCachePolicy;
+ optional<CachePolicy> _overrideCachePolicy;
typedef std::set<std::string> StringSet;
StringSet _blacklistedFilenames;
@@ -211,6 +232,8 @@ namespace osgEarth
typedef std::vector<const Units*> UnitsVector;
UnitsVector _unitsVector;
+ osg::ref_ptr<StateSetCache> _stateSetCache;
+
std::string _terrainEngineDriver;
};
}
diff --git a/src/osgEarth/Registry.cpp b/src/osgEarth/Registry.cpp
index ec39de7..dbaf68f 100644
--- a/src/osgEarth/Registry.cpp
+++ b/src/osgEarth/Registry.cpp
@@ -19,10 +19,12 @@
#include <osgEarth/Registry>
#include <osgEarth/Capabilities>
#include <osgEarth/Cube>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/ShaderFactory>
#include <osgEarth/TaskService>
#include <osgEarth/IOTypes>
#include <osgEarth/ColorFilter>
+#include <osgEarth/StateSetCache>
#include <osgEarthDrivers/cache_filesystem/FileSystemCache>
#include <osg/Notify>
#include <osg/Version>
@@ -62,6 +64,7 @@ _terrainEngineDriver( "osgterrain" )
_shaderLib = new ShaderFactory();
_taskServiceManager = new TaskServiceManager();
+ _stateSetCache = new StateSetCache();
// activate KMZ support
osgDB::Registry::instance()->addArchiveExtension ( "kmz" );
@@ -108,23 +111,17 @@ _terrainEngineDriver( "osgterrain" )
// activate cache-only mode from the environment
if ( ::getenv("OSGEARTH_CACHE_ONLY") )
{
- _defaultCachePolicy = CachePolicy::CACHE_ONLY;
+ setOverrideCachePolicy( CachePolicy::CACHE_ONLY );
OE_INFO << LC << "CACHE-ONLY MODE set from environment variable" << std::endl;
}
// activate no-cache mode from the environment
else if ( ::getenv("OSGEARTH_NO_CACHE") )
{
- _defaultCachePolicy = CachePolicy::NO_CACHE;
+ setOverrideCachePolicy( CachePolicy::NO_CACHE );
OE_INFO << LC << "NO-CACHE MODE set from environment variable" << std::endl;
}
- // if there's a default caching policy, add it to the default options.
- if ( _defaultCachePolicy.isSet() )
- {
- _defaultCachePolicy->apply( _defaultOptions.get() );
- }
-
// set the default terrain engine driver from the environment
const char* teStr = ::getenv("OSGEARTH_TERRAIN_ENGINE");
if ( teStr )
@@ -282,6 +279,48 @@ Registry::getNamedProfile( const std::string& name ) const
return NULL;
}
+void
+Registry::setDefaultCachePolicy( const CachePolicy& value )
+{
+ _defaultCachePolicy = value;
+ if ( !_overrideCachePolicy.isSet() )
+ _defaultCachePolicy->apply(_defaultOptions.get());
+ else
+ _overrideCachePolicy->apply(_defaultOptions.get());
+}
+
+void
+Registry::setOverrideCachePolicy( const CachePolicy& value )
+{
+ _overrideCachePolicy = value;
+ _overrideCachePolicy->apply( _defaultOptions.get() );
+}
+
+bool
+Registry::getCachePolicy( optional<CachePolicy>& cp, const osgDB::Options* options ) const
+{
+ if ( overrideCachePolicy().isSet() )
+ {
+ // if there is a system-wide override in place, use it.
+ cp = overrideCachePolicy().value();
+ }
+ else
+ {
+ // Try to read the cache policy from the db-options
+ CachePolicy::fromOptions( options, cp );
+
+ if ( !cp.isSet() )
+ {
+ if ( defaultCachePolicy().isSet() )
+ {
+ cp = defaultCachePolicy().value();
+ }
+ }
+ }
+
+ return cp.isSet();
+}
+
osgEarth::Cache*
Registry::getCache() const
{
@@ -443,6 +482,18 @@ Registry::setDefaultTerrainEngineDriverName(const std::string& name)
_terrainEngineDriver = name;
}
+void
+Registry::setStateSetCache( StateSetCache* cache )
+{
+ _stateSetCache = cache;
+}
+
+StateSetCache*
+Registry::getStateSetCache() const
+{
+ return _stateSetCache.get();
+}
+
//Simple class used to add a file extension alias for the earth_tile to the earth plugin
class RegisterEarthTileExtension
diff --git a/src/osgEarth/Revisioning b/src/osgEarth/Revisioning
index 7f511c4..ac20587 100644
--- a/src/osgEarth/Revisioning
+++ b/src/osgEarth/Revisioning
@@ -157,8 +157,8 @@ namespace osgEarth
struct DirtyCounter : public osg::Referenced
{
DirtyCounter(DirtyNotifier* owner) : _owner(owner), _count(1) { }
- int _count;
DirtyNotifier* _owner;
+ int _count;
friend class DirtyNotifer;
};
osg::ref_ptr<DirtyCounter> _counter;
diff --git a/src/osgEarth/Revisioning.cpp b/src/osgEarth/Revisioning.cpp
index 2e416af..baba623 100644
--- a/src/osgEarth/Revisioning.cpp
+++ b/src/osgEarth/Revisioning.cpp
@@ -23,69 +23,6 @@
using namespace osgEarth;
-//------------------------------------------------------------------------
-
-#if 0
-void
-Revisioned::dirty()
-{
- _revision->operator++();
-
- if ( _parents.size() > 0 )
- {
- for( std::vector< osg::observer_ptr<osg::Referenced> >::iterator i = _parents.begin(); i != _parents.end(); )
- {
- RefRevisioned* r = static_cast<RefRevisioned*>( i->get() );
- if ( r && r->get() )
- {
- r->get()->dirty();
- ++i;
- }
- else
- {
- i = _parents.erase( i );
- }
- }
- }
-}
-
-
-void
-Revisioned::addParent( Revisioned* parent )
-{
- if ( parent )
- {
- _parents.push_back( new RefRevisioned(parent) );
- parent->dirty();
- }
-}
-
-
-void
-Revisioned::removeParent( Revisioned* parent )
-{
- for( std::vector< osg::observer_ptr<osg::Referenced> >::iterator i = _parents.begin(); i != _parents.end(); )
- {
- if ( i->valid() )
- {
- RefRevisioned* r = static_cast<RefRevisioned*>( i->get() );
- if ( r->get() == parent )
- {
- i = _parents.erase( i );
- }
- else
- {
- ++i;
- }
- }
- else
- {
- i = _parents.erase( i );
- }
- }
-}
-#endif
-
//------------------------------------------------------------------------
@@ -153,6 +90,3 @@ DirtyNotifier::setDirty()
}
}
}
-
-
-//------------------------------------------------------------------------
\ No newline at end of file
diff --git a/src/osgEarth/ShaderFactory b/src/osgEarth/ShaderFactory
new file mode 100644
index 0000000..7e8a429
--- /dev/null
+++ b/src/osgEarth/ShaderFactory
@@ -0,0 +1,98 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+* Copyright 2008-2012 Pelican Mapping
+* http://osgearth.org
+*
+* osgEarth is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>
+*/
+#ifndef OSGEARTH_SHADER_FACTORY_H
+#define OSGEARTH_SHADER_FACTORY_H 1
+
+#include <osgEarth/Common>
+#include <osgEarth/VirtualProgram>
+
+namespace osgEarth
+{
+ /**
+ * A factory class that generates shader functions for the osgEarth engine.
+ * The default ShaderFactory is stored in the osgEarth registry. You can replace it
+ * if you want to replace osgEarth's default shader templates.
+ */
+ class OSGEARTH_EXPORT ShaderFactory : public osg::Referenced
+ {
+ public:
+ /** Creates a vertex shader main(). */
+ virtual osg::Shader* createVertexShaderMain(
+ const ShaderComp::FunctionLocationMap& functions =ShaderComp::FunctionLocationMap(),
+ bool useLightingShaders =true ) const;
+
+ /** Creates a fragment shader main(). */
+ virtual osg::Shader* createFragmentShaderMain(
+ const ShaderComp::FunctionLocationMap& functions =ShaderComp::FunctionLocationMap(),
+ bool useLightingShaders =true ) const;
+
+ /**
+ * Gets the uniform/shader name of the sampler corresponding the the provider
+ * texture image unit
+ */
+ virtual std::string getSamplerName( unsigned texImageUnit ) const;
+
+ /**
+ * Creates the function that sets up default texcoords in the vertex shader.
+ * The name/prototype is:
+ * void osgearth_vert_setupColoring();
+ */
+ virtual osg::Shader* createDefaultColoringVertexShader( unsigned numTexCoordSets ) const;
+
+ /**
+ * Creates the function that applies texture data in the fragment shader.
+ * The name/prototype is:
+ * osgearth_frag_applyColoring( inout vec4 color );
+ */
+ virtual osg::Shader* createDefaultColoringFragmentShader( unsigned numTexCoordSets ) const;
+
+ /**
+ * Creates the function that applies lighting calculations in the vertex shader.
+ * The name/prototype is:
+ * void osgearth_vert_setupLighting();
+ */
+ virtual osg::Shader* createDefaultLightingVertexShader() const;
+
+ /**
+ * Creates the function that applies lighting coloring in the fragment shader.
+ * The name/prototype is:
+ * void osgearth_frag_applyLighting( inout vec4 color );
+ */
+ virtual osg::Shader* createDefaultLightingFragmentShader() const;
+
+ /**
+ * Builds a shader that executes an image filter chain.
+ */
+ virtual osg::Shader* createColorFilterChainFragmentShader( const std::string& function, const ColorFilterChain& chain ) const;
+
+ /**
+ * Gets a uniform corresponding to the given mode and value
+ */
+ virtual osg::Uniform* createUniformForGLMode(
+ osg::StateAttribute::GLMode mode,
+ osg::StateAttribute::GLModeValue value );
+
+ /** dtor */
+ virtual ~ShaderFactory() { }
+ };
+
+
+} // namespace osgEarth
+
+#endif // OSGEARTH_SHADER_FACTORY_H
diff --git a/src/osgEarth/ShaderFactory.cpp b/src/osgEarth/ShaderFactory.cpp
new file mode 100644
index 0000000..c61f7f3
--- /dev/null
+++ b/src/osgEarth/ShaderFactory.cpp
@@ -0,0 +1,588 @@
+/* -*-c++-*- */
+/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
+ * Copyright 2008-2012 Pelican Mapping
+ * http://osgearth.org
+ *
+ * osgEarth is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+#include <osgEarth/ShaderFactory>
+
+#include <osgEarth/ShaderUtils>
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osg/Shader>
+#include <osg/Program>
+#include <osg/State>
+#include <osg/Notify>
+#include <sstream>
+
+#define LC "[ShaderFactory] "
+
+#define VERTEX_SETUP_COLORING "osgearth_vert_setupColoring"
+#define VERTEX_SETUP_LIGHTING "osgearth_vert_setupLighting"
+#define FRAGMENT_APPLY_COLORING "osgearth_frag_applyColoring"
+#define FRAGMENT_APPLY_LIGHTING "osgearth_frag_applyLighting"
+
+#ifdef OSG_GLES2_AVAILABLE
+# define PRECISION_MEDIUMP_FLOAT "precision mediump float;"
+ static bool s_GLES_SHADERS = true;
+# define GLENNS_PER_VERTEX_LIGHTING 1
+#else
+# define PRECISION_MEDIUMP_FLOAT ""
+ static bool s_GLES_SHADERS = false;
+# define GLENNS_PER_VERTEX_LIGHTING 1
+#endif
+
+
+using namespace osgEarth;
+using namespace osgEarth::ShaderComp;
+
+
+std::string
+ShaderFactory::getSamplerName( unsigned unit ) const
+{
+ return Stringify() << "osgearth_tex" << unit;
+}
+
+
+osg::Shader*
+ShaderFactory::createVertexShaderMain(const FunctionLocationMap& functions,
+ bool useLightingShaders ) const
+{
+ FunctionLocationMap::const_iterator i = functions.find( LOCATION_VERTEX_PRE_TEXTURING );
+ const OrderedFunctionMap* preTexture = i != functions.end() ? &i->second : 0L;
+
+ FunctionLocationMap::const_iterator j = functions.find( LOCATION_VERTEX_PRE_LIGHTING );
+ const OrderedFunctionMap* preLighting = j != functions.end() ? &j->second : 0L;
+
+ FunctionLocationMap::const_iterator k = functions.find( LOCATION_VERTEX_POST_LIGHTING );
+ const OrderedFunctionMap* postLighting = k != functions.end() ? &k->second : 0L;
+
+ std::stringstream buf;
+ buf << "#version " << GLSL_VERSION_STR << "\n"
+ << PRECISION_MEDIUMP_FLOAT "\n"
+ << "void osgearth_vert_setupColoring(); \n";
+
+ if ( useLightingShaders )
+ buf << "void osgearth_vert_setupLighting(); \n";
+
+ if ( preTexture )
+ for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
+ buf << "void " << i->second << "(); \n";
+
+ if ( preLighting )
+ for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
+ buf << "void " << i->second << "(); \n";
+
+ if ( postLighting )
+ for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
+ buf << "void " << i->second << "(); \n";
+
+ buf << "void main(void) \n"
+ << "{ \n"
+ << " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n";
+
+ if ( preTexture )
+ for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
+ buf << " " << i->second << "(); \n";
+
+ buf << " osgearth_vert_setupColoring(); \n";
+
+ if ( preLighting )
+ for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
+ buf << " " << i->second << "(); \n";
+
+ if ( useLightingShaders )
+ buf << " osgearth_vert_setupLighting(); \n";
+
+ if ( postLighting )
+ for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
+ buf << " " << i->second << "(); \n";
+
+ buf << "} \n";
+
+ std::string str;
+ str = buf.str();
+ osg::Shader* shader = new osg::Shader( osg::Shader::VERTEX, str );
+ shader->setName( "main(vert)" );
+ return shader;
+}
+
+
+osg::Shader*
+ShaderFactory::createFragmentShaderMain(const FunctionLocationMap& functions,
+ bool useLightingShaders ) const
+{
+ FunctionLocationMap::const_iterator i = functions.find( LOCATION_FRAGMENT_PRE_TEXTURING );
+ const OrderedFunctionMap* preTexture = i != functions.end() ? &i->second : 0L;
+
+ FunctionLocationMap::const_iterator j = functions.find( LOCATION_FRAGMENT_PRE_LIGHTING );
+ const OrderedFunctionMap* preLighting = j != functions.end() ? &j->second : 0L;
+
+ FunctionLocationMap::const_iterator k = functions.find( LOCATION_FRAGMENT_POST_LIGHTING );
+ const OrderedFunctionMap* postLighting = k != functions.end() ? &k->second : 0L;
+
+ std::stringstream buf;
+ buf << "#version " << GLSL_VERSION_STR << "\n"
+ << PRECISION_MEDIUMP_FLOAT << "\n"
+ << "void osgearth_frag_applyColoring( inout vec4 color ); \n";
+
+ if ( useLightingShaders )
+ buf << "void osgearth_frag_applyLighting( inout vec4 color ); \n";
+
+ if ( preTexture )
+ for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
+ buf << "void " << i->second << "( inout vec4 color ); \n";
+
+ if ( preLighting )
+ for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
+ buf << "void " << i->second << "( inout vec4 color ); \n";
+
+ if ( postLighting )
+ for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
+ buf << "void " << i->second << "( inout vec4 color ); \n";
+
+ buf << "void main(void) \n"
+ << "{ \n"
+ << " vec4 color = vec4(1,1,1,1); \n"; //gl_Color; \n";
+
+ if ( preTexture )
+ for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
+ buf << " " << i->second << "( color ); \n";
+
+ buf << " osgearth_frag_applyColoring( color ); \n";
+
+ if ( preLighting )
+ for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
+ buf << " " << i->second << "( color ); \n";
+
+ if ( useLightingShaders )
+ buf << " osgearth_frag_applyLighting( color ); \n";
+
+ if ( postLighting )
+ for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
+ buf << " " << i->second << "( color ); \n";
+
+ buf << " gl_FragColor = color; \n"
+
+#if 0 // GW: testing logarithmic depth buffer remapping
+ << " float A = gl_ProjectionMatrix[2].z; \n"
+ << " float B = gl_ProjectionMatrix[3].z; \n"
+ << " float n = -B/(1.0-A); \n"
+ << " float f = B/(1.0+A); \n"
+ << " float C = 1; \n"
+ << " gl_FragDepth = log(C*gl_FragCoord.z+1) / log(C*f+1); \n"
+#endif
+ << "} \n";
+
+ std::string str;
+ str = buf.str();
+ osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
+ shader->setName( "main(frag)" );
+ return shader;
+}
+
+
+osg::Shader*
+ShaderFactory::createDefaultColoringVertexShader( unsigned numTexCoordSets ) const
+{
+ std::stringstream buf;
+
+ buf <<
+ "#version " << GLSL_VERSION_STR << "\n"
+ PRECISION_MEDIUMP_FLOAT "\n";
+
+ buf << "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n";
+
+ buf
+ << "varying vec4 osg_FrontColor; \n"
+ << "varying vec4 osg_FrontSecondaryColor; \n"
+
+ << "void osgearth_vert_setupColoring() \n"
+ << "{ \n"
+ << " osg_FrontColor = gl_Color; \n"
+ << " osg_FrontSecondaryColor = vec4(0.0); \n";
+
+ //TODO: gl_TexCoord et.al. are depcrecated so we should replace them;
+ // this approach also only support up to 8 texture coord units
+ for(unsigned i=0; i<numTexCoordSets; ++i )
+ {
+ buf << " osg_TexCoord["<< i <<"] = gl_MultiTexCoord"<< i << "; \n";
+ }
+
+ buf << "} \n";
+
+ std::string str;
+ str = buf.str();
+
+ osg::Shader* shader = new osg::Shader(osg::Shader::VERTEX, str);
+ shader->setName( VERTEX_SETUP_COLORING );
+ return shader;
+}
+
+
+osg::Shader*
+ShaderFactory::createDefaultColoringFragmentShader( unsigned numTexImageUnits ) const
+{
+ std::stringstream buf;
+
+ buf << "#version " << GLSL_VERSION_STR << "\n"
+ << PRECISION_MEDIUMP_FLOAT << "\n";
+
+ buf << "varying vec4 osg_FrontColor; \n";
+
+ if ( numTexImageUnits > 0 )
+ {
+ buf << "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n";
+ buf << "uniform sampler2D ";
+ for( unsigned i=0; i<numTexImageUnits; ++i )
+ {
+ buf << getSamplerName(i) << (i+1 < numTexImageUnits? "," : "; \n");
+ }
+ }
+
+ buf << "void osgearth_frag_applyColoring( inout vec4 color ) \n"
+ << "{ \n"
+ << " color = color * osg_FrontColor; \n";
+
+ if ( numTexImageUnits > 0 )
+ {
+ buf << " vec4 texel; \n";
+
+ for(unsigned i=0; i<numTexImageUnits; ++i )
+ {
+ buf << " texel = texture2D(" << getSamplerName(i) << ", osg_TexCoord["<< i <<"].st); \n";
+ buf << " color.rgb = mix( color.rgb, texel.rgb, texel.a ); \n";
+ if ( i == 0 )
+ buf << " color.a = texel.a * color.a; \n";
+ }
+ }
+
+ buf << "} \n";
+
+ std::string str;
+ str = buf.str();
+
+ osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
+ shader->setName( FRAGMENT_APPLY_COLORING );
+ return shader;
+}
+
+#ifdef GLENNS_PER_VERTEX_LIGHTING
+
+osg::Shader*
+ShaderFactory::createDefaultLightingVertexShader() const
+{
+ std::string str = Stringify() <<
+
+ "#version " GLSL_VERSION_STR "\n"
+ PRECISION_MEDIUMP_FLOAT "\n"
+
+ "uniform bool oe_mode_GL_LIGHTING; \n"
+ "varying vec4 oe_lighting_adjustment; \n"
+ "varying vec4 oe_zero_vec; \n"
+
+ "void osgearth_vert_setupLighting() \n"
+ "{ \n"
+ " oe_lighting_adjustment = vec4(1.0); \n"
+ " if (oe_mode_GL_LIGHTING) \n"
+ " { \n"
+ " vec3 N = normalize(gl_NormalMatrix * gl_Normal); \n"
+ " float NdotL = dot( N, normalize(gl_LightSource[0].position.xyz) ); \n"
+ " NdotL = max( 0.0, NdotL ); \n"
+ " oe_zero_vec = vec4(0.0); \n"
+ " vec4 adj = \n"
+ //" gl_FrontLightModelProduct.sceneColor + \n" // not available in GLES yet
+ " gl_FrontLightProduct[0].ambient + \n"
+ " gl_FrontLightProduct[0].diffuse * NdotL; \n"
+ " oe_lighting_adjustment = clamp( adj, 0.0, 1.0 ); \n"
+ " } \n"
+ "} \n";
+
+ osg::Shader* shader = new osg::Shader( osg::Shader::VERTEX, str );
+ shader->setName( VERTEX_SETUP_LIGHTING );
+ return shader;
+}
+
+
+osg::Shader*
+ShaderFactory::createDefaultLightingFragmentShader() const
+{
+ std::string str = Stringify() <<
+
+ "#version " GLSL_VERSION_STR "\n"
+ PRECISION_MEDIUMP_FLOAT "\n"
+
+ "varying vec4 oe_lighting_adjustment; \n"
+ "varying vec4 oe_zero_vec; \n"
+
+ "uniform bool oe_mode_GL_LIGHTING; \n"
+ "void osgearth_frag_applyLighting( inout vec4 color ) \n"
+ "{ \n"
+ " if ( oe_mode_GL_LIGHTING ) \n"
+ " { \n"
+ " float alpha = color.a; \n"
+ " color = color * oe_lighting_adjustment + oe_zero_vec; \n"
+ " color.a = alpha; \n"
+ " } \n"
+ "} \n";
+
+ osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
+ shader->setName( FRAGMENT_APPLY_LIGHTING );
+ return shader;
+}
+
+#endif
+
+
+#ifdef GLENNS_PER_FRAGMENT_LIGHTING // does not work on GLES - unresolved
+
+osg::Shader*
+ShaderFactory::createDefaultLightingVertexShader() const
+{
+ std::string str = Stringify() <<
+
+ "#version " GLSL_VERSION_STR "\n"
+ PRECISION_MEDIUMP_FLOAT "\n"
+
+ "uniform bool oe_mode_GL_LIGHTING; \n"
+ "varying vec3 oe_lighting_normal; \n"
+
+ "void osgearth_vert_setupLighting() \n"
+ "{ \n"
+ " if (oe_mode_GL_LIGHTING) \n"
+ " { \n"
+ " oe_lighting_normal = normalize(gl_NormalMatrix * gl_Normal); \n"
+ " } \n"
+ "} \n";
+
+ osg::Shader* shader = new osg::Shader( osg::Shader::VERTEX, str );
+ shader->setName( VERTEX_SETUP_LIGHTING );
+ return shader;
+}
+
+
+osg::Shader*
+ShaderFactory::createDefaultLightingFragmentShader() const
+{
+ std::string str = Stringify() <<
+
+ "#version " GLSL_VERSION_STR "\n"
+ PRECISION_MEDIUMP_FLOAT "\n"
+
+ "uniform bool oe_mode_GL_LIGHTING; \n"
+ "varying vec3 oe_lighting_normal; \n"
+
+ "void osgearth_frag_applyLighting( inout vec4 color ) \n"
+ "{ \n"
+ " if ( oe_mode_GL_LIGHTING ) \n"
+ " { \n"
+ " float alpha = color.a; \n"
+ " vec3 n = normalize( oe_lighting_normal ); \n"
+ " float NdotL = dot( n, normalize(gl_LightSource[0].position.xyz) ); \n"
+ " NdotL = max( 0.0, NdotL ); \n"
+ " vec4 adjustment = \n"
+ //" gl_FrontLightModelProduct.sceneColor + \n" // not available in GLES yet
+ " gl_FrontLightProduct[0].ambient + \n"
+ " gl_FrontLightProduct[0].diffuse * NdotL; \n"
+ " color *= clamp(adjustment, 0.0, 1.0); \n"
+
+ // specular highlights: (skip them for now)
+ //" float NdotHV = dot( n, gl_LightSource[0].halfVector.xyz ); \n"
+ //" NdotHV = max( 0.0, NdotHV ); \n"
+ //" if ( NdotL * NdotHV > 0.0 ) \n"
+ //" color += gl_FrontLightProduct[0].specular * \n"
+ //" pow( NdotHV, gl_FrontMaterial.shininess ); \n"
+
+ " color.a = alpha; \n"
+ " } \n"
+ "} \n";
+
+ osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
+ shader->setName( FRAGMENT_APPLY_LIGHTING );
+ return shader;
+}
+
+#endif // GLENNS_PER_FRAGMENT_LIGHTING
+
+
+#ifdef TOMS_PER_VERTEX_LIGHTING
+
+osg::Shader*
+ShaderFactory::createDefaultLightingVertexShader() const
+{
+ int maxLights = Registry::capabilities().getMaxLights();
+
+ std::stringstream buf;
+ buf << "#version " << GLSL_VERSION_STR << "\n";
+
+ if ( s_GLES_SHADERS )
+ {
+ buf << "precision mediump float;\n"
+ << osg_LightSourceParameters::glslDefinition() << "\n"
+ << osg_LightProducts::glslDefinition() << "\n"
+ << "uniform osg_LightSourceParameters osg_LightSource0;\n"
+ << "uniform osg_LightProducts osg_FrontLightProduct0;\n";
+ }
+
+ buf
+ << "varying vec4 osg_FrontColor; \n"
+ << "varying vec4 osg_FrontSecondaryColor; \n"
+ << "uniform bool oe_mode_GL_LIGHTING; \n";
+
+ if ( s_GLES_SHADERS )
+ {
+ buf
+ << "void osgearth_vert_setupLighting() \n"
+ << "{ \n"
+ << " if (oe_mode_GL_LIGHTING) \n"
+ << " { \n"
+ << " float shine = 10.0;\n"
+ << " vec4 lightModelAmbi = vec4(0.1,0.1,0.1,1.0);\n"
+ //gl_FrontMaterial.shininess
+ //gl_LightModel.ambient
+ << " vec3 normal = gl_NormalMatrix * gl_Normal; \n"
+ << " float NdotL = dot( normal, normalize(osg_LightSource0.position.xyz) ); \n"
+ << " NdotL = max( 0.0, NdotL ); \n"
+ << " float NdotHV = dot( normal, osg_LightSource0.halfVector.xyz ); \n"
+ << " NdotHV = max( 0.0, NdotHV ); \n"
+
+ << " osg_FrontColor.rgb = osg_FrontColor.rgb * \n"
+ << " clamp( \n"
+ << " lightModelAmbi + \n"
+ << " osg_FrontLightProduct0.ambient + \n"
+ << " osg_FrontLightProduct0.diffuse * NdotL, 0.0, 1.0).rgb; \n"
+
+ << " osg_FrontSecondaryColor = vec4(0.0); \n"
+
+ << " if ( NdotL * NdotHV > 0.0 ) \n"
+ << " { \n"
+ << " osg_FrontSecondaryColor.rgb = (osg_FrontLightProduct0.specular * \n"
+ << " pow( NdotHV, shine )).rgb;\n"
+ << " } \n"
+ << " } \n"
+ << "} \n";
+ }
+ else // !s_GLES_SHADERS
+ {
+ buf
+ << "void osgearth_vert_setupLighting() \n"
+ << "{ \n"
+ << " if (oe_mode_GL_LIGHTING) \n"
+ << " { \n"
+ << " vec3 normal = gl_NormalMatrix * gl_Normal; \n"
+ << " float NdotL = dot( normal, normalize(gl_LightSource[0].position.xyz) ); \n"
+ << " NdotL = max( 0.0, NdotL ); \n"
+ << " float NdotHV = dot( normal, gl_LightSource[0].halfVector.xyz ); \n"
+ << " NdotHV = max( 0.0, NdotHV ); \n"
+
+ << " osg_FrontColor.rgb = osg_FrontColor.rgb * \n"
+ << " clamp( \n"
+ << " gl_LightModel.ambient + \n"
+ << " gl_FrontLightProduct[0].ambient + \n"
+ << " gl_FrontLightProduct[0].diffuse * NdotL, 0.0, 1.0).rgb; \n"
+
+ << " osg_FrontSecondaryColor = vec4(0.0); \n"
+ << " if ( NdotL * NdotHV > 0.0 ) \n"
+ << " { \n"
+ << " osg_FrontSecondaryColor.rgb = (gl_FrontLightProduct[0].specular * \n"
+ << " pow( NdotHV, gl_FrontMaterial.shininess )).rgb;\n"
+ << " } \n"
+ << " } \n"
+ << "} \n";
+ }
+
+ osg::Shader* shader = new osg::Shader( osg::Shader::VERTEX, buf.str().c_str() );
+ shader->setName( VERTEX_SETUP_LIGHTING );
+ return shader;
+}
+
+
+osg::Shader*
+ShaderFactory::createDefaultLightingFragmentShader() const
+{
+ std::stringstream buf;
+
+ buf << "#version " << GLSL_VERSION_STR << "\n"
+ << PRECISION_MEDIUMP_FLOAT << "\n"
+
+ << "varying vec4 osg_FrontColor; \n"
+ << "varying vec4 osg_FrontSecondaryColor; \n"
+
+ << "uniform bool oe_mode_GL_LIGHTING; \n"
+ << "void osgearth_frag_applyLighting( inout vec4 color ) \n"
+ << "{ \n"
+ << " if ( oe_mode_GL_LIGHTING ) \n"
+ << " { \n"
+ << " float alpha = color.a; \n"
+ << " color = (color * osg_FrontColor) + osg_FrontSecondaryColor; \n"
+ << " color.a = alpha; \n"
+ << " } \n"
+ << "} \n";
+
+ osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, buf.str().c_str() );
+ shader->setName( FRAGMENT_APPLY_LIGHTING );
+ return shader;
+}
+
+#endif // TOMS_PER_VERTEX_LIGHTING
+
+
+osg::Shader*
+ShaderFactory::createColorFilterChainFragmentShader( const std::string& function, const ColorFilterChain& chain ) const
+{
+ std::stringstream buf;
+ buf << "#version " << GLSL_VERSION_STR << "\n"
+ << PRECISION_MEDIUMP_FLOAT << "\n";
+
+ // write out the shader function prototypes:
+ for( ColorFilterChain::const_iterator i = chain.begin(); i != chain.end(); ++i )
+ {
+ ColorFilter* filter = i->get();
+ buf << "void " << filter->getEntryPointFunctionName() << "(in int slot, inout vec4 color);\n";
+ }
+
+ // write out the main function:
+ buf << "void " << function << "(in int slot, inout vec4 color) \n"
+ << "{ \n";
+
+ // write out the function calls. if there are none, it's a NOP.
+ for( ColorFilterChain::const_iterator i = chain.begin(); i != chain.end(); ++i )
+ {
+ ColorFilter* filter = i->get();
+ buf << " " << filter->getEntryPointFunctionName() << "(slot, color);\n";
+ }
+
+ buf << "} \n";
+
+ std::string bufstr;
+ bufstr = buf.str();
+ return new osg::Shader(osg::Shader::FRAGMENT, bufstr);
+}
+
+
+osg::Uniform*
+ShaderFactory::createUniformForGLMode(osg::StateAttribute::GLMode mode,
+ osg::StateAttribute::GLModeValue value)
+{
+ osg::Uniform* u = 0L;
+
+ if ( mode == GL_LIGHTING )
+ {
+ osg::Uniform* u = new osg::Uniform(osg::Uniform::BOOL, "oe_mode_GL_LIGHTING");
+ u->set( (value & osg::StateAttribute::ON) != 0 );
+ }
+
+ return u;
+}
diff --git a/src/osgEarth/ShaderGenerator b/src/osgEarth/ShaderGenerator
index 4bd0346..51fcafd 100644
--- a/src/osgEarth/ShaderGenerator
+++ b/src/osgEarth/ShaderGenerator
@@ -21,9 +21,10 @@
#define OSGEARTH_SHADER_GENERATOR_H 1
#include <osgEarth/Common>
+#include <osgEarth/StateSetCache>
+#include <osgEarth/VirtualProgram>
#include <osg/NodeVisitor>
#include <osg/State>
-#include <osgEarth/StateSetCache>
namespace osgEarth
{
@@ -46,6 +47,7 @@ namespace osgEarth
*/
ShaderGenerator( StateSetCache* cache );
+ /** dtor. */
virtual ~ShaderGenerator() { }
@@ -59,11 +61,15 @@ namespace osgEarth
void apply( osg::Drawable* );
- bool generate( osg::StateSet* stateSet, osg::ref_ptr<osg::StateSet>& replacement );
+ bool processGeometry( osg::StateSet* stateSet, osg::ref_ptr<osg::StateSet>& replacement );
+
+ bool processText( osg::StateSet* stateSet, osg::ref_ptr<osg::StateSet>& replacement );
osg::ref_ptr<osg::State> _state;
osg::ref_ptr<StateSetCache> _stateSetCache;
+
+ osg::ref_ptr<VirtualProgram> _defaultVP;
};
} // namespace osgEarth
diff --git a/src/osgEarth/ShaderGenerator.cpp b/src/osgEarth/ShaderGenerator.cpp
index 5e1de73..17419c7 100644
--- a/src/osgEarth/ShaderGenerator.cpp
+++ b/src/osgEarth/ShaderGenerator.cpp
@@ -17,11 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
+#include <osgEarth/Capabilities>
+#include <osgEarth/Registry>
+#include <osgEarth/ShaderFactory>
#include <osgEarth/ShaderGenerator>
-#include <osgEarth/ShaderComposition>
#include <osgEarth/StringUtils>
-#include <osgEarth/Registry>
-#include <osgEarth/Capabilities>
#include <osg/Drawable>
#include <osg/Geode>
@@ -29,6 +29,7 @@
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osg/TexEnv>
+#include <osgText/Text>
#define LC "[ShaderGenerator] "
@@ -51,10 +52,12 @@ using namespace osgEarth;
#endif
// shader names
-#define TEX_COORD "oe_sg_texcoord"
-#define SAMPLER "oe_sg_sampler"
-#define ATTRIB "oe_sg_attrib"
-#define TEXENV_COLOR "oe_sg_texenvcolor"
+#define TEX_COORD "oe_sg_texcoord"
+#define TEX_COORD_TEXT "oe_sg_texcoord_text"
+#define SAMPLER "oe_sg_sampler"
+#define SAMPLER_TEXT "oe_sg_sampler_text"
+#define ATTRIB "oe_sg_attrib"
+#define TEXENV_COLOR "oe_sg_texenvcolor"
#define VERTEX_FUNCTION "oe_sg_vert"
#define FRAGMENT_FUNCTION "oe_sg_frag"
@@ -136,6 +139,8 @@ osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
{
_state = new StateEx();
_stateSetCache = new StateSetCache();
+ _defaultVP = new VirtualProgram();
+ _defaultVP->installDefaultColoringAndLightingShaders();
}
@@ -144,6 +149,8 @@ osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
{
_state = new StateEx();
_stateSetCache = cache ? cache : new StateSetCache();
+ _defaultVP = new VirtualProgram();
+ _defaultVP->installDefaultColoringAndLightingShaders();
}
@@ -156,7 +163,7 @@ ShaderGenerator::apply( osg::Node& node )
_state->pushStateSet( ss.get() );
osg::ref_ptr<osg::StateSet> replacement;
- if ( generate(ss.get(), replacement) )
+ if ( processGeometry(ss.get(), replacement) )
{
_state->popStateSet();
node.setStateSet( replacement.get() );
@@ -182,7 +189,7 @@ ShaderGenerator::apply( osg::Geode& geode )
_state->pushStateSet( ss.get() );
osg::ref_ptr<osg::StateSet> replacement;
- if ( generate(ss.get(), replacement) )
+ if ( processGeometry(ss.get(), replacement) )
{
_state->popStateSet();
geode.setStateSet( replacement.get() );
@@ -211,11 +218,22 @@ ShaderGenerator::apply( osg::Drawable* drawable )
if ( ss.valid() )
{
_state->pushStateSet(ss.get());
-
+
osg::ref_ptr<osg::StateSet> replacement;
- if ( generate(ss.get(), replacement) )
+
+ if ( dynamic_cast<osgText::Text*>(drawable) != 0L )
+ {
+ if ( processText(ss.get(), replacement) )
+ {
+ drawable->setStateSet( replacement.get() );
+ }
+ }
+ else
{
- drawable->setStateSet(replacement.get());
+ if ( processGeometry(ss.get(), replacement) )
+ {
+ drawable->setStateSet(replacement.get());
+ }
}
_state->popStateSet();
@@ -225,7 +243,7 @@ ShaderGenerator::apply( osg::Drawable* drawable )
bool
-ShaderGenerator::generate( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& replacement )
+ShaderGenerator::processText( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& replacement )
{
// do nothing if there's no GLSL support
if ( !Registry::capabilities().supportsGLSL() )
@@ -240,28 +258,89 @@ ShaderGenerator::generate( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& repla
if ( dynamic_cast<osg::Program*>(program) != 0L )
return false;
- // New stateset that we'll merge with the existing one.
- osg::ref_ptr<osg::StateSet> newStateSet = new osg::StateSet();
+ // see if the current state set contains a VirtualProgram already. If so,
+ // we will add to it if necessary.
+ VirtualProgram* vp = dynamic_cast<VirtualProgram*>( ss->getAttribute(VirtualProgram::SA_TYPE) );
+
+ replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL);
+
+ std::string vertSrc =
+ "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION "\n"
+ "varying " MEDIUMP "vec4 " TEX_COORD_TEXT ";\n"
+ "void " VERTEX_FUNCTION "()\n"
+ "{ \n"
+ INDENT TEX_COORD_TEXT " = gl_MultiTexCoord0;\n"
+ "} \n";
+
+ std::string fragSrc =
+ "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION "\n"
+ "uniform sampler2D " SAMPLER_TEXT ";\n"
+ "varying " MEDIUMP "vec4 " TEX_COORD_TEXT ";\n"
+ "void " FRAGMENT_FUNCTION "(inout vec4 color)\n"
+ "{ \n"
+ INDENT MEDIUMP "vec4 texel = texture2D(" SAMPLER_TEXT ", " TEX_COORD_TEXT ".xy);\n"
+ INDENT "color.a *= texel.a; \n"
+ "}\n";
+
+ if ( !vp )
+ vp = osg::clone( _defaultVP.get() );
+ replacement->setAttributeAndModes( vp, osg::StateAttribute::ON );
+
+ vp->setUseLightingShaders( false );
+ vp->setFunction( VERTEX_FUNCTION, vertSrc, ShaderComp::LOCATION_VERTEX_PRE_LIGHTING );
+ vp->setFunction( FRAGMENT_FUNCTION, fragSrc, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
+ replacement->getOrCreateUniform( SAMPLER_TEXT, osg::Uniform::SAMPLER_2D )->set( 0 );
+
+ return replacement.valid();
+}
+
+
+bool
+ShaderGenerator::processGeometry( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& replacement )
+{
+ // do nothing if there's no GLSL support
+ if ( !Registry::capabilities().supportsGLSL() )
+ return false;
+
+ // State object with extra accessors:
+ StateEx* state = static_cast<StateEx*>(_state.get());
+
+ // check for a real osg::Program in the whole state stack. If it exists, bail out
+ // so that OSG can use the program already in the graph. We never override a
+ // full Program.
+ osg::StateAttribute* program = state->getAttribute(osg::StateAttribute::PROGRAM);
+ if ( dynamic_cast<osg::Program*>(program) != 0L )
+ return false;
+
+ // see if the current state set contains a VirtualProgram already. If so,
+ // we will add to it if necessary.
+ VirtualProgram* vp = dynamic_cast<VirtualProgram*>( ss->getAttribute(VirtualProgram::SA_TYPE) );
- // check whether the lighting state has changed.
+ // Check whether the lighting state has changed and install a mode uniform.
if ( ss->getMode(GL_LIGHTING) != osg::StateAttribute::INHERIT )
{
+ if ( !replacement.valid() )
+ replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL);
+
+ ShaderFactory* sf = Registry::instance()->getShaderFactory();
osg::StateAttribute::GLModeValue value = state->getMode(GL_LIGHTING); // from the state, not the ss.
- osg::Uniform* lighting = newStateSet->getOrCreateUniform( "osgearth_LightingEnabled", osg::Uniform::BOOL );
- lighting->set( (value & osg::StateAttribute::ON) != 0 );
+ replacement->addUniform( sf->createUniformForGLMode(GL_LIGHTING, value) );
}
// if the stateset changes any texture attributes, we need a new virtual program:
- if ( ss->getTextureAttributeList().size() > 0 )
+ if (ss->getTextureAttributeList().size() > 0)
{
+ if ( !replacement.valid() )
+ replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL);
+
// work off the state's accumulated texture attribute set:
int texCount = state->getNumTextureAttributes();
- // check for an existing VirtualProgram; if found, we'll add to it.
- // if not, we'll make a new one.
- osg::ref_ptr<VirtualProgram> vp = dynamic_cast<VirtualProgram*>(program);
- if ( !vp.valid() )
- vp = new VirtualProgram();
+ if ( !vp )
+ {
+ vp = osg::clone( _defaultVP.get() );
+ replacement->setAttributeAndModes( vp, osg::StateAttribute::ON );
+ }
// start generating the shader source.
std::stringstream vertHead, vertBody, fragHead, fragBody;
@@ -277,9 +356,10 @@ ShaderGenerator::generate( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& repla
for( int t = 0; t < texCount; ++t )
{
- //todo: consider TexEnv for DECAL/MODULATE
-
- fragBody << INDENT << MEDIUMP "vec4 texel; \n";
+ if (t == 0)
+ {
+ fragBody << INDENT << MEDIUMP "vec4 texel; \n";
+ }
osg::StateAttribute* tex = state->getTextureAttribute( t, osg::StateAttribute::TEXTURE );
if ( tex )
@@ -292,7 +372,7 @@ ShaderGenerator::generate( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& repla
blendingMode = env->getMode();
if ( blendingMode == osg::TexEnv::BLEND )
{
- newStateSet->getOrCreateUniform( Stringify() << TEXENV_COLOR << t, osg::Uniform::FLOAT_VEC4 )->set( env->getColor() );
+ replacement->getOrCreateUniform( Stringify() << TEXENV_COLOR << t, osg::Uniform::FLOAT_VEC4 )->set( env->getColor() );
}
}
@@ -305,19 +385,19 @@ ShaderGenerator::generate( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& repla
{
fragHead << "uniform sampler1D " SAMPLER << t << ";\n";
fragBody << INDENT "texel = texture1D(" SAMPLER << t << ", " TEX_COORD << t << ".x);\n";
- newStateSet->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_1D )->set( t );
+ replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_1D )->set( t );
}
else if ( dynamic_cast<osg::Texture2D*>(tex) )
{
fragHead << "uniform sampler2D " SAMPLER << t << ";\n";
fragBody << INDENT "texel = texture2D(" SAMPLER << t << ", " TEX_COORD << t << ".xy);\n";
- newStateSet->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D )->set( t );
+ replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D )->set( t );
}
else if ( dynamic_cast<osg::Texture3D*>(tex) )
{
fragHead << "uniform sampler3D " SAMPLER << t << ";\n";
fragBody << INDENT "texel = texture3D(" SAMPLER << t << ", " TEX_COORD << t << ".xyz);\n";
- newStateSet->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_3D )->set( t );
+ replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_3D )->set( t );
}
// See http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
@@ -367,23 +447,7 @@ ShaderGenerator::generate( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& repla
// inject the shaders:
vp->setFunction( VERTEX_FUNCTION, vertSrc, ShaderComp::LOCATION_VERTEX_PRE_LIGHTING );
vp->setFunction( FRAGMENT_FUNCTION, fragSrc, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
-
- // optimize sharing of VPs.
- newStateSet->setAttributeAndModes( vp.get(), osg::StateAttribute::ON );
-
- //osg::ref_ptr<osg::StateAttribute> sharedVP;
- //_stateSetCache->share( vp.get(), sharedVP );
- //newStateSet->setAttributeAndModes( sharedVP.get(), osg::StateAttribute::ON );
}
- // pop the current stateset off the stack so we can change it:
- osg::ref_ptr<osg::StateSet> current = osg::clone( ss );
-
- // merge in the new state set:
- current->merge( *newStateSet.get() );
-
- // optimize sharing:
- _stateSetCache->share(current, replacement);
-
- return true;
+ return replacement.valid();
}
diff --git a/src/osgEarth/ShaderUtils b/src/osgEarth/ShaderUtils
index 39e938e..b59b64f 100644
--- a/src/osgEarth/ShaderUtils
+++ b/src/osgEarth/ShaderUtils
@@ -30,22 +30,36 @@
namespace osgEarth
{
/**
+ * ShaderPolicy encodes general behavior when deciding how to
+ * employ shaders in certain situations
+ */
+ enum ShaderPolicy
+ {
+ SHADERPOLICY_DISABLE,
+ SHADERPOLICY_GENERATE,
+ SHADERPOLICY_INHERIT
+ };
+
+
+ /**
* Container for light uniforms
*/
//light product
- class osg_LightProducts
+ struct osg_LightProducts
{
- public:
osg_LightProducts(int id);
osg::ref_ptr<osg::Uniform> ambient; // vec4
osg::ref_ptr<osg::Uniform> diffuse; // vec4
osg::ref_ptr<osg::Uniform> specular; //vec4
+
+ // GLSL strings
+ static std::string glslDefinition();
};
-
- class osg_LightSourceParameters
+
+
+ struct osg_LightSourceParameters
{
- public:
osg_LightSourceParameters(int id);
void setUniformsFromOsgLight(const osg::Light* light, osg::Matrix viewMatrix, const osg::Material* frontMat);
@@ -57,17 +71,30 @@ namespace osgEarth
osg::ref_ptr<osg::Uniform> position; // vec4
osg::ref_ptr<osg::Uniform> halfVector; // vec4
osg::ref_ptr<osg::Uniform> spotDirection; // vec3
- osg::ref_ptr<osg::Uniform> spotExponent; // float
- osg::ref_ptr<osg::Uniform> spotCutoff; // float
- osg::ref_ptr<osg::Uniform> spotCosCutoff; // float
+ osg::ref_ptr<osg::Uniform> spotExponent; // float
+ osg::ref_ptr<osg::Uniform> spotCutoff; // float
+ osg::ref_ptr<osg::Uniform> spotCosCutoff; // float
osg::ref_ptr<osg::Uniform> constantAttenuation; // float
osg::ref_ptr<osg::Uniform> linearAttenuation; // float
osg::ref_ptr<osg::Uniform> quadraticAttenuation; // float
//just store the light product in here
osg_LightProducts _frontLightProduct;
+
+ // GLSL strings
+ static std::string glslDefinition();
+ };
+
+ /**
+ * Preprocesses GLES shader source to include our osg_LightProducts and osg_LightSourceParameters
+ * definitions and uniforms.
+ */
+ class OSGEARTH_EXPORT ShaderPreProcessor
+ {
+ public:
+ static void run(osg::Shader* shader);
};
-
+
/**
* A callback that will update the osgEarth lighting uniforms (based on the
* FFP lighting state) if necessary.
diff --git a/src/osgEarth/ShaderUtils.cpp b/src/osgEarth/ShaderUtils.cpp
index fac88e2..4402220 100644
--- a/src/osgEarth/ShaderUtils.cpp
+++ b/src/osgEarth/ShaderUtils.cpp
@@ -28,6 +28,13 @@ using namespace osgEarth;
namespace
{
+#if !defined(OSG_GL_FIXED_FUNCTION_AVAILABLE)
+ static bool s_NO_FFP = true;
+#else
+ static bool s_NO_FFP = false;
+#endif
+
+
typedef std::list<const osg::StateSet*> StateSetStack;
static osg::StateAttribute::GLModeValue
@@ -122,10 +129,98 @@ namespace
//------------------------------------------------------------------------
+namespace State_Utils
+{
+ // Code borrowed from osg::State.cpp
+ bool replace(std::string& str, const std::string& original_phrase, const std::string& new_phrase)
+ {
+ bool replacedStr = false;
+ std::string::size_type pos = 0;
+ while((pos=str.find(original_phrase, pos))!=std::string::npos)
+ {
+ std::string::size_type endOfPhrasePos = pos+original_phrase.size();
+ if (endOfPhrasePos<str.size())
+ {
+ char c = str[endOfPhrasePos];
+ if ((c>='0' && c<='9') ||
+ (c>='a' && c<='z') ||
+ (c>='A' && c<='Z') ||
+ (c==']'))
+ {
+ pos = endOfPhrasePos;
+ continue;
+ }
+ }
+
+ replacedStr = true;
+ str.replace(pos, original_phrase.size(), new_phrase);
+ }
+ return replacedStr;
+ }
+
+ void replaceAndInsertDeclaration(std::string& source, std::string::size_type declPos, const std::string& originalStr, const std::string& newStr, const std::string& declarationPrefix, const std::string& declarationSuffix ="")
+ {
+ if (replace(source, originalStr, newStr))
+ {
+ source.insert(declPos, declarationPrefix + newStr + declarationSuffix + std::string(";\n"));
+ }
+ }
+}
+
+void
+ShaderPreProcessor::run(osg::Shader* shader)
+{
+ // only runs for non-FFP (GLES, GL3+, etc.)
+
+ if ( s_NO_FFP && shader )
+ {
+ std::string source = shader->getShaderSource();
+
+ // find the first legal insertion point for replacement declarations. GLSL requires that nothing
+ // precede a "#verson" compiler directive, so we must insert new declarations after it.
+ std::string::size_type declPos = source.rfind( "#version " );
+ if ( declPos != std::string::npos )
+ {
+ // found the string, now find the next linefeed and set the insertion point after it.
+ declPos = source.find( '\n', declPos );
+ declPos = declPos != std::string::npos ? declPos+1 : source.length();
+ }
+ else
+ {
+ declPos = 0;
+ }
+
+ int maxLights = Registry::capabilities().getMaxLights();
+
+ for( int i=0; i<maxLights; ++i )
+ {
+ State_Utils::replaceAndInsertDeclaration(
+ source, declPos,
+ Stringify() << "gl_LightSource[" << i << "]",
+ Stringify() << "osg_LightSource" << i,
+ Stringify()
+ << osg_LightSourceParameters::glslDefinition() << "\n"
+ << "uniform osg_LightSourceParameters " );
+
+ State_Utils::replaceAndInsertDeclaration(
+ source, declPos,
+ Stringify() << "gl_FrontLightProduct[" << i << "]",
+ Stringify() << "osg_FrontLightProduct" << i,
+ Stringify()
+ << osg_LightProducts::glslDefinition() << "\n"
+ << "uniform osg_LightProducts " );
+ }
+
+ shader->setShaderSource( source );
+ }
+}
+
+//------------------------------------------------------------------------
+
osg_LightProducts::osg_LightProducts(int id)
{
std::stringstream uniNameStream;
- uniNameStream << "osg_FrontLightProduct[" << id << "]";
+ uniNameStream << "osg_FrontLightProduct" << id; //[" << id << "]";
std::string uniName = uniNameStream.str();
ambient = new osg::Uniform(osg::Uniform::FLOAT_VEC4, uniName+".ambient"); // vec4
@@ -133,11 +228,24 @@ osg_LightProducts::osg_LightProducts(int id)
specular = new osg::Uniform(osg::Uniform::FLOAT_VEC4, uniName+".specular"); // vec4
}
+std::string
+osg_LightProducts::glslDefinition()
+{
+ return
+ "struct osg_LightProducts {"
+ " vec4 ambient;"
+ " vec4 diffuse;"
+ " vec4 specular;"
+ " };";
+}
+
+//------------------------------------------------------------------------
+
osg_LightSourceParameters::osg_LightSourceParameters(int id)
: _frontLightProduct(id)
{
std::stringstream uniNameStream;
- uniNameStream << "osg_LightSource[" << id << "]";
+ uniNameStream << "osg_LightSource" << id; // [" << id << "]";
std::string uniName = uniNameStream.str();
ambient = new osg::Uniform(osg::Uniform::FLOAT_VEC4, uniName+".ambient"); // vec4
@@ -224,6 +332,28 @@ void osg_LightSourceParameters::applyState(osg::StateSet* stateset)
stateset->addUniform(_frontLightProduct.specular.get());
}
+std::string
+osg_LightSourceParameters::glslDefinition()
+{
+ return
+ "struct osg_LightSourceParameters {"
+ " vec4 ambient;"
+ " vec4 diffuse;"
+ " vec4 specular;"
+ " vec4 position;"
+ " vec4 halfVector;"
+ " vec3 spotDirection;"
+ " float spotExponent;"
+ " float spotCutoff;"
+ " float spotCosCutoff;"
+ " float constantAttenuation;"
+ " float linearAttenuation;"
+ " float quadraticAttenuation;"
+ " };";
+}
+
+//------------------------------------------------------------------------
+
#undef LC
#define LC "[UpdateLightingUniformHelper] "
@@ -238,17 +368,17 @@ _useUpdateTrav ( useUpdateTrav )
_lightEnabled = new bool[ _maxLights ];
if ( _maxLights > 0 ){
- _lightEnabled[0] = 1;
+ _lightEnabled[0] = true;
//allocate light
_osgLightSourceParameters.push_back(osg_LightSourceParameters(0));
}
for(int i=1; i<_maxLights; ++i ){
- _lightEnabled[i] = 0;
+ _lightEnabled[i] = true;
_osgLightSourceParameters.push_back(osg_LightSourceParameters(i));
}
- _lightingEnabledUniform = new osg::Uniform( osg::Uniform::BOOL, "osgearth_LightingEnabled" );
- _lightEnabledUniform = new osg::Uniform( osg::Uniform::INT, "osgearth_LightEnabled", _maxLights );
+ _lightingEnabledUniform = new osg::Uniform( osg::Uniform::BOOL, "oe_mode_GL_LIGHTING" );
+ _lightEnabledUniform = new osg::Uniform( osg::Uniform::BOOL, "oe_mode_GL_LIGHT", _maxLights );
if ( !_useUpdateTrav )
{
@@ -286,7 +416,7 @@ UpdateLightingUniformsHelper::cullTraverse( osg::Node* node, osg::NodeVisitor* n
// Update the overall lighting-enabled value:
bool lightingEnabled =
( getModeValue(stateSetStack, GL_LIGHTING) & osg::StateAttribute::ON ) != 0;
-
+
if ( lightingEnabled != _lightingEnabled || !_applied )
{
_lightingEnabled = lightingEnabled;
@@ -296,30 +426,50 @@ UpdateLightingUniformsHelper::cullTraverse( osg::Node* node, osg::NodeVisitor* n
_lightingEnabledUniform->set( _lightingEnabled );
}
- // Update the list of enabled lights:
- for( int i=0; i < _maxLights; ++i )
+ osg::View* view = cv->getCurrentCamera()->getView();
+ if ( view )
{
- bool enabled =
- ( getModeValue( stateSetStack, GL_LIGHT0 + i ) & osg::StateAttribute::ON ) != 0;
-
- const osg::Light* light = getLightByID(stateSetStack, i);
- const osg::Material* material = getFrontMaterial(stateSetStack);
+ osg::Light* light = view->getLight();
+ if ( light )
+ {
+ const osg::Material* material = getFrontMaterial(stateSetStack);
+ _osgLightSourceParameters[0].setUniformsFromOsgLight(light, cv->getCurrentCamera()->getViewMatrix(), material);
+ }
+ }
- if ( _lightEnabled[i] != enabled || !_applied )
+ else
+ {
+ // Update the list of enabled lights:
+ for( int i=0; i < _maxLights; ++i )
{
- _lightEnabled[i] = enabled;
- if ( _useUpdateTrav ){
- _dirty = true;
- }else{
- _lightEnabledUniform->setElement( i, _lightEnabled[i] );
+ bool enabled =
+ ( getModeValue( stateSetStack, GL_LIGHT0 + i ) & osg::StateAttribute::ON ) != 0;
+
+ const osg::Light* light = getLightByID(stateSetStack, i);
+ const osg::Material* material = getFrontMaterial(stateSetStack);
+
+ if ( light )
+ {
+ OE_NOTICE << "Found Light " << i << std::endl;
}
- }
-
- //update light position info regardsless of if applied for now
- if(light){
- _osgLightSourceParameters[i].setUniformsFromOsgLight(light, cv->getCurrentCamera()->getViewMatrix(), material);
- }
- }
+
+ if ( _lightEnabled[i] != enabled || !_applied )
+ {
+ _lightEnabled[i] = enabled;
+ if ( _useUpdateTrav ){
+ _dirty = true;
+ }else{
+ _lightEnabledUniform->setElement( i, _lightEnabled[i] );
+ }
+ }
+
+ //update light position info regardsless of if applied for now
+ if(light){
+ OE_NOTICE << "Setting light source params." << std::endl;
+ _osgLightSourceParameters[i].setUniformsFromOsgLight(light, cv->getCurrentCamera()->getViewMatrix(), material);
+ }
+ }
+ }
// apply if necessary:
if ( !_applied && !_useUpdateTrav )
diff --git a/src/osgEarth/StateSetCache b/src/osgEarth/StateSetCache
index 1f0f857..d55be5c 100644
--- a/src/osgEarth/StateSetCache
+++ b/src/osgEarth/StateSetCache
@@ -36,6 +36,16 @@ namespace osgEarth
virtual ~StateSetCache() { }
/**
+ * Check whether a StateSet is eligible for sharing.
+ */
+ bool eligible( osg::StateSet* stateSet ) const;
+
+ /**
+ * Check whether a StateAttribute is eligible for sharing.
+ */
+ bool eligible( osg::StateAttribute* attr ) const;
+
+ /**
* Traverse the node and consolidate equivalent state sets, updating
* the cache along the way.
*/
@@ -50,7 +60,8 @@ namespace osgEarth
*/
bool share(
osg::ref_ptr<osg::StateSet>& input,
- osg::ref_ptr<osg::StateSet>& output );
+ osg::ref_ptr<osg::StateSet>& output,
+ bool checkEligible =true );
/**
* Looks in the attribute cache for an attribute matching the input.
@@ -61,13 +72,19 @@ namespace osgEarth
*/
bool share(
osg::ref_ptr<osg::StateAttribute>& input,
- osg::ref_ptr<osg::StateAttribute>& output );
+ osg::ref_ptr<osg::StateAttribute>& output,
+ bool checkEligible =true );
/**
* Number of statesets in the cache.
*/
unsigned size() const { return _stateSetCache.size(); }
+ /**
+ * Clears out the cache.
+ */
+ void clear();
+
protected:
struct CompareStateSets {
bool operator()(
diff --git a/src/osgEarth/StateSetCache.cpp b/src/osgEarth/StateSetCache.cpp
index 47c947b..610bf9b 100644
--- a/src/osgEarth/StateSetCache.cpp
+++ b/src/osgEarth/StateSetCache.cpp
@@ -19,6 +19,7 @@
#include <osgEarth/StateSetCache>
#include <osg/NodeVisitor>
#include <osg/Geode>
+#include <osg/BufferIndexBinding>
#define LC "[StateSetCache] "
@@ -172,23 +173,76 @@ StateSetCache::optimize(osg::Node* node)
bool
-StateSetCache::share(osg::ref_ptr<osg::StateSet>& input,
- osg::ref_ptr<osg::StateSet>& output )
+StateSetCache::eligible(osg::StateSet* stateSet) const
{
- Threading::ScopedMutexLock lock( _mutex );
+ if ( !stateSet )
+ return false;
- std::pair<StateSetSet::iterator,bool> result = _stateSetCache.insert( input );
- if ( result.second )
+ // DYNAMIC means the user intends to change it later. So it needs to
+ // stay independent.
+ if ( stateSet->getDataVariance() == osg::Object::DYNAMIC )
+ return false;
+
+ const osg::StateSet::AttributeList& attrs = stateSet->getAttributeList();
+ for( osg::StateSet::AttributeList::const_iterator i = attrs.begin(); i != attrs.end(); ++i )
{
- // first use
- output = input.get();
+ osg::StateAttribute* a = i->second.first.get();
+ if ( !eligible(a) )
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+StateSetCache::eligible(osg::StateAttribute* attr) const
+{
+ if ( !attr )
return false;
+
+ // DYNAMIC means the user intends to change it later. So it needs to
+ // stay independent.
+ if ( attr->getDataVariance() == osg::Object::DYNAMIC )
+ return false;
+
+ // cannot share BIB's. They don't clone well since they have underlying buffer objects
+ // that may be in use. It results in OpenGL invalid enumerant errors and errors such as
+ // "uniform block xxx has no binding"
+ if (dynamic_cast<osg::BufferIndexBinding*>(attr) != 0L)
+ return false;
+
+ return true;
+}
+
+
+bool
+StateSetCache::share(osg::ref_ptr<osg::StateSet>& input,
+ osg::ref_ptr<osg::StateSet>& output,
+ bool checkEligible)
+{
+ if ( !checkEligible || eligible(input.get()) )
+ {
+ Threading::ScopedMutexLock lock( _mutex );
+
+ std::pair<StateSetSet::iterator,bool> result = _stateSetCache.insert( input );
+ if ( result.second )
+ {
+ // first use
+ output = input.get();
+ return false;
+ }
+ else
+ {
+ // found a share!
+ output = result.first->get();
+ return true;
+ }
}
else
{
- // found a share!
- output = result.first->get();
- return true;
+ output = input.get();
+ return false;
}
}
@@ -196,21 +250,40 @@ StateSetCache::share(osg::ref_ptr<osg::StateSet>& input,
bool
StateSetCache::share(osg::ref_ptr<osg::StateAttribute>& input,
- osg::ref_ptr<osg::StateAttribute>& output)
+ osg::ref_ptr<osg::StateAttribute>& output,
+ bool checkEligible)
{
- Threading::ScopedMutexLock lock( _mutex );
-
- std::pair<StateAttributeSet::iterator,bool> result = _stateAttributeCache.insert( input );
- if ( result.second )
+ if ( !checkEligible || eligible(input.get()) )
{
- // first use
- output = input.get();
- return false;
+ Threading::ScopedMutexLock lock( _mutex );
+
+ std::pair<StateAttributeSet::iterator,bool> result = _stateAttributeCache.insert( input );
+ if ( result.second )
+ {
+ // first use
+ output = input.get();
+ return false;
+ }
+ else
+ {
+ // found a share!
+ output = result.first->get();
+ return true;
+ }
}
else
{
- // found a share!
- output = result.first->get();
- return true;
+ output = input.get();
+ return false;
}
}
+
+
+void
+StateSetCache::clear()
+{
+ Threading::ScopedMutexLock lock( _mutex );
+
+ _stateAttributeCache.clear();
+ _stateSetCache.clear();
+}
diff --git a/src/osgEarth/Terrain b/src/osgEarth/Terrain
index 685ccb0..1aa276c 100644
--- a/src/osgEarth/Terrain
+++ b/src/osgEarth/Terrain
@@ -95,6 +95,9 @@ namespace osgEarth
double y,
double* out_heightAboveMSL,
double* out_heightAboveEllipsoid =0L) const =0;
+
+ /** dtor */
+ virtual ~TerrainHeightProvider() { }
};
diff --git a/src/osgEarth/TerrainEngineNode b/src/osgEarth/TerrainEngineNode
index 611ef04..a474b3b 100644
--- a/src/osgEarth/TerrainEngineNode
+++ b/src/osgEarth/TerrainEngineNode
@@ -20,6 +20,7 @@
#define OSGEARTH_TERRAIN_ENGINE_NODE_H 1
#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
#include <osgEarth/Terrain>
#include <osgEarth/TextureCompositor>
#include <osgEarth/ShaderUtils>
diff --git a/src/osgEarth/TerrainEngineNode.cpp b/src/osgEarth/TerrainEngineNode.cpp
index 72908b9..b80cc6d 100644
--- a/src/osgEarth/TerrainEngineNode.cpp
+++ b/src/osgEarth/TerrainEngineNode.cpp
@@ -21,6 +21,7 @@
#include <osgEarth/Registry>
#include <osgEarth/TextureCompositor>
#include <osgEarth/NodeUtils>
+#include <osgEarth/MapModelChange>
#include <osgDB/ReadFile>
#include <osg/CullFace>
#include <osg/PolygonOffset>
@@ -353,7 +354,7 @@ TerrainEngineNode::updateImageUniforms()
// layer count has changed, but the shader has not yet caught up. In the future we might use this to disable
// "ghost" layers that used to exist at a given index, but no longer do.
- _imageLayerController->_layerVisibleUniform.attach( "osgearth_ImageLayerVisible", osg::Uniform::BOOL, stateSet, MAX_IMAGE_LAYERS );
+ _imageLayerController->_layerVisibleUniform.attach( "osgearth_ImageLayerVisible", osg::Uniform::BOOL, stateSet, mapf.imageLayers().size() );
_imageLayerController->_layerOpacityUniform.attach( "osgearth_ImageLayerOpacity", osg::Uniform::FLOAT, stateSet, mapf.imageLayers().size() );
_imageLayerController->_layerRangeUniform.attach ( "osgearth_ImageLayerRange", osg::Uniform::FLOAT, stateSet, 2 * mapf.imageLayers().size() );
@@ -429,7 +430,7 @@ TerrainEngineNode::traverse( osg::NodeVisitor& nv )
}
- if ( Registry::instance()->getCapabilities().supportsGLSL() )
+ if ( Registry::capabilities().supportsGLSL() )
{
_updateLightingUniformsHelper.cullTraverse( this, &nv );
diff --git a/src/osgEarth/TerrainLayer.cpp b/src/osgEarth/TerrainLayer.cpp
index 4df7302..fa6528e 100644
--- a/src/osgEarth/TerrainLayer.cpp
+++ b/src/osgEarth/TerrainLayer.cpp
@@ -587,8 +587,8 @@ TerrainLayer::initTileSource()
bool
TerrainLayer::isKeyValid(const TileKey& key) const
-{
- if (!key.valid() || _tileSourceInitFailed)
+{
+ if (!key.valid())
return false;
// Check to see if an explicity max LOD is set. Do NOT compare against the minLevel,
@@ -650,31 +650,25 @@ TerrainLayer::setDBOptions( const osgDB::Options* dbOptions )
void
TerrainLayer::initializeCachePolicy( const osgDB::Options* options )
{
- // establish this layer's cache policy.
+ optional<CachePolicy> cp;
+
if ( _initOptions.cachePolicy().isSet() )
{
- // if this layer defines its own CP, use it.
- setCachePolicy( *_initOptions.cachePolicy() );
+ // if the initialization options specify a cache policy, attempt to use it
+ osg::ref_ptr<osgDB::Options> temp = Registry::instance()->cloneOrCreateOptions(options);
+ _initOptions.cachePolicy()->apply( temp.get() );
+
+ if ( ! Registry::instance()->getCachePolicy(cp, temp.get()) )
+ cp = CachePolicy::DEFAULT;
}
- else
+ else
{
- // see if the new DBOptions has one set; if so, inherit that:
- optional<CachePolicy> incomingCP;
- if ( CachePolicy::fromOptions(options, incomingCP) )
- {
- setCachePolicy( incomingCP.get() );
- }
- else if ( Registry::instance()->defaultCachePolicy().isSet() )
- {
- // not set, no try to inherit from the registry:
- setCachePolicy( Registry::instance()->defaultCachePolicy().value() );
- }
- else
- {
- // not found anywhere; set to the default.
- setCachePolicy( CachePolicy::DEFAULT );
- }
+ // otherwise go the normal route.
+ if ( ! Registry::instance()->getCachePolicy(cp, options) )
+ cp = CachePolicy::DEFAULT;
}
+
+ setCachePolicy( *cp );
}
void
diff --git a/src/osgEarth/TerrainOptions b/src/osgEarth/TerrainOptions
index 16303c2..c0c3e68 100644
--- a/src/osgEarth/TerrainOptions
+++ b/src/osgEarth/TerrainOptions
@@ -145,14 +145,7 @@ namespace osgEarth
* Default = 6.0.
*/
optional<float>& minTileRangeFactor() { return _minTileRangeFactor; }
- const optional<float>& minTileRangeFactor() const { return _minTileRangeFactor; }
-
- /**
- * Whether to monitor terrain tile boundaries and match up the vertices.
- * Default = false.
- */
- optional<bool>& normalizeEdges() { return _normalizeEdges; }
- const optional<bool>& normalizeEdges() const { return _normalizeEdges; }
+ const optional<float>& minTileRangeFactor() const { return _minTileRangeFactor; }
/**
* Whether to apply the default layer combination logic using TexEnvCombine.
@@ -241,14 +234,14 @@ namespace osgEarth
/**
* The min filter to be applied to textures
*/
- optional<osg::Texture::FilterMode> minFilter() { return _minFilter;}
- const optional<osg::Texture::FilterMode> minFilter() const { return _minFilter;}
+ optional<osg::Texture::FilterMode>& minFilter() { return _minFilter;}
+ const optional<osg::Texture::FilterMode>& minFilter() const { return _minFilter;}
/**
* The mag filter to be applied to textures
*/
- optional<osg::Texture::FilterMode> magFilter() { return _magFilter;}
- const optional<osg::Texture::FilterMode> magFilter() const { return _magFilter;}
+ optional<osg::Texture::FilterMode>& magFilter() { return _magFilter;}
+ const optional<osg::Texture::FilterMode>& magFilter() const { return _magFilter;}
/**
* Whether to enable blending
@@ -294,8 +287,7 @@ namespace osgEarth
optional<float> _verticalScale;
optional<float> _heightFieldSampleRatio;
- optional<float> _minTileRangeFactor;
- optional<bool> _normalizeEdges;
+ optional<float> _minTileRangeFactor;
optional<bool> _combineLayers;
optional<LoadingPolicy> _loadingPolicy;
optional<CompositingTechnique> _compositingTech;
diff --git a/src/osgEarth/TerrainOptions.cpp b/src/osgEarth/TerrainOptions.cpp
index fb3e678..0788469 100644
--- a/src/osgEarth/TerrainOptions.cpp
+++ b/src/osgEarth/TerrainOptions.cpp
@@ -90,7 +90,6 @@ DriverConfigOptions( options ),
_verticalScale( 1.0f ),
_heightFieldSampleRatio( 1.0f ),
_minTileRangeFactor( 6.0 ),
-_normalizeEdges( false ),
_combineLayers( true ),
_loadingPolicy( LoadingPolicy() ),
_compositingTech( COMPOSITING_AUTO ),
@@ -125,8 +124,7 @@ TerrainOptions::getConfig() const
conf.updateObjIfSet( "loading_policy", _loadingPolicy );
conf.updateIfSet( "vertical_scale", _verticalScale );
- conf.updateIfSet( "min_tile_range_factor", _minTileRangeFactor );
- conf.updateIfSet( "normalize_edges", _normalizeEdges );
+ conf.updateIfSet( "min_tile_range_factor", _minTileRangeFactor );
conf.updateIfSet( "combine_layers", _combineLayers );
conf.updateIfSet( "max_lod", _maxLOD );
conf.updateIfSet( "min_lod", _minLOD );
@@ -173,8 +171,7 @@ TerrainOptions::fromConfig( const Config& conf )
conf.getObjIfSet( "loading_policy", _loadingPolicy );
conf.getIfSet( "vertical_scale", _verticalScale );
- conf.getIfSet( "min_tile_range_factor", _minTileRangeFactor );
- conf.getIfSet( "normalize_edges", _normalizeEdges );
+ conf.getIfSet( "min_tile_range_factor", _minTileRangeFactor );
conf.getIfSet( "combine_layers", _combineLayers );
conf.getIfSet( "max_lod", _maxLOD ); conf.getIfSet( "max_level", _maxLOD );
conf.getIfSet( "min_lod", _minLOD ); conf.getIfSet( "min_level", _minLOD );
diff --git a/src/osgEarth/TextureCompositor b/src/osgEarth/TextureCompositor
index fde89d1..509ee19 100644
--- a/src/osgEarth/TextureCompositor
+++ b/src/osgEarth/TextureCompositor
@@ -26,8 +26,6 @@
#include <osg/StateSet>
#include <osg/Program>
-#define MAX_IMAGE_LAYERS 16
-
namespace osgEarth
{
class ImageLayer;
diff --git a/src/osgEarth/TextureCompositor.cpp b/src/osgEarth/TextureCompositor.cpp
index 2803689..960b1bc 100644
--- a/src/osgEarth/TextureCompositor.cpp
+++ b/src/osgEarth/TextureCompositor.cpp
@@ -24,6 +24,7 @@
#include <osgEarth/ImageUtils>
#include <osgEarth/Registry>
#include <osgEarth/Map>
+#include <osgEarth/MapModelChange>
#include <osg/Texture2DArray>
#include <osg/Texture2D>
#include <osg/Texture3D>
diff --git a/src/osgEarth/TextureCompositorMulti.cpp b/src/osgEarth/TextureCompositorMulti.cpp
index 1f7f5f2..b1cd1ad 100644
--- a/src/osgEarth/TextureCompositorMulti.cpp
+++ b/src/osgEarth/TextureCompositorMulti.cpp
@@ -19,7 +19,7 @@
#include <osgEarth/TextureCompositorMulti>
#include <osgEarth/ImageUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/ShaderUtils>
#include <osgEarth/TileKey>
#include <osgEarth/StringUtils>
@@ -51,17 +51,20 @@ namespace
buf << "#version " << GLSL_VERSION_STR << "\n";
- buf << "varying vec4 osg_FrontColor;\n"
- << "varying vec4 osg_FrontSecondaryColor;\n";
+ buf << "varying vec4 osg_FrontColor; \n"
+ << "varying vec4 osg_FrontSecondaryColor; \n";
+
+ // NOTE: always use the "max GPU coord sets" for texture coordinates
+ // to support proper shader merging under GLES. -gw
if ( slots.size() > 0 )
{
- buf << "varying vec4 osg_TexCoord[" << Registry::instance()->getCapabilities().getMaxGPUTextureCoordSets() << "];\n";
+ buf << "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n";
}
if ( blending )
{
- buf << "uniform mat4 osgearth_TexBlendMatrix[" << Registry::instance()->getCapabilities().getMaxGPUTextureCoordSets() << "];\n";
+ buf << "uniform mat4 osgearth_TexBlendMatrix[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n";
}
buf << "void osgearth_vert_setupColoring() \n"
@@ -82,12 +85,12 @@ namespace
if ( slot == primarySlot )
{
// normal unit:
- buf << " osg_TexCoord["<< slot <<"] = gl_MultiTexCoord" << slot << ";\n";
+ buf << " osg_TexCoord["<< slot <<"] = gl_MultiTexCoord" << slot << "; \n";
}
else
{
// secondary (blending) unit:
- buf << " osg_TexCoord["<< slot <<"] = osgearth_TexBlendMatrix["<< primarySlot << "] * gl_MultiTexCoord" << primarySlot << ";\n";
+ buf << " osg_TexCoord["<< slot <<"] = osgearth_TexBlendMatrix["<< primarySlot << "] * gl_MultiTexCoord" << primarySlot << "; \n";
}
}
}
@@ -111,11 +114,6 @@ namespace
buf << "precision mediump float;\n";
#endif
- if ( maxSlots > 0 )
- {
- buf << "varying vec4 osg_TexCoord[" << Registry::instance()->getCapabilities().getMaxGPUTextureCoordSets() << "];\n";
- }
-
if ( blending )
{
buf << "#extension GL_ARB_shader_texture_lod : enable \n"
@@ -124,12 +122,15 @@ namespace
<< "uniform float osgearth_LODRangeFactor; \n";
}
- buf << "uniform float osgearth_ImageLayerOpacity[" << maxSlots << "]; \n"
- //The enabled array is a fixed size. Make sure this corresponds EXCATLY to the size definition in TerrainEngineNode.cpp
- << "uniform bool osgearth_ImageLayerVisible[" << MAX_IMAGE_LAYERS << "]; \n"
- << "uniform float osgearth_ImageLayerRange[" << 2 * maxSlots << "]; \n"
- << "uniform float osgearth_ImageLayerAttenuation; \n"
- << "uniform float osgearth_CameraElevation; \n";
+ if ( maxSlots > 0 )
+ {
+ buf << "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n"
+ << "uniform float osgearth_ImageLayerOpacity[" << maxSlots << "]; \n"
+ << "uniform bool osgearth_ImageLayerVisible[" << maxSlots << "]; \n"
+ << "uniform float osgearth_ImageLayerRange[" << 2 * maxSlots << "]; \n"
+ << "uniform float osgearth_ImageLayerAttenuation; \n"
+ << "uniform float osgearth_CameraElevation; \n";
+ }
const TextureLayout::TextureSlotVector& slots = layout.getTextureSlots();
@@ -300,25 +301,21 @@ namespace
bool
TextureCompositorMultiTexture::isSupported( bool useGPU )
{
- const Capabilities& caps = osgEarth::Registry::instance()->getCapabilities();
+ const Capabilities& caps = osgEarth::Registry::capabilities();
if ( useGPU )
-#ifndef OSG_GLES2_AVAILABLE
- return caps.supportsGLSL( 1.10f ) && caps.supportsMultiTexture();
-#else
- return caps.supportsGLSL( 1.0f ) && caps.supportsMultiTexture();
-#endif
+ return caps.supportsGLSL() && caps.supportsMultiTexture();
else
return caps.supportsMultiTexture();
}
TextureCompositorMultiTexture::TextureCompositorMultiTexture( bool useGPU, const TerrainOptions& options ) :
_lodTransitionTime( *options.lodTransitionTime() ),
-_enableMipmapping( *options.enableMipmapping() ),
-_minFilter( *options.minFilter() ),
-_magFilter( *options.magFilter() ),
-_useGPU( useGPU )
+_enableMipmapping ( *options.enableMipmapping() ),
+_minFilter ( *options.minFilter() ),
+_magFilter ( *options.magFilter() ),
+_useGPU ( useGPU )
{
- _enableMipmappingOnUpdatedTextures = Registry::instance()->getCapabilities().supportsMipmappedTextureUpdates();
+ _enableMipmappingOnUpdatedTextures = Registry::capabilities().supportsMipmappedTextureUpdates();
}
void
@@ -403,24 +400,21 @@ TextureCompositorMultiTexture::updateMasterStateSet(osg::StateSet* stateSe
}
VirtualProgram* vp = static_cast<VirtualProgram*>( stateSet->getAttribute(VirtualProgram::SA_TYPE) );
- if ( maxUnits > 0 )
- {
- // see if we have any blended layers:
- bool hasBlending = layout.containsSecondarySlots( maxUnits );
+ // see if we have any blended layers:
+ bool hasBlending = layout.containsSecondarySlots( maxUnits );
- vp->setShader(
- "osgearth_vert_setupColoring",
- s_createTextureVertexShader(layout, hasBlending) );
+ // Why are these marked as PROTECTED? See the comments in MapNode.cpp for the answer.
+ // (Where it sets up the top-level VirtualProgram)
- vp->setShader(
- "osgearth_frag_applyColoring",
- s_createTextureFragShaderFunction(layout, maxUnits, hasBlending, _lodTransitionTime ) );
- }
- else
- {
- vp->removeShader( "osgearth_frag_applyColoring" );
- vp->removeShader( "osgearth_vert_setupColoring" );
- }
+ vp->setShader(
+ "osgearth_vert_setupColoring",
+ s_createTextureVertexShader(layout, hasBlending),
+ osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
+
+ vp->setShader(
+ "osgearth_frag_applyColoring",
+ s_createTextureFragShaderFunction(layout, maxUnits, hasBlending, _lodTransitionTime),
+ osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
}
else
@@ -524,22 +518,29 @@ TextureCompositorMultiTexture::createSamplerFunction(UID layerUID,
int slot = layout.getSlot( layerUID );
if ( slot >= 0 )
{
- std::stringstream buf;
-
- buf << "uniform sampler2D "<< makeSamplerName(slot) << "; \n"
- << "vec4 " << functionName << "() \n"
- << "{ \n";
+ std::string src;
if ( type == osg::Shader::VERTEX )
- buf << " return texture2D("<< makeSamplerName(slot) << ", gl_MultiTexCoord"<< slot <<".st); \n";
- else
- buf << " return texture2D("<< makeSamplerName(slot) << ", gl_TexCoord["<< slot << "].st); \n";
-
- buf << "} \n";
+ {
+ src = Stringify()
+ << "uniform sampler2D "<< makeSamplerName(slot) << "; \n"
+ << "vec4 " << functionName << "() \n"
+ << "{ \n"
+ << " return texture2D("<< makeSamplerName(slot) << ", gl_MultiTexCoord"<< slot <<".st); \n"
+ << "} \n";
+ }
+ else // if ( type != osg::Shader::FRAGMENT )
+ {
+ src = Stringify()
+ << "uniform sampler2D "<< makeSamplerName(slot) << "; \n"
+ << "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "]; \n"
+ << "vec4 " << functionName << "() \n"
+ << "{ \n"
+ << " return texture2D("<< makeSamplerName(slot) << ", osg_TexCoord["<< slot << "].st); \n"
+ << "} \n";
+ }
- std::string str;
- str = buf.str();
- result = new osg::Shader( type, str );
+ result = new osg::Shader( type, src );
}
return result;
}
diff --git a/src/osgEarth/TextureCompositorTexArray b/src/osgEarth/TextureCompositorTexArray
index b973920..6279dcb 100644
--- a/src/osgEarth/TextureCompositorTexArray
+++ b/src/osgEarth/TextureCompositorTexArray
@@ -76,6 +76,8 @@ namespace osgEarth
private:
float _lodTransitionTime;
+ osg::Texture::FilterMode _minFilter;
+ osg::Texture::FilterMode _magFilter;
};
}
diff --git a/src/osgEarth/TextureCompositorTexArray.cpp b/src/osgEarth/TextureCompositorTexArray.cpp
index 843abbe..4d02923 100644
--- a/src/osgEarth/TextureCompositorTexArray.cpp
+++ b/src/osgEarth/TextureCompositorTexArray.cpp
@@ -25,7 +25,7 @@
#include <osgEarth/ImageUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/SparseTexture2DArray>
#include <osgEarth/ShaderUtils>
#include <osgEarth/TileKey>
@@ -184,7 +184,7 @@ namespace
{
osg::Texture2DArray*
s_getTexture( osg::StateSet* stateSet, const TextureLayout& layout,
- int unit, unsigned textureSize )
+ int unit, unsigned textureSize, osg::Texture::FilterMode minFilter, osg::Texture::FilterMode magFilter )
{
osg::Texture2DArray* tex = static_cast<osg::Texture2DArray*>(
stateSet->getTextureAttribute( unit, osg::StateAttribute::TEXTURE ) );
@@ -201,8 +201,8 @@ namespace
// configure the mipmapping
tex->setMaxAnisotropy(16.0f);
tex->setResizeNonPowerOfTwoHint(false);
- tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
- tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
+ tex->setFilter( osg::Texture::MAG_FILTER, magFilter );
+ tex->setFilter( osg::Texture::MIN_FILTER, minFilter );
// configure the wrapping
tex->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
@@ -290,7 +290,9 @@ TextureCompositorTexArray::isSupported()
}
TextureCompositorTexArray::TextureCompositorTexArray( const TerrainOptions& options ) :
-_lodTransitionTime( *options.lodTransitionTime() )
+_lodTransitionTime( *options.lodTransitionTime() ),
+_minFilter ( *options.minFilter() ),
+_magFilter ( *options.magFilter() )
{
//nop
}
@@ -341,7 +343,7 @@ TextureCompositorTexArray::applyLayerUpdate(osg::StateSet* stateSet,
// access the texture array, creating or growing it if necessary:
osg::Texture2DArray* texture = s_getTexture( stateSet, layout, 0,
- textureSize() );
+ textureSize(), _minFilter, _magFilter);
ensureSampler( stateSet, 0 );
// assign the new image at the proper position in the texture array.
osg::Image* image = preparedImage.getImage();
@@ -421,11 +423,13 @@ TextureCompositorTexArray::updateMasterStateSet( osg::StateSet* stateSet, const
vp->setShader(
"osgearth_vert_setupColoring",
- s_createTextureVertSetupShaderFunction(layout) );
+ s_createTextureVertSetupShaderFunction(layout),
+ osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
vp->setShader(
"osgearth_frag_applyColoring",
- s_createTextureFragShaderFunction(layout, true, _lodTransitionTime ) );
+ s_createTextureFragShaderFunction(layout, true, _lodTransitionTime ),
+ osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
}
osg::Shader*
diff --git a/src/osgEarth/TileKey b/src/osgEarth/TileKey
index 9c74cfd..588d88c 100644
--- a/src/osgEarth/TileKey
+++ b/src/osgEarth/TileKey
@@ -31,6 +31,7 @@ namespace osgEarth
{
/**
* Uniquely identifies a single tile on the map, relative to a Profile.
+ * Profiles have an origin of 0,0 at the top left.
*/
class OSGEARTH_EXPORT TileKey
{
@@ -124,10 +125,10 @@ namespace osgEarth
/**
* Creates a key that represents this tile's neighbor at the same LOD. Wraps
- * around in X and Y automatically.
+ * around in X and Y automatically. For example, xoffset=-1 yoffset=1 will
+ * give you the key for the tile SW of this tile.
*/
- enum Direction { NORTH, SOUTH, EAST, WEST };
- TileKey createNeighborKey( Direction dir ) const;
+ TileKey createNeighborKey( int xoffset, int yoffset ) const;
/**
* Gets the level of detail of the tile represented by this key.
diff --git a/src/osgEarth/TileKey.cpp b/src/osgEarth/TileKey.cpp
index 42e1c28..a6360f5 100644
--- a/src/osgEarth/TileKey.cpp
+++ b/src/osgEarth/TileKey.cpp
@@ -152,20 +152,24 @@ TileKey::createAncestorKey( int ancestorLod ) const
}
TileKey
-TileKey::createNeighborKey( TileKey::Direction dir ) const
+TileKey::createNeighborKey( int xoffset, int yoffset ) const
{
- unsigned int tx, ty;
+ unsigned tx, ty;
getProfile()->getNumTiles( _lod, tx, ty );
- unsigned int x =
- dir == WEST ? _x > 0 ? _x-1 : tx-1 :
- dir == EAST ? _x+1 < tx ? _x+1 : 0 :
- _x;
+ int sx = (int)_x + xoffset;
+ unsigned x =
+ sx < 0 ? (unsigned)((int)tx + sx) :
+ sx >= (int)tx ? (unsigned)sx - tx :
+ (unsigned)sx;
- unsigned int y =
- dir == SOUTH ? _y > 0 ? _y-1 : ty-1 :
- dir == NORTH ? _y+1 < ty ? _y+1 : 0 :
- _y;
+ int sy = (int)_y + yoffset;
+ unsigned y =
+ sy < 0 ? (unsigned)((int)ty + sy) :
+ sy >= (int)ty ? (unsigned)sy - ty :
+ (unsigned)sy;
+
+ //OE_NOTICE << "Returning neighbor " << x << ", " << y << " for tile " << str() << " offset=" << xoffset << ", " << yoffset << std::endl;
return TileKey( _lod, x, y, _profile.get() );
}
diff --git a/src/osgEarth/TileSource b/src/osgEarth/TileSource
index 72c927d..a629d43 100644
--- a/src/osgEarth/TileSource
+++ b/src/osgEarth/TileSource
@@ -57,7 +57,7 @@ namespace osgEarth
/**
* Configuration options for a tile source driver.
*/
- class OSGEARTH_EXPORT TileSourceOptions : public DriverConfigOptions // no export; header only
+ class OSGEARTH_EXPORT TileSourceOptions : public DriverConfigOptions
{
public:
@@ -82,6 +82,9 @@ namespace osgEarth
optional<int>& L2CacheSize() { return _L2CacheSize; }
const optional<int>& L2CacheSize() const { return _L2CacheSize; }
+ optional<bool>& bilinearReprojection() { return _bilinearReprojection; }
+ const optional<bool>& bilinearReprojection() const { return _bilinearReprojection; }
+
public:
TileSourceOptions( const ConfigOptions& options =ConfigOptions() );
@@ -102,6 +105,7 @@ namespace osgEarth
optional<ProfileOptions> _profileOptions;
optional<std::string> _blacklistFilename;
optional<int> _L2CacheSize;
+ optional<bool> _bilinearReprojection;
};
typedef std::vector<TileSourceOptions> TileSourceOptionsVector;
diff --git a/src/osgEarth/TileSource.cpp b/src/osgEarth/TileSource.cpp
index ca8030e..dd64a4f 100644
--- a/src/osgEarth/TileSource.cpp
+++ b/src/osgEarth/TileSource.cpp
@@ -144,12 +144,13 @@ TileBlacklist::write(std::ostream &output) const
TileSourceOptions::TileSourceOptions( const ConfigOptions& options ) :
-DriverConfigOptions( options ),
-_tileSize ( 256 ),
-_noDataValue ( (float)SHRT_MIN ),
-_noDataMinValue ( -32000.0f ),
-_noDataMaxValue ( 32000.0f ),
-_L2CacheSize ( 16 )
+DriverConfigOptions ( options ),
+_tileSize ( 256 ),
+_noDataValue ( (float)SHRT_MIN ),
+_noDataMinValue ( -32000.0f ),
+_noDataMaxValue ( 32000.0f ),
+_L2CacheSize ( 16 ),
+_bilinearReprojection ( true )
{
fromConfig( _conf );
}
@@ -165,6 +166,7 @@ TileSourceOptions::getConfig() const
conf.updateIfSet( "nodata_max", _noDataMaxValue );
conf.updateIfSet( "blacklist_filename", _blacklistFilename);
conf.updateIfSet( "l2_cache_size", _L2CacheSize );
+ conf.updateIfSet( "bilinear_reprojection", _bilinearReprojection );
conf.updateObjIfSet( "profile", _profileOptions );
return conf;
}
@@ -187,6 +189,7 @@ TileSourceOptions::fromConfig( const Config& conf )
conf.getIfSet( "nodata_max", _noDataMaxValue );
conf.getIfSet( "blacklist_filename", _blacklistFilename);
conf.getIfSet( "l2_cache_size", _L2CacheSize );
+ conf.getIfSet( "bilinear_reprojection", _bilinearReprojection );
conf.getObjIfSet( "profile", _profileOptions );
// special handling of default tile size:
diff --git a/src/osgEarth/URI b/src/osgEarth/URI
index 7263063..c8ad898 100644
--- a/src/osgEarth/URI
+++ b/src/osgEarth/URI
@@ -341,6 +341,31 @@ namespace osgEarth
}
};
+
+//------------------------------------------------------------------------
+
+ /**
+ * You can install a post-read callback in a osgDB::Options and the URI
+ * class till invoke it on a ReadResult before returning.
+ */
+ class /*header-only*/ URIPostReadCallback : public osg::Referenced
+ {
+ public:
+ URIPostReadCallback() { }
+ virtual ~URIPostReadCallback() { }
+
+ virtual void operator()( ReadResult& result ) =0;
+
+ public:
+ void apply(osgDB::Options* options) {
+ if ( options ) options->setPluginData("osgEarth::URIPostReadCallback", this);
+ }
+
+ static URIPostReadCallback* from(const osgDB::Options* options) {
+ return options ? static_cast<URIPostReadCallback*>(const_cast<osgDB::Options*>(options)->getPluginData("osgEarth::URIPostReadCallback")) : 0L;
+ }
+ };
+
//------------------------------------------------------------------------
diff --git a/src/osgEarth/URI.cpp b/src/osgEarth/URI.cpp
index ddbb576..d90c9fe 100644
--- a/src/osgEarth/URI.cpp
+++ b/src/osgEarth/URI.cpp
@@ -340,134 +340,147 @@ namespace
{
ReadResult result;
- if ( inputURI.empty() )
- return result;
-
- // establish our IO options:
- const osgDB::Options* localOptions = dbOptions ? dbOptions : Registry::instance()->getDefaultOptions();
-
- READ_FUNCTOR reader;
-
- URI uri = inputURI;
-
- // check if there's an alias map, and if so, attempt to resolve the alias:
- URIAliasMap* aliasMap = URIAliasMap::from( localOptions );
- if ( aliasMap )
+ if ( !inputURI.empty() )
{
- uri = aliasMap->resolve(inputURI.full(), inputURI.context());
- }
+ // establish our IO options:
+ const osgDB::Options* localOptions = dbOptions ? dbOptions : Registry::instance()->getDefaultOptions();
- // check if there's a URI cache in the options.
- URIResultCache* memCache = URIResultCache::from( localOptions );
- if ( memCache )
- {
- URIResultCache::Record r = memCache->get( uri );
- if ( r.valid() ) result = r.value();
- }
+ READ_FUNCTOR reader;
- if ( result.empty() )
- {
- // see if there's a read callback installed.
- URIReadCallback* cb = Registry::instance()->getURIReadCallback();
+ URI uri = inputURI;
- // for a local URI, bypass all the caching logic
- if ( !uri.isRemote() )
- {
- // try to use the callback if it's set. Callback ignores the caching policy.
- if ( cb )
- {
- result = reader.fromCallback( cb, uri.full(), localOptions );
- if (result.code() != ReadResult::RESULT_NOT_IMPLEMENTED)
- {
- // only "NOT_IMPLEMENTED" is a reason to fallback. Anything else if a FAIL
- return result;
- }
- }
+ bool gotResultFromCallback = false;
- if ( result.empty() )
- {
- result = reader.fromFile( uri.full(), localOptions );
- }
+ // check if there's an alias map, and if so, attempt to resolve the alias:
+ URIAliasMap* aliasMap = URIAliasMap::from( localOptions );
+ if ( aliasMap )
+ {
+ uri = aliasMap->resolve(inputURI.full(), inputURI.context());
}
- // remote URI, consider caching:
- else
+ // check if there's a URI cache in the options.
+ URIResultCache* memCache = URIResultCache::from( localOptions );
+ if ( memCache )
{
- bool callbackCachingOK = !cb || reader.callbackRequestsCaching(cb);
-
- // by default, use a CachePolicy specified by the caller:
- optional<CachePolicy> cp;
- CachePolicy::fromOptions( localOptions, cp );
-
- // if not, use the system defult:
- if ( !cp.isSet() && Registry::instance()->defaultCachePolicy().isSet() )
- cp = Registry::instance()->defaultCachePolicy().value();
-
- // otherwise, just use a default (read/write)
- if ( !cp.isSet() )
- cp = CachePolicy::DEFAULT;
-
-
- // get a cache bin if we need it:
- CacheBin* bin = 0L;
- if ( (cp->usage() != CachePolicy::USAGE_NO_CACHE) && callbackCachingOK )
+ URIResultCache::Record r = memCache->get( uri );
+ if ( r.valid() )
{
- bin = s_getCacheBin( dbOptions );
+ result = r.value();
}
+ }
- // first try to go to the cache if there is one:
- if ( bin && cp->isCacheReadable() )
- {
- result = reader.fromCache( bin, uri.cacheKey(), *cp->maxAge() );
- if ( result.succeeded() )
- result.setIsFromCache(true);
- }
+ if ( result.empty() )
+ {
+ // see if there's a read callback installed.
+ URIReadCallback* cb = Registry::instance()->getURIReadCallback();
- // not in the cache, so proceed to read it from the network.
- if ( result.empty() )
+ // for a local URI, bypass all the caching logic
+ if ( !uri.isRemote() )
{
// try to use the callback if it's set. Callback ignores the caching policy.
if ( cb )
- {
+ {
+ // if this returns "not implemented" we fill fall back
result = reader.fromCallback( cb, uri.full(), localOptions );
+
if ( result.code() != ReadResult::RESULT_NOT_IMPLEMENTED )
{
- return result;
+ // "not implemented" is the only excuse to fall back.
+ gotResultFromCallback = true;
}
}
- // still no data, go to the source:
- if ( result.empty() && cp->usage() != CachePolicy::USAGE_CACHE_ONLY )
+ if ( !gotResultFromCallback )
{
- result = reader.fromHTTP( uri.full(), localOptions, progress );
+ // no callback, just read from a local file.
+ result = reader.fromFile( uri.full(), localOptions );
}
+ }
- // write the result to the cache if possible:
- if ( result.succeeded() && bin && cp->isCacheWriteable() )
+ // remote URI, consider caching:
+ else
+ {
+ bool callbackCachingOK = !cb || reader.callbackRequestsCaching(cb);
+
+ // establish the caching policy.
+ optional<CachePolicy> cp;
+ if ( !Registry::instance()->getCachePolicy( cp, localOptions ) )
+ cp = CachePolicy::DEFAULT;
+
+ // get a cache bin if we need it:
+ CacheBin* bin = 0L;
+ if ( (cp->usage() != CachePolicy::USAGE_NO_CACHE) && callbackCachingOK )
{
- bin->write( uri.cacheKey(), result.getObject(), result.metadata() );
+ bin = s_getCacheBin( dbOptions );
}
- }
- OE_TEST << LC
- << uri.base() << ": "
- << (result.succeeded() ? "OK" : "FAILED")
- << "; policy=" << cp->usageString()
- << (result.isFromCache() && result.succeeded() ? "; (from cache)" : "")
- << std::endl;
- }
+ // first try to go to the cache if there is one:
+ if ( bin && cp->isCacheReadable() )
+ {
+ result = reader.fromCache( bin, uri.cacheKey(), *cp->maxAge() );
+ if ( result.succeeded() )
+ result.setIsFromCache(true);
+ }
- if ( result.getObject() )
- {
- result.getObject()->setName( uri.base() );
+ // not in the cache, so proceed to read it from the network.
+ if ( result.empty() )
+ {
+ // try to use the callback if it's set. Callback ignores the caching policy.
+ if ( cb )
+ {
+ result = reader.fromCallback( cb, uri.full(), localOptions );
+
+ if ( result.code() != ReadResult::RESULT_NOT_IMPLEMENTED )
+ {
+ // "not implemented" is the only excuse for falling back
+ gotResultFromCallback = true;
+ }
+ }
- if ( memCache )
+ if ( !gotResultFromCallback )
+ {
+ // still no data, go to the source:
+ if ( result.empty() && cp->usage() != CachePolicy::USAGE_CACHE_ONLY )
+ {
+ result = reader.fromHTTP( uri.full(), localOptions, progress );
+ }
+
+ // write the result to the cache if possible:
+ if ( result.succeeded() && bin && cp->isCacheWriteable() )
+ {
+ bin->write( uri.cacheKey(), result.getObject(), result.metadata() );
+ }
+ }
+ }
+
+ OE_TEST << LC
+ << uri.base() << ": "
+ << (result.succeeded() ? "OK" : "FAILED")
+ << "; policy=" << cp->usageString()
+ << (result.isFromCache() && result.succeeded() ? "; (from cache)" : "")
+ << std::endl;
+ }
+
+
+ if ( result.getObject() && !gotResultFromCallback )
{
- memCache->insert( uri, result );
+ result.getObject()->setName( uri.base() );
+
+ if ( memCache )
+ {
+ memCache->insert( uri, result );
+ }
}
}
}
+ // post-process if there's a post-URI callback.
+ URIPostReadCallback* post = URIPostReadCallback::from(dbOptions);
+ if ( post )
+ {
+ (*post)(result);
+ }
+
return result;
}
}
diff --git a/src/osgEarth/Version b/src/osgEarth/Version
index 991ba10..b578931 100644
--- a/src/osgEarth/Version
+++ b/src/osgEarth/Version
@@ -25,9 +25,10 @@
extern "C" {
#define OSGEARTH_MAJOR_VERSION 2
-#define OSGEARTH_MINOR_VERSION 2
+#define OSGEARTH_MINOR_VERSION 3
#define OSGEARTH_PATCH_VERSION 0
#define OSGEARTH_SOVERSION 0
+#define OSGEARTH_RC_VERSION 0
/* Convenience macro that can be used to decide whether a feature is present or not i.e.
* #if OSGEARTH_MIN_VERSION_REQUIRED(1,4,0)
diff --git a/src/osgEarth/Version.cpp b/src/osgEarth/Version.cpp
index 09caa85..344d773 100644
--- a/src/osgEarth/Version.cpp
+++ b/src/osgEarth/Version.cpp
@@ -30,13 +30,13 @@ const char* osgEarthGetVersion()
static int osgearth_version_init = 1;
if (osgearth_version_init)
{
- if (OSGEARTH_VERSION_REVISION==0)
+ if (OSGEARTH_RC_VERSION == 0 )
{
sprintf(osgearth_version,"%d.%d.%d",OSGEARTH_MAJOR_VERSION,OSGEARTH_MINOR_VERSION,OSGEARTH_PATCH_VERSION);
}
else
{
- sprintf(osgearth_version,"%d.%d.%d-%d",OSGEARTH_MAJOR_VERSION,OSGEARTH_MINOR_VERSION,OSGEARTH_PATCH_VERSION,OSGEARTH_VERSION_REVISION);
+ sprintf(osgearth_version,"%d.%d.%d RC%d",OSGEARTH_MAJOR_VERSION,OSGEARTH_MINOR_VERSION,OSGEARTH_PATCH_VERSION, OSGEARTH_RC_VERSION);
}
osgearth_version_init = 0;
diff --git a/src/osgEarth/ShaderComposition b/src/osgEarth/VirtualProgram
similarity index 70%
rename from src/osgEarth/ShaderComposition
rename to src/osgEarth/VirtualProgram
index ed61de4..5561189 100644
--- a/src/osgEarth/ShaderComposition
+++ b/src/osgEarth/VirtualProgram
@@ -16,8 +16,8 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
-#ifndef OSGEARTH_SHADER_COMPOSITION_H
-#define OSGEARTH_SHADER_COMPOSITION_H 1
+#ifndef OSGEARTH_VIRTUAL_PROGRAM_H
+#define OSGEARTH_VIRTUAL_PROGRAM_H 1
#include <osgEarth/Common>
#include <osgEarth/Revisioning>
@@ -36,7 +36,7 @@
#endif
namespace osgEarth
-{
+{
namespace ShaderComp
{
// User function injection points.
@@ -55,85 +55,8 @@ namespace osgEarth
// user function sets, categorized by function location.
typedef std::map<FunctionLocation, OrderedFunctionMap> FunctionLocationMap;
-
- // hints that can be used to automatically generate shader code
- class OSGEARTH_EXPORT RenderingHints
- {
- public:
- RenderingHints();
- RenderingHints(const RenderingHints& rhs);
- bool operator == (const RenderingHints& rhs) const;
- bool operator != (const RenderingHints& rhs) const { return !operator==(rhs); }
-
- void useNumTextures(unsigned num);
- unsigned numTextures() const { return _numTextures; }
-
- protected:
- virtual ~RenderingHints() { }
- unsigned _numTextures;
- };
}
- /**
- * A factory class that generates shader functions for the osgEarth engine.
- * The default ShaderFactory is stored in the osgEarth registry. You can replace it
- * if you want to replace osgEarth's default shader templates.
- */
- class OSGEARTH_EXPORT ShaderFactory : public osg::Referenced
- {
- public:
- /** Creates a vertex shader main(). */
- virtual osg::Shader* createVertexShaderMain(
- const ShaderComp::FunctionLocationMap& functions =ShaderComp::FunctionLocationMap(),
- bool useLightingShaders =true ) const;
-
- /** Creates a fragment shader main(). */
- virtual osg::Shader* createFragmentShaderMain(
- const ShaderComp::FunctionLocationMap& functions =ShaderComp::FunctionLocationMap(),
- bool useLightingShaders =true ) const;
-
- /**
- * Gets the uniform/shader name of the sampler corresponding the the provider
- * texture image unit
- */
- virtual std::string getSamplerName( unsigned texImageUnit ) const;
-
- /**
- * Creates the function that sets up default texcoords in the vertex shader.
- * The name/prototype is:
- * void osgearth_vert_setupColoring();
- */
- virtual osg::Shader* createDefaultColoringVertexShader( unsigned numTexCoordSets ) const;
-
- /**
- * Creates the function that applies texture data in the fragment shader.
- * The name/prototype is:
- * osgearth_frag_applyColoring( inout vec4 color );
- */
- virtual osg::Shader* createDefaultColoringFragmentShader( unsigned numTexCoordSets ) const;
-
- /**
- * Creates the function that applies lighting calculations in the vertex shader.
- * The name/prototype is:
- * void osgearth_vert_setupLighting();
- */
- virtual osg::Shader* createDefaultLightingVertexShader() const;
-
- /**
- * Creates the function that applies lighting coloring in the fragment shader.
- * The name/prototype is:
- * void osgearth_frag_applyLighting( inout vec4 color );
- */
- virtual osg::Shader* createDefaultLightingFragmentShader() const;
-
- /**
- * Builds a shader that executes an image filter chain.
- */
- virtual osg::Shader* createColorFilterChainFragmentShader( const std::string& function, const ColorFilterChain& chain ) const;
-
- /** dtor */
- virtual ~ShaderFactory() { }
- };
/**
* VirtualProgram enables basic GLSL shader composition within osgEarth.
@@ -174,17 +97,23 @@ namespace osgEarth
* Installs default shaders for implementing basic coloring and lighting.
* The default shaders come from the ShaderFactory.
*/
- void installDefaultColoringAndLightingShaders( unsigned numTextures =0u );
+ void installDefaultColoringAndLightingShaders(
+ unsigned numTextures =0u,
+ osg::StateAttribute::OverrideValue qualifiers =osg::StateAttribute::ON );
/**
* Installs default shader for basic coloring/texturing.
*/
- void installDefaultColoringShaders( unsigned numTextures =0u );
+ void installDefaultColoringShaders(
+ unsigned numTextures =0u,
+ osg::StateAttribute::OverrideValue qualifiers =osg::StateAttribute::ON );
+
/**
* Installs default shader for basic lighting.
*/
- void installDefaultLightingShaders();
+ void installDefaultLightingShaders(
+ osg::StateAttribute::OverrideValue qualifiers =osg::StateAttribute::ON );
/**
* Sets whether to use lighting shaders at all - set this to false if you
@@ -301,5 +230,4 @@ namespace osgEarth
} // namespace osgEarth
-#endif // OSGEARTH_SHADER_COMPOSITION_H
-
+#endif // OSGEARTH_VIRTUAL_PROGRAM_H
diff --git a/src/osgEarth/ShaderComposition.cpp b/src/osgEarth/VirtualProgram.cpp
similarity index 54%
rename from src/osgEarth/ShaderComposition.cpp
rename to src/osgEarth/VirtualProgram.cpp
index a058e7d..ad549fc 100644
--- a/src/osgEarth/ShaderComposition.cpp
+++ b/src/osgEarth/VirtualProgram.cpp
@@ -16,10 +16,12 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/Registry>
#include <osgEarth/Capabilities>
+#include <osgEarth/ShaderFactory>
+#include <osgEarth/ShaderUtils>
#include <osg/Shader>
#include <osg/Program>
#include <osg/State>
@@ -34,27 +36,24 @@ using namespace osgEarth::ShaderComp;
#define OE_TEST OE_NULL
//#define OE_TEST OE_NOTICE
-#ifdef OSG_GLES2_AVAILABLE
- #define MERGE_SHADERS 1
-#else
- //#define MERGE_SHADERS 1
-#endif
-
//------------------------------------------------------------------------
#define VERTEX_MAIN "osgearth_vert_main"
#define FRAGMENT_MAIN "osgearth_frag_main"
-#define VERTEX_SETUP_COLORING "osgearth_vert_setupColoring"
-#define VERTEX_SETUP_LIGHTING "osgearth_vert_setupLighting"
-#define FRAGMENT_APPLY_COLORING "osgearth_frag_applyColoring"
-#define FRAGMENT_APPLY_LIGHTING "osgearth_frag_applyLighting"
-
-#define OSGEARTH_DUMP_SHADERS "OSGEARTH_DUMP_SHADERS"
+// environment variable control
+#define OSGEARTH_DUMP_SHADERS "OSGEARTH_DUMP_SHADERS"
+#define OSGEARTH_MERGE_SHADERS "OSGEARTH_MERGE_SHADERS"
namespace
{
- bool s_dumpShaders = false;
+#ifdef OSG_GLES2_AVAILABLE
+ bool s_mergeShaders = true;
+#else
+ bool s_mergeShaders = false;
+#endif
+
+ bool s_dumpShaders = false; // debugging
/** A hack for OSG 2.8.x to get access to the state attribute vector. */
/** TODO: no longer needed in OSG 3+ ?? */
@@ -80,32 +79,6 @@ namespace
//------------------------------------------------------------------------
-RenderingHints::RenderingHints() :
-_numTextures( 0 )
-{
- //nop
-}
-
-RenderingHints::RenderingHints(const RenderingHints& rhs) :
-_numTextures( rhs._numTextures )
-{
- //nop
-}
-
-bool
-RenderingHints::operator == (const RenderingHints& rhs) const
-{
- return _numTextures == rhs._numTextures;
-}
-
-void
-RenderingHints::useNumTextures(unsigned num)
-{
- _numTextures = std::max( _numTextures, num );
-}
-
-//------------------------------------------------------------------------
-
// same type as PROGRAM (for proper state sorting)
const osg::StateAttribute::Type VirtualProgram::SA_TYPE = osg::StateAttribute::PROGRAM;
@@ -116,7 +89,8 @@ _inherit ( true ),
_useLightingShaders( true )
{
// because we sometimes update/change the attribute's members from within the apply() method
- this->setDataVariance( osg::Object::DYNAMIC );
+ // gw-commented out b/c apply() is only called from draw, and the changes are mutexed anyway
+ //this->setDataVariance( osg::Object::DYNAMIC );
// check the the dump env var
if ( ::getenv(OSGEARTH_DUMP_SHADERS) != 0L )
@@ -124,6 +98,12 @@ _useLightingShaders( true )
s_dumpShaders = true;
}
+ // check the merge env var
+ if ( ::getenv(OSGEARTH_MERGE_SHADERS) != 0L )
+ {
+ s_mergeShaders = true;
+ }
+
// a template object to hold program data (so we don't have to dupliate all the
// osg::Program methods..)
_template = new osg::Program();
@@ -132,12 +112,12 @@ _useLightingShaders( true )
VirtualProgram::VirtualProgram(const VirtualProgram& rhs, const osg::CopyOp& copyop ) :
osg::StateAttribute( rhs, copyop ),
-//osg::Program( rhs, copyop ),
_shaderMap ( rhs._shaderMap ),
_mask ( rhs._mask ),
_functions ( rhs._functions ),
_inherit ( rhs._inherit ),
-_useLightingShaders( rhs._useLightingShaders )
+_useLightingShaders( rhs._useLightingShaders ),
+_template ( osg::clone(rhs._template.get()) )
{
//nop
}
@@ -234,6 +214,10 @@ VirtualProgram::setShader(osg::Shader* shader,
return 0L;
}
+ // pre-processes the shader's source to include GLES uniforms as necessary
+ // (no-op on non-GLES)
+ ShaderPreProcessor::run( shader );
+
_shaderMap[shader->getName()] = ShaderEntry(shader, ov);
return shader;
@@ -329,39 +313,41 @@ VirtualProgram::addToAccumulatedMap(ShaderMap& accumShaderMap,
void
-VirtualProgram::installDefaultColoringAndLightingShaders( unsigned numTextures )
+VirtualProgram::installDefaultColoringAndLightingShaders(unsigned numTextures,
+ osg::StateAttribute::OverrideValue qual )
{
ShaderFactory* sf = osgEarth::Registry::instance()->getShaderFactory();
- this->setShader( sf->createDefaultColoringVertexShader(numTextures) );
- this->setShader( sf->createDefaultLightingVertexShader() );
+ this->setShader( sf->createDefaultColoringVertexShader(numTextures), qual );
+ this->setShader( sf->createDefaultLightingVertexShader(), qual );
- this->setShader( sf->createDefaultColoringFragmentShader(numTextures) );
- this->setShader( sf->createDefaultLightingFragmentShader() );
+ this->setShader( sf->createDefaultColoringFragmentShader(numTextures), qual );
+ this->setShader( sf->createDefaultLightingFragmentShader(), qual );
setUseLightingShaders( true );
}
void
-VirtualProgram::installDefaultLightingShaders()
+VirtualProgram::installDefaultLightingShaders(osg::StateAttribute::OverrideValue qual)
{
ShaderFactory* sf = osgEarth::Registry::instance()->getShaderFactory();
- this->setShader( sf->createDefaultLightingVertexShader() );
- this->setShader( sf->createDefaultLightingFragmentShader() );
+ this->setShader( sf->createDefaultLightingVertexShader(), qual );
+ this->setShader( sf->createDefaultLightingFragmentShader(), qual );
setUseLightingShaders( true );
}
void
-VirtualProgram::installDefaultColoringShaders( unsigned numTextures )
+VirtualProgram::installDefaultColoringShaders(unsigned numTextures,
+ osg::StateAttribute::OverrideValue qual )
{
ShaderFactory* sf = osgEarth::Registry::instance()->getShaderFactory();
- this->setShader( sf->createDefaultColoringVertexShader(numTextures) );
- this->setShader( sf->createDefaultColoringFragmentShader(numTextures) );
+ this->setShader( sf->createDefaultColoringVertexShader(numTextures), qual );
+ this->setShader( sf->createDefaultColoringFragmentShader(numTextures), qual );
}
@@ -399,12 +385,14 @@ namespace
StringVector lines;
StringTokenizer( source, lines, "\n", "", true, false );
- for( StringVector::const_iterator line = lines.begin(); line != lines.end(); ++line )
+ for( StringVector::const_iterator line_iter = lines.begin(); line_iter != lines.end(); ++line_iter )
{
- if ( line->size() > 0 )
+ std::string line = trim(*line_iter);
+
+ if ( line.size() > 0 )
{
StringVector tokens;
- StringTokenizer( *line, tokens, " \t", "", false, true );
+ StringTokenizer( line, tokens, " \t", "", false, true );
if (tokens[0] == "#version")
{
@@ -427,13 +415,13 @@ namespace
tokens[0] == "uniform" ||
tokens[0] == "attribute")
{
- std::string& header = headers[*line];
- header = *line;
+ std::string& header = headers[line];
+ header = line;
}
else
{
- body << (*line) << "\n";
+ body << (*line_iter) << "\n";
}
}
}
@@ -446,13 +434,7 @@ VirtualProgram::addShadersToProgram(const ShaderVector& shaders,
const AttribBindingList& attribBindings,
osg::Program* program )
{
-#ifdef MERGE_SHADERS
- bool mergeShaders = true;
-#else
- bool mergeShaders = false;
-#endif
-
- if ( mergeShaders )
+ if ( s_mergeShaders )
{
unsigned vertVersion = 0;
HeaderMap vertHeaders;
@@ -501,9 +483,12 @@ VirtualProgram::addShadersToProgram(const ShaderVector& shaders,
program->addShader( new osg::Shader(osg::Shader::VERTEX, vertBodyText) );
program->addShader( new osg::Shader(osg::Shader::FRAGMENT, fragBodyText) );
- OE_TEST << LC
- << "\nMERGED VERTEX SHADER: \n\n" << vertBodyText << "\n\n"
- << "MERGED FRAGMENT SHADER: \n\n" << fragBodyText << "\n" << std::endl;
+ if ( s_dumpShaders )
+ {
+ OE_NOTICE << LC
+ << "\nMERGED VERTEX SHADER: \n\n" << vertBodyText << "\n\n"
+ << "MERGED FRAGMENT SHADER: \n\n" << fragBodyText << "\n" << std::endl;
+ }
}
else
{
@@ -556,18 +541,6 @@ VirtualProgram::buildProgram(osg::State& state,
osg::ref_ptr<osg::Shader> oldFragMain = _fragMain.get();
_fragMain = sf->createFragmentShaderMain( _accumulatedFunctions, _useLightingShaders );
-#if 0
- osg::Shader* old_vert_main = getShader( VERTEX_MAIN );
- osg::ref_ptr<osg::Shader> vert_main = sf->createVertexShaderMain( _accumulatedFunctions, _useLightingShaders );
- setShader( VERTEX_MAIN, vert_main.get() );
- addToAccumulatedMap( accumShaderMap, VERTEX_MAIN, ShaderEntry(vert_main.get(), osg::StateAttribute::ON) );
-
- osg::Shader* old_frag_main = getShader( FRAGMENT_MAIN );
- osg::ref_ptr<osg::Shader> frag_main = sf->createFragmentShaderMain( _accumulatedFunctions, _useLightingShaders );
- setShader( FRAGMENT_MAIN, frag_main.get() );
- addToAccumulatedMap( accumShaderMap, FRAGMENT_MAIN, ShaderEntry(frag_main.get(), osg::StateAttribute::ON) );
-#endif
-
// rebuild the shader list now that we've changed the shader map.
ShaderVector keyVector;
for( ShaderMap::iterator i = accumShaderMap.begin(); i != accumShaderMap.end(); ++i )
@@ -594,7 +567,6 @@ VirtualProgram::buildProgram(osg::State& state,
// Since we replaced the "mains", we have to go through the cache and update all its
// entries to point at the new mains instead of the old ones.
-// if ( old_vert_main || old_frag_main )
if ( oldVertMain.valid() || oldFragMain.valid() )
{
ProgramMap newProgramCache;
@@ -603,21 +575,6 @@ VirtualProgram::buildProgram(osg::State& state,
{
const ShaderVector& originalKey = m->first;
-#if 0
- // build a new cache key:
- ShaderVector newKey;
-
- for( ShaderVector::const_iterator i = original.begin(); i != original.end(); ++i )
- {
- if ( i->get() == old_vert_main )
- newKey.push_back( vert_main.get() );
- else if ( i->get() == old_frag_main )
- newKey.push_back( frag_main.get() );
- else
- newKey.push_back( i->get() );
- }
-#endif
-
osg::Program* newProgram = new osg::Program();
newProgram->setName( m->second->getName() );
@@ -628,7 +585,6 @@ VirtualProgram::buildProgram(osg::State& state,
addTemplateDataToProgram( newProgram );
- //newProgramCache[newKey] = newProgram;
newProgramCache[originalKey] = newProgram;
}
@@ -798,10 +754,22 @@ VirtualProgram::refreshAccumulatedFunctions( const osg::State& state )
for( FunctionLocationMap::const_iterator j = rhs.begin(); j != rhs.end(); ++j )
{
- const OrderedFunctionMap& ofm = j->second;
- for( OrderedFunctionMap::const_iterator k = ofm.begin(); k != ofm.end(); ++k )
+ const OrderedFunctionMap& source = j->second;
+ OrderedFunctionMap& dest = _accumulatedFunctions[j->first];
+
+ for( OrderedFunctionMap::const_iterator k = source.begin(); k != source.end(); ++k )
{
- _accumulatedFunctions[j->first].insert( *k );
+ // remove/override an existing function with the same name
+ for( OrderedFunctionMap::iterator exists = dest.begin(); exists != dest.end(); ++exists )
+ {
+ if ( exists->second.compare( k->second ) == 0 )
+ {
+ dest.erase(exists);
+ break;
+ }
+ }
+ dest.insert( *k );
+ //_accumulatedFunctions[j->first].insert( *k );
}
}
}
@@ -812,461 +780,22 @@ VirtualProgram::refreshAccumulatedFunctions( const osg::State& state )
// add the local ones too:
for( FunctionLocationMap::const_iterator j = _functions.begin(); j != _functions.end(); ++j )
{
- const OrderedFunctionMap& ofm = j->second;
- for( OrderedFunctionMap::const_iterator k = ofm.begin(); k != ofm.end(); ++k )
- {
- _accumulatedFunctions[j->first].insert( *k );
- }
- }
-}
-
-//----------------------------------------------------------------------------
-
-std::string
-ShaderFactory::getSamplerName( unsigned unit ) const
-{
- return Stringify() << "osgearth_tex" << unit;
-}
-
-
-osg::Shader*
-ShaderFactory::createVertexShaderMain(const FunctionLocationMap& functions,
- bool useLightingShaders ) const
-{
- FunctionLocationMap::const_iterator i = functions.find( LOCATION_VERTEX_PRE_TEXTURING );
- const OrderedFunctionMap* preTexture = i != functions.end() ? &i->second : 0L;
-
- FunctionLocationMap::const_iterator j = functions.find( LOCATION_VERTEX_PRE_LIGHTING );
- const OrderedFunctionMap* preLighting = j != functions.end() ? &j->second : 0L;
-
- FunctionLocationMap::const_iterator k = functions.find( LOCATION_VERTEX_POST_LIGHTING );
- const OrderedFunctionMap* postLighting = k != functions.end() ? &k->second : 0L;
-
- std::stringstream buf;
- buf << "#version " << GLSL_VERSION_STR << "\n"
-#ifdef OSG_GLES2_AVAILABLE
- << "precision mediump float;\n"
-#endif
- << "void osgearth_vert_setupColoring(); \n";
-
- if ( useLightingShaders )
- buf << "void osgearth_vert_setupLighting(); \n";
-
- if ( preTexture )
- for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
- buf << "void " << i->second << "(); \n";
-
- if ( preLighting )
- for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
- buf << "void " << i->second << "(); \n";
-
- if ( postLighting )
- for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
- buf << "void " << i->second << "(); \n";
-
- buf << "void main(void) \n"
- << "{ \n"
- << " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n";
-
- if ( preTexture )
- for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
- buf << " " << i->second << "(); \n";
-
- buf << " osgearth_vert_setupColoring(); \n";
-
- if ( preLighting )
- for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
- buf << " " << i->second << "(); \n";
-
- if ( useLightingShaders )
- buf << " osgearth_vert_setupLighting(); \n";
-
- if ( postLighting )
- for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
- buf << " " << i->second << "(); \n";
-
- buf << "} \n";
-
- std::string str;
- str = buf.str();
- //OE_INFO << str << std::endl;
- return new osg::Shader( osg::Shader::VERTEX, str );
-}
-
-
-osg::Shader*
-ShaderFactory::createFragmentShaderMain(const FunctionLocationMap& functions,
- bool useLightingShaders ) const
-{
- FunctionLocationMap::const_iterator i = functions.find( LOCATION_FRAGMENT_PRE_TEXTURING );
- const OrderedFunctionMap* preTexture = i != functions.end() ? &i->second : 0L;
-
- FunctionLocationMap::const_iterator j = functions.find( LOCATION_FRAGMENT_PRE_LIGHTING );
- const OrderedFunctionMap* preLighting = j != functions.end() ? &j->second : 0L;
-
- FunctionLocationMap::const_iterator k = functions.find( LOCATION_FRAGMENT_POST_LIGHTING );
- const OrderedFunctionMap* postLighting = k != functions.end() ? &k->second : 0L;
-
- std::stringstream buf;
- buf << "#version " << GLSL_VERSION_STR << "\n"
-#ifdef OSG_GLES2_AVAILABLE
- << "precision mediump float;\n"
-#endif
- << "void osgearth_frag_applyColoring( inout vec4 color ); \n";
-
- if ( useLightingShaders )
- buf << "void osgearth_frag_applyLighting( inout vec4 color ); \n";
-
- if ( preTexture )
- for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
- buf << "void " << i->second << "( inout vec4 color ); \n";
-
- if ( preLighting )
- for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
- buf << "void " << i->second << "( inout vec4 color ); \n";
-
- if ( postLighting )
- for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
- buf << "void " << i->second << "( inout vec4 color ); \n";
-
- buf << "void main(void) \n"
- << "{ \n"
- << " vec4 color = vec4(1,1,1,1); \n"; //gl_Color; \n"; //vec4(1,1,1,1); \n";
-
- if ( preTexture )
- for( OrderedFunctionMap::const_iterator i = preTexture->begin(); i != preTexture->end(); ++i )
- buf << " " << i->second << "( color ); \n";
-
- buf << " osgearth_frag_applyColoring( color ); \n";
-
- if ( preLighting )
- for( OrderedFunctionMap::const_iterator i = preLighting->begin(); i != preLighting->end(); ++i )
- buf << " " << i->second << "( color ); \n";
-
- if ( useLightingShaders )
- buf << " osgearth_frag_applyLighting( color ); \n";
-
- if ( postLighting )
- for( OrderedFunctionMap::const_iterator i = postLighting->begin(); i != postLighting->end(); ++i )
- buf << " " << i->second << "( color ); \n";
-
- buf << " gl_FragColor = color; \n"
-
-#if 0 // GW: testing logarithmic depth buffer remapping
- << " float A = gl_ProjectionMatrix[2].z; \n"
- << " float B = gl_ProjectionMatrix[3].z; \n"
- << " float n = -B/(1.0-A); \n"
- << " float f = B/(1.0+A); \n"
- << " float C = 1; \n"
- << " gl_FragDepth = log(C*gl_FragCoord.z+1) / log(C*f+1); \n"
-#endif
- << "} \n";
-
- std::string str;
- str = buf.str();
- //OE_INFO << str;
- return new osg::Shader( osg::Shader::FRAGMENT, str );
-}
-
-
-osg::Shader*
-ShaderFactory::createDefaultColoringVertexShader( unsigned numTexCoordSets ) const
-{
- std::stringstream buf;
-
- buf << "#version " << GLSL_VERSION_STR << "\n";
-#ifdef OSG_GLES2_AVAILABLE
- buf << "precision mediump float;\n";
-#endif
-
- //if ( numTexCoordSets > 0 )
- //{
- // buf << "varying vec4 osg_TexCoord[" << numTexCoordSets << "];\n";
- //}
- buf << "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "];\n";
-
- buf
- << "varying vec4 osg_FrontColor;\n"
- << "varying vec4 osg_FrontSecondaryColor;\n"
-
- << "void osgearth_vert_setupColoring() \n"
- << "{ \n"
- << " osg_FrontColor = gl_Color; \n"
- << " osg_FrontSecondaryColor = vec4(0.0); \n";
-
- //TODO: gl_TexCoord et.al. are depcrecated so we should replace them;
- // this approach also only support up to 8 texture coord units
- for(unsigned i=0; i<numTexCoordSets; ++i )
- {
- buf << " osg_TexCoord["<< i <<"] = gl_MultiTexCoord"<< i << "; \n";
- }
-
- buf << "} \n";
-
- std::string str;
- str = buf.str();
-
- osg::Shader* shader = new osg::Shader(osg::Shader::VERTEX, str);
- shader->setName( VERTEX_SETUP_COLORING );
- return shader;
-}
-
-
-osg::Shader*
-ShaderFactory::createDefaultColoringFragmentShader( unsigned numTexImageUnits ) const
-{
- std::stringstream buf;
-
- buf << "#version " << GLSL_VERSION_STR << "\n";
-#ifdef OSG_GLES2_AVAILABLE
- buf << "precision mediump float;\n";
-#endif
-
- buf << "varying vec4 osg_FrontColor;\n";
-
- if ( numTexImageUnits > 0 )
- {
- buf << "varying vec4 osg_TexCoord[" << Registry::capabilities().getMaxGPUTextureCoordSets() << "];\n";
- buf << "uniform sampler2D ";
- for( unsigned i=0; i<numTexImageUnits; ++i )
- {
- buf << getSamplerName(i) << (i+1 < numTexImageUnits? "," : "; \n");
- }
- }
-
- buf << "void osgearth_frag_applyColoring( inout vec4 color ) \n"
- << "{ \n"
- << " color = color * osg_FrontColor; \n";
-
- if ( numTexImageUnits > 0 )
- {
- buf << " vec4 texel; \n";
+ const OrderedFunctionMap& source = j->second;
+ OrderedFunctionMap& dest = _accumulatedFunctions[j->first];
- for(unsigned i=0; i<numTexImageUnits; ++i )
+ for( OrderedFunctionMap::const_iterator k = source.begin(); k != source.end(); ++k )
{
- buf << " texel = texture2D(" << getSamplerName(i) << ", osg_TexCoord["<< i <<"].st); \n";
- buf << " color.rgb = mix( color.rgb, texel.rgb, texel.a ); \n";
- if ( i == 0 )
- buf << " color.a = texel.a * color.a; \n";
+ // remove/override an existing function with the same name
+ for( OrderedFunctionMap::iterator exists = dest.begin(); exists != dest.end(); ++exists )
+ {
+ if ( exists->second.compare( k->second ) == 0 )
+ {
+ dest.erase(exists);
+ break;
+ }
+ }
+ dest.insert( *k );
+ //_accumulatedFunctions[j->first].insert( *k );
}
- }
-
- buf << "} \n";
-
- std::string str;
- str = buf.str();
-
- osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, str );
- shader->setName( FRAGMENT_APPLY_COLORING );
- return shader;
-}
-
-
-osg::Shader*
-ShaderFactory::createDefaultLightingVertexShader() const
-{
- int maxLights = Registry::capabilities().getMaxLights();
-
- std::stringstream buf;
- buf << "#version " << GLSL_VERSION_STR << "\n"
-#ifdef OSG_GLES2_AVAILABLE
- << "precision mediump float;\n"
-
- //add lightsource typedef and uniform array
- << "struct osg_LightSourceParameters {"
- << " vec4 ambient;"
- << " vec4 diffuse;"
- << " vec4 specular;"
- << " vec4 position;"
- << " vec4 halfVector;"
- << " vec3 spotDirection;"
- << " float spotExponent;"
- << " float spotCutoff;"
- << " float spotCosCutoff;"
- << " float constantAttenuation;"
- << " float linearAttenuation;"
- << " float quadraticAttenuation;"
- << "};\n"
- << "uniform osg_LightSourceParameters osg_LightSource[" << maxLights << "];\n"
-
- << "struct osg_LightProducts {"
- << " vec4 ambient;"
- << " vec4 diffuse;"
- << " vec4 specular;"
- << "};\n"
- << "uniform osg_LightProducts osg_FrontLightProduct[" << maxLights << "];\n"
-
-#endif
-
- << "varying vec4 osg_FrontColor;\n"
- << "varying vec4 osg_FrontSecondaryColor;\n"
-
- << "uniform bool osgearth_LightingEnabled; \n"
-
-#ifndef OSG_GLES2_AVAILABLE
- << "void osgearth_vert_setupLighting() \n"
- << "{ \n"
- << " if (osgearth_LightingEnabled) \n"
- << " { \n"
- << " vec3 normal = gl_NormalMatrix * gl_Normal; \n"
- << " float NdotL = dot( normal, normalize(gl_LightSource[0].position.xyz) ); \n"
- << " NdotL = max( 0.0, NdotL ); \n"
- << " float NdotHV = dot( normal, gl_LightSource[0].halfVector.xyz ); \n"
- << " NdotHV = max( 0.0, NdotHV ); \n"
-
- << " osg_FrontColor.rgb = osg_FrontColor.rgb * \n"
- << " clamp( \n"
- << " gl_LightModel.ambient + \n"
- << " gl_FrontLightProduct[0].ambient + \n"
- << " gl_FrontLightProduct[0].diffuse * NdotL, 0.0, 1.0).rgb; \n"
-
- << " osg_FrontSecondaryColor = vec4(0.0); \n"
- << " if ( NdotL * NdotHV > 0.0 ) \n"
- << " { \n"
- << " osg_FrontSecondaryColor.rgb = (gl_FrontLightProduct[0].specular * \n"
- << " pow( NdotHV, gl_FrontMaterial.shininess )).rgb;\n"
- << " } \n"
-
-// << " gl_BackColor = gl_FrontColor; \n"
-// << " gl_BackSecondaryColor = gl_FrontSecondaryColor; \n"
- << " } \n"
- << "} \n";
-#else
- << "void osgearth_vert_setupLighting() \n"
- << "{ \n"
- << " if (osgearth_LightingEnabled) \n"
- << " { \n"
- << " float shine = 10.0;\n"
- << " vec4 lightModelAmbi = vec4(0.1,0.1,0.1,1.0);\n"
-//gl_FrontMaterial.shininess
-//gl_LightModel.ambient
- << " vec3 normal = gl_NormalMatrix * gl_Normal; \n"
- << " float NdotL = dot( normal, normalize(osg_LightSource[0].position.xyz) ); \n"
- << " NdotL = max( 0.0, NdotL ); \n"
- << " float NdotHV = dot( normal, osg_LightSource[0].halfVector.xyz ); \n"
- << " NdotHV = max( 0.0, NdotHV ); \n"
-
- << " osg_FrontColor.rgb = osg_FrontColor.rgb * \n"
- << " clamp( \n"
- << " lightModelAmbi + \n"
- << " osg_FrontLightProduct[0].ambient + \n"
- << " osg_FrontLightProduct[0].diffuse * NdotL, 0.0, 1.0).rgb; \n"
-
- << " osg_FrontSecondaryColor = vec4(0.0); \n"
-
- << " if ( NdotL * NdotHV > 0.0 ) \n"
- << " { \n"
- << " osg_FrontSecondaryColor.rgb = (osg_FrontLightProduct[0].specular * \n"
- << " pow( NdotHV, shine )).rgb;\n"
- << " } \n"
- // << " gl_BackColor = gl_FrontColor; \n"
- // << " gl_BackSecondaryColor = gl_FrontSecondaryColor; \n"
- << " } \n"
- << "} \n";
-#endif
-
- osg::Shader* shader = new osg::Shader( osg::Shader::VERTEX, buf.str().c_str() );
- shader->setName( VERTEX_SETUP_LIGHTING );
- return shader;
-}
-
-
-osg::Shader*
-ShaderFactory::createDefaultLightingFragmentShader() const
-{
- std::stringstream buf;
-
- buf << "#version " << GLSL_VERSION_STR << "\n"
-#ifdef OSG_GLES2_AVAILABLE
- << "precision mediump float;\n"
-#endif
-
- << "varying vec4 osg_FrontColor;\n"
- << "varying vec4 osg_FrontSecondaryColor;\n"
-
- << "uniform bool osgearth_LightingEnabled; \n"
- << "void osgearth_frag_applyLighting( inout vec4 color ) \n"
- << "{ \n"
- << " if ( osgearth_LightingEnabled ) \n"
- << " { \n"
- << " float alpha = color.a; \n"
- << " color = (color * osg_FrontColor) + osg_FrontSecondaryColor; \n"
- << " color.a = alpha; \n"
- << " } \n"
- << "} \n";
-
- osg::Shader* shader = new osg::Shader( osg::Shader::FRAGMENT, buf.str().c_str() );
- shader->setName( FRAGMENT_APPLY_LIGHTING );
- return shader;
-}
-
-
-osg::Shader*
-ShaderFactory::createColorFilterChainFragmentShader( const std::string& function, const ColorFilterChain& chain ) const
-{
- std::stringstream buf;
- buf << "#version " << GLSL_VERSION_STR << "\n";
-#ifdef OSG_GLES2_AVAILABLE
- buf << "precision mediump float;\n";
-#endif
-
- // write out the shader function prototypes:
- for( ColorFilterChain::const_iterator i = chain.begin(); i != chain.end(); ++i )
- {
- ColorFilter* filter = i->get();
- buf << "void " << filter->getEntryPointFunctionName() << "(in int slot, inout vec4 color);\n";
- }
-
- // write out the main function:
- buf << "void " << function << "(in int slot, inout vec4 color) \n"
- << "{ \n";
-
- // write out the function calls. if there are none, it's a NOP.
- for( ColorFilterChain::const_iterator i = chain.begin(); i != chain.end(); ++i )
- {
- ColorFilter* filter = i->get();
- buf << " " << filter->getEntryPointFunctionName() << "(slot, color);\n";
- }
-
- buf << "} \n";
-
- std::string bufstr;
- bufstr = buf.str();
- return new osg::Shader(osg::Shader::FRAGMENT, bufstr);
+ }
}
-
-
-//--------------------------------------------------------------------------
-
-#if 0
-// This is just a holding pen for various stuff
-
-static char s_PerFragmentLighting_VertexShaderSource[] =
- "varying vec3 Normal; \n"
- "varying vec3 Position; \n"
- "void osgearth_vert_setupLighting() \n"
- "{ \n"
- " Normal = normal; \n"
- " Position = position; \n"
- "} \n";
-
-static char s_PerFragmentDirectionalLighting_FragmentShaderSource[] =
- "varying vec3 Normal; \n"
- "varying vec3 Position; \n"
- "void osgearth_frag_applyLighting( inout vec4 color ) \n"
- "{ \n"
- " vec3 n = normalize( Normal ); \n"
- " float NdotL = dot( n, normalize(gl_LightSource[0].position.xyz) ); \n"
- " NdotL = max( 0.0, NdotL ); \n"
- " float NdotHV = dot( n, gl_LightSource[0].halfVector.xyz ); \n"
- " NdotHV = max( 0.0, NdotHV ); \n"
- " color *= gl_FrontLightModelProduct.sceneColor + \n"
- " gl_FrontLightProduct[0].ambient + \n"
- " gl_FrontLightProduct[0].diffuse * NdotL; \n"
- " if ( NdotL * NdotHV > 0.0 ) \n"
- " color += gl_FrontLightProduct[0].specular * \n"
- " pow( NdotHV, gl_FrontMaterial.shininess ); \n"
- "} \n";
-
-#endif
-
diff --git a/src/osgEarth/XmlUtils.cpp b/src/osgEarth/XmlUtils.cpp
index 7dac714..77c9cc1 100644
--- a/src/osgEarth/XmlUtils.cpp
+++ b/src/osgEarth/XmlUtils.cpp
@@ -20,6 +20,7 @@
#include <osgEarth/XmlUtils>
#include <osgEarth/StringUtils>
#include <osg/Notify>
+
#include "tinyxml.h"
#include <algorithm>
#include <sstream>
@@ -429,49 +430,46 @@ XmlDocument::getConfig() const
return conf;
}
-#define INDENT 4
-
static void
-storeNode( const XmlNode* node, int depth, std::ostream& out )
+storeNode( const XmlNode* node, TiXmlNode* parent)
{
- out << std::fixed; // always use fixed notation
-
- for( int k=0; k<depth*INDENT; k++ ) out << " ";
-
- if ( node->isElement() )
+ if (node->isElement())
{
XmlElement* e = (XmlElement*)node;
- out << "<" << e->getName();
+ TiXmlElement* element = new TiXmlElement( e->getName().c_str() );
+ //Write out all the attributes
for( XmlAttributes::iterator a = e->getAttrs().begin(); a != e->getAttrs().end(); a++ )
{
- out << " " << a->first << "=" << "\"" << a->second << "\"";
+ element->SetAttribute(a->first.c_str(), a->second.c_str() );
}
- out << ">" << std::endl;
+
+ //Write out all the child nodes
for( XmlNodeList::iterator i = e->getChildren().begin(); i != e->getChildren().end(); i++ )
{
- storeNode( i->get(), depth+1, out );
+ storeNode( i->get(), element );
}
- for( int k=0; k<depth*INDENT; k++ ) out << " ";
- out << "</" << e->getName() << ">" << std::endl;
+ parent->LinkEndChild( element );
}
- else if ( node->isText() )
+ else if (node->isText())
{
XmlText* t = (XmlText*)node;
- const std::string& text = t->getValue();
- if ( text.find_first_of( "<&" ) != std::string::npos )
- out << "<![CDATA[" << text << "]]>" << std::endl;
- else
- out << text << std::endl;
+ parent->LinkEndChild( new TiXmlText( t->getValue().c_str() ) );
}
}
void
XmlDocument::store( std::ostream& out ) const
-{
- out << "<?xml version=\"1.0\"?>" << std::endl;
- storeNode( this, 0, out);
- /*for( XmlNodeList::const_iterator i = getChildren().begin(); i != getChildren().end(); i++ )
- {
- storeNode( i->get(), 0, out );
- }*/
+{
+ TiXmlDocument doc;
+ doc.LinkEndChild( new TiXmlDeclaration( "1.0", "", ""));
+ storeNode( this, &doc );
+
+
+ //Use TiXmlPrinter to do pretty printing.
+ TiXmlPrinter printer;
+ printer.SetIndent(" ");
+ doc.Accept(&printer);
+ out << printer.CStr();
+
+ //out << doc;
}
diff --git a/src/osgEarthAnnotation/AnnotationNode b/src/osgEarthAnnotation/AnnotationNode
index ebeaea5..eee588b 100644
--- a/src/osgEarthAnnotation/AnnotationNode
+++ b/src/osgEarthAnnotation/AnnotationNode
@@ -151,12 +151,20 @@ namespace osgEarth { namespace Annotation
*/
virtual void setDepthAdjustment( bool value );
+ /**
+ * Sets a lighting override but only if lighting is not already set.
+ */
+ void setLightingIfNotSet( bool lighting );
+
// utility funcion to make a geopoint absolute height
bool makeAbsolute( GeoPoint& mapPoint, osg::Node* patch =0L ) const;
// hidden default ctor
AnnotationNode( MapNode* mapNode =0L );
+ // hidden config ctor
+ AnnotationNode( MapNode* mapNode, const Config& conf );
+
// hidden copy ctor
AnnotationNode(const AnnotationNode& rhs, const osg::CopyOp& op=osg::CopyOp::DEEP_COPY_ALL) { }
@@ -194,7 +202,14 @@ namespace osgEarth { namespace Annotation
protected:
- PositionedAnnotationNode(MapNode* mapNode =0L) : AnnotationNode(mapNode) { }
+ PositionedAnnotationNode()
+ : AnnotationNode() { }
+
+ PositionedAnnotationNode(MapNode* mapNode)
+ : AnnotationNode( mapNode ) { }
+
+ PositionedAnnotationNode(MapNode* mapNode, const Config& conf)
+ : AnnotationNode( mapNode, conf ) { }
};
diff --git a/src/osgEarthAnnotation/AnnotationNode.cpp b/src/osgEarthAnnotation/AnnotationNode.cpp
index 13fc4cb..6207e82 100644
--- a/src/osgEarthAnnotation/AnnotationNode.cpp
+++ b/src/osgEarthAnnotation/AnnotationNode.cpp
@@ -61,6 +61,35 @@ _activeDs ( 0L )
//nop
//Note: Cannot call setMapNode() here because it's a virtual function.
// Each subclass will be separately responsible at ctor time.
+
+ // always blend.
+ this->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
+}
+
+AnnotationNode::AnnotationNode(MapNode* mapNode, const Config& conf) :
+_mapNode ( mapNode ),
+_dynamic ( false ),
+_autoclamp ( false ),
+_depthAdj ( false ),
+_activeDs ( 0L )
+{
+ if ( conf.hasValue("lighting") )
+ {
+ bool lighting = conf.value<bool>("lighting", false);
+ setLightingIfNotSet( lighting );
+ }
+
+ if ( conf.hasValue("backface_culling") )
+ {
+ bool culling = conf.value<bool>("backface_culling", false);
+ getOrCreateStateSet()->setMode( GL_CULL_FACE, (culling?1:0) | osg::StateAttribute::OVERRIDE );
+ }
+
+ if ( conf.hasValue("blending") )
+ {
+ bool blending = conf.value<bool>("blending", false);
+ getOrCreateStateSet()->setMode( GL_BLEND, (blending?1:0) | osg::StateAttribute::OVERRIDE );
+ }
}
AnnotationNode::~AnnotationNode()
@@ -69,6 +98,19 @@ AnnotationNode::~AnnotationNode()
}
void
+AnnotationNode::setLightingIfNotSet( bool lighting )
+{
+ osg::StateSet* ss = this->getOrCreateStateSet();
+
+ if ( ss->getMode(GL_LIGHTING) == osg::StateAttribute::INHERIT )
+ {
+ this->getOrCreateStateSet()->setMode(
+ GL_LIGHTING,
+ (lighting ? 1 : 0) | osg::StateAttribute::OVERRIDE );
+ }
+}
+
+void
AnnotationNode::setMapNode( MapNode* mapNode )
{
if ( getMapNode() != mapNode )
@@ -327,7 +369,4 @@ AnnotationNode::applyStyle( const Style& style)
_altitude = style.get<AltitudeSymbol>();
setAutoClamp( true );
}
-
- bool enableLighting = style.has<ExtrusionSymbol>();
- this->getOrCreateStateSet()->setMode( GL_LIGHTING, enableLighting );
}
diff --git a/src/osgEarthAnnotation/AnnotationUtils b/src/osgEarthAnnotation/AnnotationUtils
index 30d4262..6bb3b29 100644
--- a/src/osgEarthAnnotation/AnnotationUtils
+++ b/src/osgEarthAnnotation/AnnotationUtils
@@ -74,11 +74,15 @@ namespace osgEarth { namespace Annotation
*/
static osg::Uniform* createHighlightUniform();
+#if 0
/**
* Install a program that implements fading, highligting, etc. on annotation
* objects.
*/
- static void installAnnotationProgram( osg::StateSet* stateSet );
+ static void installAnnotationProgram(
+ osg::StateSet* stateSet,
+ osg::StateAttribute::OverrideValue value =osg::StateAttribute::ON );
+#endif
/**
* Builds a graph on top of the specified that that implements a 2-pass
diff --git a/src/osgEarthAnnotation/AnnotationUtils.cpp b/src/osgEarthAnnotation/AnnotationUtils.cpp
index e3d0f7a..2d4052d 100644
--- a/src/osgEarthAnnotation/AnnotationUtils.cpp
+++ b/src/osgEarthAnnotation/AnnotationUtils.cpp
@@ -23,7 +23,7 @@
#include <osgEarthSymbology/MeshSubdivider>
#include <osgEarth/ThreadingUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/Capabilities>
@@ -124,6 +124,11 @@ AnnotationUtils::createTextDrawable(const std::string& text,
{
t->setBackdropColor( symbol->halo()->color() );
t->setBackdropType( osgText::Text::OUTLINE );
+
+ if ( symbol->haloOffset().isSet() )
+ {
+ t->setBackdropOffset( *symbol->haloOffset(), *symbol->haloOffset() );
+ }
}
else if ( !symbol )
{
@@ -175,7 +180,7 @@ AnnotationUtils::createImageGeometry(osg::Image* image,
osg::StateSet* dstate = new osg::StateSet;
dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
- dstate->setMode(GL_BLEND, 1);
+ //dstate->setMode(GL_BLEND, 1); // redundant. AnnotationNode sets blending.
dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
// set up the geoset.
@@ -245,11 +250,12 @@ AnnotationUtils::createHighlightUniform()
return u;
}
+#if 0
void
-AnnotationUtils::installAnnotationProgram( osg::StateSet* stateSet )
+AnnotationUtils::installAnnotationProgram(osg::StateSet* stateSet,
+ osg::StateAttribute::OverrideValue qualifier)
{
- static Threading::Mutex s_mutex;
- //static osg::ref_ptr<osg::Program> s_program;
+ static Threading::Mutex s_mutex;
static osg::ref_ptr<VirtualProgram> s_program;
static osg::ref_ptr<osg::Uniform> s_samplerUniform;
static osg::ref_ptr<osg::Uniform> s_defaultFadeUniform;
@@ -262,6 +268,9 @@ AnnotationUtils::installAnnotationProgram( osg::StateSet* stateSet )
{
std::string vertSource =
"#version " GLSL_VERSION_STR "\n"
+#ifdef OSG_GLES2_AVAILABLE
+ "precision mediump float;\n"
+#endif
//NOTE: Tom commented this out; I commented it back in b/c that breaks things
//( //not sure why but these arn't merging properly, osg earth color funcs decalre it anyhow for now)
"varying vec4 osg_FrontColor; \n"
@@ -279,33 +288,30 @@ AnnotationUtils::installAnnotationProgram( osg::StateSet* stateSet )
#endif
"uniform float " << UNIFORM_FADE() << "; \n"
"uniform bool " << UNIFORM_IS_TEXT() << "; \n"
- //"uniform bool " << UNIFORM_HIGHLIGHT() << "; \n"
"uniform sampler2D oeAnno_tex0; \n"
- "varying vec4 osg_FrontColor; \n"
"varying vec4 oeAnno_texCoord; \n"
+ "varying vec4 osg_FrontColor; \n"
"void oeAnno_fragColoring( inout vec4 color ) \n"
"{ \n"
+ " color = osg_FrontColor; \n"
" if (" << UNIFORM_IS_TEXT() << ") \n"
" { \n"
" float alpha = texture2D(oeAnno_tex0, oeAnno_texCoord.st).a; \n"
- " color = vec4(osg_FrontColor.rgb, osg_FrontColor.a * alpha * " << UNIFORM_FADE() << "); \n"
+ " color = vec4(color.rgb, color.a * alpha * " << UNIFORM_FADE() << "); \n"
" } \n"
" else \n"
" { \n"
- " color = osg_FrontColor * texture2D(oeAnno_tex0, oeAnno_texCoord.st) * vec4(1,1,1," << UNIFORM_FADE() << "); \n"
+ " color = color * texture2D(oeAnno_tex0, oeAnno_texCoord.st) * vec4(1,1,1," << UNIFORM_FADE() << "); \n"
" } \n"
- //" if (" << UNIFORM_HIGHLIGHT() << ") \n"
- //" { \n"
- //" color = vec4(color.r*1.5, color.g*0.5, color.b*0.25, color.a); \n"
- //" } \n"
"} \n";
s_program = new VirtualProgram();
s_program->setName( PROGRAM_NAME() );
+ s_program->setInheritShaders( false );
s_program->setUseLightingShaders( false );
s_program->installDefaultColoringShaders();
s_program->setFunction( "oeAnno_vertColoring", vertSource, ShaderComp::LOCATION_VERTEX_PRE_LIGHTING );
- s_program->setFunction( "oeAnno_fragColoring", fragSource, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING );
+ s_program->setFunction( "oeAnno_fragColoring", fragSource, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING, 2.0f );
s_samplerUniform = new osg::Uniform(osg::Uniform::SAMPLER_2D, "oeAnno_tex0");
s_samplerUniform->set( 0 );
@@ -314,54 +320,15 @@ AnnotationUtils::installAnnotationProgram( osg::StateSet* stateSet )
s_defaultIsTextUniform = new osg::Uniform(osg::Uniform::BOOL, "oeAnno_isText");
s_defaultIsTextUniform->set( false );
-
-#if 0
- std::string vert_source = // Stringify() <<
- "#version 110 \n"
- "void main() { \n"
- " osg_FrontColor = gl_Color; \n"
- " osg_TexCoord[0] = gl_MultiTexCoord0; \n"
- " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
- "} \n";
-
- std::string frag_source = Stringify() <<
-#ifdef OSG_GLES2_AVAILABLE
- "precision mediump float;\n"
-#endif
- "uniform float " << UNIFORM_FADE() << "; \n"
- "uniform bool " << UNIFORM_IS_TEXT() << "; \n"
- "uniform bool " << UNIFORM_HIGHLIGHT() << "; \n"
- "uniform sampler2D tex0; \n"
- "varying vec4 osg_TexCoord[" << Registry::instance()->getCapabilities().getMaxGPUTextureCoordSets() << "];\n"
- "varying vec4 osg_FrontColor; \n"
- "void main() { \n"
- " vec4 color; \n"
- " if (" << UNIFORM_IS_TEXT() << ") { \n"
- " float alpha = texture2D(tex0,osg_TexCoord[0].st).a; \n"
- " color = vec4( osg_FrontColor.rgb, osg_FrontColor.a * alpha * " << UNIFORM_FADE() << "); \n"
- " } \n"
- " else { \n"
- " color = osg_FrontColor * texture2D(tex0,osg_TexCoord[0].st) * vec4(1,1,1," << UNIFORM_FADE() << "); \n"
- " } \n"
- " if (" << UNIFORM_HIGHLIGHT() << ") { \n"
- " color = vec4(color.r*1.5, color.g*0.5, color.b*0.25, color.a); \n"
- " } \n"
- " gl_FragColor = color; \n"
- "} \n";
-
- s_program = new osg::Program();
- s_program->setName( PROGRAM_NAME() );
- s_program->addShader( new osg::Shader(osg::Shader::VERTEX, vert_source) );
- s_program->addShader( new osg::Shader(osg::Shader::FRAGMENT, frag_source) );
-#endif
}
}
- stateSet->setAttributeAndModes( s_program.get() );
+ stateSet->setAttributeAndModes( s_program.get(), qualifier );
stateSet->addUniform( s_samplerUniform.get() );
stateSet->addUniform( s_defaultFadeUniform.get() );
stateSet->addUniform( s_defaultIsTextUniform.get() );
}
+#endif
//-------------------------------------------------------------------------
@@ -667,7 +634,7 @@ AnnotationUtils::createFullScreenQuad( const osg::Vec4& color )
osg::StateSet* s = geom->getOrCreateStateSet();
s->setMode(GL_LIGHTING,0);
- s->setMode(GL_BLEND,1);
+ //s->setMode(GL_BLEND,1); // redundant. AnnotationNode sets blend.
s->setMode(GL_DEPTH_TEST,0);
s->setMode(GL_CULL_FACE,0);
s->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );
diff --git a/src/osgEarthAnnotation/CircleNode.cpp b/src/osgEarthAnnotation/CircleNode.cpp
index e3b77ba..a5a8f18 100644
--- a/src/osgEarthAnnotation/CircleNode.cpp
+++ b/src/osgEarthAnnotation/CircleNode.cpp
@@ -125,6 +125,8 @@ CircleNode::rebuild()
}
applyStyle( _style );
+
+ setLightingIfNotSet( false );
}
setDecoration( currentDecoration );
@@ -139,7 +141,7 @@ OSGEARTH_REGISTER_ANNOTATION( circle, osgEarth::Annotation::CircleNode );
CircleNode::CircleNode(MapNode* mapNode,
const Config& conf,
const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode ),
+LocalizedNode( mapNode, conf ),
_radius ( 1.0, Units::KILOMETERS ),
_draped ( false ),
_numSegments ( 0 )
diff --git a/src/osgEarthAnnotation/EllipseNode.cpp b/src/osgEarthAnnotation/EllipseNode.cpp
index 774e4be..a4ae020 100644
--- a/src/osgEarthAnnotation/EllipseNode.cpp
+++ b/src/osgEarthAnnotation/EllipseNode.cpp
@@ -162,6 +162,8 @@ EllipseNode::rebuild()
}
applyStyle( _style );
+
+ setLightingIfNotSet( false );
}
setDecoration( currentDecoration );
@@ -177,7 +179,7 @@ OSGEARTH_REGISTER_ANNOTATION( ellipse, osgEarth::Annotation::EllipseNode );
EllipseNode::EllipseNode(MapNode* mapNode,
const Config& conf,
const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode ),
+LocalizedNode( mapNode, conf ),
_draped ( false ),
_numSegments ( 0 )
{
diff --git a/src/osgEarthAnnotation/FeatureNode.cpp b/src/osgEarthAnnotation/FeatureNode.cpp
index 8491951..4186d58 100644
--- a/src/osgEarthAnnotation/FeatureNode.cpp
+++ b/src/osgEarthAnnotation/FeatureNode.cpp
@@ -31,6 +31,7 @@
#include <osgEarth/NodeUtils>
#include <osgEarth/Utils>
#include <osgEarth/Registry>
+#include <osgEarth/ShaderGenerator>
#include <osg/BoundingSphere>
#include <osg/Polytope>
@@ -121,13 +122,16 @@ FeatureNode::init()
{
this->addChild( _attachPoint );
}
- }
- // workaround until we can auto-clamp extruded/sub'd geometries.
- if ( autoClamping )
- {
- applyStyle( *_feature->style() );
- clampMesh( getMapNode()->getTerrain()->getGraph() );
+ // workaround until we can auto-clamp extruded/sub'd geometries.
+ if ( autoClamping )
+ {
+ applyStyle( *_feature->style() );
+
+ setLightingIfNotSet( _feature->style()->has<ExtrusionSymbol>() );
+
+ clampMesh( getMapNode()->getTerrain()->getGraph() );
+ }
}
}
}
@@ -207,7 +211,7 @@ OSGEARTH_REGISTER_ANNOTATION( feature, osgEarth::Annotation::FeatureNode );
FeatureNode::FeatureNode(MapNode* mapNode,
const Config& conf,
const osgDB::Options* dbOptions ) :
-AnnotationNode( mapNode )
+AnnotationNode( mapNode, conf )
{
osg::ref_ptr<Geometry> geom;
if ( conf.hasChild("geometry") )
diff --git a/src/osgEarthAnnotation/ImageOverlay.cpp b/src/osgEarthAnnotation/ImageOverlay.cpp
index 5591103..dd17251 100644
--- a/src/osgEarthAnnotation/ImageOverlay.cpp
+++ b/src/osgEarthAnnotation/ImageOverlay.cpp
@@ -26,7 +26,9 @@
#include <osgEarth/NodeUtils>
#include <osgEarth/ImageUtils>
#include <osgEarth/DrapeableNode>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Texture2D>
@@ -56,7 +58,7 @@ namespace
OSGEARTH_REGISTER_ANNOTATION( imageoverlay, osgEarth::Annotation::ImageOverlay );
ImageOverlay::ImageOverlay(MapNode* mapNode, const Config& conf, const osgDB::Options* dbOptions) :
-AnnotationNode(mapNode),
+AnnotationNode(mapNode, conf),
_lowerLeft (10, 10),
_lowerRight (20, 10),
_upperRight (20, 20),
@@ -191,18 +193,17 @@ ImageOverlay::postCTOR()
d->addChild( _transform );
- // need a shader that supports one texture
- VirtualProgram* vp = new VirtualProgram();
- vp->setName( "imageoverlay");
- vp->installDefaultColoringShaders(1);
- //vp->installDefaultColoringAndLightingShaders(1);
- //vp->setInheritShaders(false);
- d->getOrCreateStateSet()->setAttributeAndModes( vp, 1 );
-
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ // need a shader that supports one texture
+ VirtualProgram* vp = new VirtualProgram();
+ vp->setName( "imageoverlay");
+ vp->installDefaultColoringShaders(1);
+ d->getOrCreateStateSet()->setAttributeAndModes( vp, 1 );
+ }
+
init();
ADJUST_UPDATE_TRAV_COUNT( this, 1 );
-
-// getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
}
void
@@ -305,6 +306,7 @@ ImageOverlay::init()
Style style;
style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
applyStyle( style );
+ setLightingIfNotSet( false );
clampMesh( getMapNode()->getTerrain()->getGraph() );
}
}
diff --git a/src/osgEarthAnnotation/LabelNode b/src/osgEarthAnnotation/LabelNode
index cb42564..7fcd158 100644
--- a/src/osgEarthAnnotation/LabelNode
+++ b/src/osgEarthAnnotation/LabelNode
@@ -90,10 +90,15 @@ namespace osgEarth { namespace Annotation
const std::string& text() const { return _text; }
/**
- * Gets the text style.
+ * Gets a copy of the text style.
*/
const Style style() const { return _style; }
+ /**
+ * Sets a new text style
+ */
+ void setStyle( const Style& style );
+
public: // OrthoNode override
virtual void setAnnotationData( AnnotationData* data );
@@ -103,7 +108,7 @@ namespace osgEarth { namespace Annotation
virtual Config getConfig() const;
protected:
- void init();
+ void init(const Style& style);
std::string _text;
class osg::Geode* _geode;
diff --git a/src/osgEarthAnnotation/LabelNode.cpp b/src/osgEarthAnnotation/LabelNode.cpp
index c1048fa..b57dd2d 100644
--- a/src/osgEarthAnnotation/LabelNode.cpp
+++ b/src/osgEarthAnnotation/LabelNode.cpp
@@ -22,6 +22,8 @@
#include <osgEarthAnnotation/AnnotationUtils>
#include <osgEarthAnnotation/AnnotationRegistry>
#include <osgEarthSymbology/Color>
+#include <osgEarth/Registry>
+#include <osgEarth/ShaderGenerator>
#include <osgText/Text>
#include <osg/Depth>
#include <osgUtil/IntersectionVisitor>
@@ -43,10 +45,9 @@ LabelNode::LabelNode(MapNode* mapNode,
OrthoNode( mapNode, position ),
_text ( text ),
-_geode ( 0L ),
-_style ( style )
+_geode ( 0L )
{
- init();
+ init( style );
}
LabelNode::LabelNode(MapNode* mapNode,
@@ -58,66 +59,46 @@ OrthoNode( mapNode, position ),
_text ( text ),
_geode ( 0L )
{
- _style.add( const_cast<TextSymbol*>(symbol) );
- init();
+ Style style;
+ style.add( const_cast<TextSymbol*>(symbol) );
+ init( style );
}
-#if 0
-LabelNode::LabelNode(const SpatialReference* mapSRS,
- const GeoPoint& position,
- const std::string& text,
- const TextSymbol* symbol ) :
-
-OrthoNode( mapSRS, position ),
-_text ( text ),
-_geode ( 0L )
-{
- _style.add( const_cast<TextSymbol*>(symbol) );
- init();
-}
-#endif
-
LabelNode::LabelNode(const std::string& text,
const Style& style ) :
OrthoNode(),
_text ( text ),
-_geode ( 0L ),
-_style ( style )
+_geode ( 0L )
{
- init();
+ init( style );
}
LabelNode::LabelNode(MapNode* mapNode,
const GeoPoint& position,
const Style& style ) :
OrthoNode( mapNode, position ),
-_geode ( 0L ),
-_style ( style )
+_geode ( 0L )
{
- init();
+ init( style );
}
void
-LabelNode::init()
+LabelNode::init( const Style& style )
{
- const TextSymbol* symbol = _style.get<TextSymbol>();
-
- if ( _text.empty() )
- _text = symbol->content()->eval();
-
_geode = new osg::Geode();
-
- osg::Drawable* t = AnnotationUtils::createTextDrawable( _text, symbol, osg::Vec3(0,0,0) );
- _geode->addDrawable(t);
+ getAttachPoint()->addChild( _geode );
osg::StateSet* stateSet = _geode->getOrCreateStateSet();
stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );
- getAttachPoint()->addChild( _geode );
+ setStyle( style );
- AnnotationUtils::installAnnotationProgram( stateSet );
+ applyStyle( style );
- applyStyle( _style );
+ setLightingIfNotSet( false );
+
+ ShaderGenerator gen( Registry::stateSetCache() );
+ this->accept( gen );
}
void
@@ -138,6 +119,32 @@ LabelNode::setText( const std::string& text )
}
void
+LabelNode::setStyle( const Style& style )
+{
+ if ( !_dynamic && getNumParents() > 0 )
+ {
+ OE_WARN << LC << "Illegal state: cannot change a LabelNode that is not dynamic" << std::endl;
+ return;
+ }
+
+ _geode->removeDrawables( 0, _geode->getNumDrawables() );
+
+ _style = style;
+
+ const TextSymbol* symbol = _style.get<TextSymbol>();
+
+ if ( _text.empty() )
+ _text = symbol->content()->eval();
+
+ osg::Drawable* t = AnnotationUtils::createTextDrawable( _text, symbol, osg::Vec3(0,0,0) );
+ _geode->addDrawable(t);
+
+ applyStyle( _style );
+
+ setLightingIfNotSet( false );
+}
+
+void
LabelNode::setAnnotationData( AnnotationData* data )
{
OrthoNode::setAnnotationData( data );
@@ -174,10 +181,12 @@ LabelNode::LabelNode(MapNode* mapNode,
const osgDB::Options* dbOptions ) :
OrthoNode( mapNode, GeoPoint::INVALID )
{
- conf.getObjIfSet( "style", _style );
- conf.getIfSet ( "text", _text );
+ optional<Style> style;
+
+ conf.getObjIfSet( "style", style );
+ conf.getIfSet ( "text", _text );
- init();
+ init( *style );
if ( conf.hasChild("position") )
setPosition( GeoPoint(conf.child("position")) );
diff --git a/src/osgEarthAnnotation/LocalGeometryNode.cpp b/src/osgEarthAnnotation/LocalGeometryNode.cpp
index 393267a..dfe2f2f 100644
--- a/src/osgEarthAnnotation/LocalGeometryNode.cpp
+++ b/src/osgEarthAnnotation/LocalGeometryNode.cpp
@@ -63,6 +63,8 @@ _draped ( draped )
// this will activate the clamping logic
applyStyle( style );
+
+ setLightingIfNotSet( style.has<ExtrusionSymbol>() );
}
}
@@ -99,7 +101,7 @@ OSGEARTH_REGISTER_ANNOTATION( local_geometry, osgEarth::Annotation::LocalGeometr
LocalGeometryNode::LocalGeometryNode(MapNode* mapNode,
const Config& conf,
const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode )
+LocalizedNode( mapNode, conf )
{
if ( conf.hasChild("geometry") )
{
diff --git a/src/osgEarthAnnotation/LocalizedNode b/src/osgEarthAnnotation/LocalizedNode
index cf476c6..fc7c3da 100644
--- a/src/osgEarthAnnotation/LocalizedNode
+++ b/src/osgEarthAnnotation/LocalizedNode
@@ -44,17 +44,12 @@ namespace osgEarth { namespace Annotation
* @param is2D Whether to autotransform the node to face/scale to the screen
*/
LocalizedNode(
- MapNode* mapNode =0L,
+ MapNode* mapNode,
const GeoPoint& pos =GeoPoint::INVALID,
bool is2D =false );
LocalizedNode(
MapNode* mapNode,
- const osg::Vec3d& pos,
- bool is2D =false );
-
- LocalizedNode(
- MapNode* mapNode,
const Config& conf );
virtual ~LocalizedNode() { }
@@ -133,9 +128,14 @@ namespace osgEarth { namespace Annotation
// copy constructor
+ LocalizedNode() { }
LocalizedNode(const LocalizedNode& rhs, const osg::CopyOp& op=osg::CopyOp::DEEP_COPY_ALL) { }
bool updateTransforms(const GeoPoint& absPt, osg::Node* patch =0L);
+
+ private:
+
+ void init( MapNode* mapNode, const GeoPoint& position );
};
diff --git a/src/osgEarthAnnotation/LocalizedNode.cpp b/src/osgEarthAnnotation/LocalizedNode.cpp
index 4b13c80..eef0fb2 100644
--- a/src/osgEarthAnnotation/LocalizedNode.cpp
+++ b/src/osgEarthAnnotation/LocalizedNode.cpp
@@ -30,14 +30,30 @@ using namespace osgEarth;
using namespace osgEarth::Annotation;
-LocalizedNode::LocalizedNode(MapNode* mapNode,
- const GeoPoint& position,
- bool is2D ) :
+LocalizedNode::LocalizedNode(MapNode* mapNode,
+ const GeoPoint& position,
+ bool is2D ) :
PositionedAnnotationNode( mapNode ),
_horizonCulling ( false ),
_autoTransform ( is2D ),
_scale ( 1.0f, 1.0f, 1.0f )
{
+ init( mapNode, position );
+}
+
+LocalizedNode::LocalizedNode(MapNode* mapNode, const Config& conf) :
+PositionedAnnotationNode(mapNode, conf),
+_horizonCulling ( false ),
+_autoTransform ( false ),
+_scale ( 1.0f, 1.0f, 1.0f )
+{
+ init( mapNode, GeoPoint::INVALID );
+}
+
+
+void
+LocalizedNode::init( MapNode* mapNode, const GeoPoint& position )
+{
if ( _autoTransform )
{
osg::AutoTransform* at = new osg::AutoTransform();
@@ -53,7 +69,7 @@ _scale ( 1.0f, 1.0f, 1.0f )
this->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
}
- this->getOrCreateStateSet()->setMode( GL_BLEND, 1 );
+ //this->getOrCreateStateSet()->setMode( GL_BLEND, 1 );
setHorizonCulling( true );
diff --git a/src/osgEarthAnnotation/ModelNode.cpp b/src/osgEarthAnnotation/ModelNode.cpp
index 8430c7a..f136619 100644
--- a/src/osgEarthAnnotation/ModelNode.cpp
+++ b/src/osgEarthAnnotation/ModelNode.cpp
@@ -22,7 +22,9 @@
#include <osgEarthSymbology/Style>
#include <osgEarthSymbology/InstanceSymbol>
#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
#include <osgEarth/ShaderGenerator>
+#include <osgEarth/VirtualProgram>
#define LC "[ModelNode] "
@@ -60,28 +62,51 @@ ModelNode::init(const osgDB::Options* dbOptions)
if ( sym.valid() )
{
- if ( sym->url().isSet() )
+ if ( ( sym->url().isSet() ) || (sym->getModel() != NULL) )
{
- URI uri( sym->url()->eval(), sym->url()->uriContext() );
- osg::Node* node = 0L;
-
- if ( sym->uriAliasMap()->empty() )
- {
- node = uri.getNode( dbOptions );
- }
- else
+ // Try to get a model from symbol
+ osg::ref_ptr<osg::Node> node = sym->getModel();
+
+ // Try to get a model from URI
+ if (node.valid() == false)
{
- // install an alias map if there's one in the symbology.
- osg::ref_ptr<osgDB::Options> tempOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
- tempOptions->setReadFileCallback( new URIAliasMapReadCallback(*sym->uriAliasMap(), uri.full()) );
- node = uri.getNode( tempOptions.get() );
+ URI uri( sym->url()->eval(), sym->url()->uriContext() );
+
+ if ( sym->uriAliasMap()->empty() )
+ {
+ node = uri.getNode( dbOptions );
+ }
+ else
+ {
+ // install an alias map if there's one in the symbology.
+ osg::ref_ptr<osgDB::Options> tempOptions = Registry::instance()->cloneOrCreateOptions(dbOptions);
+ tempOptions->setReadFileCallback( new URIAliasMapReadCallback(*sym->uriAliasMap(), uri.full()) );
+ node = uri.getNode( tempOptions.get() );
+ }
+
+ if (node.valid() == false)
+ {
+ OE_WARN << LC << "No model and failed to load data from " << uri.full() << std::endl;
+ }
}
- if ( node )
+ if (node.valid() == true)
{
- ShaderGenerator gen;
- node->accept( gen );
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ // generate shader code for the loaded model:
+ ShaderGenerator gen( Registry::stateSetCache() );
+ node->accept( gen );
+ // need a top-level shader too:
+ VirtualProgram* vp = new VirtualProgram();
+ vp->installDefaultColoringAndLightingShaders();
+ this->getOrCreateStateSet()->setAttributeAndModes( vp, 1 );
+
+ node->addCullCallback( new UpdateLightingUniformsHelper() );
+ }
+
+ // attach to the transform:
getTransform()->addChild( node );
this->addChild( getTransform() );
@@ -108,12 +133,12 @@ ModelNode::init(const osgDB::Options* dbOptions)
}
else
{
- OE_WARN << LC << "Failed to load data from " << uri.full() << std::endl;
+ OE_WARN << LC << "No model" << std::endl;
}
}
else
{
- OE_WARN << LC << "Symbology: no URI" << std::endl;
+ OE_WARN << LC << "Symbology: no URI or model" << std::endl;
}
}
else
@@ -128,7 +153,7 @@ OSGEARTH_REGISTER_ANNOTATION( model, osgEarth::Annotation::ModelNode );
ModelNode::ModelNode(MapNode* mapNode, const Config& conf, const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode )
+LocalizedNode( mapNode, conf )
{
conf.getObjIfSet( "style", _style );
diff --git a/src/osgEarthAnnotation/OrthoNode b/src/osgEarthAnnotation/OrthoNode
index 47c0580..3e5887b 100644
--- a/src/osgEarthAnnotation/OrthoNode
+++ b/src/osgEarthAnnotation/OrthoNode
@@ -53,15 +53,10 @@ namespace osgEarth { namespace Annotation
MapNode* mapNode,
const GeoPoint& position );
+
/**
- * Constructs an ortho node that resides at an absolute position on the map
+ * dtor.
*/
-#if 0
- OrthoNode(
- const SpatialReference* mapSRS,
- const GeoPoint& position );
-#endif
-
virtual ~OrthoNode() { }
/**
diff --git a/src/osgEarthAnnotation/PlaceNode.cpp b/src/osgEarthAnnotation/PlaceNode.cpp
index 725842d..84a9460 100644
--- a/src/osgEarthAnnotation/PlaceNode.cpp
+++ b/src/osgEarthAnnotation/PlaceNode.cpp
@@ -24,6 +24,7 @@
#include <osgEarthFeatures/LabelSource>
#include <osgEarth/Utils>
#include <osgEarth/Registry>
+#include <osgEarth/ShaderGenerator>
#include <osg/Depth>
#include <osgText/Text>
@@ -187,12 +188,15 @@ PlaceNode::init(const osgDB::Options* dbOptions)
osg::StateSet* stateSet = _geode->getOrCreateStateSet();
stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );
- AnnotationUtils::installAnnotationProgram( stateSet );
-
getAttachPoint()->addChild( _geode );
// for clamping
applyStyle( _style );
+
+ setLightingIfNotSet( false );
+
+ ShaderGenerator gen( Registry::stateSetCache() );
+ this->accept( gen );
}
@@ -256,7 +260,7 @@ OSGEARTH_REGISTER_ANNOTATION( place, osgEarth::Annotation::PlaceNode );
PlaceNode::PlaceNode(MapNode* mapNode,
const Config& conf,
const osgDB::Options* dbOptions) :
-OrthoNode( mapNode, GeoPoint::INVALID )
+OrthoNode( mapNode, conf )
{
conf.getObjIfSet( "style", _style );
conf.getIfSet ( "text", _text );
diff --git a/src/osgEarthAnnotation/RectangleNode.cpp b/src/osgEarthAnnotation/RectangleNode.cpp
index 1b34a66..19ddc62 100644
--- a/src/osgEarthAnnotation/RectangleNode.cpp
+++ b/src/osgEarthAnnotation/RectangleNode.cpp
@@ -32,13 +32,12 @@ using namespace osgEarth::Features;
using namespace osgEarth::Symbology;
-RectangleNode::RectangleNode(
- MapNode* mapNode,
- const GeoPoint& position,
- const Linear& width,
- const Linear& height,
- const Style& style,
- bool draped ) :
+RectangleNode::RectangleNode(MapNode* mapNode,
+ const GeoPoint& position,
+ const Linear& width,
+ const Linear& height,
+ const Style& style,
+ bool draped ) :
LocalizedNode( mapNode, position, false ),
_width ( width ),
_height ( height ),
@@ -362,6 +361,8 @@ RectangleNode::rebuild()
}
applyStyle( _style );
+
+ setLightingIfNotSet( false );
}
setDecoration( currentDecoration );
@@ -377,7 +378,7 @@ OSGEARTH_REGISTER_ANNOTATION( rectangle, osgEarth::Annotation::RectangleNode );
RectangleNode::RectangleNode(MapNode* mapNode,
const Config& conf,
const osgDB::Options* dbOptions) :
-LocalizedNode( mapNode ),
+LocalizedNode( mapNode, conf ),
_draped ( false )
{
conf.getObjIfSet( "width", _width );
diff --git a/src/osgEarthAnnotation/TrackNode.cpp b/src/osgEarthAnnotation/TrackNode.cpp
index f42777f..feac0ad 100644
--- a/src/osgEarthAnnotation/TrackNode.cpp
+++ b/src/osgEarthAnnotation/TrackNode.cpp
@@ -20,6 +20,8 @@
#include <osgEarthAnnotation/TrackNode>
#include <osgEarthAnnotation/AnnotationUtils>
#include <osgEarth/MapNode>
+#include <osgEarth/Registry>
+#include <osgEarth/ShaderGenerator>
#include <osg/Depth>
#include <osgText/Text>
@@ -93,9 +95,12 @@ TrackNode::init( const TrackNodeFieldSchema& schema )
osg::StateSet* stateSet = _geode->getOrCreateStateSet();
stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 );
- AnnotationUtils::installAnnotationProgram( stateSet );
+ setLightingIfNotSet( false );
getAttachPoint()->addChild( _geode );
+
+ ShaderGenerator gen( Registry::stateSetCache() );
+ this->accept( gen );
}
void
@@ -113,7 +118,7 @@ TrackNode::setFieldValue( const std::string& name, const osgText::String& value
if (drawable->getDataVariance() == osg::Object::DYNAMIC || this->getNumParents() == 0)
{
// btw, setText checks for assigning an equal value, so we don't have to
- drawable->setText( value );
+ drawable->setText( value );
}
else
{
diff --git a/src/osgEarthDrivers/earth/EarthFileSerializer b/src/osgEarthDrivers/earth/EarthFileSerializer
index e96d66e..749b5c2 100644
--- a/src/osgEarthDrivers/earth/EarthFileSerializer
+++ b/src/osgEarthDrivers/earth/EarthFileSerializer
@@ -22,20 +22,24 @@
#include <osgEarth/Config>
#include <osgEarth/MapNode>
-using namespace osgEarth;
-
-class EarthFileSerializer1
+namespace osgEarth_osgearth
{
-public:
- MapNode* deserialize( const Config& conf, const std::string& referenceURI ) const;
-};
+ using namespace osgEarth;
-class EarthFileSerializer2
-{
-public:
- MapNode* deserialize( const Config& conf, const std::string& referenceURI ) const;
+ class EarthFileSerializer1
+ {
+ public:
+ MapNode* deserialize( const Config& conf, const std::string& referenceURI ) const;
+ };
+
+ class EarthFileSerializer2
+ {
+ public:
+ MapNode* deserialize( const Config& conf, const std::string& referenceURI ) const;
+
+ Config serialize( MapNode* mapNode ) const;
+ };
- Config serialize( MapNode* mapNode ) const;
-};
+} // namespace osgEarth_osgearth
#endif // OSGEARTH_EARTH_PLUGIN_SERIALIZER_H
diff --git a/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp b/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp
index 4428240..d69f68b 100644
--- a/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp
+++ b/src/osgEarthDrivers/earth/EarthFileSerializer1.cpp
@@ -18,6 +18,7 @@
*/
#include "EarthFileSerializer"
+using namespace osgEarth_osgearth;
using namespace osgEarth;
MapNode*
diff --git a/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp b/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp
index f651f08..3b6cefc 100644
--- a/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp
+++ b/src/osgEarthDrivers/earth/EarthFileSerializer2.cpp
@@ -18,7 +18,9 @@
*/
#include "EarthFileSerializer"
#include <osgEarth/FileUtils>
+#include <osgEarth/MapFrame>
+using namespace osgEarth_osgearth;
using namespace osgEarth;
MapNode*
diff --git a/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp b/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp
index dfc5214..dc15657 100644
--- a/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp
+++ b/src/osgEarthDrivers/earth/ReaderWriterOsgEarth.cpp
@@ -28,6 +28,7 @@
#include <sstream>
#include <osgEarthUtil/Common>
+using namespace osgEarth_osgearth;
using namespace osgEarth;
#define LC "[ReaderWriterEarth] "
diff --git a/src/osgEarthDrivers/engine_osgterrain/CustomTerrainTechnique b/src/osgEarthDrivers/engine_osgterrain/CustomTerrainTechnique
index 957ebe8..5303702 100644
--- a/src/osgEarthDrivers/engine_osgterrain/CustomTerrainTechnique
+++ b/src/osgEarthDrivers/engine_osgterrain/CustomTerrainTechnique
@@ -25,55 +25,59 @@
#include <osg/NodeVisitor>
#include <osgEarth/Progress>
-using namespace osgEarth;
+namespace osgEarth_engine_osgterrain
+{
+ using namespace osgEarth;
-class Tile;
-class TileUpdate;
+ class Tile;
+ class TileUpdate;
-class TerrainTechnique : public osg::Object
-{
-public:
- virtual void init() =0;
+ class TerrainTechnique : public osg::Object
+ {
+ public:
+ virtual void init() =0;
- virtual void traverse( osg::NodeVisitor& nv ) =0;
+ virtual void traverse( osg::NodeVisitor& nv ) =0;
- virtual void releaseGLObjects( osg::State* state ) const =0;
+ virtual void releaseGLObjects( osg::State* state ) const =0;
-protected:
- TerrainTechnique() : _tile(0L) { }
+ protected:
+ TerrainTechnique() : _tile(0L) { }
- TerrainTechnique( const TerrainTechnique& rhs, const osg::CopyOp& op ) : _tile(0L) { }
+ TerrainTechnique( const TerrainTechnique& rhs, const osg::CopyOp& op ) : _tile(0L) { }
- /** dtor */
- virtual ~TerrainTechnique() { }
+ /** dtor */
+ virtual ~TerrainTechnique() { }
- Tile* _tile;
+ Tile* _tile;
- friend class Tile;
-};
+ friend class Tile;
+ };
-class CustomTerrainTechnique : public TerrainTechnique
-{
-public:
- virtual void compile( const TileUpdate& updateSpec, ProgressCallback* progress ) =0;
+ class CustomTerrainTechnique : public TerrainTechnique
+ {
+ public:
+ virtual void compile( const TileUpdate& updateSpec, ProgressCallback* progress ) =0;
+
+ virtual bool applyTileUpdates() =0;
- virtual bool applyTileUpdates() =0;
+ virtual void setParentTile( class Tile* tile ) =0;
- virtual void setParentTile( class Tile* tile ) =0;
+ virtual void setOptimizeTriangleOrientation( bool optimizeTriangleOrientation ) =0;
- virtual void setOptimizeTriangleOrientation( bool optimizeTriangleOrientation ) =0;
+ virtual bool getOptimizeTriangleOrientation() const =0;
- virtual bool getOptimizeTriangleOrientation() const =0;
+ protected:
+ CustomTerrainTechnique() { }
-protected:
- CustomTerrainTechnique() { }
+ CustomTerrainTechnique( const CustomTerrainTechnique& rhs, const osg::CopyOp& op )
+ : TerrainTechnique( rhs, op ) { }
- CustomTerrainTechnique( const CustomTerrainTechnique& rhs, const osg::CopyOp& op )
- : TerrainTechnique( rhs, op ) { }
+ /** dtor */
+ virtual ~CustomTerrainTechnique() { }
+ };
- /** dtor */
- virtual ~CustomTerrainTechnique() { }
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_EXTENDED_TERRAIN_TECHNIQUE
diff --git a/src/osgEarthDrivers/engine_osgterrain/DynamicLODScaleCallback b/src/osgEarthDrivers/engine_osgterrain/DynamicLODScaleCallback
index 62cbc7c..73aa43a 100644
--- a/src/osgEarthDrivers/engine_osgterrain/DynamicLODScaleCallback
+++ b/src/osgEarthDrivers/engine_osgterrain/DynamicLODScaleCallback
@@ -23,59 +23,63 @@
#include <osg/NodeCallback>
#include <osg/CullStack>
-/**
- * Cull callback that dynamically computes an LOD scale based on
- * distance to the camera and a "fall off" metric. As the fall off
- * increases, farther objects' LOD scale will increase. A good
- * range for the fall-off number is 0..5.
- */
-struct DynamicLODScaleCallback : public osg::NodeCallback
+namespace osgEarth_engine_osgterrain
{
- DynamicLODScaleCallback( float fallOff ) : _fallOff(fallOff) { }
+ /**
+ * Cull callback that dynamically computes an LOD scale based on
+ * distance to the camera and a "fall off" metric. As the fall off
+ * increases, farther objects' LOD scale will increase. A good
+ * range for the fall-off number is 0..5.
+ */
+ struct DynamicLODScaleCallback : public osg::NodeCallback
+ {
+ DynamicLODScaleCallback( float fallOff ) : _fallOff(fallOff) { }
- /** dtor */
- virtual ~DynamicLODScaleCallback() { }
+ /** dtor */
+ virtual ~DynamicLODScaleCallback() { }
- void operator()( osg::Node* node, osg::NodeVisitor* nv )
- {
- osg::CullStack* cs = dynamic_cast<osg::CullStack*>(nv);
- if ( cs )
+ void operator()( osg::Node* node, osg::NodeVisitor* nv )
{
- osg::LOD* lod = static_cast<osg::LOD*>( node );
- osg::Vec3 center = lod->getCenter();
+ osg::CullStack* cs = dynamic_cast<osg::CullStack*>(nv);
+ if ( cs )
+ {
+ osg::LOD* lod = static_cast<osg::LOD*>( node );
+ osg::Vec3 center = lod->getCenter();
- osg::Vec3 eye = nv->getEyePoint();
- osg::Vec3 eyeVec = eye; eyeVec.normalize();
- float has = osg::clampAbove( eye.length() - 6356752.3142f, 0.0f );
- float centerToEye = nv->getDistanceToViewPoint(center, false);
- float bsToEye = centerToEye - lod->getChild(0)->getBound().radius();
+ osg::Vec3 eye = nv->getEyePoint();
+ osg::Vec3 eyeVec = eye; eyeVec.normalize();
+ float has = osg::clampAbove( eye.length() - 6356752.3142f, 0.0f );
+ float centerToEye = nv->getDistanceToViewPoint(center, false);
+ float bsToEye = centerToEye - lod->getChild(0)->getBound().radius();
- float scaleAdj = 1.0f;
- if ( bsToEye > has )
+ float scaleAdj = 1.0f;
+ if ( bsToEye > has )
+ {
+ float denom = osg::maximum(0.1f, (1.0f/_fallOff)) * 10000.0f;
+ scaleAdj = osg::clampBetween( log10f(bsToEye/denom), 1.0f, 3.0f );
+
+ //OE_INFO << LC
+ // << std::fixed
+ // << "centerToEye=" << centerToEye
+ // << ", bsToEye=" << bsToEye
+ // << ", scaleAdj=" << scaleAdj
+ // << std::endl;
+ }
+
+ float lodScale = cs->getLODScale();
+ cs->setLODScale( lodScale * scaleAdj );
+ traverse( node, nv );
+ cs->setLODScale( lodScale );
+ }
+ else
{
- float denom = osg::maximum(0.1f, (1.0f/_fallOff)) * 10000.0f;
- scaleAdj = osg::clampBetween( log10f(bsToEye/denom), 1.0f, 3.0f );
-
- //OE_INFO << LC
- // << std::fixed
- // << "centerToEye=" << centerToEye
- // << ", bsToEye=" << bsToEye
- // << ", scaleAdj=" << scaleAdj
- // << std::endl;
+ traverse( node, nv );
}
-
- float lodScale = cs->getLODScale();
- cs->setLODScale( lodScale * scaleAdj );
- traverse( node, nv );
- cs->setLODScale( lodScale );
- }
- else
- {
- traverse( node, nv );
}
- }
- float _fallOff;
-};
+ float _fallOff;
+ };
+
+} // namespace osgEarth_engine_osgterrain
#endif //OSGEARTH_ENGINE_OSGTERRAIN_DYNAMIC_LOD_SCALE_CALLBACK_H
diff --git a/src/osgEarthDrivers/engine_osgterrain/FileLocationCallback b/src/osgEarthDrivers/engine_osgterrain/FileLocationCallback
index 3b06645..b826cb6 100644
--- a/src/osgEarthDrivers/engine_osgterrain/FileLocationCallback
+++ b/src/osgEarthDrivers/engine_osgterrain/FileLocationCallback
@@ -25,56 +25,60 @@
#include <osgEarth/Export>
+namespace osgEarth_engine_osgterrain
+{
#define USE_FILELOCATIONCALLBACK OSG_MIN_VERSION_REQUIRED(2,9,5)
#if USE_FILELOCATIONCALLBACK
-/**
- * A database pager callback that determines if the given filename is cached or not
- */
-class FileLocationCallback : public osgDB::FileLocationCallback
-{
-public:
- FileLocationCallback() { }
-
- /** dtor */
- virtual ~FileLocationCallback() { }
-
- virtual Location fileLocation(const std::string& filename, const osgDB::Options* options)
+ /**
+ * A database pager callback that determines if the given filename is cached or not
+ */
+ class FileLocationCallback : public osgDB::FileLocationCallback
{
- Location result = REMOTE_FILE;
- //OE_NOTICE<<"fileLocation = "<<filename<<std::endl;
-
- unsigned int lod, x, y, id;
- sscanf(filename.c_str(), "%d/%d/%d.%d", &lod, &x, &y, &id);
+ public:
+ FileLocationCallback() { }
- osg::ref_ptr<OSGTerrainEngineNode> engine;
- OSGTerrainEngineNode::getEngineByUID( (UID)id, engine );
+ /** dtor */
+ virtual ~FileLocationCallback() { }
- if ( engine.valid() )
+ virtual Location fileLocation(const std::string& filename, const osgDB::Options* options)
{
- const osgEarth::Profile* profile = engine->getMap()->getProfile();
- osgEarth::TileKey mapKey( lod, x, y, profile );
+ Location result = REMOTE_FILE;
+ //OE_NOTICE<<"fileLocation = "<<filename<<std::endl;
- result = LOCAL_FILE;
+ unsigned int lod, x, y, id;
+ sscanf(filename.c_str(), "%d/%d/%d.%d", &lod, &x, &y, &id);
- MapFrame mapf( engine->getMap() );
- for( unsigned i=0; i<4; ++i )
+ osg::ref_ptr<OSGTerrainEngineNode> engine;
+ OSGTerrainEngineNode::getEngineByUID( (UID)id, engine );
+
+ if ( engine.valid() )
{
- TileKey childKey = mapKey.createChildKey( i );
- if ( !mapf.isCached( childKey ) )
+ const osgEarth::Profile* profile = engine->getMap()->getProfile();
+ osgEarth::TileKey mapKey( lod, x, y, profile );
+
+ result = LOCAL_FILE;
+
+ MapFrame mapf( engine->getMap() );
+ for( unsigned i=0; i<4; ++i )
{
- result = REMOTE_FILE;
- break;
+ TileKey childKey = mapKey.createChildKey( i );
+ if ( !mapf.isCached( childKey ) )
+ {
+ result = REMOTE_FILE;
+ break;
+ }
}
}
+
+ return result;
}
- return result;
- }
+ virtual bool useFileCache() const { return false; }
+ };
- virtual bool useFileCache() const { return false; }
-};
+} //namespace osgEarth_engine_osgterrain
#endif // USE_FILELOCATIONCALLBACK
diff --git a/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory b/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory
index 9fb3cca..101a5c9 100644
--- a/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory
+++ b/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory
@@ -23,24 +23,28 @@
#include <osgEarth/TileKey>
#include <osg/Node>
-using namespace osgEarth;
-
-/**
- * A scene graph node that holds a terrain tile (as the single child of its
- * osg::Group) and can load subtiles when they come into LOD range.
- */
-class KeyNodeFactory : public osg::Referenced
+namespace osgEarth_engine_osgterrain
{
-public:
- virtual osg::Node* createRootNode( const TileKey& key ) =0;
+ using namespace osgEarth;
+
+ /**
+ * A scene graph node that holds a terrain tile (as the single child of its
+ * osg::Group) and can load subtiles when they come into LOD range.
+ */
+ class KeyNodeFactory : public osg::Referenced
+ {
+ public:
+ virtual osg::Node* createRootNode( const TileKey& key ) =0;
+
+ virtual osg::Node* createNode( const TileKey& key ) =0;
- virtual osg::Node* createNode( const TileKey& key ) =0;
+ protected:
+ KeyNodeFactory();
-protected:
- KeyNodeFactory();
+ /** dtor */
+ virtual ~KeyNodeFactory() { }
+ };
- /** dtor */
- virtual ~KeyNodeFactory() { }
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_QUAD_TILE_NODE
diff --git a/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory.cpp b/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory.cpp
index 8ab3fda..4de5916 100644
--- a/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/KeyNodeFactory.cpp
@@ -18,6 +18,7 @@
*/
#include "KeyNodeFactory"
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
#define LC "[KeyNodeFactory] "
diff --git a/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback b/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback
index 0fdbbe2..929272f 100644
--- a/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback
+++ b/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback
@@ -22,14 +22,13 @@
#include <osg/NodeCallback>
-namespace osgEarth
+namespace osgEarth_engine_osgterrain
{
- namespace Drivers
+ struct LODFactorCallback : public osg::NodeCallback
{
- struct LODFactorCallback : public osg::NodeCallback
- {
- void operator()(osg::Node* node, osg::NodeVisitor* nv);
- };
- }
-}
+ void operator()(osg::Node* node, osg::NodeVisitor* nv);
+ };
+
+} // namespace osgEarth_engine_osgterrain
+
#endif
diff --git a/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback.cpp b/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback.cpp
index 78923fa..4bbffb5 100644
--- a/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/LODFactorCallback.cpp
@@ -24,62 +24,58 @@
#include <osg/Uniform>
#include <osgUtil/CullVisitor>
-namespace osgEarth
+using namespace osgEarth_engine_osgterrain;
+
+// This callback sets a uniform, osgearth_LODRangeFactor, based on the
+// distance from the camera and its relation to the minimum and
+// maximum distance for a tile. The maximum distance isn't actually
+// available, so 2 * min distance is used as an estimate. The range
+// factor's value goes from 0 - at the maximum range - to 1 for the
+// minimum range.
+
+void LODFactorCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
- namespace Drivers
+ // test the type since this is not always a PagedLOD.
+ osg::PagedLOD* lod = static_cast<osg::PagedLOD*>(node);
+ osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
+ osg::LOD::RangeMode rangeMode = lod->getRangeMode();
+ float requiredRange = 0.0f;
+ float rangeFactor = 1.0f;
+ const osg::LOD::RangeList& rangeList = lod->getRangeList();
+ if (rangeMode == osg::LOD::DISTANCE_FROM_EYE_POINT)
{
- // This callback sets a uniform, osgearth_LODRangeFactor, based on the
- // distance from the camera and its relation to the minimum and
- // maximum distance for a tile. The maximum distance isn't actually
- // available, so 2 * min distance is used as an estimate. The range
- // factor's value goes from 0 - at the maximum range - to 1 for the
- // minimum range.
-
- void LODFactorCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+ requiredRange = cv->getDistanceToViewPoint(lod->getCenter(), true);
+ }
+ else if (cv->getLODScale() > 0.0f)
+ {
+ requiredRange = cv->clampedPixelSize(lod->getBound()) / cv->getLODScale();
+ }
+ else
+ {
+ // The comment in osg/PagedLOD.cpp says that this algorithm
+ // finds the highest res tile, but it actually finds the
+ // lowest res tile!
+ for (osg::LOD::RangeList::const_iterator itr = rangeList.begin(), end = rangeList.end();
+ itr != end;
+ ++itr)
{
- // test the type since this is not always a PagedLOD.
- osg::PagedLOD* lod = static_cast<osg::PagedLOD*>(node);
- osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
- osg::LOD::RangeMode rangeMode = lod->getRangeMode();
- float requiredRange = 0.0f;
- float rangeFactor = 1.0f;
- const osg::LOD::RangeList& rangeList = lod->getRangeList();
- if (rangeMode == osg::LOD::DISTANCE_FROM_EYE_POINT)
- {
- requiredRange = cv->getDistanceToViewPoint(lod->getCenter(), true);
- }
- else if (cv->getLODScale() > 0.0f)
- {
- requiredRange = cv->clampedPixelSize(lod->getBound()) / cv->getLODScale();
- }
- else
- {
- // The comment in osg/PagedLOD.cpp says that this algorithm
- // finds the highest res tile, but it actually finds the
- // lowest res tile!
- for (osg::LOD::RangeList::const_iterator itr = rangeList.begin(), end = rangeList.end();
- itr != end;
- ++itr)
- {
- requiredRange = osg::maximum(requiredRange, itr->first);
- }
- }
- // We're counting on only finding one valid LOD, unlike the
- // general OSG behavior.
- if (!rangeList.empty() && rangeList[0].first <= requiredRange
- && requiredRange < rangeList[0].second)
- {
- rangeFactor = 1.0f - (requiredRange - rangeList[0].first) / rangeList[0].first;
- rangeFactor = osg::clampTo(rangeFactor, 0.0f, 1.0f);
- }
- osg::ref_ptr<osg::Uniform> ufact
- = new osg::Uniform("osgearth_LODRangeFactor", rangeFactor);
- osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
- ss->addUniform(ufact.get());
-
- cv->pushStateSet(ss.get());
- traverse(node, nv);
- cv->popStateSet();
+ requiredRange = osg::maximum(requiredRange, itr->first);
}
}
+ // We're counting on only finding one valid LOD, unlike the
+ // general OSG behavior.
+ if (!rangeList.empty() && rangeList[0].first <= requiredRange
+ && requiredRange < rangeList[0].second)
+ {
+ rangeFactor = 1.0f - (requiredRange - rangeList[0].first) / rangeList[0].first;
+ rangeFactor = osg::clampTo(rangeFactor, 0.0f, 1.0f);
+ }
+ osg::ref_ptr<osg::Uniform> ufact
+ = new osg::Uniform("osgearth_LODRangeFactor", rangeFactor);
+ osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
+ ss->addUniform(ufact.get());
+
+ cv->pushStateSet(ss.get());
+ traverse(node, nv);
+ cv->popStateSet();
}
diff --git a/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique b/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique
index a49cc7f..8d4e190 100644
--- a/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique
+++ b/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique
@@ -32,50 +32,53 @@
#include <osgEarth/TextureCompositor>
-
-class MultiPassTerrainTechnique : public TerrainTechnique
+namespace osgEarth_engine_osgterrain
{
-public:
+ class MultiPassTerrainTechnique : public TerrainTechnique
+ {
+ public:
+
+ MultiPassTerrainTechnique( TextureCompositor* texCompositor =0L );
- MultiPassTerrainTechnique( TextureCompositor* texCompositor =0L );
+ /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
+ MultiPassTerrainTechnique(const MultiPassTerrainTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+ META_Object( osgEarth, MultiPassTerrainTechnique );
- /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
- MultiPassTerrainTechnique(const MultiPassTerrainTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
-
- META_Object( osgEarth, MultiPassTerrainTechnique );
+ virtual void init();
+
+ virtual osgTerrain::Locator* computeMasterLocator();
+
+ virtual osg::Vec3d computeCenterModel(osgTerrain::Locator* masterLocator);
+
+ virtual void generateGeometry(osgTerrain::Locator* masterLocator, const osg::Vec3d& centerModel);
- virtual void init();
-
- virtual osgTerrain::Locator* computeMasterLocator();
-
- virtual osg::Vec3d computeCenterModel(osgTerrain::Locator* masterLocator);
-
- virtual void generateGeometry(osgTerrain::Locator* masterLocator, const osg::Vec3d& centerModel);
+ virtual osg::Geometry* createGeometryPrototype(osgTerrain::Locator* masterLocator, const osg::Vec3d& centerModel);
- virtual osg::Geometry* createGeometryPrototype(osgTerrain::Locator* masterLocator, const osg::Vec3d& centerModel);
+ osg::Geode* createPass(unsigned int order, const CustomColorLayer* layer, osgTerrain::Locator* masterLocator, const osg::Vec3d& centerModel, osg::Geometry* geometry);
- osg::Geode* createPass(unsigned int order, const CustomColorLayer* layer, osgTerrain::Locator* masterLocator, const osg::Vec3d& centerModel, osg::Geometry* geometry);
+ /** Traverse the terain subgraph.*/
+ virtual void traverse(osg::NodeVisitor& nv);
- /** Traverse the terain subgraph.*/
- virtual void traverse(osg::NodeVisitor& nv);
+ /** If State is non-zero, this function releases any associated OpenGL objects for
+ * the specified graphics context. Otherwise, releases OpenGL objects
+ * for all graphics contexts. */
+ virtual void releaseGLObjects(osg::State* = 0) const;
- /** If State is non-zero, this function releases any associated OpenGL objects for
- * the specified graphics context. Otherwise, releases OpenGL objects
- * for all graphics contexts. */
- virtual void releaseGLObjects(osg::State* = 0) const;
+ private:
-private:
+ void updateTransparency();
+ void updateGeometry();
- void updateTransparency();
- void updateGeometry();
+ virtual ~MultiPassTerrainTechnique();
- virtual ~MultiPassTerrainTechnique();
+ osg::ref_ptr<osg::MatrixTransform> _transform;
+ osg::ref_ptr<osg::Group> _passes;
+ bool _terrainTileInitialized;
+ osg::ref_ptr<TextureCompositor> _texCompositor;
+ };
- osg::ref_ptr<osg::MatrixTransform> _transform;
- osg::ref_ptr<osg::Group> _passes;
- bool _terrainTileInitialized;
- osg::ref_ptr<TextureCompositor> _texCompositor;
-};
+} // namespace osgEarth_engine_osgterrain
#endif //OSGEARTH_ENGINE_OSGTERRAIN_MULTIPASS_TERRAIN_TECHNIQUE
diff --git a/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique.cpp b/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique.cpp
index 4bdbb5a..1e1b313 100644
--- a/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/MultiPassTerrainTechnique.cpp
@@ -34,6 +34,7 @@
#include <osg/Depth>
#include <osg/Version>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
#define NEW_COORD_CODE
diff --git a/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode b/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode
index 880a323..5e8f33c 100644
--- a/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode
+++ b/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode
@@ -32,106 +32,110 @@
#include <osg/Geode>
#include <osg/NodeCallback>
-using namespace osgEarth;
-
-class OSGTerrainEngineNode : public TerrainEngineNode
+namespace osgEarth_engine_osgterrain
{
-public:
- OSGTerrainEngineNode();
- META_Node(osgEarth,OSGTerrainEngineNode);
- virtual ~OSGTerrainEngineNode();
-
-public:
- osg::Node* createNode(const TileKey& key);
-
-public: // TerrainEngineNode overrides
- virtual void preInitialize( const Map* map, const TerrainOptions& options );
- virtual void postInitialize( const Map* map, const TerrainOptions& options );
- virtual void validateTerrainOptions( TerrainOptions& options );
- virtual const TerrainOptions& getTerrainOptions() const { return _terrainOptions; }
- virtual void traverse( osg::NodeVisitor& );
- virtual osg::BoundingSphere computeBound() const;
-
- // for standalone tile creation outside of a terrain
- osg::Node* createTile(const TileKey& key);
-
-public: // MapCallback adapter functions
- void onMapInfoEstablished( const MapInfo& mapInfo ); // not virtual!
- void onMapModelChanged( const MapModelChange& change ); // not virtual!
-
- UID getUID() const;
- OSGTileFactory* getTileFactory() const { return _tileFactory.get(); }
- class TerrainNode* getTerrainNode() const { return _terrain; }
-
-public: // statics
- static void registerEngine( OSGTerrainEngineNode* engineNode );
- static void unregisterEngine( UID uid );
- static void getEngineByUID( UID uid, osg::ref_ptr<OSGTerrainEngineNode>& output );
-
-public:
- class ElevationChangedCallback : public ElevationLayerCallback
+ using namespace osgEarth;
+
+ class OSGTerrainEngineNode : public TerrainEngineNode
{
public:
- ElevationChangedCallback( OSGTerrainEngineNode* terrain );
+ OSGTerrainEngineNode();
+ META_Node(osgEarth,OSGTerrainEngineNode);
+ virtual ~OSGTerrainEngineNode();
- virtual void onVisibleChanged( TerrainLayer* layer );
+ public:
+ osg::Node* createNode(const TileKey& key);
- OSGTerrainEngineNode* _terrain;
- friend class OSGTerrainEngineNode;
- };
+ public: // TerrainEngineNode overrides
+ virtual void preInitialize( const Map* map, const TerrainOptions& options );
+ virtual void postInitialize( const Map* map, const TerrainOptions& options );
+ virtual void validateTerrainOptions( TerrainOptions& options );
+ virtual const TerrainOptions& getTerrainOptions() const { return _terrainOptions; }
+ virtual void traverse( osg::NodeVisitor& );
+ virtual osg::BoundingSphere computeBound() const;
+
+ // for standalone tile creation outside of a terrain
+ osg::Node* createTile(const TileKey& key);
+
+ public: // MapCallback adapter functions
+ void onMapInfoEstablished( const MapInfo& mapInfo ); // not virtual!
+ void onMapModelChanged( const MapModelChange& change ); // not virtual!
+
+ UID getUID() const;
+ OSGTileFactory* getTileFactory() const { return _tileFactory.get(); }
+ class TerrainNode* getTerrainNode() const { return _terrain; }
-protected:
- virtual void onVerticalScaleChanged();
+ public: // statics
+ static void registerEngine( OSGTerrainEngineNode* engineNode );
+ static void unregisterEngine( UID uid );
+ static void getEngineByUID( UID uid, osg::ref_ptr<OSGTerrainEngineNode>& output );
-private:
- void init();
- void syncMapModel();
- void installTerrainTechnique();
+ public:
+ class ElevationChangedCallback : public ElevationLayerCallback
+ {
+ public:
+ ElevationChangedCallback( OSGTerrainEngineNode* terrain );
+
+ virtual void onVisibleChanged( TerrainLayer* layer );
+
+ OSGTerrainEngineNode* _terrain;
+ friend class OSGTerrainEngineNode;
+ };
+
+ protected:
+ virtual void onVerticalScaleChanged();
- /**
- * Reloads all the tiles in the terrain due to a data model change
- */
- void refresh();
+ private:
+ void init();
+ void syncMapModel();
+ void installTerrainTechnique();
+ /**
+ * Reloads all the tiles in the terrain due to a data model change
+ */
+ void refresh();
- void addImageLayer( ImageLayer* layer );
- void addElevationLayer( ElevationLayer* layer );
- void removeImageLayer( ImageLayer* layerRemoved );
- void removeElevationLayer( ElevationLayer* layerRemoved );
+ void addImageLayer( ImageLayer* layer );
+ void addElevationLayer( ElevationLayer* layer );
- void moveImageLayer( unsigned int oldIndex, unsigned int newIndex );
- void moveElevationLayer( unsigned int oldIndex, unsigned int newIndex );
-
- void updateElevation( Tile* tile );
- void installShaders();
- void updateTextureCombining();
+ void removeImageLayer( ImageLayer* layerRemoved );
+ void removeElevationLayer( ElevationLayer* layerRemoved );
-private:
- osg::ref_ptr<OSGTileFactory> _tileFactory;
- //class CustomTerrainNode* _terrain;
- class TerrainNode* _terrain;
- UID _uid;
- osgEarth::Drivers::OSGTerrainOptions _terrainOptions;
- Revision _shaderLibRev;
- osg::ref_ptr<TaskServiceManager> _taskServiceMgr;
+ void moveImageLayer( unsigned int oldIndex, unsigned int newIndex );
+ void moveElevationLayer( unsigned int oldIndex, unsigned int newIndex );
+
+ void updateElevation( Tile* tile );
+ void installShaders();
+ void updateTextureCombining();
- osg::ref_ptr< ElevationChangedCallback > _elevationCallback;
+ private:
+ osg::ref_ptr<OSGTileFactory> _tileFactory;
+ //class CustomTerrainNode* _terrain;
+ class TerrainNode* _terrain;
+ UID _uid;
+ osgEarth::Drivers::OSGTerrainOptions _terrainOptions;
+ Revision _shaderLibRev;
+ osg::ref_ptr<TaskServiceManager> _taskServiceMgr;
- // store a separate map frame for each of the traversal threads
- MapFrame* _update_mapf; // map frame for the main/update traversal thread
- MapFrame* _cull_mapf; // map frame for the cull traversal thread
+ osg::ref_ptr< ElevationChangedCallback > _elevationCallback;
- osg::ref_ptr<TaskService> _tileService;
- osg::ref_ptr<KeyNodeFactory> _keyNodeFactory;
- osg::ref_ptr<TileBuilder> _tileBuilder;
+ // store a separate map frame for each of the traversal threads
+ MapFrame* _update_mapf; // map frame for the main/update traversal thread
+ MapFrame* _cull_mapf; // map frame for the cull traversal thread
- osg::Timer _timer;
- unsigned _tileCount;
- double _tileCreationTime;
- bool _isStreaming;
+ osg::ref_ptr<TaskService> _tileService;
+ osg::ref_ptr<KeyNodeFactory> _keyNodeFactory;
+ osg::ref_ptr<TileBuilder> _tileBuilder;
+
+ osg::Timer _timer;
+ unsigned _tileCount;
+ double _tileCreationTime;
+ bool _isStreaming;
+
+ OSGTerrainEngineNode( const OSGTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) { }
+ };
- OSGTerrainEngineNode( const OSGTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) { }
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_ENGINE_NODE_H
diff --git a/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode.cpp b/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode.cpp
index 6eb4353..c347610 100644
--- a/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/OSGTerrainEngineNode.cpp
@@ -27,7 +27,9 @@
#include <osgEarth/ImageUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/ShaderFactory>
+#include <osgEarth/MapModelChange>
#include <osg/TexEnv>
#include <osg/TexEnvCombine>
#include <osg/PagedLOD>
@@ -35,6 +37,7 @@
#define LC "[OSGTerrainEngine] "
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
//------------------------------------------------------------------------
diff --git a/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory b/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory
index 12227b4..73ff184 100644
--- a/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory
+++ b/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory
@@ -34,140 +34,144 @@
#include <osg/ClusterCullingCallback>
#include <vector>
-using namespace osgEarth;
-using namespace osgEarth::Drivers;
-
-class TerrainNode;
-class StreamingTerrainNode;
-class Tile;
-class StreamingTile;
-
-/**
-* TileFactory is the main workhorse - it generates osg Nodes for TileKeys.
-*/
-class OSGTileFactory : public osg::Referenced
+namespace osgEarth_engine_osgterrain
{
-public:
- OSGTileFactory(
- unsigned engineId,
- const MapFrame& cull_thread_mapf,
- const OSGTerrainOptions& props =OSGTerrainOptions() );
-
- /** dtor */
- virtual ~OSGTileFactory() { }
-
-public:
- /**
- * Creates a node graph containing four tiles that correspond to the four
- * subkeys of the provided TileKey.
- */
- osg::Node* createSubTiles(
- const MapFrame& mapf,
- TerrainNode* terrain,
- const TileKey& key,
- bool populateLayers );
+ using namespace osgEarth;
+ using namespace osgEarth::Drivers;
- /**
- * Creates a single terrain tile corresponding to the provided TileKey.
- */
- osg::Node* createTile(
- const MapFrame& mapf,
- TerrainNode* terrain,
- const TileKey& key,
- bool populateLayers,
- bool wrapInPagedLOD,
- bool fallback,
- bool& out_validData);
-
-
- CustomColorLayerRef* createImageLayer(
- const MapInfo& mapInfo,
- ImageLayer* layer,
- const TileKey& key,
- ProgressCallback* progress);
-
- osgTerrain::HeightFieldLayer* createHeightFieldLayer(
- const MapFrame& mapf,
- const TileKey& key,
- bool exactOnly );
+ class TerrainNode;
+ class StreamingTerrainNode;
+ class Tile;
+ class StreamingTile;
/**
- * Gets the properties that customize how this engine renders tile data.
+ * TileFactory is the main workhorse - it generates osg Nodes for TileKeys.
*/
- const OSGTerrainOptions& getTerrainOptions() const;
-
- /**
- * Gets a pagedLOD child URI given a tile key.
- */
- std::string createURI( unsigned int id, const TileKey& key );
-
- /**
- * Wraps a tile in a paged LOD and setup up all its parameters
- */
- osg::Node* prepareTile(
- Tile* tile,
- TerrainNode* terrain,
- const MapInfo& mapInfo,
- bool wrapInPagedLOD );
-
- bool createValidGeoImage(
- ImageLayer* layer,
- const TileKey& key,
- GeoImage& out_image,
- TileKey& out_actualTileKey,
- ProgressCallback* progress = 0);
-
- osg::Matrixd getTransformFromExtents(double minX, double minY, double maxX, double maxY) const;
-
- // checks whether more data exists below the specified key's level of detail
- bool hasMoreLevels( Map* map, const TileKey& key );
-
- static osg::HeightField* createEmptyHeightField(
- const TileKey& key,
- unsigned numCols =8,
- unsigned numRows =8 );
-
- osgTerrain::HeightFieldLayer* createPlaceholderHeightfieldLayer(
- osg::HeightField* ancestorHF,
- const TileKey& ancestorKey,
- const TileKey& key,
- GeoLocator* locator );
-
-protected:
-
- osg::Node* createPlaceholderTile(
- const MapFrame& mapf,
- StreamingTerrainNode* terrain,
- const TileKey& key );
-
- osg::Node* createPopulatedTile(
- const MapFrame& mapf,
- TerrainNode* terrain,
- const TileKey& key,
- bool wrapInPagedLOD,
- bool fallback,
- bool& out_validData);
-
- void addPlaceholderImageLayers( Tile* tile, Tile* ancestorTile );
-
- void addPlaceholderHeightfieldLayer(
- StreamingTile* tile,
- StreamingTile* ancestorTile,
- GeoLocator* defaultLocator,
- const TileKey& key,
- const TileKey& ancestorKey );
-
- osg::ClusterCullingCallback* createClusterCullingCallback(
- Tile* tile,
- osg::EllipsoidModel* et );
-
- void init();
-
-protected:
-
- unsigned _engineId;
- const MapFrame& _cull_thread_mapf;
- OSGTerrainOptions _terrainOptions;
-};
+ class OSGTileFactory : public osg::Referenced
+ {
+ public:
+ OSGTileFactory(
+ unsigned engineId,
+ const MapFrame& cull_thread_mapf,
+ const OSGTerrainOptions& props =OSGTerrainOptions() );
+
+ /** dtor */
+ virtual ~OSGTileFactory() { }
+
+ public:
+ /**
+ * Creates a node graph containing four tiles that correspond to the four
+ * subkeys of the provided TileKey.
+ */
+ osg::Node* createSubTiles(
+ const MapFrame& mapf,
+ TerrainNode* terrain,
+ const TileKey& key,
+ bool populateLayers );
+
+ /**
+ * Creates a single terrain tile corresponding to the provided TileKey.
+ */
+ osg::Node* createTile(
+ const MapFrame& mapf,
+ TerrainNode* terrain,
+ const TileKey& key,
+ bool populateLayers,
+ bool wrapInPagedLOD,
+ bool fallback,
+ bool& out_validData);
+
+
+ CustomColorLayerRef* createImageLayer(
+ const MapInfo& mapInfo,
+ ImageLayer* layer,
+ const TileKey& key,
+ ProgressCallback* progress);
+
+ osgTerrain::HeightFieldLayer* createHeightFieldLayer(
+ const MapFrame& mapf,
+ const TileKey& key,
+ bool exactOnly );
+
+ /**
+ * Gets the properties that customize how this engine renders tile data.
+ */
+ const OSGTerrainOptions& getTerrainOptions() const;
+
+ /**
+ * Gets a pagedLOD child URI given a tile key.
+ */
+ std::string createURI( unsigned int id, const TileKey& key );
+
+ /**
+ * Wraps a tile in a paged LOD and setup up all its parameters
+ */
+ osg::Node* prepareTile(
+ Tile* tile,
+ TerrainNode* terrain,
+ const MapInfo& mapInfo,
+ bool wrapInPagedLOD );
+
+ bool createValidGeoImage(
+ ImageLayer* layer,
+ const TileKey& key,
+ GeoImage& out_image,
+ TileKey& out_actualTileKey,
+ ProgressCallback* progress = 0);
+
+ osg::Matrixd getTransformFromExtents(double minX, double minY, double maxX, double maxY) const;
+
+ // checks whether more data exists below the specified key's level of detail
+ bool hasMoreLevels( Map* map, const TileKey& key );
+
+ static osg::HeightField* createEmptyHeightField(
+ const TileKey& key,
+ unsigned numCols =8,
+ unsigned numRows =8 );
+
+ osgTerrain::HeightFieldLayer* createPlaceholderHeightfieldLayer(
+ osg::HeightField* ancestorHF,
+ const TileKey& ancestorKey,
+ const TileKey& key,
+ GeoLocator* locator );
+
+ protected:
+
+ osg::Node* createPlaceholderTile(
+ const MapFrame& mapf,
+ StreamingTerrainNode* terrain,
+ const TileKey& key );
+
+ osg::Node* createPopulatedTile(
+ const MapFrame& mapf,
+ TerrainNode* terrain,
+ const TileKey& key,
+ bool wrapInPagedLOD,
+ bool fallback,
+ bool& out_validData);
+
+ void addPlaceholderImageLayers( Tile* tile, Tile* ancestorTile );
+
+ void addPlaceholderHeightfieldLayer(
+ StreamingTile* tile,
+ StreamingTile* ancestorTile,
+ GeoLocator* defaultLocator,
+ const TileKey& key,
+ const TileKey& ancestorKey );
+
+ osg::ClusterCullingCallback* createClusterCullingCallback(
+ Tile* tile,
+ osg::EllipsoidModel* et );
+
+ void init();
+
+ protected:
+
+ unsigned _engineId;
+ const MapFrame& _cull_thread_mapf;
+ OSGTerrainOptions _terrainOptions;
+ };
+
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_TILE_FACTORY_H
diff --git a/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory.cpp b/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory.cpp
index a8c2390..e6c3e95 100644
--- a/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/OSGTileFactory.cpp
@@ -43,6 +43,7 @@
#include <stdlib.h>
using namespace OpenThreads;
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace osgEarth::Drivers;
@@ -418,16 +419,7 @@ OSGTileFactory::createPlaceholderTile(const MapFrame& mapf,
tile->setTerrainTechnique( terrain->cloneTechnique() );
tile->setVerticalScale( _terrainOptions.verticalScale().value() );
tile->setDataVariance( osg::Object::DYNAMIC );
- //tile->setLocator( locator.get() );
-
- // Attach an updatecallback to normalize the edges of TerrainTiles.
-#if 0
- if ( hasElevation && _terrainOptions.normalizeEdges().get() )
- {
- tile->setUpdateCallback(new TerrainTileEdgeNormalizerUpdateCallback());
- tile->setDataVariance(osg::Object::DYNAMIC);
- }
-#endif
+ //tile->setLocator( locator.get() );
// Generate placeholder imagery and elevation layers. These "inherit" data from an
// ancestor tile.
@@ -665,15 +657,6 @@ OSGTileFactory::createPopulatedTile(const MapFrame& mapf,
//tile->setRequiresNormals( true );
tile->setDataVariance(osg::Object::DYNAMIC);
-#if 0
- //Attach an updatecallback to normalize the edges of TerrainTiles.
- if (hasElevation && _terrainOptions.normalizeEdges().get() )
- {
- tile->setUpdateCallback(new TerrainTileEdgeNormalizerUpdateCallback());
- tile->setDataVariance(osg::Object::DYNAMIC);
- }
-#endif
-
//Assign the terrain system to the TerrainTile.
//It is very important the terrain system is set while the MapConfig's sourceMutex is locked.
//This registers the terrain tile so that adding/removing layers are always in sync. If you don't do this
diff --git a/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory b/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory
index 5bd1efe..d152fae 100644
--- a/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory
+++ b/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory
@@ -22,23 +22,27 @@
#include "Common"
#include "SerialKeyNodeFactory"
-using namespace osgEarth;
-
-class ParallelKeyNodeFactory : public SerialKeyNodeFactory
+namespace osgEarth_engine_osgterrain
{
-public:
- ParallelKeyNodeFactory(
- TileBuilder* builder,
- const OSGTerrainOptions& options,
- const MapInfo& mapInfo,
- TerrainNode* terrain,
- UID engineUID );
+ using namespace osgEarth;
+
+ class ParallelKeyNodeFactory : public SerialKeyNodeFactory
+ {
+ public:
+ ParallelKeyNodeFactory(
+ TileBuilder* builder,
+ const OSGTerrainOptions& options,
+ const MapInfo& mapInfo,
+ TerrainNode* terrain,
+ UID engineUID );
+
+ /** dtor */
+ virtual ~ParallelKeyNodeFactory() { }
- /** dtor */
- virtual ~ParallelKeyNodeFactory() { }
+ osg::Node* createRootNode( const TileKey& key );
+ osg::Node* createNode( const TileKey& key );
+ };
- osg::Node* createRootNode( const TileKey& key );
- osg::Node* createNode( const TileKey& key );
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_PARALLEL_KEY_NODE_FACTORY
diff --git a/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory.cpp b/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory.cpp
index 2911a91..07f599f 100644
--- a/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/ParallelKeyNodeFactory.cpp
@@ -20,6 +20,7 @@
#include <osgEarth/Registry>
#include <osg/PagedLOD>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_osgterrain/Plugin.cpp b/src/osgEarthDrivers/engine_osgterrain/Plugin.cpp
index 3a5b4b5..ef095c1 100644
--- a/src/osgEarthDrivers/engine_osgterrain/Plugin.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/Plugin.cpp
@@ -26,12 +26,13 @@
#define LC "[osgterrain_engine Plugin] "
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth::Drivers;
-class OSGTerrainEnginePlugin : public osgDB::ReaderWriter
+class osgEarth_OSGTerrainEnginePlugin : public osgDB::ReaderWriter
{
public:
- OSGTerrainEnginePlugin() {}
+ osgEarth_OSGTerrainEnginePlugin() {}
virtual const char* className()
{
@@ -136,4 +137,4 @@ public:
}
};
-REGISTER_OSGPLUGIN(osgearth_engine_osgterrain, OSGTerrainEnginePlugin)
+REGISTER_OSGPLUGIN(osgearth_engine_osgterrain, osgEarth_OSGTerrainEnginePlugin)
diff --git a/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory b/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory
index 01dc3fa..7fc1725 100644
--- a/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory
+++ b/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory
@@ -24,32 +24,36 @@
#include "TerrainNode"
#include "TileBuilder"
-using namespace osgEarth;
-
-class SerialKeyNodeFactory : public KeyNodeFactory
+namespace osgEarth_engine_osgterrain
{
-public:
- SerialKeyNodeFactory(
- TileBuilder* builder,
- const OSGTerrainOptions& options,
- const MapInfo& mapInfo,
- TerrainNode* terrain,
- UID engineUID );
-
- /** dtor */
- virtual ~SerialKeyNodeFactory() { }
-
- osg::Node* createRootNode( const TileKey& key );
- osg::Node* createNode( const TileKey& key );
-
-protected:
- void addTile(Tile* tile, bool tileHasRealData, bool tileHasLodBlending, osg::Group* parent );
-
- osg::ref_ptr< TileBuilder> _builder;
- const OSGTerrainOptions& _options;
- const MapInfo _mapInfo;
- osg::ref_ptr< TerrainNode > _terrain;
- UID _engineUID;
-};
+ using namespace osgEarth;
+
+ class SerialKeyNodeFactory : public KeyNodeFactory
+ {
+ public:
+ SerialKeyNodeFactory(
+ TileBuilder* builder,
+ const OSGTerrainOptions& options,
+ const MapInfo& mapInfo,
+ TerrainNode* terrain,
+ UID engineUID );
+
+ /** dtor */
+ virtual ~SerialKeyNodeFactory() { }
+
+ osg::Node* createRootNode( const TileKey& key );
+ osg::Node* createNode( const TileKey& key );
+
+ protected:
+ void addTile(Tile* tile, bool tileHasRealData, bool tileHasLodBlending, osg::Group* parent );
+
+ osg::ref_ptr< TileBuilder> _builder;
+ const OSGTerrainOptions& _options;
+ const MapInfo _mapInfo;
+ osg::ref_ptr< TerrainNode > _terrain;
+ UID _engineUID;
+ };
+
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_PARALLEL_KEY_NODE_FACTORY
diff --git a/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory.cpp b/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory.cpp
index f9014f6..62437a7 100644
--- a/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/SerialKeyNodeFactory.cpp
@@ -28,6 +28,7 @@
#include <osgEarth/MapNode>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace OpenThreads;
@@ -117,7 +118,7 @@ SerialKeyNodeFactory::addTile(Tile* tile, bool tileHasRealData, bool tileHasLodB
{
// Make the LOD transition distance, and a measure of how
// close the tile is to an LOD change, to shaders.
- result->addCullCallback(new Drivers::LODFactorCallback);
+ result->addCullCallback(new LODFactorCallback);
}
}
else
diff --git a/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique b/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique
index 73172e3..61ee27f 100644
--- a/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique
+++ b/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique
@@ -41,158 +41,162 @@
#include <queue>
-class Tile;
-class TileFrame;
-
-// --------------------------------------------------------------------------
-
-/**
- * A terrain technique that uses a single texture unit by compositing image layer textures
- * on the GPU.
- *
- * This technique works by creating a single "mosaic" texture and copying each image layer's
- * texture into that mosaic. It then creates a uniform array that conveys the relative offset
- * and scale information of each sub-texture to a shader. The shader then composites the
- * approprate mosaic texels on the GPU.
- *
- * Limitations:
- *
- * This technique is limited by the maximum texture size your GPU will support, since it
- * creates a single mosaic texture. For example, if your GPU's max texture size is 2048,
- * this technique can support 64 256-pixel layers.
- */
-class SinglePassTerrainTechnique : public CustomTerrainTechnique
+namespace osgEarth_engine_osgterrain
{
-public:
- SinglePassTerrainTechnique( TextureCompositor* compositor =0L ); //osgTerrain::Locator* locator =0L );
+ class Tile;
+ class TileFrame;
- SinglePassTerrainTechnique(const SinglePassTerrainTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
-
- META_Object( osgEarth, SinglePassTerrainTechnique );
-
- /** dtor */
- virtual ~SinglePassTerrainTechnique();
-
-public: /* overrides */
-
- virtual void init();
-
-#if 0
-#if OSG_MIN_VERSION_REQUIRED(2,9,8)
- virtual void init(int dirtyMask, bool assumeMultiThreaded);
-#else
- virtual void init();
-#endif
-#endif
-
- void setParentTile( Tile* tile ) { _parentTile = tile; }
-
- void compile( const TileUpdate& updateSpec, ProgressCallback* progress );
-
- // returns TRUE if a swap occurred and a new subgraph is now in place.
- bool applyTileUpdates();
-
- /** Traverse the terrain subgraph.*/
- virtual void traverse( osg::NodeVisitor& nv );
-
-public:
-
- /**
- * Sets a factor by which to scale elevation height values. By default, this object
- * will get the vertical scale from the osgTerrain::Terrain with which the tile is
- * associated. Setting this value overrides that (or sets it if there is no terrain).
- */
- void setVerticalScaleOverride( float value );
+ // --------------------------------------------------------------------------
/**
- * Gets the overriden vertical scale value.
- */
- float getVerticalScaleOverride() const;
-
- /**
- * Sets whether to try to optimize the triangle orientation based on the elevation values.
- * If false,
+ * A terrain technique that uses a single texture unit by compositing image layer textures
+ * on the GPU.
+ *
+ * This technique works by creating a single "mosaic" texture and copying each image layer's
+ * texture into that mosaic. It then creates a uniform array that conveys the relative offset
+ * and scale information of each sub-texture to a shader. The shader then composites the
+ * approprate mosaic texels on the GPU.
+ *
+ * Limitations:
+ *
+ * This technique is limited by the maximum texture size your GPU will support, since it
+ * creates a single mosaic texture. For example, if your GPU's max texture size is 2048,
+ * this technique can support 64 256-pixel layers.
*/
- void setOptimizeTriangleOrientation(bool optimizeTriangleOrientation);
- bool getOptimizeTriangleOrientation() const;
+ class SinglePassTerrainTechnique : public CustomTerrainTechnique
+ {
+ public:
+ SinglePassTerrainTechnique( TextureCompositor* compositor =0L ); //osgTerrain::Locator* locator =0L );
- /** If State is non-zero, this function releases any associated OpenGL objects for
- * the specified graphics context. Otherwise, releases OpenGL objects
- * for all graphics contexts. */
- virtual void releaseGLObjects(osg::State* = 0) const;
+ SinglePassTerrainTechnique(const SinglePassTerrainTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
- osg::StateSet* getActiveStateSet() const;
+ META_Object( osgEarth, SinglePassTerrainTechnique );
- /** Gets to the underlying transform that parents the actual constructed geometry. */
- osg::Transform* getTransform() const { return _transform.get(); }
- osg::Transform* takeTransform() { return _transform.release(); }
+ /** dtor */
+ virtual ~SinglePassTerrainTechnique();
- bool getClearDataAfterCompile() const { return _clearDataAfterCompile;}
- void setClearDataAfterCompile( bool value) { _clearDataAfterCompile = value;}
+ public: /* overrides */
-protected:
+ virtual void init();
- void calculateSampling( unsigned int& out_rows, unsigned int& out_cols, double& out_i, double& out_j );
+ #if 0
+ #if OSG_MIN_VERSION_REQUIRED(2,9,8)
+ virtual void init(int dirtyMask, bool assumeMultiThreaded);
+ #else
+ virtual void init();
+ #endif
+ #endif
-private:
- bool _debug;
+ void setParentTile( Tile* tile ) { _parentTile = tile; }
- OpenThreads::Mutex _compileMutex;
- //OpenThreads::Mutex _writeBufferMutex;
- osg::ref_ptr<osg::MatrixTransform> _transform;
- osg::ref_ptr<osg::Group> _backNode;
- osg::ref_ptr<osg::Uniform> _imageLayerStampUniform;
- osg::Vec3d _centerModel;
- float _verticalScaleOverride;
- osg::ref_ptr<GeoLocator> _masterLocator;
+ void compile( const TileUpdate& updateSpec, ProgressCallback* progress );
+
+ // returns TRUE if a swap occurred and a new subgraph is now in place.
+ bool applyTileUpdates();
- int _initCount;
- bool _pendingFullUpdate;
- bool _pendingGeometryUpdate;
- bool _clearDataAfterCompile;
+ /** Traverse the terrain subgraph.*/
+ virtual void traverse( osg::NodeVisitor& nv );
+
+ public:
+
+ /**
+ * Sets a factor by which to scale elevation height values. By default, this object
+ * will get the vertical scale from the osgTerrain::Terrain with which the tile is
+ * associated. Setting this value overrides that (or sets it if there is no terrain).
+ */
+ void setVerticalScaleOverride( float value );
+
+ /**
+ * Gets the overriden vertical scale value.
+ */
+ float getVerticalScaleOverride() const;
+
+ /**
+ * Sets whether to try to optimize the triangle orientation based on the elevation values.
+ * If false,
+ */
+ void setOptimizeTriangleOrientation(bool optimizeTriangleOrientation);
+ bool getOptimizeTriangleOrientation() const;
+
+ /** If State is non-zero, this function releases any associated OpenGL objects for
+ * the specified graphics context. Otherwise, releases OpenGL objects
+ * for all graphics contexts. */
+ virtual void releaseGLObjects(osg::State* = 0) const;
+
+ osg::StateSet* getActiveStateSet() const;
+
+ /** Gets to the underlying transform that parents the actual constructed geometry. */
+ osg::Transform* getTransform() const { return _transform.get(); }
+ osg::Transform* takeTransform() { return _transform.release(); }
+
+ bool getClearDataAfterCompile() const { return _clearDataAfterCompile;}
+ void setClearDataAfterCompile( bool value) { _clearDataAfterCompile = value;}
+
+ protected:
+
+ void calculateSampling( unsigned int& out_rows, unsigned int& out_cols, double& out_i, double& out_j );
+
+ private:
+ bool _debug;
+
+ OpenThreads::Mutex _compileMutex;
+ //OpenThreads::Mutex _writeBufferMutex;
+ osg::ref_ptr<osg::MatrixTransform> _transform;
+ osg::ref_ptr<osg::Group> _backNode;
+ osg::ref_ptr<osg::Uniform> _imageLayerStampUniform;
+ osg::Vec3d _centerModel;
+ float _verticalScaleOverride;
+ osg::ref_ptr<GeoLocator> _masterLocator;
+
+ int _initCount;
+ bool _pendingFullUpdate;
+ bool _pendingGeometryUpdate;
+ bool _clearDataAfterCompile;
+
+ struct ImageLayerUpdate {
+ GeoImage _image;
+ UID _layerUID;
+ bool _isRealData; // versus fallback data
+ };
+ typedef std::queue<ImageLayerUpdate> ImageLayerUpdates;
+ ImageLayerUpdates _pendingImageLayerUpdates;
+
+ // associates each texture index with a layer UID.
+ typedef std::map< UID, int > LayerUIDtoIndexMap;
+ LayerUIDtoIndexMap _layerUIDtoIndexMap;
- struct ImageLayerUpdate {
- GeoImage _image;
- UID _layerUID;
- bool _isRealData; // versus fallback data
+ // XXX Are these both necessary?
+ GeoExtent _tileExtent;
+ TileKey _tileKey;
+
+ bool _optimizeTriangleOrientation;
+
+ osg::ref_ptr<const TextureCompositor> _texCompositor;
+ bool _frontGeodeInstalled;
+
+ OpenThreads::Atomic _atomicCallOnce;
+
+ private:
+
+ osg::Vec3d computeCenterModel();
+ bool createGeoImage( const CustomColorLayer& layer, GeoImage& image ) const; //const osgTerrain::Layer* imageLayer ) const;
+ osg::Group* createGeometry( const TileFrame& tilef );
+ osg::StateSet* createStateSet( const TileFrame& tilef );
+ void prepareImageLayerUpdate( int layerIndex, const TileFrame& tilef );
+ //Threading::ReadWriteMutex& getMutex();
+ inline osg::Group* getFrontNode() const {
+ if (_transform.valid() && _transform->getNumChildren() > 0)
+ return static_cast<osg::Group*>(_transform->getChild(0));
+ return NULL;
+ }
+ osg::StateSet* getParentStateSet() const;
+ //const CustomColorLayer* getLayerByUID( UID uid ) const;
+ int getIndexOfColorLayerWithUID( UID uid ) const;
+
+
+ osg::observer_ptr<Tile> _parentTile;
};
- typedef std::queue<ImageLayerUpdate> ImageLayerUpdates;
- ImageLayerUpdates _pendingImageLayerUpdates;
-
- // associates each texture index with a layer UID.
- typedef std::map< UID, int > LayerUIDtoIndexMap;
- LayerUIDtoIndexMap _layerUIDtoIndexMap;
-
- // XXX Are these both necessary?
- GeoExtent _tileExtent;
- TileKey _tileKey;
-
- bool _optimizeTriangleOrientation;
-
- osg::ref_ptr<const TextureCompositor> _texCompositor;
- bool _frontGeodeInstalled;
-
- OpenThreads::Atomic _atomicCallOnce;
-
-private:
-
- osg::Vec3d computeCenterModel();
- bool createGeoImage( const CustomColorLayer& layer, GeoImage& image ) const; //const osgTerrain::Layer* imageLayer ) const;
- osg::Group* createGeometry( const TileFrame& tilef );
- osg::StateSet* createStateSet( const TileFrame& tilef );
- void prepareImageLayerUpdate( int layerIndex, const TileFrame& tilef );
- //Threading::ReadWriteMutex& getMutex();
- inline osg::Group* getFrontNode() const {
- if (_transform.valid() && _transform->getNumChildren() > 0)
- return static_cast<osg::Group*>(_transform->getChild(0));
- return NULL;
- }
- osg::StateSet* getParentStateSet() const;
- //const CustomColorLayer* getLayerByUID( UID uid ) const;
- int getIndexOfColorLayerWithUID( UID uid ) const;
-
-
- osg::observer_ptr<Tile> _parentTile;
-};
+
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_SINGLE_PASS_TERRAIN_TECHNIQUE
diff --git a/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique.cpp b/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique.cpp
index 9dc652b..19ffae3 100644
--- a/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/SinglePassTerrainTechnique.cpp
@@ -40,6 +40,7 @@
#include <sstream>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace osgEarth::Symbology;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode b/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode
index 74ec20c..662b862 100644
--- a/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode
+++ b/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode
@@ -23,65 +23,69 @@
#include "StreamingTile"
#include <osgEarth/TaskService>
-using namespace osgEarth;
-
-/**
- * Terrain implementation that supports the SEQUENTIAL and PREEMPTIVE loading policies.
- */
-class StreamingTerrainNode : public TerrainNode
+namespace osgEarth_engine_osgterrain
{
-public:
- StreamingTerrainNode(
- const MapFrame& update_mapf,
- const MapFrame& cull_mapf,
- OSGTileFactory* factory,
- bool quickReleaseGLObjects );
+ using namespace osgEarth;
- virtual const char* libraryName() const { return "osgEarth"; }
- virtual const char* className() const { return "StreamingTerrainNode"; }
-
- //override
- virtual Tile* createTile(const TileKey& key, GeoLocator* locator) const;
+ /**
+ * Terrain implementation that supports the SEQUENTIAL and PREEMPTIVE loading policies.
+ */
+ class StreamingTerrainNode : public TerrainNode
+ {
+ public:
+ StreamingTerrainNode(
+ const MapFrame& update_mapf,
+ const MapFrame& cull_mapf,
+ OSGTileFactory* factory,
+ bool quickReleaseGLObjects );
-public:
+ virtual const char* libraryName() const { return "osgEarth"; }
+ virtual const char* className() const { return "StreamingTerrainNode"; }
+
+ //override
+ virtual Tile* createTile(const TileKey& key, GeoLocator* locator) const;
- TaskService* getImageryTaskService(int layerId);
- TaskService* getElevationTaskService();
- TaskService* getTileGenerationTaskService();
+ public:
- /**
- * Updates the catalog of task service threads - this gets called by the OSGTerrainEngine
- * in response to a change in the Map's data model. The map frame is that of the terrain
- * engine.
- */
- void updateTaskServiceThreads( const MapFrame& mapf );
+ TaskService* getImageryTaskService(int layerId);
+ TaskService* getElevationTaskService();
+ TaskService* getTileGenerationTaskService();
+
+ /**
+ * Updates the catalog of task service threads - this gets called by the OSGTerrainEngine
+ * in response to a change in the Map's data model. The map frame is that of the terrain
+ * engine.
+ */
+ void updateTaskServiceThreads( const MapFrame& mapf );
+
+ const LoadingPolicy& getLoadingPolicy() const { return _loadingPolicy; }
- const LoadingPolicy& getLoadingPolicy() const { return _loadingPolicy; }
+ protected:
-protected:
+ virtual ~StreamingTerrainNode();
- virtual ~StreamingTerrainNode();
+ //override
+ virtual unsigned getNumActiveTasks() const;
- //override
- virtual unsigned getNumActiveTasks() const;
+ //override
+ virtual void updateTraversal( osg::NodeVisitor& nv );
- //override
- virtual void updateTraversal( osg::NodeVisitor& nv );
+ private:
-private:
+ TaskService* createTaskService( const std::string& name, int id, int numThreads );
+ TaskService* getTaskService( int id );
- TaskService* createTaskService( const std::string& name, int id, int numThreads );
- TaskService* getTaskService( int id );
+ void refreshFamily( const MapInfo& info, const TileKey& key, StreamingTile::Relative* family, bool tileTableLocked );
- void refreshFamily( const MapInfo& info, const TileKey& key, StreamingTile::Relative* family, bool tileTableLocked );
+ typedef std::map< int, osg::ref_ptr< TaskService > > TaskServiceMap;
- typedef std::map< int, osg::ref_ptr< TaskService > > TaskServiceMap;
+ TaskServiceMap _taskServices;
+ OpenThreads::Mutex _taskServiceMutex;
+ int _numLoadingThreads;
+ LoadingPolicy _loadingPolicy;
+ UID _elevationTaskServiceUID;
+ };
- TaskServiceMap _taskServices;
- OpenThreads::Mutex _taskServiceMutex;
- int _numLoadingThreads;
- LoadingPolicy _loadingPolicy;
- UID _elevationTaskServiceUID;
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_STREAMING_TERRAIN
diff --git a/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode.cpp b/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode.cpp
index d8af364..3dfb4aa 100644
--- a/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/StreamingTerrainNode.cpp
@@ -21,7 +21,8 @@
#include "TransparentLayer"
#include <osgEarth/Registry>
-#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
+#include <osgEarth/MapInfo>
#include <osgEarth/NodeUtils>
#include <osg/NodeCallback>
@@ -31,6 +32,7 @@
#include <OpenThreads/ScopedLock>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_osgterrain/StreamingTile b/src/osgEarthDrivers/engine_osgterrain/StreamingTile
index 203a25e..5eed3e5 100644
--- a/src/osgEarthDrivers/engine_osgterrain/StreamingTile
+++ b/src/osgEarthDrivers/engine_osgterrain/StreamingTile
@@ -22,124 +22,127 @@
#include "Tile"
#include <osgEarth/TaskService>
-class TileFactory;
-class StreamingTerrain;
+namespace osgEarth_engine_osgterrain
+{
+ class TileFactory;
+ class StreamingTerrain;
-using namespace osgEarth;
+ using namespace osgEarth;
-//------------------------------------------------------------------------
+ //------------------------------------------------------------------------
-class StreamingTile : public Tile
-{
-public:
- // Please refer the StreamingTerrain::refreshFamily() method for more info on this structure.
- struct Relative
+ class StreamingTile : public Tile
{
- int getImageLOD(unsigned int layerID)
+ public:
+ // Please refer the StreamingTerrain::refreshFamily() method for more info on this structure.
+ struct Relative
{
- LayerIDtoLODMap::iterator itr = imageLODs.find(layerID);
- if (itr != imageLODs.end()) return itr->second;
- return -1;
- }
-
- typedef std::map<unsigned int, int> LayerIDtoLODMap;
-
- bool expected;
- int elevLOD;
- LayerIDtoLODMap imageLODs;
- osgTerrain::TileID tileID;
-
- enum Direction {
- PARENT =0,
- WEST =1,
- NORTH =2,
- EAST =3,
- SOUTH =4
+ int getImageLOD(unsigned int layerID)
+ {
+ LayerIDtoLODMap::iterator itr = imageLODs.find(layerID);
+ if (itr != imageLODs.end()) return itr->second;
+ return -1;
+ }
+
+ typedef std::map<unsigned int, int> LayerIDtoLODMap;
+
+ bool expected;
+ int elevLOD;
+ LayerIDtoLODMap imageLODs;
+ osgTerrain::TileID tileID;
+
+ enum Direction {
+ PARENT =0,
+ WEST =1,
+ NORTH =2,
+ EAST =3,
+ SOUTH =4
+ };
+
+ Relative() { }
};
- Relative() { }
- };
+ public:
+ StreamingTile( const TileKey& key, GeoLocator* keyLocator, bool quickReleaseGLObjects );
-public:
- StreamingTile( const TileKey& key, GeoLocator* keyLocator, bool quickReleaseGLObjects );
+ virtual const char* libraryName() const { return "osgEarth"; }
+ virtual const char* className() const { return "StreamingTile"; }
- virtual const char* libraryName() const { return "osgEarth"; }
- virtual const char* className() const { return "StreamingTile"; }
+ // Updates and services this tile's image request tasks
+ void servicePendingImageRequests( const MapFrame& mapf, int stamp );
- // Updates and services this tile's image request tasks
- void servicePendingImageRequests( const MapFrame& mapf, int stamp );
+ // Updates and services this tile's heightfield request tasks
+ void servicePendingElevationRequests( const MapFrame& mapf, int stamp, bool tileTableLocked );
- // Updates and services this tile's heightfield request tasks
- void servicePendingElevationRequests( const MapFrame& mapf, int stamp, bool tileTableLocked );
+ // returns TRUE if the tile was modified as a result of a completed request.
+ bool serviceCompletedRequests( const MapFrame& mapf, bool tileTableLocked );
- // returns TRUE if the tile was modified as a result of a completed request.
- bool serviceCompletedRequests( const MapFrame& mapf, bool tileTableLocked );
+ /** Setting this hint tells the tile whether it should bother trying to load elevation data. */
+ void setHasElevationHint( bool hasElevation );
- /** Setting this hint tells the tile whether it should bother trying to load elevation data. */
- void setHasElevationHint( bool hasElevation );
+ /** Gets whether the tile's real (not placeholder) elevation data has been loaded. */
+ bool isElevationLayerUpToDate() const { return _elevationLayerUpToDate; }
- /** Gets whether the tile's real (not placeholder) elevation data has been loaded. */
- bool isElevationLayerUpToDate() const { return _elevationLayerUpToDate; }
+ /** Gets or sets the LOD of this tile's current heightfield data. */
+ int getElevationLOD() const { return _elevationLOD; }
+ void setElevationLOD( int lod );
- /** Gets or sets the LOD of this tile's current heightfield data. */
- int getElevationLOD() const { return _elevationLOD; }
- void setElevationLOD( int lod );
+ /** Gets the terrain object to which this tile belongs. */
+ class StreamingTerrainNode* getStreamingTerrain();
+ const class StreamingTerrainNode* getStreamingTerrain() const;
- /** Gets the terrain object to which this tile belongs. */
- class StreamingTerrainNode* getStreamingTerrain();
- const class StreamingTerrainNode* getStreamingTerrain() const;
+ // updates one image layer
+ void updateImagery( ImageLayer* layer, const MapFrame& mapf, OSGTileFactory* factory );
- // updates one image layer
- void updateImagery( ImageLayer* layer, const MapFrame& mapf, OSGTileFactory* factory );
+ // are we using a task service for tile generation?
+ bool getUseTileGenRequest() const { return _useTileGenRequest; }
- // are we using a task service for tile generation?
- bool getUseTileGenRequest() const { return _useTileGenRequest; }
+ // gets this tile's relatives
+ Relative* getFamily() { return _family; }
- // gets this tile's relatives
- Relative* getFamily() { return _family; }
-
- // marks a request to regenerate the tile based on the specified change(s).
- void queueTileUpdate( TileUpdate::Action action, int index =-1 );
-
- void applyImmediateTileUpdate( TileUpdate::Action action, int index =-1 );
+ // marks a request to regenerate the tile based on the specified change(s).
+ void queueTileUpdate( TileUpdate::Action action, int index =-1 );
+
+ void applyImmediateTileUpdate( TileUpdate::Action action, int index =-1 );
- // marks any pending or running requests for cancelation, and returns true if they
- // are all canceled.
- virtual bool cancelActiveTasks(); //override
+ // marks any pending or running requests for cancelation, and returns true if they
+ // are all canceled.
+ virtual bool cancelActiveTasks(); //override
- void resetElevationRequests( const MapFrame& mapf );
+ void resetElevationRequests( const MapFrame& mapf );
-protected:
+ protected:
- virtual ~StreamingTile();
+ virtual ~StreamingTile();
-private:
+ private:
- bool _requestsInstalled;
- bool _hasElevation;
- bool _elevationLayerDirty;
- bool _colorLayersDirty;
- bool _elevationLayerRequested;
- bool _elevationLayerUpToDate;
- int _elevationLOD;
- bool _useTileGenRequest;
- bool _sequentialImagery;
+ bool _requestsInstalled;
+ bool _hasElevation;
+ bool _elevationLayerDirty;
+ bool _colorLayersDirty;
+ bool _elevationLayerRequested;
+ bool _elevationLayerUpToDate;
+ int _elevationLOD;
+ bool _useTileGenRequest;
+ bool _sequentialImagery;
- typedef std::queue<TileUpdate> TileUpdateQueue;
- TileUpdateQueue _tileUpdates;
+ typedef std::queue<TileUpdate> TileUpdateQueue;
+ TileUpdateQueue _tileUpdates;
- TaskRequestList _requests;
- osg::ref_ptr<TaskRequest> _elevRequest;
- osg::ref_ptr<TaskRequest> _elevPlaceholderRequest;
- osg::ref_ptr<TaskRequest> _tileGenRequest;
+ TaskRequestList _requests;
+ osg::ref_ptr<TaskRequest> _elevRequest;
+ osg::ref_ptr<TaskRequest> _elevPlaceholderRequest;
+ osg::ref_ptr<TaskRequest> _tileGenRequest;
- Relative _family[5];
+ Relative _family[5];
- /** Deals with completed requests during the UPDATE traversal. */
- void installRequests( const MapFrame& mapf, int stamp );
- bool readyForNewElevation();
- bool readyForNewImagery(osgEarth::ImageLayer* layer, int currentLOD);
-};
+ /** Deals with completed requests during the UPDATE traversal. */
+ void installRequests( const MapFrame& mapf, int stamp );
+ bool readyForNewElevation();
+ bool readyForNewImagery(osgEarth::ImageLayer* layer, int currentLOD);
+ };
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_STREAMING_TILE
diff --git a/src/osgEarthDrivers/engine_osgterrain/StreamingTile.cpp b/src/osgEarthDrivers/engine_osgterrain/StreamingTile.cpp
index b498164..5760575 100644
--- a/src/osgEarthDrivers/engine_osgterrain/StreamingTile.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/StreamingTile.cpp
@@ -23,7 +23,7 @@
#include <osgEarth/Registry>
#include <osgEarth/Locators>
-#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
#include <osgEarth/NodeUtils>
#include <osg/NodeCallback>
@@ -34,6 +34,7 @@
#include <OpenThreads/ScopedLock>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace OpenThreads;
@@ -89,8 +90,8 @@ namespace
MapFrame _mapf;
//osg::ref_ptr<Map> _map;
osg::ref_ptr<OSGTileFactory> _tileFactory;
- unsigned int _numTries;
- unsigned int _maxTries;
+ unsigned int _numTries;
+ unsigned int _maxTries;
};
struct TileColorLayerRequest : public TileLayerRequest
@@ -104,10 +105,10 @@ namespace
if ( imageLayer.valid() )
{
_result = _tileFactory->createImageLayer( _mapf.getMapInfo(), imageLayer.get(), _key, progress );
- if (!wasCanceled())
- {
- _numTries++;
- }
+ if (!wasCanceled())
+ {
+ _numTries++;
+ }
}
}
UID _layerUID;
@@ -124,7 +125,7 @@ namespace
void operator()( ProgressCallback* progress )
{
_result = _tileFactory->createHeightFieldLayer( _mapf, _key, true ); //exactOnly=true
- _numTries++;
+ _numTries++;
}
};
@@ -410,8 +411,8 @@ StreamingTile::resetElevationRequests( const MapFrame& mapf )
_elevRequest->setPriority( priority );
std::stringstream ss;
ss << "TileElevationLayerRequest " << _key.str() << std::endl;
- std::string ssStr;
- ssStr = ss.str();
+ std::string ssStr;
+ ssStr = ss.str();
_elevRequest->setName( ssStr );
// this request will load placeholder elevation data for the tile:
@@ -421,7 +422,7 @@ StreamingTile::resetElevationRequests( const MapFrame& mapf )
_elevPlaceholderRequest->setPriority( priority );
ss.str("");
ss << "TileElevationPlaceholderLayerRequest " << _key.str() << std::endl;
- ssStr = ss.str();
+ ssStr = ss.str();
_elevPlaceholderRequest->setName( ssStr );
}
diff --git a/src/osgEarthDrivers/engine_osgterrain/TerrainNode b/src/osgEarthDrivers/engine_osgterrain/TerrainNode
index b0fa3fb..3e80003 100644
--- a/src/osgEarthDrivers/engine_osgterrain/TerrainNode
+++ b/src/osgEarthDrivers/engine_osgterrain/TerrainNode
@@ -32,121 +32,125 @@
#include <queue>
#include <vector>
-class TileFactory;
+namespace osgEarth_engine_osgterrain
+{
+ class TileFactory;
-using namespace osgEarth;
+ using namespace osgEarth;
-/**
- */
-class TerrainNode : public osg::Group //osgTerrain::Terrain
-{
-public:
- TerrainNode(
- const MapFrame& update_mapf,
- const MapFrame& cull_mapf,
- OSGTileFactory* factory,
- bool quickReleaseGLObjects );
+ /**
+ */
+ class TerrainNode : public osg::Group //osgTerrain::Terrain
+ {
+ public:
+ TerrainNode(
+ const MapFrame& update_mapf,
+ const MapFrame& cull_mapf,
+ OSGTileFactory* factory,
+ bool quickReleaseGLObjects );
- virtual const char* libraryName() const { return "osgEarth"; }
+ virtual const char* libraryName() const { return "osgEarth"; }
- virtual const char* className() const { return "TerrainNode"; }
+ virtual const char* className() const { return "TerrainNode"; }
-public:
+ public:
- OSGTileFactory* getTileFactory() { return _tileFactory.get(); }
+ OSGTileFactory* getTileFactory() { return _tileFactory.get(); }
- bool getQuickReleaseGLObjects() const { return _quickReleaseGLObjects; }
+ bool getQuickReleaseGLObjects() const { return _quickReleaseGLObjects; }
- const MapFrame& getUpdateThreadMapFrame() { return _update_mapf; }
+ const MapFrame& getUpdateThreadMapFrame() { return _update_mapf; }
- const MapFrame& getCullThreadMapFrame() { return _cull_mapf; }
+ const MapFrame& getCullThreadMapFrame() { return _cull_mapf; }
- virtual Tile* createTile( const TileKey& key, GeoLocator* locator ) const;
-
- void setTechniquePrototype( TerrainTechnique* tech );
+ virtual Tile* createTile( const TileKey& key, GeoLocator* locator ) const;
+
+ void setTechniquePrototype( TerrainTechnique* tech );
- TerrainTechnique* cloneTechnique() const;
+ TerrainTechnique* cloneTechnique() const;
- void setSampleRatio( float value );
+ void setSampleRatio( float value );
- float getSampleRatio() const { return _sampleRatio; }
+ float getSampleRatio() const { return _sampleRatio; }
- void setVerticalScale( float value );
+ void setVerticalScale( float value );
- float getVerticalScale() const { return _verticalScale; }
+ float getVerticalScale() const { return _verticalScale; }
- virtual void traverse( osg::NodeVisitor &nv );
+ virtual void traverse( osg::NodeVisitor &nv );
-protected:
+ protected:
- virtual ~TerrainNode();
+ virtual ~TerrainNode();
- // subclass can override to notify of running tasks
- virtual unsigned getNumActiveTasks() const { return 0; }
+ // subclass can override to notify of running tasks
+ virtual unsigned getNumActiveTasks() const { return 0; }
- // subclass can override this to perform addition UPDATE traversal operations
- virtual void updateTraversal( osg::NodeVisitor& nv ) { }
+ // subclass can override this to perform addition UPDATE traversal operations
+ virtual void updateTraversal( osg::NodeVisitor& nv ) { }
- typedef std::map< osgTerrain::TileID, osg::ref_ptr<Tile> > TileTable;
+ typedef std::map< osgTerrain::TileID, osg::ref_ptr<Tile> > TileTable;
- typedef std::queue< osg::ref_ptr<Tile> > TileQueue;
- typedef std::list< osg::ref_ptr<Tile> > TileList;
- typedef std::vector< osg::ref_ptr<Tile> > TileVector;
- typedef std::queue< osgTerrain::TileID > TileIDQueue;
+ typedef std::queue< osg::ref_ptr<Tile> > TileQueue;
+ typedef std::list< osg::ref_ptr<Tile> > TileList;
+ typedef std::vector< osg::ref_ptr<Tile> > TileVector;
+ typedef std::queue< osgTerrain::TileID > TileIDQueue;
- Threading::ReadWriteMutex _tilesMutex;
- TileTable _tiles;
- TileList _tilesToShutDown;
- TileVector _tilesToRelease;
- Threading::Mutex _tilesToReleaseMutex;
+ Threading::ReadWriteMutex _tilesMutex;
+ TileTable _tiles;
+ TileList _tilesToShutDown;
+ TileVector _tilesToRelease;
+ Threading::Mutex _tilesToReleaseMutex;
- float _sampleRatio;
- float _verticalScale;
+ float _sampleRatio;
+ float _verticalScale;
-public:
+ public:
- void releaseGLObjectsForTiles( osg::State* state );
+ void releaseGLObjectsForTiles( osg::State* state );
- void registerTile( Tile* newTile );
+ void registerTile( Tile* newTile );
- /** Gets a thread-safe copy of the entire tile list */
- void getTiles( TileVector& out_tiles );
+ /** Gets a thread-safe copy of the entire tile list */
+ void getTiles( TileVector& out_tiles );
- /** Fetches a tile from the repo */
- template<typename T>
- void getTile(const osgTerrain::TileID& id, osg::ref_ptr<T>& out_tile, bool lock =true ) const {
- if ( lock ) {
- Threading::ScopedReadLock lock( const_cast<TerrainNode*>(this)->_tilesMutex );
- TileTable::const_iterator i = _tiles.find( id );
- out_tile = i != _tiles.end()? static_cast<T*>(i->second.get()) : 0L;
+ /** Fetches a tile from the repo */
+ template<typename T>
+ void getTile(const osgTerrain::TileID& id, osg::ref_ptr<T>& out_tile, bool lock =true ) const {
+ if ( lock ) {
+ Threading::ScopedReadLock lock( const_cast<TerrainNode*>(this)->_tilesMutex );
+ TileTable::const_iterator i = _tiles.find( id );
+ out_tile = i != _tiles.end()? static_cast<T*>(i->second.get()) : 0L;
+ }
+ else {
+ TileTable::const_iterator i = _tiles.find( id );
+ out_tile = i != _tiles.end()? static_cast<T*>(i->second.get()) : 0L;
+ }
}
- else {
- TileTable::const_iterator i = _tiles.find( id );
- out_tile = i != _tiles.end()? static_cast<T*>(i->second.get()) : 0L;
- }
- }
-protected:
+ protected:
+
+ osg::ref_ptr<OSGTileFactory> _tileFactory;
+ osg::ref_ptr<const Profile> _profile;
- osg::ref_ptr<OSGTileFactory> _tileFactory;
- osg::ref_ptr<const Profile> _profile;
+ bool _alwaysUpdate;
+ int _onDemandDelay; // #frames
- bool _alwaysUpdate;
- int _onDemandDelay; // #frames
+ void setDelay( unsigned frames );
+ void decDelay();
- void setDelay( unsigned frames );
- void decDelay();
+ bool _registeredWithReleaseGLCallback;
- bool _registeredWithReleaseGLCallback;
+ // store a separate map frame for each of the traversal threads
+ const MapFrame& _update_mapf; // map frame for the main/update traversal thread
+ const MapFrame& _cull_mapf; // map frame for the cull traversal thread
- // store a separate map frame for each of the traversal threads
- const MapFrame& _update_mapf; // map frame for the main/update traversal thread
- const MapFrame& _cull_mapf; // map frame for the cull traversal thread
+ bool _quickReleaseGLObjects;
+ bool _quickReleaseCallbackInstalled;
- bool _quickReleaseGLObjects;
- bool _quickReleaseCallbackInstalled;
+ osg::ref_ptr<TerrainTechnique> _techPrototype;
+ };
- osg::ref_ptr<TerrainTechnique> _techPrototype;
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_STANDARD_TERRAIN
diff --git a/src/osgEarthDrivers/engine_osgterrain/TerrainNode.cpp b/src/osgEarthDrivers/engine_osgterrain/TerrainNode.cpp
index 3bf02f9..975f1fc 100644
--- a/src/osgEarthDrivers/engine_osgterrain/TerrainNode.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/TerrainNode.cpp
@@ -30,6 +30,7 @@
#include <osg/Node>
#include <osgGA/EventVisitor>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_osgterrain/Tile b/src/osgEarthDrivers/engine_osgterrain/Tile
index 4276ef3..b2651d2 100644
--- a/src/osgEarthDrivers/engine_osgterrain/Tile
+++ b/src/osgEarthDrivers/engine_osgterrain/Tile
@@ -34,170 +34,174 @@
#include <queue>
#include <iterator>
-class TileFactory;
-class TerrainTechnique;
-
-using namespace osgEarth;
-
-typedef std::map<UID, CustomColorLayer> ColorLayersByUID;
+namespace osgEarth_engine_osgterrain
+{
+ class TileFactory;
+ class TerrainTechnique;
-//------------------------------------------------------------------------
+ using namespace osgEarth;
-// Records a tile change request so that we can update tiles piecemeal
-class TileUpdate
-{
-public:
- enum Action {
- ADD_IMAGE_LAYER,
- REMOVE_IMAGE_LAYER,
- MOVE_IMAGE_LAYER,
- UPDATE_IMAGE_LAYER,
- UPDATE_ALL_IMAGE_LAYERS,
- UPDATE_ELEVATION,
- UPDATE_ALL
- };
+ typedef std::map<UID, CustomColorLayer> ColorLayersByUID;
- TileUpdate( Action action, UID layerUID =(UID)-1 )
- : _action(action), _layerUID(layerUID) { }
+ //------------------------------------------------------------------------
- Action getAction() const { return _action; }
+ // Records a tile change request so that we can update tiles piecemeal
+ class TileUpdate
+ {
+ public:
+ enum Action {
+ ADD_IMAGE_LAYER,
+ REMOVE_IMAGE_LAYER,
+ MOVE_IMAGE_LAYER,
+ UPDATE_IMAGE_LAYER,
+ UPDATE_ALL_IMAGE_LAYERS,
+ UPDATE_ELEVATION,
+ UPDATE_ALL
+ };
- UID getLayerUID() const { return _layerUID; }
+ TileUpdate( Action action, UID layerUID =(UID)-1 )
+ : _action(action), _layerUID(layerUID) { }
-private:
- Action _action;
- UID _layerUID;
-};
+ Action getAction() const { return _action; }
-//------------------------------------------------------------------------
+ UID getLayerUID() const { return _layerUID; }
-class Tile : public osg::Node
-{
-public:
- Tile( const TileKey& key, GeoLocator* keyLocator, bool quickReleaseGLObjects );
+ private:
+ Action _action;
+ UID _layerUID;
+ };
- /** Gets the tilekey associated with this tile. */
- const TileKey& getKey() const { return _key; }
+ //------------------------------------------------------------------------
- /** Gets the terrain object to which this tile belongs. */
- class TerrainNode* getTerrain() { return _terrain.get(); }
- const class TerrainNode* getTerrain() const { return _terrain.get(); }
+ class Tile : public osg::Node
+ {
+ public:
+ Tile( const TileKey& key, GeoLocator* keyLocator, bool quickReleaseGLObjects );
- // attaches this tile to a terrain and registers it.
- void attachToTerrain( TerrainNode* terrain );
+ /** Gets the tilekey associated with this tile. */
+ const TileKey& getKey() const { return _key; }
- /** intializes the tile and clears its dirty flag */
- void init();
+ /** Gets the terrain object to which this tile belongs. */
+ class TerrainNode* getTerrain() { return _terrain.get(); }
+ const class TerrainNode* getTerrain() const { return _terrain.get(); }
- /** Gets or sets the terrain mask geometry. */
- const MaskLayerVector& getTerrainMasks() { return _masks; }
- void setTerrainMasks(const MaskLayerVector& terrainMask) { _masks.clear(); std::copy( terrainMask.begin(), terrainMask.end(), std::back_inserter(_masks) ); }
+ // attaches this tile to a terrain and registers it.
+ void attachToTerrain( TerrainNode* terrain );
- /** Whether OSG has traversed the tile at least once. */
- bool getHasBeenTraversed() const { return _hasBeenTraversed; }
+ /** intializes the tile and clears its dirty flag */
+ void init();
- /** Mutex that protects access to the tile contents. */
- Threading::ReadWriteMutex& getTileLayersMutex() { return _tileLayersMutex; }
+ /** Gets or sets the terrain mask geometry. */
+ const MaskLayerVector& getTerrainMasks() { return _masks; }
+ void setTerrainMasks(const MaskLayerVector& terrainMask) { _masks.clear(); std::copy( terrainMask.begin(), terrainMask.end(), std::back_inserter(_masks) ); }
- // marks a request to regenerate the tile based on the specified change(s).
- virtual void queueTileUpdate( TileUpdate::Action action, int index =-1 );
-
- void applyImmediateTileUpdate( TileUpdate::Action action, int index =-1 );
+ /** Whether OSG has traversed the tile at least once. */
+ bool getHasBeenTraversed() const { return _hasBeenTraversed; }
- virtual bool cancelActiveTasks() { return true; }
+ /** Mutex that protects access to the tile contents. */
+ Threading::ReadWriteMutex& getTileLayersMutex() { return _tileLayersMutex; }
- /** The scale factor for elevation heights */
- float getVerticalScale() const { return _verticalScale; }
- void setVerticalScale( float verticalScale );
+ // marks a request to regenerate the tile based on the specified change(s).
+ virtual void queueTileUpdate( TileUpdate::Action action, int index =-1 );
+
+ void applyImmediateTileUpdate( TileUpdate::Action action, int index =-1 );
- osgTerrain::Locator* getLocator() const { return _locator.get(); }
+ virtual bool cancelActiveTasks() { return true; }
- const osgTerrain::TileID& getTileId() const { return _tileId; }
+ /** The scale factor for elevation heights */
+ float getVerticalScale() const { return _verticalScale; }
+ void setVerticalScale( float verticalScale );
- bool getDirty() const { return _dirty; }
- void setDirty( bool value ) { _dirty = value; }
+ osgTerrain::Locator* getLocator() const { return _locator.get(); }
- void setTerrainTechnique( TerrainTechnique* value );
- TerrainTechnique* getTerrainTechnique() const { return _tech.get(); }
+ const osgTerrain::TileID& getTileId() const { return _tileId; }
- /** Tile contents. We don't use the TerrainTile color layer list, we use our own */
- void removeCustomColorLayer( UID layerUID, bool writeLock =true );
- bool getCustomColorLayer( UID layerUID, CustomColorLayer& output, bool readLock =true ) const;
- void getCustomColorLayers( ColorLayersByUID& out, bool readLock =true ) const;
- void setCustomColorLayers( const ColorLayersByUID& in, bool writeLock =true );
- void setCustomColorLayer( const CustomColorLayer& colorLayer, bool writeLock =true );
+ bool getDirty() const { return _dirty; }
+ void setDirty( bool value ) { _dirty = value; }
- void clear();
+ void setTerrainTechnique( TerrainTechnique* value );
+ TerrainTechnique* getTerrainTechnique() const { return _tech.get(); }
- osgTerrain::HeightFieldLayer* getElevationLayer() const { return _elevationLayer.get(); }
- void setElevationLayer( osgTerrain::HeightFieldLayer* value ) { _elevationLayer = value; }
+ /** Tile contents. We don't use the TerrainTile color layer list, we use our own */
+ void removeCustomColorLayer( UID layerUID, bool writeLock =true );
+ bool getCustomColorLayer( UID layerUID, CustomColorLayer& output, bool readLock =true ) const;
+ void getCustomColorLayers( ColorLayersByUID& out, bool readLock =true ) const;
+ void setCustomColorLayers( const ColorLayersByUID& in, bool writeLock =true );
+ void setCustomColorLayer( const CustomColorLayer& colorLayer, bool writeLock =true );
-public: // OVERRIDES
+ void clear();
- virtual void traverse( class osg::NodeVisitor& nv );
+ osgTerrain::HeightFieldLayer* getElevationLayer() const { return _elevationLayer.get(); }
+ void setElevationLayer( osgTerrain::HeightFieldLayer* value ) { _elevationLayer = value; }
- /** If State is non-zero, this function releases any associated OpenGL objects for
- * the specified graphics context. Otherwise, releases OpenGL objects
- * for all graphics contexts. */
- virtual void releaseGLObjects(osg::State* = 0) const;
+ public: // OVERRIDES
- virtual osg::BoundingSphere computeBound() const;
+ virtual void traverse( class osg::NodeVisitor& nv );
-protected:
+ /** If State is non-zero, this function releases any associated OpenGL objects for
+ * the specified graphics context. Otherwise, releases OpenGL objects
+ * for all graphics contexts. */
+ virtual void releaseGLObjects(osg::State* = 0) const;
- virtual ~Tile();
+ virtual osg::BoundingSphere computeBound() const;
- bool _hasBeenTraversed;
- bool _quickReleaseGLObjects;
- bool _parentTileSet;
- bool _dirty;
+ protected:
- TileKey _key;
- osgTerrain::TileID _tileId;
- osg::ref_ptr<GeoLocator> _locator;
- osg::observer_ptr<TerrainNode> _terrain;
- MaskLayerVector _masks;
+ virtual ~Tile();
- Threading::ReadWriteMutex _tileLayersMutex;
- ColorLayersByUID _colorLayers;
- float _verticalScale;
+ bool _hasBeenTraversed;
+ bool _quickReleaseGLObjects;
+ bool _parentTileSet;
+ bool _dirty;
- osg::ref_ptr<osgTerrain::HeightFieldLayer> _elevationLayer;
- osg::ref_ptr<TerrainTechnique> _tech;
+ TileKey _key;
+ osgTerrain::TileID _tileId;
+ osg::ref_ptr<GeoLocator> _locator;
+ osg::observer_ptr<TerrainNode> _terrain;
+ MaskLayerVector _masks;
+ Threading::ReadWriteMutex _tileLayersMutex;
+ ColorLayersByUID _colorLayers;
+ float _verticalScale;
-public:
- friend class TileFrame;
-};
+ osg::ref_ptr<osgTerrain::HeightFieldLayer> _elevationLayer;
+ osg::ref_ptr<TerrainTechnique> _tech;
-class TileVector : public std::vector< osg::ref_ptr<Tile> > { };
-// --------------------------------------------------------------------------
+ public:
+ friend class TileFrame;
+ };
-/**
- * Thread-safe working copy of Tile contents.
- */
-class TileFrame
-{
-public:
- TileFrame( Tile* tile );
-
- TileKey _tileKey;
- ColorLayersByUID _colorLayers;
- osg::ref_ptr< osgTerrain::HeightFieldLayer > _elevationLayer;
- osg::ref_ptr< osgTerrain::Locator > _locator;
- float _sampleRatio;
- MaskLayerVector _masks;
-
- // convenience funciton to pull out a layer by its UID.
- bool getCustomColorLayer( UID layerUID, CustomColorLayer& out ) const {
- ColorLayersByUID::const_iterator i = _colorLayers.find( layerUID );
- if ( i != _colorLayers.end() ) {
- out = i->second;
- return true;
+ class TileVector : public std::vector< osg::ref_ptr<Tile> > { };
+
+ // --------------------------------------------------------------------------
+
+ /**
+ * Thread-safe working copy of Tile contents.
+ */
+ class TileFrame
+ {
+ public:
+ TileFrame( Tile* tile );
+
+ TileKey _tileKey;
+ ColorLayersByUID _colorLayers;
+ osg::ref_ptr< osgTerrain::HeightFieldLayer > _elevationLayer;
+ osg::ref_ptr< osgTerrain::Locator > _locator;
+ float _sampleRatio;
+ MaskLayerVector _masks;
+
+ // convenience funciton to pull out a layer by its UID.
+ bool getCustomColorLayer( UID layerUID, CustomColorLayer& out ) const {
+ ColorLayersByUID::const_iterator i = _colorLayers.find( layerUID );
+ if ( i != _colorLayers.end() ) {
+ out = i->second;
+ return true;
+ }
+ return false;
}
- return false;
- }
-};
+ };
+
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_OSGTERRAIN_CUSTOM_TILE
diff --git a/src/osgEarthDrivers/engine_osgterrain/Tile.cpp b/src/osgEarthDrivers/engine_osgterrain/Tile.cpp
index ce3462f..208a1dd 100644
--- a/src/osgEarthDrivers/engine_osgterrain/Tile.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/Tile.cpp
@@ -34,7 +34,7 @@
#include <OpenThreads/ScopedLock>
-
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_osgterrain/TileBuilder b/src/osgEarthDrivers/engine_osgterrain/TileBuilder
index 8924f28..f7b6c49 100644
--- a/src/osgEarthDrivers/engine_osgterrain/TileBuilder
+++ b/src/osgEarthDrivers/engine_osgterrain/TileBuilder
@@ -21,78 +21,83 @@
#include "Common"
#include "Tile"
-#include <osgEarth/Map>
+#include <osgEarth/MapInfo>
+#include <osgEarth/MapFrame>
#include <osgEarth/TaskService>
#include <osg/Group>
-using namespace osgEarth;
-
-class TileBuilder : public osg::Referenced
+namespace osgEarth_engine_osgterrain
{
-public:
- struct SourceRepo
- {
- SourceRepo() { }
+ using namespace osgEarth;
- void add( const CustomColorLayer& layer )
+ class TileBuilder : public osg::Referenced
+ {
+ public:
+ struct SourceRepo
{
- Threading::ScopedMutexLock lock(_m);
- _colorLayers[ layer.getUID() ] = layer;
- }
-
- void set( const CustomElevLayer& elevLayer )
+ SourceRepo() { }
+
+ void add( const CustomColorLayer& layer )
+ {
+ Threading::ScopedMutexLock lock(_m);
+ _colorLayers[ layer.getUID() ] = layer;
+ }
+
+ void set( const CustomElevLayer& elevLayer )
+ {
+ // only one...no lock required
+ _elevLayer = elevLayer;
+ }
+
+ ColorLayersByUID _colorLayers;
+ CustomElevLayer _elevLayer;
+ Threading::Mutex _m;
+ };
+
+ struct Job : public osg::Referenced
{
- // only one...no lock required
- _elevLayer = elevLayer;
- }
-
- ColorLayersByUID _colorLayers;
- CustomElevLayer _elevLayer;
- Threading::Mutex _m;
- };
-
- struct Job : public osg::Referenced
- {
- Job(const TileKey& key, const Map* map) : _key(key), _mapf(map, Map::TERRAIN_LAYERS) { }
-
- TileKey _key;
- MapFrame _mapf;
- SourceRepo _repo;
- TaskRequestVector _tasks;
+ Job(const TileKey& key, const Map* map) : _key(key), _mapf(map, Map::TERRAIN_LAYERS) { }
+
+ TileKey _key;
+ MapFrame _mapf;
+ SourceRepo _repo;
+ TaskRequestVector _tasks;
+ };
+
+ public:
+ TileBuilder(
+ const Map* map,
+ const OSGTerrainOptions& terrainOptions,
+ TaskService* service );
+
+ /** dtor */
+ virtual ~TileBuilder() { }
+
+ void createTile(
+ const TileKey& key,
+ bool parallelize,
+ osg::ref_ptr<Tile>& out_tile,
+ bool& out_hasRealData,
+ bool& out_hasLodBlendedLayers );
+
+ Job* createJob( const TileKey& key, Threading::MultiEvent& semaphore );
+
+ void runJob( Job* job );
+
+ void finalizeJob(
+ Job* job,
+ osg::ref_ptr<Tile>& out_tile,
+ bool& out_hasRealData,
+ bool& out_hasLodBlending );
+
+ TaskService* getTaskService() const { return _service; }
+
+ private:
+ const Map* _map;
+ TaskService* _service;
+ const OSGTerrainOptions& _terrainOptions;
};
-public:
- TileBuilder(
- const Map* map,
- const OSGTerrainOptions& terrainOptions,
- TaskService* service );
-
- /** dtor */
- virtual ~TileBuilder() { }
-
- void createTile(
- const TileKey& key,
- bool parallelize,
- osg::ref_ptr<Tile>& out_tile,
- bool& out_hasRealData,
- bool& out_hasLodBlendedLayers );
-
- Job* createJob( const TileKey& key, Threading::MultiEvent& semaphore );
-
- void runJob( Job* job );
-
- void finalizeJob(
- Job* job,
- osg::ref_ptr<Tile>& out_tile,
- bool& out_hasRealData,
- bool& out_hasLodBlending );
-
- TaskService* getTaskService() const { return _service; }
-
-private:
- const Map* _map;
- TaskService* _service;
- const OSGTerrainOptions& _terrainOptions;
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_TILE_BUILDER
diff --git a/src/osgEarthDrivers/engine_osgterrain/TileBuilder.cpp b/src/osgEarthDrivers/engine_osgterrain/TileBuilder.cpp
index e2eb1b6..ca89060 100644
--- a/src/osgEarthDrivers/engine_osgterrain/TileBuilder.cpp
+++ b/src/osgEarthDrivers/engine_osgterrain/TileBuilder.cpp
@@ -22,6 +22,7 @@
#include <osgEarth/TaskService>
#include <osgEarth/HeightFieldUtils>
+using namespace osgEarth_engine_osgterrain;
using namespace osgEarth;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_osgterrain/TransparentLayer b/src/osgEarthDrivers/engine_osgterrain/TransparentLayer
index 9eddd35..be6fe54 100644
--- a/src/osgEarthDrivers/engine_osgterrain/TransparentLayer
+++ b/src/osgEarthDrivers/engine_osgterrain/TransparentLayer
@@ -28,103 +28,107 @@
#include <osgEarth/TileKey>
#include <osg/Image>
-class CustomColorLayer
+namespace osgEarth_engine_osgterrain
{
-public:
- CustomColorLayer() { }
-
- /** dtor */
- virtual ~CustomColorLayer() { }
-
- CustomColorLayer(
- const osgEarth::ImageLayer* imageLayer,
- osg::Image* image,
- const osgTerrain::Locator* locator,
- int lod,
- const osgEarth::TileKey& tileKey,
- bool fallbackData =false )
- : _layer(imageLayer), _locator(locator), _image(image), _tileKey(tileKey), _lod(lod), _fallbackData(fallbackData) { }
-
- CustomColorLayer( const CustomColorLayer& rhs ) :
- _layer( rhs._layer.get() ),
- _locator( rhs._locator.get() ),
- _image( rhs._image.get() ),
- _tileKey( rhs._tileKey ),
- _lod( rhs._lod ),
- _fallbackData( rhs._fallbackData ) { }
-
- osgEarth::UID getUID() const {
- return _layer->getUID();
- }
-
- const osgTerrain::Locator* getLocator() const {
- return _locator.get();
- }
-
- osg::Image* getImage() const {
- return _image.get(); }
-
- const osgEarth::TileKey& getTileKey() const {
- return _tileKey; }
-
- const osgEarth::ImageLayer* getMapLayer() const {
- return _layer.get(); }
-
- int getLevelOfDetail() const {
- return _lod; }
-
- bool isFallbackData() const {
- return _fallbackData; }
-
- osg::BoundingSphere computeBound() const {
- osg::BoundingSphere bs;
- osg::Vec3d v;
- if (getLocator()->convertLocalToModel(osg::Vec3d(0.5,0.5,0.0), v)) {
- bs.center() = v;
+ class CustomColorLayer
+ {
+ public:
+ CustomColorLayer() { }
+
+ /** dtor */
+ virtual ~CustomColorLayer() { }
+
+ CustomColorLayer(
+ const osgEarth::ImageLayer* imageLayer,
+ osg::Image* image,
+ const osgTerrain::Locator* locator,
+ int lod,
+ const osgEarth::TileKey& tileKey,
+ bool fallbackData =false )
+ : _layer(imageLayer), _locator(locator), _image(image), _tileKey(tileKey), _lod(lod), _fallbackData(fallbackData) { }
+
+ CustomColorLayer( const CustomColorLayer& rhs ) :
+ _layer( rhs._layer.get() ),
+ _locator( rhs._locator.get() ),
+ _image( rhs._image.get() ),
+ _tileKey( rhs._tileKey ),
+ _lod( rhs._lod ),
+ _fallbackData( rhs._fallbackData ) { }
+
+ osgEarth::UID getUID() const {
+ return _layer->getUID();
}
- if (getLocator()->convertLocalToModel(osg::Vec3d(0.0,0.0,0.0), v)) {
- bs.radius() = (bs.center() - v).length();
+
+ const osgTerrain::Locator* getLocator() const {
+ return _locator.get();
}
- return bs;
- }
+ osg::Image* getImage() const {
+ return _image.get(); }
-private:
- osg::ref_ptr<const osgEarth::ImageLayer> _layer;
- osg::ref_ptr<const osgTerrain::Locator> _locator;
- osg::ref_ptr<osg::Image> _image;
- osgEarth::TileKey _tileKey;
- int _lod;
- bool _fallbackData;
-};
+ const osgEarth::TileKey& getTileKey() const {
+ return _tileKey; }
-class CustomColorLayerRef : public osg::Referenced
-{
-public:
- CustomColorLayerRef( const CustomColorLayer& layer ) : _layer(layer) { }
- CustomColorLayer _layer;
-};
+ const osgEarth::ImageLayer* getMapLayer() const {
+ return _layer.get(); }
-class CustomElevLayer
-{
-public:
- CustomElevLayer() { }
+ int getLevelOfDetail() const {
+ return _lod; }
+
+ bool isFallbackData() const {
+ return _fallbackData; }
+
+ osg::BoundingSphere computeBound() const {
+ osg::BoundingSphere bs;
+ osg::Vec3d v;
+ if (getLocator()->convertLocalToModel(osg::Vec3d(0.5,0.5,0.0), v)) {
+ bs.center() = v;
+ }
+ if (getLocator()->convertLocalToModel(osg::Vec3d(0.0,0.0,0.0), v)) {
+ bs.radius() = (bs.center() - v).length();
+ }
+ return bs;
+ }
+
+
+ private:
+ osg::ref_ptr<const osgEarth::ImageLayer> _layer;
+ osg::ref_ptr<const osgTerrain::Locator> _locator;
+ osg::ref_ptr<osg::Image> _image;
+ osgEarth::TileKey _tileKey;
+ int _lod;
+ bool _fallbackData;
+ };
+
+ class CustomColorLayerRef : public osg::Referenced
+ {
+ public:
+ CustomColorLayerRef( const CustomColorLayer& layer ) : _layer(layer) { }
+ CustomColorLayer _layer;
+ };
+
+ class CustomElevLayer
+ {
+ public:
+ CustomElevLayer() { }
+
+ /** dtor */
+ virtual ~CustomElevLayer() { }
- /** dtor */
- virtual ~CustomElevLayer() { }
+ CustomElevLayer( osgTerrain::HeightFieldLayer* hfLayer, bool fallbackData =false )
+ : _hfLayer(hfLayer), _fallbackData(fallbackData) { }
- CustomElevLayer( osgTerrain::HeightFieldLayer* hfLayer, bool fallbackData =false )
- : _hfLayer(hfLayer), _fallbackData(fallbackData) { }
+ osgTerrain::HeightFieldLayer* getHFLayer() {
+ return _hfLayer.get(); }
- osgTerrain::HeightFieldLayer* getHFLayer() {
- return _hfLayer.get(); }
+ bool isFallbackData() const {
+ return _fallbackData; }
- bool isFallbackData() const {
- return _fallbackData; }
+ private:
+ osg::ref_ptr<osgTerrain::HeightFieldLayer> _hfLayer;
+ bool _fallbackData;
+ };
-private:
- osg::ref_ptr<osgTerrain::HeightFieldLayer> _hfLayer;
- bool _fallbackData;
-};
+} // namespace osgEarth_engine_osgterrain
#endif // OSGEARTH_ENGINE_TRANSPARENT_LAYER
diff --git a/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD b/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD
index f58cd94..477f051 100644
--- a/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD
+++ b/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD
@@ -26,44 +26,48 @@
using namespace osgEarth;
-/**
- * Customized PagedLOD node that automatically registers TileNodes
- * with a TileNodeRegistry when they are added to the scene graph.
- */
-class CustomPagedLOD : public osg::PagedLOD
+namespace osgEarth_engine_quadtree
{
-public:
/**
- * Constructs a PagedLOD node that will register TileNode's with the
- * provided registry
+ * Customized PagedLOD node that automatically registers TileNodes
+ * with a TileNodeRegistry when they are added to the scene graph.
*/
- CustomPagedLOD(
- TileNodeRegistry* liveTiles,
- TileNodeRegistry* deadTiles );
+ class CustomPagedLOD : public osg::PagedLOD
+ {
+ public:
+ /**
+ * Constructs a PagedLOD node that will register TileNode's with the
+ * provided registry
+ */
+ CustomPagedLOD(
+ TileNodeRegistry* liveTiles,
+ TileNodeRegistry* deadTiles );
- /**
- * Destructor
- */
- virtual ~CustomPagedLOD();
+ /**
+ * Destructor
+ */
+ virtual ~CustomPagedLOD();
-public: // osg::Group
+ public: // osg::Group
- /**
- * Override Group methods so that a TileNode gets registered when the
- * DatabasePager adds it to the scene graph. Of course this would happen
- * if you simply added the TileNode to any parent, but in this
- * implmementation the DatabasePager is the only entity adding a TileNode
- * to a parent.
- *
- * DatabasePager only calls addChild or removeChild, but we will implement the
- * other methods (insert, replace, etc) later if necessary
- */
- bool addChild( osg::Node* child );
- bool removeChildren(unsigned pos, unsigned numChildrenToRemove );
+ /**
+ * Override Group methods so that a TileNode gets registered when the
+ * DatabasePager adds it to the scene graph. Of course this would happen
+ * if you simply added the TileNode to any parent, but in this
+ * implmementation the DatabasePager is the only entity adding a TileNode
+ * to a parent.
+ *
+ * DatabasePager only calls addChild or removeChild, but we will implement the
+ * other methods (insert, replace, etc) later if necessary
+ */
+ bool addChild( osg::Node* child );
+ bool removeChildren(unsigned pos, unsigned numChildrenToRemove );
+
+ private:
-private:
+ osg::ref_ptr<TileNodeRegistry> _live, _dead;
+ };
- osg::ref_ptr<TileNodeRegistry> _live, _dead;
-};
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_CUSTOM_PAGED_LOD
diff --git a/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD.cpp b/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD.cpp
index 2e69801..52b1a0f 100644
--- a/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/CustomPagedLOD.cpp
@@ -18,6 +18,7 @@
*/
#include "CustomPagedLOD"
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
#define LC "[CustomPagedLOD] "
diff --git a/src/osgEarthDrivers/engine_quadtree/DynamicLODScaleCallback b/src/osgEarthDrivers/engine_quadtree/DynamicLODScaleCallback
index 62cbc7c..0f8b31f 100644
--- a/src/osgEarthDrivers/engine_quadtree/DynamicLODScaleCallback
+++ b/src/osgEarthDrivers/engine_quadtree/DynamicLODScaleCallback
@@ -23,59 +23,63 @@
#include <osg/NodeCallback>
#include <osg/CullStack>
-/**
- * Cull callback that dynamically computes an LOD scale based on
- * distance to the camera and a "fall off" metric. As the fall off
- * increases, farther objects' LOD scale will increase. A good
- * range for the fall-off number is 0..5.
- */
-struct DynamicLODScaleCallback : public osg::NodeCallback
+namespace osgEarth_engine_quadtree
{
- DynamicLODScaleCallback( float fallOff ) : _fallOff(fallOff) { }
+ /**
+ * Cull callback that dynamically computes an LOD scale based on
+ * distance to the camera and a "fall off" metric. As the fall off
+ * increases, farther objects' LOD scale will increase. A good
+ * range for the fall-off number is 0..5.
+ */
+ struct DynamicLODScaleCallback : public osg::NodeCallback
+ {
+ DynamicLODScaleCallback( float fallOff ) : _fallOff(fallOff) { }
- /** dtor */
- virtual ~DynamicLODScaleCallback() { }
+ /** dtor */
+ virtual ~DynamicLODScaleCallback() { }
- void operator()( osg::Node* node, osg::NodeVisitor* nv )
- {
- osg::CullStack* cs = dynamic_cast<osg::CullStack*>(nv);
- if ( cs )
+ void operator()( osg::Node* node, osg::NodeVisitor* nv )
{
- osg::LOD* lod = static_cast<osg::LOD*>( node );
- osg::Vec3 center = lod->getCenter();
+ osg::CullStack* cs = dynamic_cast<osg::CullStack*>(nv);
+ if ( cs )
+ {
+ osg::LOD* lod = static_cast<osg::LOD*>( node );
+ osg::Vec3 center = lod->getCenter();
- osg::Vec3 eye = nv->getEyePoint();
- osg::Vec3 eyeVec = eye; eyeVec.normalize();
- float has = osg::clampAbove( eye.length() - 6356752.3142f, 0.0f );
- float centerToEye = nv->getDistanceToViewPoint(center, false);
- float bsToEye = centerToEye - lod->getChild(0)->getBound().radius();
+ osg::Vec3 eye = nv->getEyePoint();
+ osg::Vec3 eyeVec = eye; eyeVec.normalize();
+ float has = osg::clampAbove( eye.length() - 6356752.3142f, 0.0f );
+ float centerToEye = nv->getDistanceToViewPoint(center, false);
+ float bsToEye = centerToEye - lod->getChild(0)->getBound().radius();
- float scaleAdj = 1.0f;
- if ( bsToEye > has )
+ float scaleAdj = 1.0f;
+ if ( bsToEye > has )
+ {
+ float denom = osg::maximum(0.1f, (1.0f/_fallOff)) * 10000.0f;
+ scaleAdj = osg::clampBetween( log10f(bsToEye/denom), 1.0f, 3.0f );
+
+ //OE_INFO << LC
+ // << std::fixed
+ // << "centerToEye=" << centerToEye
+ // << ", bsToEye=" << bsToEye
+ // << ", scaleAdj=" << scaleAdj
+ // << std::endl;
+ }
+
+ float lodScale = cs->getLODScale();
+ cs->setLODScale( lodScale * scaleAdj );
+ traverse( node, nv );
+ cs->setLODScale( lodScale );
+ }
+ else
{
- float denom = osg::maximum(0.1f, (1.0f/_fallOff)) * 10000.0f;
- scaleAdj = osg::clampBetween( log10f(bsToEye/denom), 1.0f, 3.0f );
-
- //OE_INFO << LC
- // << std::fixed
- // << "centerToEye=" << centerToEye
- // << ", bsToEye=" << bsToEye
- // << ", scaleAdj=" << scaleAdj
- // << std::endl;
+ traverse( node, nv );
}
-
- float lodScale = cs->getLODScale();
- cs->setLODScale( lodScale * scaleAdj );
- traverse( node, nv );
- cs->setLODScale( lodScale );
- }
- else
- {
- traverse( node, nv );
}
- }
- float _fallOff;
-};
+ float _fallOff;
+ };
+
+} // namespace osgEarth_engine_quadtree
#endif //OSGEARTH_ENGINE_OSGTERRAIN_DYNAMIC_LOD_SCALE_CALLBACK_H
diff --git a/src/osgEarthDrivers/engine_quadtree/FileLocationCallback b/src/osgEarthDrivers/engine_quadtree/FileLocationCallback
index 91179a7..ae0533b 100644
--- a/src/osgEarthDrivers/engine_quadtree/FileLocationCallback
+++ b/src/osgEarthDrivers/engine_quadtree/FileLocationCallback
@@ -27,54 +27,59 @@
#define USE_FILELOCATIONCALLBACK OSG_MIN_VERSION_REQUIRED(2,9,5)
+
#if USE_FILELOCATIONCALLBACK
-/**
- * A database pager callback that determines if the given filename is cached or not
- */
-class FileLocationCallback : public osgDB::FileLocationCallback
+namespace osgEarth_engine_quadtree
{
-public:
- FileLocationCallback() { }
-
- /** dtor */
- virtual ~FileLocationCallback() { }
-
- virtual Location fileLocation(const std::string& filename, const osgDB::Options* options)
+ /**
+ * A database pager callback that determines if the given filename is cached or not
+ */
+ class FileLocationCallback : public osgDB::FileLocationCallback
{
- Location result = REMOTE_FILE;
- //OE_NOTICE<<"fileLocation = "<<filename<<std::endl;
-
- unsigned int lod, x, y, id;
- sscanf(filename.c_str(), "%d/%d/%d.%d", &lod, &x, &y, &id);
+ public:
+ FileLocationCallback() { }
- osg::ref_ptr<QuadTreeTerrainEngineNode> engine;
- QuadTreeTerrainEngineNode::getEngineByUID( (UID)id, engine );
+ /** dtor */
+ virtual ~FileLocationCallback() { }
- if ( engine.valid() )
+ virtual Location fileLocation(const std::string& filename, const osgDB::Options* options)
{
- const osgEarth::Profile* profile = engine->getMap()->getProfile();
- osgEarth::TileKey mapKey( lod, x, y, profile );
+ Location result = REMOTE_FILE;
+ //OE_NOTICE<<"fileLocation = "<<filename<<std::endl;
- result = LOCAL_FILE;
+ unsigned int lod, x, y, id;
+ sscanf(filename.c_str(), "%d/%d/%d.%d", &lod, &x, &y, &id);
- MapFrame mapf( engine->getMap() );
- for( unsigned i=0; i<4; ++i )
+ osg::ref_ptr<QuadTreeTerrainEngineNode> engine;
+ QuadTreeTerrainEngineNode::getEngineByUID( (UID)id, engine );
+
+ if ( engine.valid() )
{
- TileKey childKey = mapKey.createChildKey( i );
- if ( !mapf.isCached( childKey ) )
+ const osgEarth::Profile* profile = engine->getMap()->getProfile();
+ osgEarth::TileKey mapKey( lod, x, y, profile );
+
+ result = LOCAL_FILE;
+
+ MapFrame mapf( engine->getMap() );
+ for( unsigned i=0; i<4; ++i )
{
- result = REMOTE_FILE;
- break;
+ TileKey childKey = mapKey.createChildKey( i );
+ if ( !mapf.isCached( childKey ) )
+ {
+ result = REMOTE_FILE;
+ break;
+ }
}
}
+
+ return result;
}
- return result;
- }
+ virtual bool useFileCache() const { return false; }
+ };
- virtual bool useFileCache() const { return false; }
-};
+} // namespace osgEarth_engine_quadtree
#endif // USE_FILELOCATIONCALLBACK
diff --git a/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory b/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory
index dc933f3..85900fa 100644
--- a/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory
+++ b/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory
@@ -25,29 +25,33 @@
using namespace osgEarth;
-/**
-* Factory object that can create a scene graph given a TileKey.
-*/
-class KeyNodeFactory : public osg::Referenced
+namespace osgEarth_engine_quadtree
{
-public:
/**
- * Creates a node for a tile key at the root level.
+ * Factory object that can create a scene graph given a TileKey.
*/
- virtual osg::Node* createRootNode( const TileKey& key ) =0;
+ class KeyNodeFactory : public osg::Referenced
+ {
+ public:
+ /**
+ * Creates a node for a tile key at the root level.
+ */
+ virtual osg::Node* createRootNode( const TileKey& key ) =0;
- /**
- * Creates a node for a tile key.
- */
- virtual osg::Node* createNode( const TileKey& key ) =0;
+ /**
+ * Creates a node for a tile key.
+ */
+ virtual osg::Node* createNode( const TileKey& key ) =0;
+
+ virtual class TileModelCompiler* getCompiler() const =0;
- virtual class TileModelCompiler* getCompiler() const =0;
+ protected:
+ KeyNodeFactory();
-protected:
- KeyNodeFactory();
+ /** dtor */
+ virtual ~KeyNodeFactory() { }
+ };
- /** dtor */
- virtual ~KeyNodeFactory() { }
-};
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_KEY_NODE_FACTORY
diff --git a/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory.cpp b/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory.cpp
index 8ab3fda..fa94232 100644
--- a/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/KeyNodeFactory.cpp
@@ -18,6 +18,7 @@
*/
#include "KeyNodeFactory"
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
#define LC "[KeyNodeFactory] "
diff --git a/src/osgEarthDrivers/engine_quadtree/LODFactorCallback b/src/osgEarthDrivers/engine_quadtree/LODFactorCallback
index 0fdbbe2..4b15d7d 100644
--- a/src/osgEarthDrivers/engine_quadtree/LODFactorCallback
+++ b/src/osgEarthDrivers/engine_quadtree/LODFactorCallback
@@ -22,14 +22,13 @@
#include <osg/NodeCallback>
-namespace osgEarth
+namespace osgEarth_engine_quadtree
{
- namespace Drivers
+ struct LODFactorCallback : public osg::NodeCallback
{
- struct LODFactorCallback : public osg::NodeCallback
- {
- void operator()(osg::Node* node, osg::NodeVisitor* nv);
- };
- }
-}
+ void operator()(osg::Node* node, osg::NodeVisitor* nv);
+ };
+
+} // namespace osgEarth_engine_quadtree
+
#endif
diff --git a/src/osgEarthDrivers/engine_quadtree/LODFactorCallback.cpp b/src/osgEarthDrivers/engine_quadtree/LODFactorCallback.cpp
index 78923fa..04ad128 100644
--- a/src/osgEarthDrivers/engine_quadtree/LODFactorCallback.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/LODFactorCallback.cpp
@@ -24,62 +24,57 @@
#include <osg/Uniform>
#include <osgUtil/CullVisitor>
-namespace osgEarth
+using namespace osgEarth_engine_quadtree;
+
+// This callback sets a uniform, osgearth_LODRangeFactor, based on the
+// distance from the camera and its relation to the minimum and
+// maximum distance for a tile. The maximum distance isn't actually
+// available, so 2 * min distance is used as an estimate. The range
+// factor's value goes from 0 - at the maximum range - to 1 for the
+// minimum range.
+void LODFactorCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
- namespace Drivers
+ // test the type since this is not always a PagedLOD.
+ osg::PagedLOD* lod = static_cast<osg::PagedLOD*>(node);
+ osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
+ osg::LOD::RangeMode rangeMode = lod->getRangeMode();
+ float requiredRange = 0.0f;
+ float rangeFactor = 1.0f;
+ const osg::LOD::RangeList& rangeList = lod->getRangeList();
+ if (rangeMode == osg::LOD::DISTANCE_FROM_EYE_POINT)
{
- // This callback sets a uniform, osgearth_LODRangeFactor, based on the
- // distance from the camera and its relation to the minimum and
- // maximum distance for a tile. The maximum distance isn't actually
- // available, so 2 * min distance is used as an estimate. The range
- // factor's value goes from 0 - at the maximum range - to 1 for the
- // minimum range.
-
- void LODFactorCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
+ requiredRange = cv->getDistanceToViewPoint(lod->getCenter(), true);
+ }
+ else if (cv->getLODScale() > 0.0f)
+ {
+ requiredRange = cv->clampedPixelSize(lod->getBound()) / cv->getLODScale();
+ }
+ else
+ {
+ // The comment in osg/PagedLOD.cpp says that this algorithm
+ // finds the highest res tile, but it actually finds the
+ // lowest res tile!
+ for (osg::LOD::RangeList::const_iterator itr = rangeList.begin(), end = rangeList.end();
+ itr != end;
+ ++itr)
{
- // test the type since this is not always a PagedLOD.
- osg::PagedLOD* lod = static_cast<osg::PagedLOD*>(node);
- osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
- osg::LOD::RangeMode rangeMode = lod->getRangeMode();
- float requiredRange = 0.0f;
- float rangeFactor = 1.0f;
- const osg::LOD::RangeList& rangeList = lod->getRangeList();
- if (rangeMode == osg::LOD::DISTANCE_FROM_EYE_POINT)
- {
- requiredRange = cv->getDistanceToViewPoint(lod->getCenter(), true);
- }
- else if (cv->getLODScale() > 0.0f)
- {
- requiredRange = cv->clampedPixelSize(lod->getBound()) / cv->getLODScale();
- }
- else
- {
- // The comment in osg/PagedLOD.cpp says that this algorithm
- // finds the highest res tile, but it actually finds the
- // lowest res tile!
- for (osg::LOD::RangeList::const_iterator itr = rangeList.begin(), end = rangeList.end();
- itr != end;
- ++itr)
- {
- requiredRange = osg::maximum(requiredRange, itr->first);
- }
- }
- // We're counting on only finding one valid LOD, unlike the
- // general OSG behavior.
- if (!rangeList.empty() && rangeList[0].first <= requiredRange
- && requiredRange < rangeList[0].second)
- {
- rangeFactor = 1.0f - (requiredRange - rangeList[0].first) / rangeList[0].first;
- rangeFactor = osg::clampTo(rangeFactor, 0.0f, 1.0f);
- }
- osg::ref_ptr<osg::Uniform> ufact
- = new osg::Uniform("osgearth_LODRangeFactor", rangeFactor);
- osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
- ss->addUniform(ufact.get());
-
- cv->pushStateSet(ss.get());
- traverse(node, nv);
- cv->popStateSet();
+ requiredRange = osg::maximum(requiredRange, itr->first);
}
}
+ // We're counting on only finding one valid LOD, unlike the
+ // general OSG behavior.
+ if (!rangeList.empty() && rangeList[0].first <= requiredRange
+ && requiredRange < rangeList[0].second)
+ {
+ rangeFactor = 1.0f - (requiredRange - rangeList[0].first) / rangeList[0].first;
+ rangeFactor = osg::clampTo(rangeFactor, 0.0f, 1.0f);
+ }
+ osg::ref_ptr<osg::Uniform> ufact
+ = new osg::Uniform("osgearth_LODRangeFactor", rangeFactor);
+ osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;
+ ss->addUniform(ufact.get());
+
+ cv->pushStateSet(ss.get());
+ traverse(node, nv);
+ cv->popStateSet();
}
diff --git a/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineNode b/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineNode
deleted file mode 100644
index 3341ce3..0000000
--- a/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineNode
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2008-2012 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_ENGINE_QUADTREE_ENGINE_NODE_H
-#define OSGEARTH_ENGINE_QUADTREE_ENGINE_NODE_H 1
-
-#include <osgEarth/TerrainEngineNode>
-#include <osgEarth/TextureCompositor>
-#include <osgEarth/Map>
-#include <osgEarth/Revisioning>
-#include <osgEarth/TaskService>
-
-#include "QuadTreeTerrainEngineOptions"
-#include "OSGTileFactory"
-#include "KeyNodeFactory"
-#include "TileBuilder"
-
-#include <osg/Geode>
-#include <osg/NodeCallback>
-
-using namespace osgEarth;
-
-class QuadTreeTerrainEngineNode : public TerrainEngineNode
-{
-public:
- QuadTreeTerrainEngineNode();
- META_Node(osgEarth,QuadTreeTerrainEngineNode);
- virtual ~QuadTreeTerrainEngineNode();
-
-public:
- osg::Node* createNode(const TileKey& key);
-
-public: // TerrainEngineNode overrides
- virtual void preInitialize( const Map* map, const TerrainOptions& options );
- virtual void postInitialize( const Map* map, const TerrainOptions& options );
- virtual void validateTerrainOptions( TerrainOptions& options );
- virtual const TerrainOptions& getTerrainOptions() const { return _terrainOptions; }
- virtual void traverse( osg::NodeVisitor& );
- virtual osg::BoundingSphere computeBound() const;
-
- // for standalone tile creation outside of a terrain
- osg::Node* createTile(const TileKey& key);
-
-public: // MapCallback adapter functions
- void onMapInfoEstablished( const MapInfo& mapInfo ); // not virtual!
- void onMapModelChanged( const MapModelChange& change ); // not virtual!
-
- UID getUID() const;
- OSGTileFactory* getTileFactory() const { return _tileFactory.get(); }
- class TerrainNode* getTerrainNode() const { return _terrain; }
-
-public: // statics
- static void registerEngine( QuadTreeTerrainEngineNode* engineNode );
- static void unregisterEngine( UID uid );
- static void getEngineByUID( UID uid, osg::ref_ptr<QuadTreeTerrainEngineNode>& output );
-
-public:
- class ElevationChangedCallback : public ElevationLayerCallback
- {
- public:
- ElevationChangedCallback( QuadTreeTerrainEngineNode* terrain );
-
- virtual void onVisibleChanged( TerrainLayer* layer );
-
- QuadTreeTerrainEngineNode* _terrain;
- friend class QuadTreeTerrainEngineNode;
- };
-
-protected:
- virtual void onVerticalScaleChanged();
-
-private:
- void init();
- void syncMapModel();
- void installTerrainTechnique();
-
- /**
- * Reloads all the tiles in the terrain due to a data model change
- */
- void refresh();
-
-
- void addImageLayer( ImageLayer* layer );
- void addElevationLayer( ElevationLayer* layer );
-
- void removeImageLayer( ImageLayer* layerRemoved );
- void removeElevationLayer( ElevationLayer* layerRemoved );
-
- void moveImageLayer( unsigned int oldIndex, unsigned int newIndex );
- void moveElevationLayer( unsigned int oldIndex, unsigned int newIndex );
-
- void updateElevation( Tile* tile );
- void installShaders();
- void updateTextureCombining();
-
-private:
- osg::ref_ptr<OSGTileFactory> _tileFactory;
- //class CustomTerrainNode* _terrain;
- class TerrainNode* _terrain;
- UID _uid;
- osgEarth::Drivers::OSGTerrainOptions _terrainOptions;
- Revision _shaderLibRev;
- osg::ref_ptr<TaskServiceManager> _taskServiceMgr;
-
- osg::ref_ptr< ElevationChangedCallback > _elevationCallback;
-
- // store a separate map frame for each of the traversal threads
- MapFrame* _update_mapf; // map frame for the main/update traversal thread
- MapFrame* _cull_mapf; // map frame for the cull traversal thread
-
- osg::ref_ptr<TaskService> _tileService;
- osg::ref_ptr<KeyNodeFactory> _keyNodeFactory;
- osg::ref_ptr<TileBuilder> _tileBuilder;
-
- osg::Timer _timer;
- unsigned _tileCount;
- double _tileCreationTime;
- bool _isStreaming;
-
- QuadTreeTerrainEngineNode( const QuadTreeTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) { }
-};
-
-#endif // OSGEARTH_ENGINE_QUADTREE_ENGINE_NODE_H
diff --git a/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineNode.cpp b/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineNode.cpp
deleted file mode 100644
index cc959bd..0000000
--- a/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineNode.cpp
+++ /dev/null
@@ -1,986 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
-* Copyright 2008-2012 Pelican Mapping
-* http://osgearth.org
-*
-* osgEarth is free software; you can redistribute it and/or modify
-* it under the terms of the GNU Lesser General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>
-*/
-#include "QuadTreeTerrainEngineNode"
-#include "MultiPassTerrainTechnique"
-#include "ParallelKeyNodeFactory"
-#include "SinglePassTerrainTechnique"
-#include "TerrainNode"
-#include "StreamingTerrainNode"
-#include "TileBuilder"
-#include "TransparentLayer"
-
-#include <osgEarth/ImageUtils>
-#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
-#include <osg/TexEnv>
-#include <osg/TexEnvCombine>
-#include <osg/PagedLOD>
-#include <osg/Timer>
-
-#define LC "[QuadTreeEngine] "
-
-using namespace osgEarth;
-
-//------------------------------------------------------------------------
-
-namespace
-{
- // adapter that lets QuadTreeTerrainEngineNode listen to Map events
- struct QuadTreeTerrainEngineNodeMapCallbackProxy : public MapCallback
- {
- QuadTreeTerrainEngineNodeMapCallbackProxy(QuadTreeTerrainEngineNode* node) : _node(node) { }
- osg::observer_ptr<QuadTreeTerrainEngineNode> _node;
-
- void onMapInfoEstablished( const MapInfo& mapInfo ) {
- _node->onMapInfoEstablished( mapInfo );
- }
-
- void onMapModelChanged( const MapModelChange& change ) {
- _node->onMapModelChanged( change );
- }
- };
-}
-
-//---------------------------------------------------------------------------
-
-//static
-//static OpenThreads::ReentrantMutex s_engineNodeCacheMutex;
-static Threading::ReadWriteMutex s_engineNodeCacheMutex;
-//Caches the MapNodes that have been created
-typedef std::map<UID, osg::observer_ptr<QuadTreeTerrainEngineNode> > EngineNodeCache;
-
-static
-EngineNodeCache& getEngineNodeCache()
-{
- static EngineNodeCache s_cache;
- return s_cache;
-}
-
-void
-QuadTreeTerrainEngineNode::registerEngine(QuadTreeTerrainEngineNode* engineNode)
-{
- Threading::ScopedWriteLock exclusiveLock( s_engineNodeCacheMutex );
- getEngineNodeCache()[engineNode->_uid] = engineNode;
- OE_DEBUG << LC << "Registered engine " << engineNode->_uid << std::endl;
-}
-
-void
-QuadTreeTerrainEngineNode::unregisterEngine( UID uid )
-{
- Threading::ScopedWriteLock exclusiveLock( s_engineNodeCacheMutex );
- EngineNodeCache::iterator k = getEngineNodeCache().find( uid );
- if (k != getEngineNodeCache().end())
- {
- getEngineNodeCache().erase(k);
- OE_DEBUG << LC << "Unregistered engine " << uid << std::endl;
- }
-}
-
-// since this method is called in a database pager thread, we use a ref_ptr output
-// parameter to avoid the engine node being destructed between the time we
-// return it and the time it's accessed; this could happen if the user removed the
-// MapNode from the scene during paging.
-void
-QuadTreeTerrainEngineNode::getEngineByUID( UID uid, osg::ref_ptr<QuadTreeTerrainEngineNode>& output )
-{
- Threading::ScopedReadLock sharedLock( s_engineNodeCacheMutex );
- EngineNodeCache::const_iterator k = getEngineNodeCache().find( uid );
- if (k != getEngineNodeCache().end())
- output = k->second.get();
-}
-
-UID
-QuadTreeTerrainEngineNode::getUID() const
-{
- return _uid;
-}
-
-//------------------------------------------------------------------------
-
-QuadTreeTerrainEngineNode::ElevationChangedCallback::ElevationChangedCallback( QuadTreeTerrainEngineNode* terrain ):
-_terrain( terrain )
-{
-}
-
-void
-QuadTreeTerrainEngineNode::ElevationChangedCallback::onVisibleChanged( TerrainLayer* layer )
-{
- osgEarth::Registry::instance()->clearBlacklist();
- _terrain->refresh();
-}
-
-//------------------------------------------------------------------------
-
-QuadTreeTerrainEngineNode::QuadTreeTerrainEngineNode() :
-TerrainEngineNode(),
-_terrain ( 0L ),
-_update_mapf ( 0L ),
-_cull_mapf ( 0L ),
-_tileCount ( 0 ),
-_tileCreationTime( 0.0 )
-{
- _uid = Registry::instance()->createUID();
- _taskServiceMgr = Registry::instance()->getTaskServiceManager();
-
- _elevationCallback = new ElevationChangedCallback( this );
-}
-
-QuadTreeTerrainEngineNode::~QuadTreeTerrainEngineNode()
-{
- unregisterEngine( _uid );
-
- if ( _update_mapf )
- {
- delete _update_mapf;
- }
-
- if ( _cull_mapf )
- {
- delete _cull_mapf;
- }
-}
-
-void
-QuadTreeTerrainEngineNode::preInitialize( const Map* map, const TerrainOptions& options )
-{
- TerrainEngineNode::preInitialize( map, options );
-
- _isStreaming =
- options.loadingPolicy()->mode() == LoadingPolicy::MODE_PREEMPTIVE ||
- options.loadingPolicy()->mode() == LoadingPolicy::MODE_SEQUENTIAL;
-
- // in standard mode, try to set the number of OSG DatabasePager threads to use.
- if ( options.loadingPolicy().isSet() && !_isStreaming )
- {
- int numThreads = -1;
-
- if ( options.loadingPolicy()->numLoadingThreads().isSet() )
- {
- numThreads = osg::maximum( 1, *options.loadingPolicy()->numLoadingThreads() );
- }
- else if ( options.loadingPolicy()->numLoadingThreadsPerCore().isSet() )
- {
- float numThreadsPerCore = *options.loadingPolicy()->numLoadingThreadsPerCore();
- numThreads = osg::maximum( (int)1, (int)osg::round(
- numThreadsPerCore * (float)OpenThreads::GetNumberOfProcessors() ) );
- }
-
- if ( numThreads > 0 )
- {
- // NOTE: this doesn't work. the pager gets created before we ever get here.
- numThreads = osg::maximum(numThreads, 2);
- int numHttpThreads = osg::clampBetween( numThreads/2, 1, numThreads-1 );
-
- //OE_INFO << LC << "Requesting pager threads in STANDARD mode: local=" << numThreads << ", http=" << numHttpThreads << std::endl;
- osg::DisplaySettings::instance()->setNumOfDatabaseThreadsHint( numThreads );
- osg::DisplaySettings::instance()->setNumOfHttpDatabaseThreadsHint( numHttpThreads );
- }
- }
-}
-
-void
-QuadTreeTerrainEngineNode::postInitialize( const Map* map, const TerrainOptions& options )
-{
- TerrainEngineNode::postInitialize( map, options );
-
- // Initialize the map frames. We need one for the update thread and one for the
- // cull thread. Someday we can detect whether these are actually the same thread
- // (depends on the viewer's threading mode).
- _update_mapf = new MapFrame( map, Map::MASKED_TERRAIN_LAYERS, "osgterrain-update" );
- _cull_mapf = new MapFrame( map, Map::TERRAIN_LAYERS, "osgterrain-cull" );
-
- // merge in the custom options:
- _terrainOptions.merge( options );
-
- // handle an already-established map profile:
- if ( _update_mapf->getProfile() )
- {
- // NOTE: this will initialize the map with the startup layers
- onMapInfoEstablished( MapInfo(map) );
- }
-
- // populate the terrain with whatever data is in the map to begin with:
- if ( _terrain )
- {
- // update the terrain revision in threaded mode
- if ( _isStreaming )
- {
- static_cast<StreamingTerrainNode*>(_terrain)->updateTaskServiceThreads( *_update_mapf );
- }
-
- updateTextureCombining();
- }
-
- // install a layer callback for processing further map actions:
- map->addMapCallback( new QuadTreeTerrainEngineNodeMapCallbackProxy(this) );
-
- //Attach to all of the existing elevation layers
- ElevationLayerVector elevationLayers;
- map->getElevationLayers( elevationLayers );
- for( ElevationLayerVector::const_iterator i = elevationLayers.begin(); i != elevationLayers.end(); ++i )
- {
- i->get()->addCallback( _elevationCallback.get() );
- }
-
- //Attach a callback to all of the
-
- // register me.
- registerEngine( this );
-
- // now that we have a map, set up to recompute the bounds
- dirtyBound();
-}
-
-osg::BoundingSphere
-QuadTreeTerrainEngineNode::computeBound() const
-{
- if ( _terrain && _terrain->getNumChildren() > 0 )
- {
- return _terrain->getBound();
- }
- else
- {
- return TerrainEngineNode::computeBound();
- }
-}
-
-void
-QuadTreeTerrainEngineNode::refresh()
-{
- {
- removeChild( _terrain );
- }
-
-
- _terrain = new TerrainNode(*_update_mapf, *_cull_mapf, _tileFactory.get(), *_terrainOptions.quickReleaseGLObjects() );
- installTerrainTechnique();
-
-
- const MapInfo& mapInfo = _update_mapf->getMapInfo();
- _keyNodeFactory = new SerialKeyNodeFactory( _tileBuilder.get(), _terrainOptions, mapInfo, _terrain, _uid );
-
- // Build the first level of the terrain.
- // Collect the tile keys comprising the root tiles of the terrain.
- std::vector< TileKey > keys;
- _update_mapf->getProfile()->getRootKeys( keys );
-
- if (_terrainOptions.enableBlending().value())
- {
- _terrain->getOrCreateStateSet()->setMode(GL_BLEND , osg::StateAttribute::ON);
- }
-
- addChild( _terrain );
-
- for( unsigned i=0; i<keys.size(); ++i )
- {
- osg::Node* node;
- if ( _keyNodeFactory.valid() )
- node = _keyNodeFactory->createRootNode( keys[i] );
- else
- node = _tileFactory->createSubTiles( *_update_mapf, _terrain, keys[i], true );
-
- if ( node )
- _terrain->addChild( node );
- else
- OE_WARN << LC << "Couldn't make tile for root key: " << keys[i].str() << std::endl;
- }
-
- updateTextureCombining();
-}
-
-void
-QuadTreeTerrainEngineNode::onMapInfoEstablished( const MapInfo& mapInfo )
-{
- LoadingPolicy::Mode mode = *_terrainOptions.loadingPolicy()->mode();
- OE_INFO << LC << "Loading policy mode = " <<
- ( mode == LoadingPolicy::MODE_PREEMPTIVE ? "PREEMPTIVE" :
- mode == LoadingPolicy::MODE_SEQUENTIAL ? "SEQUENTIAL" :
- mode == LoadingPolicy::MODE_PARALLEL ? "PARALLEL" :
- "SERIAL/STANDARD" )
- << std::endl;
-
- // create a factory for creating actual tile data
- _tileFactory = new OSGTileFactory( _uid, *_cull_mapf, _terrainOptions );
-
- // go through and build the root nodesets.
- if ( !_isStreaming )
- {
- _terrain = new TerrainNode(
- *_update_mapf, *_cull_mapf, _tileFactory.get(), *_terrainOptions.quickReleaseGLObjects() );
- }
- else
- {
- _terrain = new StreamingTerrainNode(
- *_update_mapf, *_cull_mapf, _tileFactory.get(), *_terrainOptions.quickReleaseGLObjects() );
- }
-
- this->addChild( _terrain );
-
- // set the initial properties from the options structure:
- _terrain->setVerticalScale( _terrainOptions.verticalScale().value() );
- _terrain->setSampleRatio ( _terrainOptions.heightFieldSampleRatio().value() );
-
- if (_terrainOptions.enableBlending().value())
- {
- _terrain->getOrCreateStateSet()->setMode(GL_BLEND , osg::StateAttribute::ON);
- }
-
- OE_INFO << LC << "Sample ratio = " << _terrainOptions.heightFieldSampleRatio().value() << std::endl;
-
- // install the proper layer composition technique:
-
- installTerrainTechnique();
-
- // install the shader program, if applicable:
- installShaders();
-
- // calculate a good thread pool size for non-streaming parallel processing
- if ( !_isStreaming )
- {
- unsigned num = 2 * OpenThreads::GetNumberOfProcessors();
- if ( _terrainOptions.loadingPolicy().isSet() )
- {
- if ( _terrainOptions.loadingPolicy()->numLoadingThreads().isSet() )
- {
- num = *_terrainOptions.loadingPolicy()->numLoadingThreads();
- }
- else if ( _terrainOptions.loadingPolicy()->numLoadingThreadsPerCore().isSet() )
- {
- num = (unsigned)(*_terrainOptions.loadingPolicy()->numLoadingThreadsPerCore() * OpenThreads::GetNumberOfProcessors());
- }
- }
-
- if ( mode == LoadingPolicy::MODE_PARALLEL )
- {
- _tileService = new TaskService( "TileBuilder", num );
- }
-
- // initialize the tile builder
- _tileBuilder = new TileBuilder( getMap(), _terrainOptions, _tileService.get() );
-
-
- // initialize a key node factory.
- switch( mode )
- {
- case LoadingPolicy::MODE_SERIAL:
- _keyNodeFactory = new SerialKeyNodeFactory( _tileBuilder.get(), _terrainOptions, mapInfo, _terrain, _uid );
- break;
-
- case LoadingPolicy::MODE_PARALLEL:
- _keyNodeFactory = new ParallelKeyNodeFactory( _tileBuilder.get(), _terrainOptions, mapInfo, _terrain, _uid );
- break;
-
- default:
- break;
- }
- }
-
- // Build the first level of the terrain.
- // Collect the tile keys comprising the root tiles of the terrain.
- std::vector< TileKey > keys;
- _update_mapf->getProfile()->getRootKeys( keys );
-
- for( unsigned i=0; i<keys.size(); ++i )
- {
- osg::Node* node;
- if ( _keyNodeFactory.valid() )
- node = _keyNodeFactory->createRootNode( keys[i] );
- else
- node = _tileFactory->createSubTiles( *_update_mapf, _terrain, keys[i], true );
-
- if ( node )
- _terrain->addChild( node );
- else
- OE_WARN << LC << "Couldn't make tile for root key: " << keys[i].str() << std::endl;
- }
-
- // we just added the root tiles, so mark the bound in need of recomputation.
- dirtyBound();
-}
-
-osg::Node*
-QuadTreeTerrainEngineNode::createNode( const TileKey& key )
-{
- // if the engine has been disconnected from the scene graph, bail out and don't
- // create any more tiles
- if ( getNumParents() == 0 )
- return 0L;
-
- OE_DEBUG << LC << "Create node for \"" << key.str() << "\"" << std::endl;
-
-#ifdef PROFILING
- osg::Timer_t start = _timer.tick();
-#endif
-
- osg::Node* result = 0L;
-
- osg::ref_ptr< TerrainNode > terrain = _terrain;
-
- osg::ref_ptr< KeyNodeFactory > keyNodeFactory = _keyNodeFactory;
-
- if ( _isStreaming )
- {
- // sequential or preemptive mode only.
- // create a map frame so we can safely create tiles from this dbpager thread
- MapFrame mapf( getMap(), Map::TERRAIN_LAYERS, "dbpager::earth plugin" );
- result = getTileFactory()->createSubTiles( mapf, terrain.get(), key, false );
- }
- else
- {
- if (keyNodeFactory.valid() && terrain.valid())
- {
- result = keyNodeFactory->createNode( key );
- }
- }
-
-#ifdef PROFILING
- osg::Timer_t end = osg::Timer::instance()->tick();
- if ( result )
- {
- _tileCount++;
- _tileCreationTime += _timer.delta_s(start,_timer.tick());
- if ( _tileCount % 60 == 0 )
- {
- OE_INFO << LC << "Avg tile = " << 1000.0*(_tileCreationTime/(double)_tileCount)
- << " ms, tiles per sec = " << (double)_tileCount/_timer.time_s() << std::endl;
- }
- }
-#endif
-
- return result;
-}
-
-osg::Node*
-QuadTreeTerrainEngineNode::createTile( const TileKey& key )
-{
- if ( !_tileBuilder.valid() )
- return 0L;
-
- osg::ref_ptr<Tile> tile;
- bool hasRealData, hasLodBlendedLayers;
-
- _tileBuilder->createTile(
- key,
- false,
- tile,
- hasRealData,
- hasLodBlendedLayers );
-
- if ( !tile.valid() )
- return 0L;
-
- // code block required in order to properly manage the ref count of the transform
- SinglePassTerrainTechnique* tech = new SinglePassTerrainTechnique( _texCompositor.get() );
- // prepare the interpolation technique for generating triangles:
- if ( getMap()->getMapOptions().elevationInterpolation() == INTERP_TRIANGULATE )
- tech->setOptimizeTriangleOrientation( false );
-
- tile->setTerrainTechnique( tech );
- tile->init();
-
- return tech->takeTransform();
-}
-
-void
-QuadTreeTerrainEngineNode::onMapModelChanged( const MapModelChange& change )
-{
- _update_mapf->sync();
-
- // dispatch the change handler
- if ( change.getLayer() )
- {
- // first inform the texture compositor with the new model changes:
- if ( _texCompositor.valid() && change.getImageLayer() )
- {
- _texCompositor->applyMapModelChange( change );
- }
-
- // then apply the actual change:
- switch( change.getAction() )
- {
- case MapModelChange::ADD_IMAGE_LAYER:
- addImageLayer( change.getImageLayer() );
- break;
- case MapModelChange::REMOVE_IMAGE_LAYER:
- removeImageLayer( change.getImageLayer() );
- break;
- case MapModelChange::ADD_ELEVATION_LAYER:
- addElevationLayer( change.getElevationLayer() );
- break;
- case MapModelChange::REMOVE_ELEVATION_LAYER:
- removeElevationLayer( change.getElevationLayer() );
- break;
- case MapModelChange::MOVE_IMAGE_LAYER:
- moveImageLayer( change.getFirstIndex(), change.getSecondIndex() );
- break;
- case MapModelChange::MOVE_ELEVATION_LAYER:
- moveElevationLayer( change.getFirstIndex(), change.getSecondIndex() );
- break;
- case MapModelChange::ADD_MODEL_LAYER:
- case MapModelChange::REMOVE_MODEL_LAYER:
- case MapModelChange::MOVE_MODEL_LAYER:
- default: break;
- }
- }
-
- // update the terrain revision in threaded mode
- if ( _isStreaming )
- {
- //getTerrain()->incrementRevision();
- static_cast<StreamingTerrainNode*>(_terrain)->updateTaskServiceThreads( *_update_mapf );
- }
-}
-
-void
-QuadTreeTerrainEngineNode::addImageLayer( ImageLayer* layerAdded )
-{
- if ( !layerAdded )
- return;
-
- if (!_isStreaming)
- {
- refresh();
- }
- else
- {
- // visit all existing terrain tiles and inform each one of the new image layer:
- TileVector tiles;
- _terrain->getTiles( tiles );
-
- for( TileVector::iterator itr = tiles.begin(); itr != tiles.end(); ++itr )
- {
- Tile* tile = itr->get();
-
- StreamingTile* streamingTile = 0L;
-
- GeoImage geoImage;
- bool needToUpdateImagery = false;
- int imageLOD = -1;
-
- if ( !_isStreaming || tile->getKey().getLevelOfDetail() == 1 )
- {
- // in standard mode, or at the first LOD in seq/pre mode, fetch the image immediately.
- TileKey geoImageKey = tile->getKey();
- _tileFactory->createValidGeoImage( layerAdded, tile->getKey(), geoImage, geoImageKey );
- imageLOD = tile->getKey().getLevelOfDetail();
- }
- else
- {
- // in seq/pre mode, set up a placeholder and mark the tile as dirty.
- geoImage = GeoImage(ImageUtils::createEmptyImage(), tile->getKey().getExtent() );
- needToUpdateImagery = true;
- streamingTile = static_cast<StreamingTile*>(tile);
- }
-
- if (geoImage.valid())
- {
- const MapInfo& mapInfo = _update_mapf->getMapInfo();
-
- double img_min_lon, img_min_lat, img_max_lon, img_max_lat;
- geoImage.getExtent().getBounds(img_min_lon, img_min_lat, img_max_lon, img_max_lat);
-
- //Specify a new locator for the color with the coordinates of the TileKey that was actually used to create the image
- osg::ref_ptr<GeoLocator> img_locator = tile->getKey().getProfile()->getSRS()->createLocator(
- img_min_lon, img_min_lat, img_max_lon, img_max_lat,
- !mapInfo.isGeocentric() );
-
- //Set the CS to geocentric if we are dealing with a geocentric map
- if ( mapInfo.isGeocentric() )
- {
- img_locator->setCoordinateSystemType( osgTerrain::Locator::GEOCENTRIC );
- }
-
- tile->setCustomColorLayer( CustomColorLayer(
- layerAdded,
- geoImage.getImage(),
- img_locator.get(), imageLOD, tile->getKey() ) );
-
- // if necessary, tell the tile to queue up a new imagery request (since we
- // just installed a placeholder)
- if ( needToUpdateImagery )
- {
- streamingTile->updateImagery( layerAdded, *_update_mapf, _tileFactory.get() );
- }
- }
- else
- {
- // this can happen if there's no data in the new layer for the given tile.
- // we will rely on the driver to dump out a warning if this is an error.
- }
-
- tile->applyImmediateTileUpdate( TileUpdate::ADD_IMAGE_LAYER, layerAdded->getUID() );
- }
-
- updateTextureCombining();
- }
-}
-
-void
-QuadTreeTerrainEngineNode::removeImageLayer( ImageLayer* layerRemoved )
-{
- if (!_isStreaming)
- {
- refresh();
- }
- else
- {
- // make a thread-safe copy of the tile table
- TileVector tiles;
- _terrain->getTiles( tiles );
-
- for (TileVector::iterator itr = tiles.begin(); itr != tiles.end(); ++itr)
- {
- Tile* tile = itr->get();
-
- // critical section
- tile->removeCustomColorLayer( layerRemoved->getUID() );
- }
-
- updateTextureCombining();
- }
-}
-
-void
-QuadTreeTerrainEngineNode::moveImageLayer( unsigned int oldIndex, unsigned int newIndex )
-{
- // take a thread-safe copy of the tile table
- TileVector tiles;
- _terrain->getTiles( tiles );
-
- for (TileVector::iterator itr = tiles.begin(); itr != tiles.end(); ++itr)
- {
- Tile* tile = itr->get();
- tile->applyImmediateTileUpdate( TileUpdate::MOVE_IMAGE_LAYER );
- }
-
- updateTextureCombining();
-}
-
-void
-QuadTreeTerrainEngineNode::updateElevation( Tile* tile )
-{
- Threading::ScopedWriteLock exclusiveLock( tile->getTileLayersMutex() );
-
- const TileKey& key = tile->getKey();
-
- bool hasElevation = _update_mapf->elevationLayers().size() > 0;
-
- osgTerrain::HeightFieldLayer* heightFieldLayer = dynamic_cast<osgTerrain::HeightFieldLayer*>(tile->getElevationLayer());
- if (heightFieldLayer)
- {
- // In standard mode, just load the elevation data and dirty the tile.
- if ( !_isStreaming )
- {
- osg::ref_ptr<osg::HeightField> hf;
-
- if (hasElevation)
- _update_mapf->getHeightField( key, true, hf, 0L);
-
- if (!hf.valid())
- hf = OSGTileFactory::createEmptyHeightField( key );
-
- heightFieldLayer->setHeightField( hf.get() );
- hf->setSkirtHeight( tile->getBound().radius() * _terrainOptions.heightFieldSkirtRatio().value() );
-
- //TODO: review this in favor of a tile update...
- tile->setDirty( true );
- }
-
- else // if ( isStreaming )
- {
- StreamingTile* stile = static_cast<StreamingTile*>(tile);
-
- //Update the elevation hint
- stile->setHasElevationHint( hasElevation );
-
- //In seq/pre mode, if there is no elevation, just clear out all the elevation on the tiles
- if ( !hasElevation )
- {
- osg::ref_ptr<osg::HeightField> hf = OSGTileFactory::createEmptyHeightField( key );
- heightFieldLayer->setHeightField( hf.get() );
- hf->setSkirtHeight( stile->getBound().radius() * _terrainOptions.heightFieldSkirtRatio().value() );
- stile->setElevationLOD( key.getLevelOfDetail() );
- stile->resetElevationRequests( *_update_mapf );
- stile->queueTileUpdate( TileUpdate::UPDATE_ELEVATION );
- }
- else
- {
- //Always load the first LOD so the children tiles can have something to use for placeholders
- if (stile->getKey().getLevelOfDetail() == 1)
- {
- osg::ref_ptr<osg::HeightField> hf;
- _update_mapf->getHeightField( key, true, hf, 0L);
- if (!hf.valid())
- hf = OSGTileFactory::createEmptyHeightField( key );
- heightFieldLayer->setHeightField( hf.get() );
- hf->setSkirtHeight( stile->getBound().radius() * _terrainOptions.heightFieldSkirtRatio().value() );
- stile->setElevationLOD(tile->getKey().getLevelOfDetail());
- stile->queueTileUpdate( TileUpdate::UPDATE_ELEVATION );
- }
- else
- {
- //Set the elevation LOD to -1
- stile->setElevationLOD(-1);
- stile->resetElevationRequests( *_update_mapf );
- }
- }
- }
- }
-}
-
-
-void
-QuadTreeTerrainEngineNode::addElevationLayer( ElevationLayer* layer )
-{
- if ( !layer )
- return;
-
- layer->addCallback( _elevationCallback.get() );
-
-
- if (!_isStreaming)
- {
- refresh();
- }
- else
- {
- TileVector tiles;
- _terrain->getTiles( tiles );
-
- OE_DEBUG << LC << "Found " << tiles.size() << std::endl;
-
- for (TileVector::iterator itr = tiles.begin(); itr != tiles.end(); ++itr)
- {
- updateElevation( itr->get() );
- }
- }
-}
-
-void
-QuadTreeTerrainEngineNode::removeElevationLayer( ElevationLayer* layerRemoved )
-{
- layerRemoved->removeCallback( _elevationCallback.get() );
-
- if (!_isStreaming)
- {
- refresh();
- }
- else
- {
- TileVector tiles;
- _terrain->getTiles( tiles );
-
- for (TileVector::iterator itr = tiles.begin(); itr != tiles.end(); ++itr)
- {
- updateElevation( itr->get() );
- }
- }
-}
-
-void
-QuadTreeTerrainEngineNode::moveElevationLayer( unsigned int oldIndex, unsigned int newIndex )
-{
- if (!_isStreaming)
- {
- refresh();
- }
- else
- {
- TileVector tiles;
- _terrain->getTiles( tiles );
-
- OE_DEBUG << "Found " << tiles.size() << std::endl;
-
- for (TileVector::iterator itr = tiles.begin(); itr != tiles.end(); ++itr)
- {
- updateElevation( itr->get() );
- }
- }
-}
-
-void
-QuadTreeTerrainEngineNode::validateTerrainOptions( TerrainOptions& options )
-{
- TerrainEngineNode::validateTerrainOptions( options );
-
- //nop for now.
- //note: to validate plugin-specific features, we would create an OSGTerrainOptions
- // and do the validation on that. You would then re-integrate it by calling
- // options.mergeConfig( osgTerrainOptions ).
-}
-
-void
-QuadTreeTerrainEngineNode::traverse( osg::NodeVisitor& nv )
-{
- if ( _cull_mapf ) // ensures initialize() has been called
- {
- if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR )
- {
- // update the cull-thread map frame if necessary. (We don't need to sync the
- // update_mapf becuase that happens in response to a map callback.)
-
- // TODO: address the fact that this can happen from multiple threads.
- // Really we need a _cull_mapf PER view. -gw
- _cull_mapf->sync();
- }
- }
-
- TerrainEngineNode::traverse( nv );
-}
-
-void
-QuadTreeTerrainEngineNode::installShaders()
-{
- // This method installs a default shader setup on the engine node itself. The texture compositor
- // can then override parts of the program by using a VirtualProgram on the _terrain node. We do
- // it this way so that the developer has the option of removing this top-level shader program,
- // replacing it, or migrating it higher up the scene graph if necessary.
-
- if ( _texCompositor.valid() && _texCompositor->usesShaderComposition() )
- {
- const ShaderFactory* sf = Registry::instance()->getShaderFactory();
-
- int numLayers = osg::maximum( 1, (int)_update_mapf->imageLayers().size() );
-
- VirtualProgram* vp = new VirtualProgram();
-
- // note. this stuff should probably happen automatically in VirtualProgram. gw
-
- //vp->setShader( "osgearth_vert_main", sf->createVertexShaderMain() ); // happens in VirtualProgram now
- vp->setShader( "osgearth_vert_setupLighting", sf->createDefaultLightingVertexShader() );
- vp->setShader( "osgearth_vert_setupTexturing", sf->createDefaultTextureVertexShader( numLayers ) );
-
- //vp->setShader( "osgearth_frag_main", sf->createFragmentShaderMain() ); // happend in VirtualProgram now
- vp->setShader( "osgearth_frag_applyLighting", sf->createDefaultLightingFragmentShader() );
- vp->setShader( "osgearth_frag_applyTexturing", sf->createDefaultTextureFragmentShader( numLayers ) );
-
- getOrCreateStateSet()->setAttributeAndModes( vp, osg::StateAttribute::ON );
- }
-}
-
-void
-QuadTreeTerrainEngineNode::updateTextureCombining()
-{
- if ( _texCompositor.valid() )
- {
- int numImageLayers = _update_mapf->imageLayers().size();
- osg::StateSet* terrainStateSet = _terrain->getOrCreateStateSet();
-
- if ( _texCompositor->usesShaderComposition() )
- {
- // Creates or updates the shader components that are generated by the texture compositor.
- // These components reside in the CustomTerrain's stateset, and override the components
- // installed in the VP on the engine-node's stateset in installShaders().
-
- VirtualProgram* vp = new VirtualProgram();
- terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
-
-#if 0
- VirtualProgram* vp = dynamic_cast<VirtualProgram*>( terrainStateSet->getAttribute(osg::StateAttribute::PROGRAM) );
- if ( !vp )
- {
- // create and add it the first time around..
- vp = new VirtualProgram();
- terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
- }
-#endif
-
-
- // first, update the default shader components based on the new layer count:
- const ShaderFactory* sf = Registry::instance()->getShaderFactory();
- vp->setShader( "osgearth_vert_setupTexturing", sf->createDefaultTextureVertexShader( numImageLayers ) );
-
- // second, install the per-layer color filter functions.
- for( int i=0; i<numImageLayers; ++i )
- {
- std::string layerFilterFunc = Stringify() << "osgearth_runColorFilters_" << i;
- const ColorFilterChain& chain = _update_mapf->getImageLayerAt(i)->getColorFilters();
-
- // install the wrapper function that calls all the filters in turn:
- vp->setShader( layerFilterFunc, sf->createColorFilterChainFragmentShader(layerFilterFunc, chain) );
-
- // install each of the filter entry points:
- for( ColorFilterChain::const_iterator j = chain.begin(); j != chain.end(); ++j )
- {
- const ColorFilter* filter = j->get();
- filter->install( terrainStateSet );
- }
- }
-
- // not this one, because the compositor always generates a new one.
- //vp->setShader( "osgearth_frag_applyTexturing", lib.createDefaultTextureFragmentShader( numImageLayers ) );
- }
-
- // next, inform the compositor that it needs to update based on a new layer count:
- _texCompositor->updateMasterStateSet( terrainStateSet ); //, numImageLayers );
- }
-}
-
-namespace
-{
- class UpdateElevationVisitor : public osg::NodeVisitor
- {
- public:
- UpdateElevationVisitor():
- osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
- {}
-
- void apply(osg::Node& node)
- {
- Tile* tile = dynamic_cast<Tile*>(&node);
- if (tile)
- {
- tile->applyImmediateTileUpdate(TileUpdate::UPDATE_ELEVATION);
- }
-
- traverse(node);
- }
- };
-}
-
-void
-QuadTreeTerrainEngineNode::onVerticalScaleChanged()
-{
- _terrain->setVerticalScale(getVerticalScale());
-
- UpdateElevationVisitor visitor;
- this->accept(visitor);
-}
-
-void
-QuadTreeTerrainEngineNode::installTerrainTechnique()
-{
- if ( _texCompositor->getTechnique() == TerrainOptions::COMPOSITING_MULTIPASS )
- {
- _terrain->setTechniquePrototype( new MultiPassTerrainTechnique( _texCompositor.get() ) );
- OE_INFO << LC << "Compositing technique = MULTIPASS" << std::endl;
- }
-
- else
- {
- SinglePassTerrainTechnique* tech = new SinglePassTerrainTechnique( _texCompositor.get() );
- tech->setClearDataAfterCompile( !_isStreaming );
-
-
- if ( getMap()->getMapOptions().elevationInterpolation() == INTERP_TRIANGULATE )
- tech->setOptimizeTriangleOrientation( false );
-
- _terrain->setTechniquePrototype( tech );
- }
-}
diff --git a/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineOptions b/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineOptions
deleted file mode 100644
index cb31acf..0000000
--- a/src/osgEarthDrivers/engine_quadtree/QuadTreeEngineOptions
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*-c++-*- */
-/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
- * Copyright 2008-2012 Pelican Mapping
- * http://osgearth.org
- *
- * osgEarth is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- */
-#ifndef OSGEARTH_ENGINE_QUADTREE_OPTIONS
-#define OSGEARTH_ENGINE_QUADTREE_OPTIONS 1
-
-#include <osgEarth/Common>
-#include <osgEarth/TerrainOptions>
-
-namespace osgEarth { namespace Drivers
-{
- using namespace osgEarth;
-
- class QuadTreeTerrainEngineOptions : public TerrainOptions // NO EXPORT (header-only)
- {
- public:
- QuadTreeTerrainEngineOptions( const ConfigOptions& options =ConfigOptions() ) : TerrainOptions( options ),
- _skirtRatio ( 0.05 ),
- _quickRelease( true ),
- _lodFallOff ( 0.0 )
- {
- setDriver( "quadtree" );
- fromConfig( _conf );
- }
-
- /** dtor */
- virtual ~OSGTerrainOptions() { }
-
- public:
- optional<float>& heightFieldSkirtRatio() { return _skirtRatio; }
- const optional<float>& heightFieldSkirtRatio() const { return _skirtRatio; }
-
- optional<bool>& quickReleaseGLObjects() { return _quickRelease; }
- const optional<bool>& quickReleaseGLObjects() const { return _quickRelease; }
-
- optional<float>& lodFallOff() { return _lodFallOff; }
- const optional<float>& lodFallOff() const { return _lodFallOff; }
-
- optional<osg::Node::NodeMask>& surfaceNodeMask() { return _surfaceNodeMask;}
- const optional<osg::Node::NodeMask>& surfaceNodeMask() const { return _surfaceNodeMask;}
-
- optional<osg::Node::NodeMask>& skirtNodeMask() { return _skirtNodeMask;}
- const optional<osg::Node::NodeMask>& skirtNodeMask() const { return _skirtNodeMask;}
-
-
- protected:
- virtual Config getConfig() const {
- Config conf = TerrainOptions::getConfig();
- conf.updateIfSet( "skirt_ratio", _skirtRatio );
- conf.updateIfSet( "quick_release_gl_objects", _quickRelease );
- conf.updateIfSet( "lod_fall_off", _lodFallOff );
- conf.updateIfSet( "surface_node_mask", _surfaceNodeMask);
- conf.updateIfSet( "skirt_node_mask", _skirtNodeMask);
- return conf;
- }
-
- virtual void mergeConfig( const Config& conf ) {
- TerrainOptions::mergeConfig( conf );
- fromConfig( conf );
- }
-
- private:
- void fromConfig( const Config& conf ) {
- conf.getIfSet( "skirt_ratio", _skirtRatio );
- conf.getIfSet( "quick_release_gl_objects", _quickRelease );
- conf.getIfSet( "lod_fall_off", _lodFallOff );
- conf.getIfSet( "surface_node_mask", _surfaceNodeMask);
- conf.getIfSet( "skirt_node_mask", _skirtNodeMask);
- }
-
- optional<float> _skirtRatio;
- optional<bool> _quickRelease;
- optional<float> _lodFallOff;
- optional<osg::Node::NodeMask> _surfaceNodeMask;
- optional<osg::Node::NodeMask> _skirtNodeMask;
- };
-
-} } // namespace osgEarth::Drivers
-
-#endif // OSGEARTH_ENGINE_QUADTREE_OPTIONS
diff --git a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineDriver.cpp b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineDriver.cpp
index d7a169f..a4143e9 100644
--- a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineDriver.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineDriver.cpp
@@ -27,6 +27,7 @@
#define LC "[engine_quadtree driver] "
using namespace osgEarth::Drivers;
+using namespace osgEarth_engine_quadtree;
/**
* osgEarth driver for the QuadTree terrain engine.
@@ -36,10 +37,10 @@ using namespace osgEarth::Drivers;
* - integrate support for LOD Blending (access to parent state set)
* - consider TileNodeCompiler cacheing of TexCoord arrays and other tile-shareable data
*/
-class QuadTreeTerrainEngineDriver : public osgDB::ReaderWriter
+class osgEarth_QuadTreeTerrainEngineDriver : public osgDB::ReaderWriter
{
public:
- QuadTreeTerrainEngineDriver() {}
+ osgEarth_QuadTreeTerrainEngineDriver() {}
virtual const char* className()
{
@@ -145,4 +146,4 @@ public:
}
};
-REGISTER_OSGPLUGIN(osgearth_engine_quadtree, QuadTreeTerrainEngineDriver)
+REGISTER_OSGPLUGIN(osgearth_engine_quadtree, osgEarth_QuadTreeTerrainEngineDriver)
diff --git a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode
index 69accdf..4a5b50c 100644
--- a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode
+++ b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode
@@ -37,100 +37,106 @@
using namespace osgEarth;
-class QuadTreeTerrainEngineNode : public TerrainEngineNode
+namespace osgEarth_engine_quadtree
{
-public:
- QuadTreeTerrainEngineNode();
- META_Node(osgEarth,QuadTreeTerrainEngineNode);
- virtual ~QuadTreeTerrainEngineNode();
+ class QuadTreeTerrainEngineNode : public TerrainEngineNode
+ {
+ public:
+ QuadTreeTerrainEngineNode();
+ META_Node(osgEarth,QuadTreeTerrainEngineNode);
+ virtual ~QuadTreeTerrainEngineNode();
-public:
- osg::Node* createNode(const TileKey& key);
+ public:
+ osg::Node* createNode(const TileKey& key);
-public: // TerrainEngineNode
+ public: // TerrainEngineNode
- // for standalone tile creation outside of a terrain
- osg::Node* createTile(const TileKey& key);
+ // for standalone tile creation outside of a terrain
+ osg::Node* createTile(const TileKey& key);
-public: // internal TerrainEngineNode
+ public: // internal TerrainEngineNode
- virtual void preInitialize( const Map* map, const TerrainOptions& options );
- virtual void postInitialize( const Map* map, const TerrainOptions& options );
- virtual void validateTerrainOptions( TerrainOptions& options );
- virtual const TerrainOptions& getTerrainOptions() const { return _terrainOptions; }
- virtual osg::BoundingSphere computeBound() const;
+ virtual void preInitialize( const Map* map, const TerrainOptions& options );
+ virtual void postInitialize( const Map* map, const TerrainOptions& options );
+ virtual void validateTerrainOptions( TerrainOptions& options );
+ virtual const TerrainOptions& getTerrainOptions() const { return _terrainOptions; }
+ virtual osg::BoundingSphere computeBound() const;
-public: // MapCallback adapter functions
- void onMapInfoEstablished( const MapInfo& mapInfo ); // not virtual!
- void onMapModelChanged( const MapModelChange& change ); // not virtual!
+ public: // MapCallback adapter functions
+ void onMapInfoEstablished( const MapInfo& mapInfo ); // not virtual!
+ void onMapModelChanged( const MapModelChange& change ); // not virtual!
- UID getUID() const;
+ UID getUID() const;
-public: // statics
- static void registerEngine( QuadTreeTerrainEngineNode* engineNode );
- static void unregisterEngine( UID uid );
- static void getEngineByUID( UID uid, osg::ref_ptr<QuadTreeTerrainEngineNode>& output );
+ public: // statics
+ static void registerEngine( QuadTreeTerrainEngineNode* engineNode );
+ static void unregisterEngine( UID uid );
+ static void getEngineByUID( UID uid, osg::ref_ptr<QuadTreeTerrainEngineNode>& output );
-public:
- class ElevationChangedCallback : public ElevationLayerCallback
- {
public:
- ElevationChangedCallback( QuadTreeTerrainEngineNode* terrain );
+ class ElevationChangedCallback : public ElevationLayerCallback
+ {
+ public:
+ ElevationChangedCallback( QuadTreeTerrainEngineNode* terrain );
- virtual void onVisibleChanged( TerrainLayer* layer );
+ virtual void onVisibleChanged( TerrainLayer* layer );
- QuadTreeTerrainEngineNode* _terrain;
- friend class QuadTreeTerrainEngineNode;
- };
+ QuadTreeTerrainEngineNode* _terrain;
+ friend class QuadTreeTerrainEngineNode;
+ };
+
+ protected:
+ virtual void onVerticalScaleChanged();
-protected:
- virtual void onVerticalScaleChanged();
+ private:
+ void init();
+ void syncMapModel();
-private:
- void init();
- void syncMapModel();
+ // Reloads all the tiles in the terrain due to a data model change
+ void refresh();
- // Reloads all the tiles in the terrain due to a data model change
- void refresh();
+ void addImageLayer( ImageLayer* layer );
+ void addElevationLayer( ElevationLayer* layer );
- void addImageLayer( ImageLayer* layer );
- void addElevationLayer( ElevationLayer* layer );
+ void removeImageLayer( ImageLayer* layerRemoved );
+ void removeElevationLayer( ElevationLayer* layerRemoved );
- void removeImageLayer( ImageLayer* layerRemoved );
- void removeElevationLayer( ElevationLayer* layerRemoved );
+ void moveImageLayer( unsigned int oldIndex, unsigned int newIndex );
+ void moveElevationLayer( unsigned int oldIndex, unsigned int newIndex );
+
+ //void updateElevation( TileNode* tile );
+ void installShaders();
+ void updateTextureCombining();
- void moveImageLayer( unsigned int oldIndex, unsigned int newIndex );
- void moveElevationLayer( unsigned int oldIndex, unsigned int newIndex );
-
- //void updateElevation( TileNode* tile );
- void installShaders();
- void updateTextureCombining();
+ private:
+ osgEarth::Drivers::QuadTreeTerrainEngineOptions _terrainOptions;
-private:
- osgEarth::Drivers::QuadTreeTerrainEngineOptions _terrainOptions;
+ class TerrainNode* _terrain;
+ UID _uid;
+ Revision _shaderLibRev;
- class TerrainNode* _terrain;
- UID _uid;
- Revision _shaderLibRev;
+ osg::ref_ptr< ElevationChangedCallback > _elevationCallback;
- osg::ref_ptr< ElevationChangedCallback > _elevationCallback;
+ MapFrame* _update_mapf; // map frame for the main/update traversal thread
- MapFrame* _update_mapf; // map frame for the main/update traversal thread
+ // node registry is shared across all threads.
+ osg::ref_ptr<TileNodeRegistry> _liveTiles; // tiles in the scene graph.
+ osg::ref_ptr<TileNodeRegistry> _deadTiles; // tiles that used to be in the scene graph.
- // node registry is shared across all threads.
- osg::ref_ptr<TileNodeRegistry> _liveTiles; // tiles in the scene graph.
- osg::ref_ptr<TileNodeRegistry> _deadTiles; // tiles that used to be in the scene graph.
+ Threading::PerThread< osg::ref_ptr<KeyNodeFactory> > _perThreadKeyNodeFactories;
+ KeyNodeFactory* getKeyNodeFactory();
- Threading::PerThread< osg::ref_ptr<KeyNodeFactory> > _perThreadKeyNodeFactories;
- KeyNodeFactory* getKeyNodeFactory();
+ osg::Timer _timer;
+ unsigned _tileCount;
+ double _tileCreationTime;
- osg::Timer _timer;
- unsigned _tileCount;
- double _tileCreationTime;
+ osg::Uniform* _verticalScaleUniform;
- osg::Uniform* _verticalScaleUniform;
+ osg::ref_ptr< TileModelFactory > _tileModelFactory;
+
+ QuadTreeTerrainEngineNode( const QuadTreeTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) { }
+ };
- QuadTreeTerrainEngineNode( const QuadTreeTerrainEngineNode& rhs, const osg::CopyOp& op =osg::CopyOp::DEEP_COPY_ALL ) { }
-};
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_ENGINE_NODE_H
diff --git a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode.cpp b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode.cpp
index 8b63731..fa55151 100644
--- a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineNode.cpp
@@ -25,7 +25,9 @@
#include <osgEarth/HeightFieldUtils>
#include <osgEarth/ImageUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
+#include <osgEarth/ShaderFactory>
+#include <osgEarth/MapModelChange>
#include <osg/TexEnv>
#include <osg/TexEnvCombine>
@@ -34,6 +36,7 @@
#define LC "[QuadTreeTerrainEngineNode] "
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
//------------------------------------------------------------------------
@@ -174,6 +177,10 @@ QuadTreeTerrainEngineNode::postInitialize( const Map* map, const TerrainOptions&
{
_deadTiles = new TileNodeRegistry("dead");
}
+
+ // initialize the model factory:
+ _tileModelFactory = new TileModelFactory(getMap(), _liveTiles.get(), _terrainOptions );
+
// handle an already-established map profile:
if ( _update_mapf->getProfile() )
@@ -204,6 +211,8 @@ QuadTreeTerrainEngineNode::postInitialize( const Map* map, const TerrainOptions&
// now that we have a map, set up to recompute the bounds
dirtyBound();
+
+
}
@@ -224,6 +233,13 @@ QuadTreeTerrainEngineNode::computeBound() const
void
QuadTreeTerrainEngineNode::refresh()
{
+
+ //Clear out the hf cache
+ if (_tileModelFactory)
+ {
+ _tileModelFactory->getHeightFieldCache()->clear();
+ }
+
// rebuilds the terrain graph entirely.
this->removeChild( _terrain );
@@ -311,12 +327,7 @@ QuadTreeTerrainEngineNode::getKeyNodeFactory()
// create a compiler for compiling tile models into geometry
bool optimizeTriangleOrientation =
getMap()->getMapOptions().elevationInterpolation() != INTERP_TRIANGULATE;
-
- // initialize the model builder:
- TileModelFactory* factory = new TileModelFactory(
- getMap(),
- _liveTiles.get(),
- _terrainOptions );
+
// A compiler specific to this thread:
TileModelCompiler* compiler = new TileModelCompiler(
@@ -327,7 +338,7 @@ QuadTreeTerrainEngineNode::getKeyNodeFactory()
// initialize a key node factory.
knf = new SerialKeyNodeFactory(
- factory,
+ _tileModelFactory.get(),
compiler,
_liveTiles.get(),
_deadTiles.get(),
diff --git a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineOptions b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineOptions
index ff00379..37b25a4 100644
--- a/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineOptions
+++ b/src/osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineOptions
@@ -32,7 +32,8 @@ namespace osgEarth { namespace Drivers
QuadTreeTerrainEngineOptions( const ConfigOptions& options =ConfigOptions() ) : TerrainOptions( options ),
_skirtRatio ( 0.05 ),
_quickRelease( true ),
- _lodFallOff ( 0.0 )
+ _lodFallOff ( 0.0 ),
+ _normalizeEdges( false )
{
setDriver( "quadtree" );
fromConfig( _conf );
@@ -51,6 +52,9 @@ namespace osgEarth { namespace Drivers
optional<float>& lodFallOff() { return _lodFallOff; }
const optional<float>& lodFallOff() const { return _lodFallOff; }
+ optional<bool>& normalizeEdges() { return _normalizeEdges; }
+ const optional<bool>& normalizeEdges() const { return _normalizeEdges; }
+
protected:
virtual Config getConfig() const {
@@ -58,6 +62,7 @@ namespace osgEarth { namespace Drivers
conf.updateIfSet( "skirt_ratio", _skirtRatio );
conf.updateIfSet( "quick_release_gl_objects", _quickRelease );
conf.updateIfSet( "lod_fall_off", _lodFallOff );
+ conf.updateIfSet( "normalize_edges", _normalizeEdges);
return conf;
}
@@ -71,11 +76,13 @@ namespace osgEarth { namespace Drivers
conf.getIfSet( "skirt_ratio", _skirtRatio );
conf.getIfSet( "quick_release_gl_objects", _quickRelease );
conf.getIfSet( "lod_fall_off", _lodFallOff );
+ conf.getIfSet( "normalize_edges", _normalizeEdges );
}
optional<float> _skirtRatio;
optional<bool> _quickRelease;
optional<float> _lodFallOff;
+ optional<bool> _normalizeEdges;
};
} } // namespace osgEarth::Drivers
diff --git a/src/osgEarthDrivers/engine_quadtree/QuickReleaseGLObjects b/src/osgEarthDrivers/engine_quadtree/QuickReleaseGLObjects
index dc58340..9a32417 100644
--- a/src/osgEarthDrivers/engine_quadtree/QuickReleaseGLObjects
+++ b/src/osgEarthDrivers/engine_quadtree/QuickReleaseGLObjects
@@ -23,7 +23,7 @@
#include "TileNodeRegistry"
#include <osg/Camera>
-namespace
+namespace osgEarth_engine_quadtree
{
/**
* A draw callback to calls another, nested draw callback.
@@ -85,6 +85,7 @@ namespace
osg::ref_ptr<TileNodeRegistry> _tilesToRelease;
};
-}
+
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_QUICK_RELEASE_GL_OBJECTS
diff --git a/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory b/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory
index 88a3f93..954c602 100644
--- a/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory
+++ b/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory
@@ -24,46 +24,51 @@
#include "TerrainNode"
#include "TileModelFactory"
#include "TileNodeRegistry"
+#include <osgEarth/MapInfo>
using namespace osgEarth;
using namespace osgEarth::Drivers;
-class SerialKeyNodeFactory : public KeyNodeFactory
+namespace osgEarth_engine_quadtree
{
-public:
- SerialKeyNodeFactory(
- TileModelFactory* modelFactory,
- TileModelCompiler* modelCompiler,
- TileNodeRegistry* liveTiles,
- TileNodeRegistry* deadTiles,
- const QuadTreeTerrainEngineOptions& options,
- const MapInfo& mapInfo,
- TerrainNode* terrain,
- UID engineUID );
+ class SerialKeyNodeFactory : public KeyNodeFactory
+ {
+ public:
+ SerialKeyNodeFactory(
+ TileModelFactory* modelFactory,
+ TileModelCompiler* modelCompiler,
+ TileNodeRegistry* liveTiles,
+ TileNodeRegistry* deadTiles,
+ const QuadTreeTerrainEngineOptions& options,
+ const MapInfo& mapInfo,
+ TerrainNode* terrain,
+ UID engineUID );
- /** dtor */
- virtual ~SerialKeyNodeFactory() { }
+ /** dtor */
+ virtual ~SerialKeyNodeFactory() { }
-public: // KeyNodeFactory
+ public: // KeyNodeFactory
- osg::Node* createRootNode( const TileKey& key );
+ osg::Node* createRootNode( const TileKey& key );
- osg::Node* createNode( const TileKey& key );
+ osg::Node* createNode( const TileKey& key );
- TileModelCompiler* getCompiler() const { return _modelCompiler.get(); }
+ TileModelCompiler* getCompiler() const { return _modelCompiler.get(); }
-protected:
- void addTile(TileModel* model, bool tileHasRealData, bool tileHasLodBlending, osg::Group* parent );
+ protected:
+ void addTile(TileModel* model, bool tileHasRealData, bool tileHasLodBlending, osg::Group* parent );
- osg::ref_ptr<TileModelFactory> _modelFactory;
- osg::ref_ptr<TileModelCompiler> _modelCompiler;
- osg::ref_ptr<TileNodeRegistry> _liveTiles;
- osg::ref_ptr<TileNodeRegistry> _deadTiles;
- const QuadTreeTerrainEngineOptions& _options;
- const MapInfo _mapInfo;
- osg::ref_ptr< TerrainNode > _terrain;
- UID _engineUID;
-};
+ osg::ref_ptr<TileModelFactory> _modelFactory;
+ osg::ref_ptr<TileModelCompiler> _modelCompiler;
+ osg::ref_ptr<TileNodeRegistry> _liveTiles;
+ osg::ref_ptr<TileNodeRegistry> _deadTiles;
+ const QuadTreeTerrainEngineOptions& _options;
+ const MapInfo _mapInfo;
+ osg::ref_ptr< TerrainNode > _terrain;
+ UID _engineUID;
+ };
+
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_SERIAL_KEY_NODE_FACTORY
diff --git a/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory.cpp b/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory.cpp
index a760491..082705b 100644
--- a/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/SerialKeyNodeFactory.cpp
@@ -30,6 +30,7 @@
#include <osgEarth/MapNode>
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
using namespace OpenThreads;
@@ -126,7 +127,7 @@ SerialKeyNodeFactory::addTile(TileModel* model, bool tileHasRealData, bool tileH
{
// Make the LOD transition distance, and a measure of how
// close the tile is to an LOD change, to shaders.
- result->addCullCallback(new Drivers::LODFactorCallback);
+ result->addCullCallback(new LODFactorCallback);
}
}
else
diff --git a/src/osgEarthDrivers/engine_quadtree/TerrainNode b/src/osgEarthDrivers/engine_quadtree/TerrainNode
index 15fafa4..b9243ce 100644
--- a/src/osgEarthDrivers/engine_quadtree/TerrainNode
+++ b/src/osgEarthDrivers/engine_quadtree/TerrainNode
@@ -22,35 +22,39 @@
#include "Common"
#include "TileNodeRegistry"
-class TileFactory;
-
-using namespace osgEarth;
-using namespace osgEarth::Drivers;
-
-/**
- * Parent node for the TileNode quadtree hierarchy.
- */
-class TerrainNode : public osg::Group
+namespace osgEarth_engine_quadtree
{
-public:
+ class TileFactory;
+
+ using namespace osgEarth;
+ using namespace osgEarth::Drivers;
/**
- * Constructs a new terrain node.
- * @param[in ] deadTiles If non-NULL, the terrain node will active GL object
- * quick-release and use this registry to track dead tiles.
+ * Parent node for the TileNode quadtree hierarchy.
*/
- TerrainNode( TileNodeRegistry* deadTiles );
+ class TerrainNode : public osg::Group
+ {
+ public:
+
+ /**
+ * Constructs a new terrain node.
+ * @param[in ] deadTiles If non-NULL, the terrain node will active GL object
+ * quick-release and use this registry to track dead tiles.
+ */
+ TerrainNode( TileNodeRegistry* deadTiles );
+
+ public: // osg::Node
-public: // osg::Node
+ virtual void traverse( osg::NodeVisitor &nv );
- virtual void traverse( osg::NodeVisitor &nv );
+ protected:
-protected:
+ virtual ~TerrainNode() { }
- virtual ~TerrainNode() { }
+ osg::ref_ptr<TileNodeRegistry> _tilesToQuickRelease;
+ bool _quickReleaseCallbackInstalled;
+ };
- osg::ref_ptr<TileNodeRegistry> _tilesToQuickRelease;
- bool _quickReleaseCallbackInstalled;
-};
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_TERRAIN_NODE
diff --git a/src/osgEarthDrivers/engine_quadtree/TerrainNode.cpp b/src/osgEarthDrivers/engine_quadtree/TerrainNode.cpp
index 1edcb97..143c200 100644
--- a/src/osgEarthDrivers/engine_quadtree/TerrainNode.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/TerrainNode.cpp
@@ -29,6 +29,7 @@
#include <osg/Node>
#include <osgGA/EventVisitor>
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_quadtree/TileModel b/src/osgEarthDrivers/engine_quadtree/TileModel
index 56f68f0..cc093bc 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileModel
+++ b/src/osgEarthDrivers/engine_quadtree/TileModel
@@ -30,131 +30,165 @@
#include <osg/StateSet>
#include <map>
-using namespace osgEarth;
-
-
-class TileModel : public osg::Referenced
+namespace osgEarth_engine_quadtree
{
-public:
- class ElevationData
- {
- public:
- ElevationData() { }
- virtual ~ElevationData() { }
- ElevationData( osgTerrain::HeightFieldLayer* hfLayer, bool fallbackData =false )
- : _hfLayer(hfLayer), _fallbackData(fallbackData) { }
-
- osgTerrain::HeightFieldLayer* getHFLayer() const { return _hfLayer.get(); }
- bool isFallbackData() const { return _fallbackData; }
-
- private:
- osg::ref_ptr<osgTerrain::HeightFieldLayer> _hfLayer;
- bool _fallbackData;
- };
+ using namespace osgEarth;
-
- class ColorData
+ class TileModel : public osg::Referenced
{
public:
- ColorData() { }
-
- /** dtor */
- virtual ~ColorData() { }
-
- ColorData(
- const osgEarth::ImageLayer* imageLayer,
- osg::Image* image,
- const osgTerrain::Locator* locator,
- int lod,
- const osgEarth::TileKey& tileKey,
- bool fallbackData =false )
- : _layer(imageLayer), _locator(locator), _image(image), _tileKey(tileKey), _lod(lod), _fallbackData(fallbackData) { }
-
- ColorData( const ColorData& rhs ) :
- _layer( rhs._layer.get() ),
- _locator( rhs._locator.get() ),
- _image( rhs._image.get() ),
- _tileKey( rhs._tileKey ),
- _lod( rhs._lod ),
- _fallbackData( rhs._fallbackData ) { }
-
- osgEarth::UID getUID() const {
- return _layer->getUID();
- }
+ // do not change the order of these.
+ enum Neighbor
+ {
+ NORTHWEST = 0,
+ NORTH = 1,
+ NORTHEAST = 2,
+ WEST = 3,
+ EAST = 4,
+ SOUTHWEST = 5,
+ SOUTH = 6,
+ SOUTHEAST = 7
+ };
+
+ class ElevationData
+ {
+ public:
+ ElevationData() { }
+ virtual ~ElevationData() { }
+ ElevationData( osgTerrain::HeightFieldLayer* hfLayer, bool fallbackData =false )
+ : _hfLayer(hfLayer), _fallbackData(fallbackData) { }
+
+ osgTerrain::HeightFieldLayer* getHFLayer() const { return _hfLayer.get(); }
+ bool isFallbackData() const { return _fallbackData; }
+
+ osg::HeightField* getNeighbor(int xoffset, int yoffset) const
+ {
+ int index = getNeighborIndex(xoffset, yoffset);
+ return _neighbors[index];
+ }
- const osgTerrain::Locator* getLocator() const {
- return _locator.get();
- }
+ void setNeighbor(int xoffset, int yoffset, osg::HeightField* hf )
+ {
+ int index = getNeighborIndex(xoffset, yoffset);
+ _neighbors[index] = hf;
+ }
- osg::Image* getImage() const {
- return _image.get(); }
+ private:
+ static int getNeighborIndex(int xoffset, int yoffset)
+ {
+ int index = 3*(yoffset+1)+(xoffset+1);
+ if (index > 4) index--;
+ return index;
+ }
+ osg::ref_ptr<osgTerrain::HeightFieldLayer> _hfLayer;
+ bool _fallbackData;
+ osg::ref_ptr<osg::HeightField> _neighbors[8];
+ };
+
+
+ class ColorData
+ {
+ public:
+ ColorData() { }
+
+ /** dtor */
+ virtual ~ColorData() { }
+
+ ColorData(
+ const osgEarth::ImageLayer* imageLayer,
+ osg::Image* image,
+ const osgTerrain::Locator* locator,
+ int lod,
+ const osgEarth::TileKey& tileKey,
+ bool fallbackData =false )
+ : _layer(imageLayer), _locator(locator), _image(image), _tileKey(tileKey), _lod(lod), _fallbackData(fallbackData) { }
+
+ ColorData( const ColorData& rhs ) :
+ _layer( rhs._layer.get() ),
+ _locator( rhs._locator.get() ),
+ _image( rhs._image.get() ),
+ _tileKey( rhs._tileKey ),
+ _lod( rhs._lod ),
+ _fallbackData( rhs._fallbackData ) { }
+
+ osgEarth::UID getUID() const {
+ return _layer->getUID();
+ }
- const osgEarth::TileKey& getTileKey() const {
- return _tileKey; }
+ const osgTerrain::Locator* getLocator() const {
+ return _locator.get();
+ }
- const osgEarth::ImageLayer* getMapLayer() const {
- return _layer.get(); }
+ osg::Image* getImage() const {
+ return _image.get(); }
- int getLevelOfDetail() const {
- return _lod; }
+ const osgEarth::TileKey& getTileKey() const {
+ return _tileKey; }
- bool isFallbackData() const {
- return _fallbackData; }
+ const osgEarth::ImageLayer* getMapLayer() const {
+ return _layer.get(); }
- osg::BoundingSphere computeBound() const {
- osg::BoundingSphere bs;
- osg::Vec3d v;
- if (getLocator()->convertLocalToModel(osg::Vec3d(0.5,0.5,0.0), v)) {
- bs.center() = v;
- }
- if (getLocator()->convertLocalToModel(osg::Vec3d(0.0,0.0,0.0), v)) {
- bs.radius() = (bs.center() - v).length();
- }
- return bs;
- }
+ int getLevelOfDetail() const {
+ return _lod; }
+ bool isFallbackData() const {
+ return _fallbackData; }
- private:
- osg::ref_ptr<const osgEarth::ImageLayer> _layer;
- osg::ref_ptr<const osgTerrain::Locator> _locator;
- osg::ref_ptr<osg::Image> _image;
- osgEarth::TileKey _tileKey;
- int _lod;
- bool _fallbackData;
- };
+ osg::BoundingSphere computeBound() const {
+ osg::BoundingSphere bs;
+ osg::Vec3d v;
+ if (getLocator()->convertLocalToModel(osg::Vec3d(0.5,0.5,0.0), v)) {
+ bs.center() = v;
+ }
+ if (getLocator()->convertLocalToModel(osg::Vec3d(0.0,0.0,0.0), v)) {
+ bs.radius() = (bs.center() - v).length();
+ }
+ return bs;
+ }
- class ColorDataRef : public osg::Referenced
- {
- public:
- ColorDataRef( const ColorData& layer ) : _layer(layer) { }
- ColorData _layer;
- };
+ private:
+ osg::ref_ptr<const osgEarth::ImageLayer> _layer;
+ osg::ref_ptr<const osgTerrain::Locator> _locator;
+ osg::ref_ptr<osg::Image> _image;
+ osgEarth::TileKey _tileKey;
+ int _lod;
+ bool _fallbackData;
+ };
- typedef std::map<UID, ColorData> ColorDataByUID;
+ class ColorDataRef : public osg::Referenced
+ {
+ public:
+ ColorDataRef( const ColorData& layer ) : _layer(layer) { }
+ ColorData _layer;
+ };
-public:
- TileModel() { }
- virtual ~TileModel() { }
+ typedef std::map<UID, ColorData> ColorDataByUID;
- TileKey _tileKey;
- osg::ref_ptr<GeoLocator> _tileLocator;
- ColorDataByUID _colorData;
- ElevationData _elevationData;
- float _sampleRatio;
- osg::ref_ptr<osg::StateSet> _parentStateSet;
- // convenience funciton to pull out a layer by its UID.
- bool getColorData( UID layerUID, ColorData& out ) const {
- ColorDataByUID::const_iterator i = _colorData.find( layerUID );
- if ( i != _colorData.end() ) {
- out = i->second;
- return true;
+ public:
+ TileModel() { }
+ virtual ~TileModel() { }
+
+ TileKey _tileKey;
+ osg::ref_ptr<GeoLocator> _tileLocator;
+ ColorDataByUID _colorData;
+ ElevationData _elevationData;
+ float _sampleRatio;
+ osg::ref_ptr<osg::StateSet> _parentStateSet;
+
+ // convenience funciton to pull out a layer by its UID.
+ bool getColorData( UID layerUID, ColorData& out ) const {
+ ColorDataByUID::const_iterator i = _colorData.find( layerUID );
+ if ( i != _colorData.end() ) {
+ out = i->second;
+ return true;
+ }
+ return false;
}
- return false;
- }
-};
+ };
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_TILE_MODEL
diff --git a/src/osgEarthDrivers/engine_quadtree/TileModelCompiler b/src/osgEarthDrivers/engine_quadtree/TileModelCompiler
index 293946c..ba5b1ef 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileModelCompiler
+++ b/src/osgEarthDrivers/engine_quadtree/TileModelCompiler
@@ -33,68 +33,72 @@
#include <osg/Drawable>
#include <osg/Array>
-using namespace osgEarth;
-using namespace osgEarth::Drivers;
-
-/**
- * Cache used by the TileModelCompiler. This lets us share common data across
- * compilations. Since the compiler is thread-locked, we just have a separate
- * cache per compiler.
- *
- * Important Note! Any array you store in the cache MUST have it's OWN
- * unique VBO. Call array->setVertexBufferObject( new osg::VertexBufferObject() )
- * to assign one. This will prevent non-thread-safe buffer object sharing.
- */
-struct CompilerCache
+namespace osgEarth_engine_quadtree
{
- // Texture coordinate array cache def
- struct TexCoordTableKey {
- osg::ref_ptr<const GeoLocator> _locator;
- osg::Vec4d _mat;
- unsigned _cols, _rows;
- };
- typedef std::pair< TexCoordTableKey, osg::ref_ptr<osg::Vec2Array> > LocatorTexCoordPair;
- struct TexCoordArrayCache : public std::list<LocatorTexCoordPair> {
- osg::ref_ptr<osg::Vec2Array>& get( const osg::Vec4d& mat, unsigned cols, unsigned rows );
- };
+ using namespace osgEarth;
+ using namespace osgEarth::Drivers;
- TexCoordArrayCache _surfaceTexCoordArrays;
- TexCoordArrayCache _skirtTexCoordArrays;
-};
+ /**
+ * Cache used by the TileModelCompiler. This lets us share common data across
+ * compilations. Since the compiler is thread-locked, we just have a separate
+ * cache per compiler.
+ *
+ * Important Note! Any array you store in the cache MUST have it's OWN
+ * unique VBO. Call array->setVertexBufferObject( new osg::VertexBufferObject() )
+ * to assign one. This will prevent non-thread-safe buffer object sharing.
+ */
+ struct CompilerCache
+ {
+ // Texture coordinate array cache def
+ struct TexCoordTableKey {
+ osg::ref_ptr<const GeoLocator> _locator;
+ osg::Vec4d _mat;
+ unsigned _cols, _rows;
+ };
+ typedef std::pair< TexCoordTableKey, osg::ref_ptr<osg::Vec2Array> > LocatorTexCoordPair;
+ struct TexCoordArrayCache : public std::list<LocatorTexCoordPair> {
+ osg::ref_ptr<osg::Vec2Array>& get( const osg::Vec4d& mat, unsigned cols, unsigned rows );
+ };
+ TexCoordArrayCache _surfaceTexCoordArrays;
+ TexCoordArrayCache _skirtTexCoordArrays;
+ };
-/**
- * Builds the actual tile geometry.
- *
- * When used with the KeyNodeFactory, there will be exactly one instance of this
- * class per thread. So, we can expand this to include caches for commonly shared
- * data like texture coordinate or color arrays.
- */
-class TileModelCompiler : public osg::Referenced
-{
-public:
- TileModelCompiler(
- const MaskLayerVector& masks,
- TextureCompositor* compositor,
- bool optimizeTriangleOrientation,
- const QuadTreeTerrainEngineOptions& options);
/**
- * Compiles a tile model into an OSG scene graph. The scene graph will
- * include a MatrixTransform to localize the tile data.
+ * Builds the actual tile geometry.
+ *
+ * When used with the KeyNodeFactory, there will be exactly one instance of this
+ * class per thread. So, we can expand this to include caches for commonly shared
+ * data like texture coordinate or color arrays.
*/
- bool compile(
- const TileModel* model,
- osg::Node*& out_node,
- osg::StateSet*& out_stateSet );
+ class TileModelCompiler : public osg::Referenced
+ {
+ public:
+ TileModelCompiler(
+ const MaskLayerVector& masks,
+ TextureCompositor* compositor,
+ bool optimizeTriangleOrientation,
+ const QuadTreeTerrainEngineOptions& options);
+
+ /**
+ * Compiles a tile model into an OSG scene graph. The scene graph will
+ * include a MatrixTransform to localize the tile data.
+ */
+ bool compile(
+ const TileModel* model,
+ osg::Node*& out_node,
+ osg::StateSet*& out_stateSet );
+
+ protected:
+ const MaskLayerVector& _masks;
+ osg::ref_ptr<TextureCompositor> _texCompositor;
+ bool _optimizeTriOrientation;
+ const QuadTreeTerrainEngineOptions& _options;
+ osg::ref_ptr<osg::Drawable::CullCallback> _cullByTraversalMask;
+ CompilerCache _cache;
+ };
-protected:
- const MaskLayerVector& _masks;
- osg::ref_ptr<TextureCompositor> _texCompositor;
- bool _optimizeTriOrientation;
- const QuadTreeTerrainEngineOptions& _options;
- osg::ref_ptr<osg::Drawable::CullCallback> _cullByTraversalMask;
- CompilerCache _cache;
-};
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_TILE_MODEL_COMPILER
diff --git a/src/osgEarthDrivers/engine_quadtree/TileModelCompiler.cpp b/src/osgEarthDrivers/engine_quadtree/TileModelCompiler.cpp
index 9b90d64..86221d4 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileModelCompiler.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/TileModelCompiler.cpp
@@ -28,6 +28,7 @@
#include <osg/MatrixTransform>
#include <osgUtil/DelaunayTriangulator>
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
using namespace osgEarth::Drivers;
using namespace osgEarth::Symbology;
@@ -1192,7 +1193,7 @@ namespace
* Builds triangles for the surface geometry, and recalculates the surface normals
* to be optimized for slope.
*/
- void tessellateSurfaceGeometry( Data& d, bool optimizeTriangleOrientation )
+ void tessellateSurfaceGeometry( Data& d, bool optimizeTriangleOrientation, bool normalizeEdges )
{
bool swapOrientation = !(d.model->_tileLocator->orientationOpenGL());
bool recalcNormals = d.model->_elevationData.getHFLayer() != 0L;
@@ -1249,7 +1250,7 @@ namespace
if (i00>=0) ++numValid;
if (i01>=0) ++numValid;
if (i10>=0) ++numValid;
- if (i11>=0) ++numValid;
+ if (i11>=0) ++numValid;
if (numValid==4)
{
@@ -1331,13 +1332,358 @@ namespace
}
}
- // Finally, normalize the normals.
- if ( recalcNormals )
+
+ if (recalcNormals && normalizeEdges)
+ {
+ OE_DEBUG << "Normalizing edges" << std::endl;
+ //Compute the edge normals if we have neighbor data
+ //Get all the neighbors
+ osg::ref_ptr< osg::HeightField > w_neighbor = d.model->_elevationData.getNeighbor( -1, 0 );
+ osg::ref_ptr< osg::HeightField > e_neighbor = d.model->_elevationData.getNeighbor( 1, 0 );
+ osg::ref_ptr< osg::HeightField > s_neighbor = d.model->_elevationData.getNeighbor( 0, 1 );
+ osg::ref_ptr< osg::HeightField > n_neighbor = d.model->_elevationData.getNeighbor( 0, -1 );
+
+ //Recalculate the west side
+ if (w_neighbor.valid() && w_neighbor->getNumColumns() == d.numCols && w_neighbor->getNumRows() == d.numRows)
+ {
+ osg::ref_ptr< osg::Vec3Array > boundaryVerts = new osg::Vec3Array();
+ boundaryVerts->reserve( 2 * d.numRows );
+
+ std::vector< float > boundaryElevations;
+ boundaryElevations.reserve( 2 * d.numRows );
+
+ //Compute the verts for the west side
+ for (int j = 0; j < (int)d.numRows; j++)
+ {
+ for (int i = (int)d.numCols-2; i <= (int)d.numCols-1; i++)
+ {
+ osg::Vec3d ndc( (double)(i - static_cast<int>(d.numCols-1))/(double)(d.numCols-1), ((double)j)/(double)(d.numRows-1), 0.0);
+
+ //TODO: Should probably use an interpolated method here
+ float heightValue = w_neighbor->getHeight( i, j );
+ ndc.z() = heightValue;
+
+ osg::Vec3d model;
+ d.model->_tileLocator->unitToModel( ndc, model );
+ osg::Vec3d v = model - d.centerModel;
+ boundaryVerts->push_back( v );
+ boundaryElevations.push_back( heightValue );
+ }
+ }
+
+ //The boundary verts are now populated, so go through and triangulate them add add the normals to the existing normal array
+ for (int j = 0; j < (int)d.numRows-1; j++)
+ {
+ int i00;
+ int i01;
+ int i = 0;
+ if (swapOrientation)
+ {
+ i01 = j*d.numCols + i;
+ i00 = i01+d.numCols;
+ }
+ else
+ {
+ i00 = j*d.numCols + i;
+ i01 = i00+d.numCols;
+ }
+
+
+
+ //remap indices to final vertex position
+ i00 = d.indices[i00];
+ i01 = d.indices[i01];
+
+ int baseIndex = 2 * j;
+ osg::Vec3f& v00 = (*boundaryVerts)[baseIndex ];
+ osg::Vec3f& v10 = (*boundaryVerts)[baseIndex + 1];
+ osg::Vec3f& v01 = (*boundaryVerts)[baseIndex + 2];
+ osg::Vec3f& v11 = (*boundaryVerts)[baseIndex + 3];
+
+ float e00 = boundaryElevations[baseIndex];
+ float e10 = boundaryElevations[baseIndex + 1];
+ float e01 = boundaryElevations[baseIndex + 2];
+ float e11 = boundaryElevations[baseIndex + 3];
+
+
+ if (!optimizeTriangleOrientation || (e00-e11)<fabsf(e01-e10))
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v11-v01);
+ (*d.normals)[i01] += normal1;
+
+ osg::Vec3 normal2 = (v10-v00) ^ (v11-v00);
+ (*d.normals)[i00] += normal2;
+ (*d.normals)[i01] += normal2;
+ }
+ else
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v10-v01);
+ (*d.normals)[i00] += normal1;
+
+ osg::Vec3 normal2 = (v10-v01) ^ (v11-v01);
+ (*d.normals)[i00] += normal2;
+ (*d.normals)[i01] += normal2;
+ }
+ }
+ }
+
+
+ //Recalculate the east side
+ if (e_neighbor.valid() && e_neighbor->getNumColumns() == d.numCols && e_neighbor->getNumRows() == d.numRows)
+ {
+ osg::ref_ptr< osg::Vec3Array > boundaryVerts = new osg::Vec3Array();
+ boundaryVerts->reserve( 2 * d.numRows );
+
+ std::vector< float > boundaryElevations;
+ boundaryElevations.reserve( 2 * d.numRows );
+
+ //Compute the verts for the east side
+ for (int j = 0; j < (int)d.numRows; j++)
+ {
+ for (int i = 0; i <= 1; i++)
+ {
+ osg::Vec3d ndc( ((double)(d.numCols -1 + i))/(double)(d.numCols-1), ((double)j)/(double)(d.numRows-1), 0.0);
+
+ //TODO: Should probably use an interpolated method here
+ float heightValue = e_neighbor->getHeight( i, j );
+ ndc.z() = heightValue;
+
+ osg::Vec3d model;
+ d.model->_tileLocator->unitToModel( ndc, model );
+ osg::Vec3d v = model - d.centerModel;
+ boundaryVerts->push_back( v );
+ boundaryElevations.push_back( heightValue );
+ }
+ }
+
+ //The boundary verts are now populated, so go through and triangulate them add add the normals to the existing normal array
+ for (int j = 0; j < (int)d.numRows-1; j++)
+ {
+ int i00;
+ int i01;
+ int i = d.numCols-1;
+ if (swapOrientation)
+ {
+ i01 = j*d.numCols + i;
+ i00 = i01+d.numCols;
+ }
+ else
+ {
+ i00 = j*d.numCols + i;
+ i01 = i00+d.numCols;
+ }
+
+ //remap indices to final vertex position
+ i00 = d.indices[i00];
+ i01 = d.indices[i01];
+
+ int baseIndex = 2 * j;
+ osg::Vec3f& v00 = (*boundaryVerts)[baseIndex ];
+ osg::Vec3f& v10 = (*boundaryVerts)[baseIndex + 1];
+ osg::Vec3f& v01 = (*boundaryVerts)[baseIndex + 2];
+ osg::Vec3f& v11 = (*boundaryVerts)[baseIndex + 3];
+
+ float e00 = boundaryElevations[baseIndex];
+ float e10 = boundaryElevations[baseIndex + 1];
+ float e01 = boundaryElevations[baseIndex + 2];
+ float e11 = boundaryElevations[baseIndex + 3];
+
+
+ if (!optimizeTriangleOrientation || (e00-e11)<fabsf(e01-e10))
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v11-v01);
+ (*d.normals)[i00] += normal1;
+ (*d.normals)[i01] += normal1;
+
+ osg::Vec3 normal2 = (v10-v00) ^ (v11-v00);
+ (*d.normals)[i00] += normal2;
+ }
+ else
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v10-v01);
+ (*d.normals)[i00] += normal1;
+ (*d.normals)[i01] += normal1;
+
+ osg::Vec3 normal2 = (v10-v01) ^ (v11-v01);
+ (*d.normals)[i01] += normal2;
+ }
+ }
+ }
+
+ //Recalculate the north side
+ if (n_neighbor.valid() && n_neighbor->getNumColumns() == d.numCols && n_neighbor->getNumRows() == d.numRows)
+ {
+ osg::ref_ptr< osg::Vec3Array > boundaryVerts = new osg::Vec3Array();
+ boundaryVerts->reserve( 2 * d.numCols );
+
+ std::vector< float > boundaryElevations;
+ boundaryElevations.reserve( 2 * d.numCols );
+
+ //Compute the verts for the north side
+ for (int j = 0; j <= 1; j++)
+ {
+ for (int i = 0; i < (int)d.numCols; i++)
+ {
+ osg::Vec3d ndc( (double)(i)/(double)(d.numCols-1), (double)(d.numRows -1 + j)/(double)(d.numRows-1), 0.0);
+ //osg::Vec3d ndc( (double)(i)/(double)(d.numCols-1), (double)(-static_cast<int>(j))/(double)(d.numRows-1), 0.0);
+
+ //TODO: Should probably use an interpolated method here
+ float heightValue = n_neighbor->getHeight( i, j );
+ ndc.z() = heightValue;
+
+ osg::Vec3d model;
+ d.model->_tileLocator->unitToModel( ndc, model );
+ osg::Vec3d v = model - d.centerModel;
+ boundaryVerts->push_back( v );
+ boundaryElevations.push_back( heightValue );
+ }
+ }
+
+ //The boundary verts are now populated, so go through and triangulate them add add the normals to the existing normal array
+ for (int i = 0; i < (int)d.numCols-1; i++)
+ {
+ int i00;
+ int j = d.numRows-1;
+ if (swapOrientation)
+ {
+ int i01 = j * d.numCols + i;
+ i00 = i01+d.numCols;
+ }
+ else
+ {
+ i00 = j*d.numCols + i;
+ }
+
+ int i10 = i00+1;
+
+ //remap indices to final vertex position
+ i00 = d.indices[i00];
+ i10 = d.indices[i10];
+
+ int baseIndex = i;
+ osg::Vec3f& v00 = (*boundaryVerts)[baseIndex ];
+ osg::Vec3f& v10 = (*boundaryVerts)[baseIndex + 1];
+ osg::Vec3f& v01 = (*boundaryVerts)[baseIndex + d.numCols];
+ osg::Vec3f& v11 = (*boundaryVerts)[baseIndex + d.numCols + 1];
+
+ float e00 = boundaryElevations[baseIndex];
+ float e10 = boundaryElevations[baseIndex + 1];
+ float e01 = boundaryElevations[baseIndex + d.numCols];
+ float e11 = boundaryElevations[baseIndex + d.numCols + 1];
+
+
+ if (!optimizeTriangleOrientation || (e00-e11)<fabsf(e01-e10))
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v11-v01);
+ (*d.normals)[i00] += normal1;
+ (*d.normals)[i10] += normal1;
+
+ osg::Vec3 normal2 = (v10-v00) ^ (v11-v00);
+ (*d.normals)[i10] += normal2;
+ }
+ else
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v10-v01);
+ (*d.normals)[i00] += normal1;
+
+ osg::Vec3 normal2 = (v10-v01) ^ (v11-v01);
+ (*d.normals)[i00] += normal2;
+ (*d.normals)[i10] += normal2;
+ }
+ }
+ }
+
+ //Recalculate the south side
+ if (s_neighbor.valid() && s_neighbor->getNumColumns() == d.numCols && s_neighbor->getNumRows() == d.numRows)
+ {
+ osg::ref_ptr< osg::Vec3Array > boundaryVerts = new osg::Vec3Array();
+ boundaryVerts->reserve( 2 * d.numCols );
+
+ std::vector< float > boundaryElevations;
+ boundaryElevations.reserve( 2 * d.numCols );
+
+ //Compute the verts for the south side
+ for (int j = (int)d.numRows-2; j <= (int)d.numRows-1; j++)
+ {
+ for (int i = 0; i < (int)d.numCols; i++)
+ {
+ osg::Vec3d ndc( (double)(i)/(double)(d.numCols-1), (double)(j - static_cast<int>(d.numRows-1))/(double)(d.numRows-1), 0.0);
+
+ //TODO: Should probably use an interpolated method here
+ float heightValue = s_neighbor->getHeight( i, j );
+ ndc.z() = heightValue;
+
+ osg::Vec3d model;
+ d.model->_tileLocator->unitToModel( ndc, model );
+ osg::Vec3d v = model - d.centerModel;
+ boundaryVerts->push_back( v );
+ boundaryElevations.push_back( heightValue );
+ }
+ }
+
+ //The boundary verts are now populated, so go through and triangulate them add add the normals to the existing normal array
+ for (int i = 0; i < (int)d.numCols-1; i++)
+ {
+ int i00;
+ int j = 0;
+
+
+ if (swapOrientation)
+ {
+ int i01 = j*d.numCols + i;
+ i00 = i01+d.numCols;
+ }
+ else
+ {
+ i00 = j*d.numCols + i;
+ }
+
+ int i10 = i00+1;
+
+ //remap indices to final vertex position
+ i00 = d.indices[i00];
+ i10 = d.indices[i10];
+
+ int baseIndex = i;
+ osg::Vec3f& v00 = (*boundaryVerts)[baseIndex ];
+ osg::Vec3f& v10 = (*boundaryVerts)[baseIndex + 1];
+ osg::Vec3f& v01 = (*boundaryVerts)[baseIndex + d.numCols];
+ osg::Vec3f& v11 = (*boundaryVerts)[baseIndex + d.numCols + 1];
+
+ float e00 = boundaryElevations[baseIndex];
+ float e10 = boundaryElevations[baseIndex + 1];
+ float e01 = boundaryElevations[baseIndex + d.numCols];
+ float e11 = boundaryElevations[baseIndex + d.numCols + 1];
+
+
+ if (!optimizeTriangleOrientation || (e00-e11)<fabsf(e01-e10))
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v11-v01);
+ (*d.normals)[i00] += normal1;
+
+ osg::Vec3 normal2 = (v10-v00) ^ (v11-v00);
+ (*d.normals)[i00] += normal2;
+ (*d.normals)[i10] += normal2;
+ }
+ else
+ {
+ osg::Vec3 normal1 = (v00-v01) ^ (v10-v01);
+ (*d.normals)[i00] += normal1;
+ (*d.normals)[i10] += normal1;
+
+ osg::Vec3 normal2 = (v10-v01) ^ (v11-v01);
+ (*d.normals)[i10] += normal2;
+ }
+ }
+ }
+ }
+
+ if (recalcNormals)
{
for( osg::Vec3Array::iterator nitr = d.normals->begin(); nitr != d.normals->end(); ++nitr )
{
nitr->normalize();
- }
+ }
}
}
@@ -1497,7 +1843,7 @@ TileModelCompiler::compile(const TileModel* model,
createSkirtGeometry( d, _texCompositor.get(), *_options.heightFieldSkirtRatio() );
// tesselate the surface verts into triangles.
- tessellateSurfaceGeometry( d, _optimizeTriOrientation );
+ tessellateSurfaceGeometry( d, _optimizeTriOrientation, *_options.normalizeEdges() );
// assign our texture coordinate arrays to the geometry. This must happen LAST
// since we're sharing arrays across tiles. Here is why:
diff --git a/src/osgEarthDrivers/engine_quadtree/TileModelFactory b/src/osgEarthDrivers/engine_quadtree/TileModelFactory
index 39439e7..6dbe44c 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileModelFactory
+++ b/src/osgEarthDrivers/engine_quadtree/TileModelFactory
@@ -25,39 +25,142 @@
#include "QuadTreeTerrainEngineOptions"
#include <osgEarth/Map>
#include <osgEarth/ThreadingUtils>
+#include <osgEarth/Containers>
+#include <osgEarth/HeightFieldUtils>
+#include <osgEarth/MapFrame>
+#include <osgEarth/MapInfo>
#include <osg/Group>
-using namespace osgEarth;
-
-/**
- * For a given TileKey, this class builds a a corresponding TileNode from
- * the map's data model.
- *
- * TODO: This should probably change to TileModelFactory or something since
- * the creation of the TileNode itself is trivial and can be done outside of
- * this class.
- */
-class TileModelFactory : public osg::Referenced
+namespace osgEarth_engine_quadtree
{
-public:
- TileModelFactory(
- const Map* map,
- TileNodeRegistry* liveTiles,
- const Drivers::QuadTreeTerrainEngineOptions& terrainOptions );
-
- /** dtor */
- virtual ~TileModelFactory() { }
-
- void createTileModel(
- const TileKey& key,
- osg::ref_ptr<TileModel>& out_model,
- bool& out_hasRealData,
- bool& out_hasLodBlendedLayers );
-
-private:
- const Map* _map;
- osg::ref_ptr<TileNodeRegistry> _liveTiles;
- const Drivers::QuadTreeTerrainEngineOptions& _terrainOptions;
-};
+ using namespace osgEarth;
+
+ struct HFKey {
+ TileKey _key;
+ bool _fallback;
+ bool _convertToHAE;
+ ElevationSamplePolicy _samplePolicy;
+ bool operator < (const HFKey& rhs) const {
+ if ( _key < rhs._key ) return true;
+ if ( rhs._key < _key ) return false;
+ if ( _fallback != rhs._fallback ) return true;
+ if ( _convertToHAE != rhs._convertToHAE ) return true;
+ return _samplePolicy < rhs._samplePolicy;
+ }
+ };
+
+ struct HFValue {
+ osg::ref_ptr<osg::HeightField> _hf;
+ bool _isFallback;
+ };
+
+ class HeightFieldCache : public osg::Referenced, public Revisioned
+ {
+ public:
+ HeightFieldCache():
+ _cache ( true, 128 )
+ {
+
+ }
+
+ bool getOrCreateHeightField(
+ const MapFrame& frame,
+ const TileKey& key,
+ bool fallback,
+ osg::ref_ptr<osg::HeightField>& out_hf,
+ bool* out_isFallback =0L,
+ bool convertToHAE =true,
+ ElevationSamplePolicy samplePolicy =SAMPLE_FIRST_VALID,
+ ProgressCallback* progress =0L ) const
+ {
+ // check the quick cache.
+ HFKey cachekey;
+ cachekey._key = key;
+ cachekey._fallback = fallback;
+ cachekey._convertToHAE = convertToHAE;
+ cachekey._samplePolicy = samplePolicy;
+ LRUCache<HFKey,HFValue>::Record rec = _cache.get( cachekey );
+
+ bool hit = false;
+ if ( rec.valid() )
+ {
+ out_hf = rec.value()._hf.get();
+ if ( out_isFallback )
+ *out_isFallback = rec.value()._isFallback;
+ return true;
+ }
+
+ bool isFallback;
+
+ bool ok = frame.getHeightField( key, fallback, out_hf, &isFallback, convertToHAE, samplePolicy, progress );
+
+ if ( ok )
+ {
+ // Treat Plate Carre specially by scaling the height values. (There is no need
+ // to do this with an empty heightfield)
+ const MapInfo& mapInfo = frame.getMapInfo();
+ if ( mapInfo.isPlateCarre() )
+ {
+ HeightFieldUtils::scaleHeightFieldToDegrees( out_hf.get() );
+ }
+
+ if ( out_isFallback )
+ *out_isFallback = isFallback;
+
+ // cache me
+ HFValue cacheval;
+ cacheval._hf = out_hf.get();
+ cacheval._isFallback = isFallback;
+ _cache.insert( cachekey, cacheval );
+ }
+
+ return ok;
+ }
+
+ void clear()
+ {
+ _cache.clear();
+ }
+
+ private:
+ mutable LRUCache<HFKey,HFValue> _cache;
+ };
+
+ /**
+ * For a given TileKey, this class builds a a corresponding TileNode from
+ * the map's data model.
+ *
+ * TODO: This should probably change to TileModelFactory or something since
+ * the creation of the TileNode itself is trivial and can be done outside of
+ * this class.
+ */
+ class TileModelFactory : public osg::Referenced
+ {
+ public:
+ TileModelFactory(
+ const Map* map,
+ TileNodeRegistry* liveTiles,
+ const Drivers::QuadTreeTerrainEngineOptions& terrainOptions );
+
+ HeightFieldCache* getHeightFieldCache() const;
+
+ /** dtor */
+ virtual ~TileModelFactory() { }
+
+ void createTileModel(
+ const TileKey& key,
+ osg::ref_ptr<TileModel>& out_model,
+ bool& out_hasRealData,
+ bool& out_hasLodBlendedLayers );
+
+ private:
+
+ const Map* _map;
+ osg::ref_ptr<TileNodeRegistry> _liveTiles;
+ const Drivers::QuadTreeTerrainEngineOptions& _terrainOptions;
+ osg::ref_ptr< HeightFieldCache > _hfCache;
+ };
+
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_TILE_MODEL_FACTORY
diff --git a/src/osgEarthDrivers/engine_quadtree/TileModelFactory.cpp b/src/osgEarthDrivers/engine_quadtree/TileModelFactory.cpp
index 4b013bd..ae2bdcf 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileModelFactory.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/TileModelFactory.cpp
@@ -17,9 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TileModelFactory"
+#include <osgEarth/MapFrame>
+#include <osgEarth/MapInfo>
#include <osgEarth/ImageUtils>
#include <osgEarth/HeightFieldUtils>
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
using namespace osgEarth::Drivers;
using namespace OpenThreads;
@@ -145,17 +148,18 @@ namespace
{
struct BuildElevationData
{
- void init(const TileKey& key, const MapFrame& mapf, const QuadTreeTerrainEngineOptions& opt, TileModel* model) //sourceTileNodeBuilder::SourceRepo& repo)
+ void init(const TileKey& key, const MapFrame& mapf, const QuadTreeTerrainEngineOptions& opt, TileModel* model, HeightFieldCache* hfCache) //sourceTileNodeBuilder::SourceRepo& repo)
{
_key = key;
_mapf = &mapf;
_opt = &opt;
_model = model;
+ _hfCache = hfCache;
//_repo = &repo;
}
void execute()
- {
+ {
const MapInfo& mapInfo = _mapf->getMapInfo();
// Request a heightfield from the map, falling back on lower resolution tiles
@@ -163,14 +167,9 @@ namespace
osg::ref_ptr<osg::HeightField> hf;
bool isFallback = false;
- if ( _mapf->getHeightField( _key, true, hf, &isFallback ) )
- {
- // Treat Plate Carre specially by scaling the height values. (There is no need
- // to do this with an empty heightfield)
- if ( mapInfo.isPlateCarre() )
- {
- HeightFieldUtils::scaleHeightFieldToDegrees( hf.get() );
- }
+ //if ( _mapf->getHeightField( _key, true, hf, &isFallback ) )
+ if (_hfCache->getOrCreateHeightField( *_mapf, _key, true, hf, &isFallback) )
+ {
// Put it in the repo
osgTerrain::HeightFieldLayer* hfLayer = new osgTerrain::HeightFieldLayer( hf.get() );
@@ -179,6 +178,34 @@ namespace
hfLayer->setLocator( GeoLocator::createForKey( _key, mapInfo ) );
_model->_elevationData = TileModel::ElevationData(hfLayer, isFallback);
+
+ if ( *_opt->normalizeEdges() )
+ {
+ // next, query the neighboring tiles to get adjacency information.
+ for( int x=-1; x<=1; x++ )
+ {
+ for( int y=-1; y<=1; y++ )
+ {
+ if ( x != 0 || y != 0 )
+ {
+ TileKey nk = _key.createNeighborKey(x, y);
+ if ( nk.valid() )
+ {
+ if (_hfCache->getOrCreateHeightField( *_mapf, nk, true, hf, &isFallback) )
+ //if ( _mapf->getHeightField(nk, true, hf, &isFallback) )
+ {
+ if ( mapInfo.isPlateCarre() )
+ {
+ HeightFieldUtils::scaleHeightFieldToDegrees( hf.get() );
+ }
+
+ _model->_elevationData.setNeighbor( x, y, hf.get() );
+ }
+ }
+ }
+ }
+ }
+ }
}
}
@@ -186,6 +213,7 @@ namespace
const MapFrame* _mapf;
const QuadTreeTerrainEngineOptions* _opt;
TileModel* _model;
+ osg::ref_ptr< HeightFieldCache> _hfCache;
};
}
@@ -198,7 +226,13 @@ _map ( map ),
_liveTiles ( liveTiles ),
_terrainOptions( terrainOptions )
{
- //nop
+ _hfCache = new HeightFieldCache();
+}
+
+HeightFieldCache*
+TileModelFactory::getHeightFieldCache() const
+{
+ return _hfCache;
}
@@ -242,7 +276,7 @@ TileModelFactory::createTileModel(const TileKey& key,
// make an elevation layer.
BuildElevationData build;
- build.init( key, mapf, _terrainOptions, model.get() );
+ build.init( key, mapf, _terrainOptions, model.get(), _hfCache );
build.execute();
diff --git a/src/osgEarthDrivers/engine_quadtree/TileNode b/src/osgEarthDrivers/engine_quadtree/TileNode
index 3102c87..6557259 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileNode
+++ b/src/osgEarthDrivers/engine_quadtree/TileNode
@@ -26,81 +26,84 @@
#include <osg/Group>
#include <vector>
-using namespace osgEarth;
+namespace osgEarth_engine_quadtree
+{
+ using namespace osgEarth;
-//------------------------------------------------------------------------
+ //------------------------------------------------------------------------
-/**
- * Node that represents a single quadtree terrain tile corresponding to
- * unique TileKey.
- */
-class TileNode : public osg::Group
-{
-public:
/**
- * Constructs a new tile node
+ * Node that represents a single quadtree terrain tile corresponding to
+ * unique TileKey.
*/
- TileNode( const TileKey& key, GeoLocator* keyLocator );
+ class TileNode : public osg::Group
+ {
+ public:
+ /**
+ * Constructs a new tile node
+ */
+ TileNode( const TileKey& key, GeoLocator* keyLocator );
- /**
- * The tilekey associated with this tile
- */
- const TileKey& getKey() const { return _key; }
+ /**
+ * The tilekey associated with this tile
+ */
+ const TileKey& getKey() const { return _key; }
- /**
- * The data model used to create this node's geometry.
- */
- void setTileModel( TileModel* model );
- TileModel* getTileModel() { return _model.get(); }
+ /**
+ * The data model used to create this node's geometry.
+ */
+ void setTileModel( TileModel* model );
+ TileModel* getTileModel() { return _model.get(); }
- /**
- * Compiles this node's tile model into geometry.
- * @param[in ] compiler Compiler that will compiler the model
- * @param[in ] releaseModel Whether to deallocate the tile model after compilation
- * @return True upon success
- */
- bool compile( TileModelCompiler* compiler, bool releaseModel =true );
+ /**
+ * Compiles this node's tile model into geometry.
+ * @param[in ] compiler Compiler that will compiler the model
+ * @param[in ] releaseModel Whether to deallocate the tile model after compilation
+ * @return True upon success
+ */
+ bool compile( TileModelCompiler* compiler, bool releaseModel =true );
- /**
- * The locator for geometry in this tile
- */
- GeoLocator* getLocator() const { return _locator.get(); }
+ /**
+ * The locator for geometry in this tile
+ */
+ GeoLocator* getLocator() const { return _locator.get(); }
- /**
- * The public state set associated with the compiled tile model.
- */
- osg::StateSet* getPublicStateSet() const { return _publicStateSet; }
+ /**
+ * The public state set associated with the compiled tile model.
+ */
+ osg::StateSet* getPublicStateSet() const { return _publicStateSet; }
-public: // OVERRIDES
+ public: // OVERRIDES
- virtual void traverse( class osg::NodeVisitor& nv );
+ virtual void traverse( class osg::NodeVisitor& nv );
- //virtual osg::BoundingSphere computeBound() const;
+ //virtual osg::BoundingSphere computeBound() const;
-protected:
+ protected:
- virtual ~TileNode();
+ virtual ~TileNode();
- bool _cullTraversed;
- TileKey _key;
- osg::ref_ptr<GeoLocator> _locator;
- osg::ref_ptr<TileModel> _model;
- osg::StateSet* _publicStateSet;
-};
+ bool _cullTraversed;
+ TileKey _key;
+ osg::ref_ptr<GeoLocator> _locator;
+ osg::ref_ptr<TileModel> _model;
+ osg::StateSet* _publicStateSet;
+ };
-typedef std::vector< osg::ref_ptr<TileNode> > TileNodeVector;
+ typedef std::vector< osg::ref_ptr<TileNode> > TileNodeVector;
-/**
- * Marker class.
- */
-class TileNodeGroup : public osg::Group
-{
-public:
- TileNodeGroup() : osg::Group() { }
-};
+ /**
+ * Marker class.
+ */
+ class TileNodeGroup : public osg::Group
+ {
+ public:
+ TileNodeGroup() : osg::Group() { }
+ };
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_TILE_NODE
diff --git a/src/osgEarthDrivers/engine_quadtree/TileNode.cpp b/src/osgEarthDrivers/engine_quadtree/TileNode.cpp
index 0d02019..b72752a 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileNode.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/TileNode.cpp
@@ -23,6 +23,7 @@
#include <osg/NodeCallback>
#include <osg/NodeVisitor>
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
using namespace OpenThreads;
diff --git a/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry b/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry
index 1fa0ac2..cd64a29 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry
+++ b/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry
@@ -24,59 +24,63 @@
#include <osgEarth/ThreadingUtils>
#include <map>
-using namespace osgEarth;
-
-/**
- * Holds a reference to each tile created by the driver.
- */
-class TileNodeRegistry : public osg::Referenced
+namespace osgEarth_engine_quadtree
{
-public:
- typedef std::map< TileKey, osg::ref_ptr<TileNode> > TileNodeMap;
+ using namespace osgEarth;
- // Proprtype for a locked tileset operation (see run)
- struct Operation {
- virtual void operator()( TileNodeMap& tiles ) =0;
- };
+ /**
+ * Holds a reference to each tile created by the driver.
+ */
+ class TileNodeRegistry : public osg::Referenced
+ {
+ public:
+ typedef std::map< TileKey, osg::ref_ptr<TileNode> > TileNodeMap;
- struct ConstOperation {
- virtual void operator()( const TileNodeMap& tiles ) const =0;
- };
+ // Proprtype for a locked tileset operation (see run)
+ struct Operation {
+ virtual void operator()( TileNodeMap& tiles ) =0;
+ };
-public:
- TileNodeRegistry( const std::string& name );
+ struct ConstOperation {
+ virtual void operator()( const TileNodeMap& tiles ) const =0;
+ };
- virtual ~TileNodeRegistry() { }
+ public:
+ TileNodeRegistry( const std::string& name );
- /** Adds a tile to the registry */
- void add( TileNode* tile );
+ virtual ~TileNodeRegistry() { }
- /** Adds several tiles to the registry */
- void add( const TileNodeVector& tiles );
+ /** Adds a tile to the registry */
+ void add( TileNode* tile );
- /** Moves a tile to the "removed" list */
- void remove( TileNode* tile );
+ /** Adds several tiles to the registry */
+ void add( const TileNodeVector& tiles );
- /** Finds a tile in the registry */
- bool get( const TileKey& key, osg::ref_ptr<TileNode>& out_tile );
+ /** Moves a tile to the "removed" list */
+ void remove( TileNode* tile );
- /** Finds a tile in the registry and then removes it. */
- bool take( const TileKey& key, osg::ref_ptr<TileNode>& out_tile );
+ /** Finds a tile in the registry */
+ bool get( const TileKey& key, osg::ref_ptr<TileNode>& out_tile );
- /** Whether there are tiles in this registry (snapshot in time) */
- bool empty() const;
+ /** Finds a tile in the registry and then removes it. */
+ bool take( const TileKey& key, osg::ref_ptr<TileNode>& out_tile );
- /** Runs an operation against the exclusively locked tile set. */
- void run( Operation& op );
-
- /** Runs an operation against the read-locked tile set. */
- void run( const ConstOperation& op ) const;
+ /** Whether there are tiles in this registry (snapshot in time) */
+ bool empty() const;
-protected:
+ /** Runs an operation against the exclusively locked tile set. */
+ void run( Operation& op );
+
+ /** Runs an operation against the read-locked tile set. */
+ void run( const ConstOperation& op ) const;
+
+ protected:
+
+ std::string _name;
+ TileNodeMap _tiles;
+ mutable Threading::ReadWriteMutex _tilesMutex;
+ };
- std::string _name;
- TileNodeMap _tiles;
- mutable Threading::ReadWriteMutex _tilesMutex;
-};
+} // namespace osgEarth_engine_quadtree
#endif // OSGEARTH_ENGINE_QUADTREE_TILE_NODE_REGISTRY
diff --git a/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry.cpp b/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry.cpp
index 051bdba..f8ddf42 100644
--- a/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry.cpp
+++ b/src/osgEarthDrivers/engine_quadtree/TileNodeRegistry.cpp
@@ -18,6 +18,7 @@
*/
#include "TileNodeRegistry"
+using namespace osgEarth_engine_quadtree;
using namespace osgEarth;
#define LC "[TileNodeRegistry] "
diff --git a/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp b/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp
index 9faddbf..be2f509 100644
--- a/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp
+++ b/src/osgEarthDrivers/feature_ogr/FeatureSourceOGR.cpp
@@ -154,7 +154,7 @@ public:
// attempt to open the dataset:
int openMode = _options.openWrite().isSet() && _options.openWrite().value() ? 1 : 0;
- _dsHandle = OGROpenShared( _source.c_str(), openMode, &_ogrDriverHandle );
+ _dsHandle = OGROpen( _source.c_str(), openMode, &_ogrDriverHandle );
if ( _dsHandle )
{
if (openMode == 1) _writable = true;
diff --git a/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp b/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp
index fd28c20..a2955d6 100644
--- a/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp
+++ b/src/osgEarthDrivers/gdal/ReaderWriterGDAL.cpp
@@ -1080,7 +1080,7 @@ public:
/**
* Finds a raster band based on color interpretation
*/
- static GDALRasterBand* findBand(GDALDataset *ds, GDALColorInterp colorInterp)
+ static GDALRasterBand* findBandByColorInterp(GDALDataset *ds, GDALColorInterp colorInterp)
{
GDAL_SCOPED_LOCK;
@@ -1091,6 +1091,17 @@ public:
return 0;
}
+ static GDALRasterBand* findBandByDataType(GDALDataset *ds, GDALDataType dataType)
+ {
+ GDAL_SCOPED_LOCK;
+
+ for (int i = 1; i <= ds->GetRasterCount(); ++i)
+ {
+ if (ds->GetRasterBand(i)->GetRasterDataType() == dataType) return ds->GetRasterBand(i);
+ }
+ return 0;
+ }
+
static void getPalleteIndexColor(GDALRasterBand* band, int index, osg::Vec4ub& color)
{
const GDALColorEntry *colorEntry = band->GetColorTable()->GetColorEntry( index );
@@ -1253,14 +1264,14 @@ public:
- GDALRasterBand* bandRed = findBand(_warpedDS, GCI_RedBand);
- GDALRasterBand* bandGreen = findBand(_warpedDS, GCI_GreenBand);
- GDALRasterBand* bandBlue = findBand(_warpedDS, GCI_BlueBand);
- GDALRasterBand* bandAlpha = findBand(_warpedDS, GCI_AlphaBand);
+ GDALRasterBand* bandRed = findBandByColorInterp(_warpedDS, GCI_RedBand);
+ GDALRasterBand* bandGreen = findBandByColorInterp(_warpedDS, GCI_GreenBand);
+ GDALRasterBand* bandBlue = findBandByColorInterp(_warpedDS, GCI_BlueBand);
+ GDALRasterBand* bandAlpha = findBandByColorInterp(_warpedDS, GCI_AlphaBand);
- GDALRasterBand* bandGray = findBand(_warpedDS, GCI_GrayIndex);
+ GDALRasterBand* bandGray = findBandByColorInterp(_warpedDS, GCI_GrayIndex);
- GDALRasterBand* bandPalette = findBand(_warpedDS, GCI_PaletteIndex);
+ GDALRasterBand* bandPalette = findBandByColorInterp(_warpedDS, GCI_PaletteIndex);
if (!bandRed && !bandGreen && !bandBlue && !bandAlpha && !bandGray && !bandPalette)
{
@@ -1700,8 +1711,13 @@ public:
double xmin, ymin, xmax, ymax;
key.getExtent().getBounds(xmin, ymin, xmax, ymax);
- //Just read from the first band
- GDALRasterBand* band = _warpedDS->GetRasterBand(1);
+ // Try to find a FLOAT band
+ GDALRasterBand* band = findBandByDataType(_warpedDS, GDT_Float32);
+ if (band == NULL)
+ {
+ // Just get first band
+ band = _warpedDS->GetRasterBand(1);
+ }
double dx = (xmax - xmin) / (tileSize-1);
double dy = (ymax - ymin) / (tileSize-1);
diff --git a/src/osgEarthDrivers/kml/KML b/src/osgEarthDrivers/kml/KML
index 81309c6..00f9089 100644
--- a/src/osgEarthDrivers/kml/KML
+++ b/src/osgEarthDrivers/kml/KML
@@ -26,8 +26,8 @@
#include <osgDB/FileNameUtils>
#include "KMLOptions"
-namespace osgEarth { namespace Drivers {
-
+namespace osgEarth { namespace Drivers
+{
using namespace osgEarth;
class KML // header-only (no export)
diff --git a/src/osgEarthDrivers/kml/KMLReader b/src/osgEarthDrivers/kml/KMLReader
index d7e60a2..2c441da 100644
--- a/src/osgEarthDrivers/kml/KMLReader
+++ b/src/osgEarthDrivers/kml/KMLReader
@@ -26,28 +26,32 @@
#include <iostream>
#include "KMLOptions"
-using namespace osgEarth;
-using namespace osgEarth::Drivers;
-
-class KMLReader
+namespace osgEarth_kml
{
-public:
- /** Initialized a KML reader that will work with the provided map node */
- KMLReader( MapNode* mapNode, const KMLOptions* options );
+ using namespace osgEarth;
+ using namespace osgEarth::Drivers;
+
+ class KMLReader
+ {
+ public:
+ /** Initialized a KML reader that will work with the provided map node */
+ KMLReader( MapNode* mapNode, const KMLOptions* options );
+
+ /** dtor */
+ virtual ~KMLReader() { }
- /** dtor */
- virtual ~KMLReader() { }
+ /** Reads KML from a stream and returns a node */
+ osg::Node* read( std::istream& in, const osgDB::Options* dbOptions ) ;
- /** Reads KML from a stream and returns a node */
- osg::Node* read( std::istream& in, const osgDB::Options* dbOptions ) ;
+ /** Reads KML from a Config object */
+ osg::Node* read( const Config& conf, const osgDB::Options* dbOptions );
- /** Reads KML from a Config object */
- osg::Node* read( const Config& conf, const osgDB::Options* dbOptions );
+ private:
+ MapNode* _mapNode;
+ const KMLOptions* _options;
+ };
-private:
- MapNode* _mapNode;
- const KMLOptions* _options;
-};
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_READER
diff --git a/src/osgEarthDrivers/kml/KMLReader.cpp b/src/osgEarthDrivers/kml/KMLReader.cpp
index 50bd50e..c857127 100644
--- a/src/osgEarthDrivers/kml/KMLReader.cpp
+++ b/src/osgEarthDrivers/kml/KMLReader.cpp
@@ -22,11 +22,12 @@
#include <osgEarth/Capabilities>
#include <osgEarth/XmlUtils>
#include <osgEarth/ShaderGenerator>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarthAnnotation/Decluttering>
#include <stack>
#include <iterator>
+using namespace osgEarth_kml;
using namespace osgEarth;
KMLReader::KMLReader( MapNode* mapNode, const KMLOptions* options ) :
@@ -108,15 +109,5 @@ KMLReader::read( const Config& conf, const osgDB::Options* dbOptions )
CacheStats stats = cacheUsed->getStats();
OE_INFO << LC << "URI Cache: " << stats._queries << " reads, " << (stats._hitRatio*100.0) << "% hits" << std::endl;
- if ( Registry::capabilities().supportsGLSL() )
- {
- ShaderGenerator gen;
- root->accept( gen );
-
- VirtualProgram* vp = new VirtualProgram();
- vp->installDefaultColoringAndLightingShaders();
- root->getOrCreateStateSet()->setAttributeAndModes( vp, osg::StateAttribute::ON );
- }
-
return root;
}
diff --git a/src/osgEarthDrivers/kml/KML_Common b/src/osgEarthDrivers/kml/KML_Common
index 5ef4884..32b3be0 100644
--- a/src/osgEarthDrivers/kml/KML_Common
+++ b/src/osgEarthDrivers/kml/KML_Common
@@ -32,10 +32,6 @@
#define LC "[KML] "
-using namespace osgEarth;
-using namespace osgEarth::Drivers;
-using namespace osgEarth::Symbology;
-
#define for_one( NAME, FUNC, CONF, CX ) \
{ \
Config c = conf.child( toLower( #NAME ) ); \
@@ -63,43 +59,50 @@ using namespace osgEarth::Symbology;
for_many( NetworkLink, FUNC, CONF, CX ); \
for_many( Placemark, FUNC, CONF, CX );
-struct KMLContext
+namespace osgEarth_kml
{
- MapNode* _mapNode; // reference map node
- const KMLOptions* _options; // user options
- osg::ref_ptr<StyleSheet> _sheet; // entire style sheet
- Style _activeStyle; // currently active style
- std::stack<osg::ref_ptr<osg::Group> > _groupStack; // resulting scene graph
- osg::ref_ptr<const SpatialReference> _srs; // map's spatial reference
- osg::ref_ptr<const osgDB::Options> _dbOptions; // I/O options (caching, etc)
-};
+ using namespace osgEarth;
+ using namespace osgEarth::Drivers;
+ using namespace osgEarth::Symbology;
-struct KMLUtils
-{
- // parse KML's many variants on a URL link.
- static std::string parseLink( const Config& conf )
+ struct KMLContext
{
- Config link = conf.child("link");
- if ( !link.empty() )
- {
- if ( link.hasValue("href") )
- return link.value("href");
- else if ( link.hasValue("url") )
- return link.value("url");
- else
- return link.value();
- }
- else
+ MapNode* _mapNode; // reference map node
+ const KMLOptions* _options; // user options
+ osg::ref_ptr<StyleSheet> _sheet; // entire style sheet
+ Style _activeStyle; // currently active style
+ std::stack<osg::ref_ptr<osg::Group> > _groupStack; // resulting scene graph
+ osg::ref_ptr<const SpatialReference> _srs; // map's spatial reference
+ osg::ref_ptr<const osgDB::Options> _dbOptions; // I/O options (caching, etc)
+ };
+
+ struct KMLUtils
+ {
+ // parse KML's many variants on a URL link.
+ static std::string parseLink( const Config& conf )
{
- link = conf.child("url");
- if ( link.hasValue("href") )
- return link.value("href");
+ Config link = conf.child("link");
+ if ( !link.empty() )
+ {
+ if ( link.hasValue("href") )
+ return link.value("href");
+ else if ( link.hasValue("url") )
+ return link.value("url");
+ else
+ return link.value();
+ }
else
- return link.value();
+ {
+ link = conf.child("url");
+ if ( link.hasValue("href") )
+ return link.value("href");
+ else
+ return link.value();
+ }
}
- }
-};
+ };
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_READER
diff --git a/src/osgEarthDrivers/kml/KML_Container b/src/osgEarthDrivers/kml/KML_Container
index 3354e19..55be876 100644
--- a/src/osgEarthDrivers/kml/KML_Container
+++ b/src/osgEarthDrivers/kml/KML_Container
@@ -22,26 +22,30 @@
#include "KML_Common"
#include "KML_Feature"
-using namespace osgEarth;
-
-struct KML_Container : public KML_Feature
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx )
- {
- KML_Feature::scan(conf, cx);
- }
+ using namespace osgEarth;
- virtual void scan2( const Config& conf, KMLContext& cx )
+ struct KML_Container : public KML_Feature
{
- KML_Feature::scan2(conf, cx);
- }
+ virtual void scan( const Config& conf, KMLContext& cx )
+ {
+ KML_Feature::scan(conf, cx);
+ }
- virtual void build( const Config& conf, KMLContext& cx, osg::Node* working )
- {
- // assumes the top of the group stack has a new and valid Node.
- // don't call this is there was an error in the subclass build() method
- KML_Feature::build(conf, cx, working);
- }
-};
+ virtual void scan2( const Config& conf, KMLContext& cx )
+ {
+ KML_Feature::scan2(conf, cx);
+ }
+
+ virtual void build( const Config& conf, KMLContext& cx, osg::Node* working )
+ {
+ // assumes the top of the group stack has a new and valid Node.
+ // don't call this is there was an error in the subclass build() method
+ KML_Feature::build(conf, cx, working);
+ }
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_CONTAINER
diff --git a/src/osgEarthDrivers/kml/KML_Document b/src/osgEarthDrivers/kml/KML_Document
index b3e7a1b..e269453 100644
--- a/src/osgEarthDrivers/kml/KML_Document
+++ b/src/osgEarthDrivers/kml/KML_Document
@@ -22,16 +22,20 @@
#include "KML_Common"
#include "KML_Container"
-using namespace osgEarth;
-
-struct KML_Document : public KML_Container
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
+ using namespace osgEarth;
+
+ struct KML_Document : public KML_Container
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+
+ virtual void scan2( const Config& conf, KMLContext& cx );
- virtual void scan2( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx );
+ };
- virtual void build( const Config& conf, KMLContext& cx );
-};
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_DOCUMENT
diff --git a/src/osgEarthDrivers/kml/KML_Document.cpp b/src/osgEarthDrivers/kml/KML_Document.cpp
index 169b653..4386dec 100644
--- a/src/osgEarthDrivers/kml/KML_Document.cpp
+++ b/src/osgEarthDrivers/kml/KML_Document.cpp
@@ -25,6 +25,8 @@
#include "KML_NetworkLink"
#include "KML_Placemark"
+using namespace osgEarth_kml;
+
void
KML_Document::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_Feature b/src/osgEarthDrivers/kml/KML_Feature
index a3f7eca..964206b 100644
--- a/src/osgEarthDrivers/kml/KML_Feature
+++ b/src/osgEarthDrivers/kml/KML_Feature
@@ -21,15 +21,19 @@
#include "KML_Object"
-using namespace osgEarth;
-
-struct KML_Feature : public KML_Object
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
+ using namespace osgEarth;
+
+ struct KML_Feature : public KML_Object
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+
+ virtual void scan2( const Config& conf, KMLContext& cx );
- virtual void scan2( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx, osg::Node* working );
+ };
- virtual void build( const Config& conf, KMLContext& cx, osg::Node* working );
-};
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_FEATURE
diff --git a/src/osgEarthDrivers/kml/KML_Feature.cpp b/src/osgEarthDrivers/kml/KML_Feature.cpp
index a389de0..1c98a3b 100644
--- a/src/osgEarthDrivers/kml/KML_Feature.cpp
+++ b/src/osgEarthDrivers/kml/KML_Feature.cpp
@@ -19,8 +19,11 @@
#include "KML_Feature"
#include "KML_Style"
#include "KML_StyleMap"
+#include <osg/UserDataContainer>
+#include <osg/ValueObject>
#include <osgEarth/Viewpoint>
+using namespace osgEarth_kml;
using namespace osgEarth;
void
@@ -49,7 +52,7 @@ KML_Feature::build( const Config& conf, KMLContext& cx, osg::Node* working )
{
// parse the visibility to show/hide the item by default:
if ( conf.hasValue("visibility") )
- working->setNodeMask( conf.value<bool>("visibility",true) == true ? ~0 : 0 );
+ working->setNodeMask( conf.value<int>("visibility", 1) == 1 ? ~0 : 0 );
// parse a "LookAt" element (stores a viewpoint)
AnnotationData* anno = getOrCreateAnnotationData(working);
@@ -70,5 +73,15 @@ KML_Feature::build( const Config& conf, KMLContext& cx, osg::Node* working )
anno->setViewpoint( vp );
}
+
+ const Config& extdata = conf.child("extendeddata");
+ if ( !extdata.empty() )
+ {
+ ConfigSet innerConfs = extdata.children("data");
+ for( ConfigSet::const_iterator i = innerConfs.begin(); i != innerConfs.end(); ++i )
+ {
+ working->setUserValue(i->value("name"), i->value("value"));
+ }
+ }
}
}
diff --git a/src/osgEarthDrivers/kml/KML_Folder b/src/osgEarthDrivers/kml/KML_Folder
index 82d2cd9..6463a2e 100644
--- a/src/osgEarthDrivers/kml/KML_Folder
+++ b/src/osgEarthDrivers/kml/KML_Folder
@@ -22,15 +22,19 @@
#include "KML_Common"
#include "KML_Container"
-using namespace osgEarth;
-
-struct KML_Folder : public KML_Container
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
+ using namespace osgEarth;
+
+ struct KML_Folder : public KML_Container
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+
+ virtual void scan2( const Config& conf, KMLContext& cx );
- virtual void scan2( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx );
+ };
- virtual void build( const Config& conf, KMLContext& cx );
-};
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_FOLDER
diff --git a/src/osgEarthDrivers/kml/KML_Folder.cpp b/src/osgEarthDrivers/kml/KML_Folder.cpp
index 87d8317..b5cde3b 100644
--- a/src/osgEarthDrivers/kml/KML_Folder.cpp
+++ b/src/osgEarthDrivers/kml/KML_Folder.cpp
@@ -25,6 +25,8 @@
#include "KML_NetworkLink"
#include "KML_Placemark"
+using namespace osgEarth_kml;
+
void
KML_Folder::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_Geometry b/src/osgEarthDrivers/kml/KML_Geometry
index a10b53f..bb4ad28 100644
--- a/src/osgEarthDrivers/kml/KML_Geometry
+++ b/src/osgEarthDrivers/kml/KML_Geometry
@@ -22,19 +22,23 @@
#include "KML_Object"
#include <osgEarthSymbology/Geometry>
-using namespace osgEarth;
-using namespace osgEarth::Symbology;
-
-struct KML_Geometry : public KML_Object
+namespace osgEarth_kml
{
- KML_Geometry() : _extrude(false), _tessellate(false) { }
- virtual void parseCoords( const Config& conf, KMLContext& cx );
- virtual void parseStyle( const Config& conf, KMLContext& cs, Style& style );
- virtual void build( const Config& confParent, KMLContext& cx, Style& style );
- void buildChild( const Config& conf, KMLContext& cx, Style& style );
- osg::ref_ptr<Geometry> _geom;
- bool _extrude, _tessellate;
-private:
-};
+ using namespace osgEarth;
+ using namespace osgEarth::Symbology;
+
+ struct KML_Geometry : public KML_Object
+ {
+ KML_Geometry() : _extrude(false), _tessellate(false) { }
+ virtual void parseCoords( const Config& conf, KMLContext& cx );
+ virtual void parseStyle( const Config& conf, KMLContext& cs, Style& style );
+ virtual void build( const Config& confParent, KMLContext& cx, Style& style );
+ void buildChild( const Config& conf, KMLContext& cx, Style& style );
+ osg::ref_ptr<Geometry> _geom;
+ bool _extrude, _tessellate;
+ private:
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_GEOMETRY
diff --git a/src/osgEarthDrivers/kml/KML_Geometry.cpp b/src/osgEarthDrivers/kml/KML_Geometry.cpp
index 848cab5..6432be6 100644
--- a/src/osgEarthDrivers/kml/KML_Geometry.cpp
+++ b/src/osgEarthDrivers/kml/KML_Geometry.cpp
@@ -25,6 +25,8 @@
#include "KML_Model"
#include <osgEarth/StringUtils>
+using namespace osgEarth_kml;
+
void
KML_Geometry::build( const Config& parentConf, KMLContext& cx, Style& style)
{
diff --git a/src/osgEarthDrivers/kml/KML_GroundOverlay b/src/osgEarthDrivers/kml/KML_GroundOverlay
index 9e34821..6439f08 100644
--- a/src/osgEarthDrivers/kml/KML_GroundOverlay
+++ b/src/osgEarthDrivers/kml/KML_GroundOverlay
@@ -22,12 +22,16 @@
#include "KML_Common"
#include "KML_Overlay"
-using namespace osgEarth;
-
-struct KML_GroundOverlay : public KML_Overlay
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
- virtual void build( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_GroundOverlay : public KML_Overlay
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_GROUNDOVERLAY
diff --git a/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp b/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp
index d0f3a5c..dfe8b5d 100644
--- a/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_GroundOverlay.cpp
@@ -20,6 +20,7 @@
#include "KML_Geometry"
#include <osgEarthAnnotation/ImageOverlay>
+using namespace osgEarth_kml;
using namespace osgEarth::Annotation;
void
diff --git a/src/osgEarthDrivers/kml/KML_IconStyle b/src/osgEarthDrivers/kml/KML_IconStyle
index e6e40e0..30dea09 100644
--- a/src/osgEarthDrivers/kml/KML_IconStyle
+++ b/src/osgEarthDrivers/kml/KML_IconStyle
@@ -21,11 +21,15 @@
#include "KML_Object"
-using namespace osgEarth;
-
-struct KML_IconStyle : public KML_Object
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, Style& style, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_IconStyle : public KML_Object
+ {
+ virtual void scan( const Config& conf, Style& style, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_ICONSTYLE
diff --git a/src/osgEarthDrivers/kml/KML_IconStyle.cpp b/src/osgEarthDrivers/kml/KML_IconStyle.cpp
index 3669b94..8b5ad71 100644
--- a/src/osgEarthDrivers/kml/KML_IconStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_IconStyle.cpp
@@ -19,6 +19,8 @@
#include "KML_IconStyle"
#include <osgEarthSymbology/IconSymbol>
+using namespace osgEarth_kml;
+
void
KML_IconStyle::scan( const Config& conf, Style& style, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_LabelStyle b/src/osgEarthDrivers/kml/KML_LabelStyle
index 7fba448..8f619c6 100644
--- a/src/osgEarthDrivers/kml/KML_LabelStyle
+++ b/src/osgEarthDrivers/kml/KML_LabelStyle
@@ -21,11 +21,15 @@
#include "KML_Object"
-using namespace osgEarth;
-
-struct KML_LabelStyle : public KML_Object
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, Style& style, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_LabelStyle : public KML_Object
+ {
+ virtual void scan( const Config& conf, Style& style, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_LABELSTYLE
diff --git a/src/osgEarthDrivers/kml/KML_LabelStyle.cpp b/src/osgEarthDrivers/kml/KML_LabelStyle.cpp
index d0d831f..807492d 100644
--- a/src/osgEarthDrivers/kml/KML_LabelStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_LabelStyle.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_LabelStyle"
+using namespace osgEarth_kml;
+
void
KML_LabelStyle::scan( const Config& conf, Style& style, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_LineString b/src/osgEarthDrivers/kml/KML_LineString
index aa91f49..ca2bdc3 100644
--- a/src/osgEarthDrivers/kml/KML_LineString
+++ b/src/osgEarthDrivers/kml/KML_LineString
@@ -21,12 +21,16 @@
#include "KML_Geometry"
-using namespace osgEarth;
-
-struct KML_LineString : public KML_Geometry
+namespace osgEarth_kml
{
- virtual void parseStyle( const Config& conf, KMLContext& cs, Style& style );
- virtual void parseCoords( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_LineString : public KML_Geometry
+ {
+ virtual void parseStyle( const Config& conf, KMLContext& cs, Style& style );
+ virtual void parseCoords( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_LINESTRING
diff --git a/src/osgEarthDrivers/kml/KML_LineString.cpp b/src/osgEarthDrivers/kml/KML_LineString.cpp
index ea38ce1..5e37a34 100644
--- a/src/osgEarthDrivers/kml/KML_LineString.cpp
+++ b/src/osgEarthDrivers/kml/KML_LineString.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_LineString"
+using namespace osgEarth_kml;
+
void
KML_LineString::parseStyle( const Config& conf, KMLContext& cs, Style& style )
{
diff --git a/src/osgEarthDrivers/kml/KML_LineStyle b/src/osgEarthDrivers/kml/KML_LineStyle
index 473ae4d..35a6f5b 100644
--- a/src/osgEarthDrivers/kml/KML_LineStyle
+++ b/src/osgEarthDrivers/kml/KML_LineStyle
@@ -21,11 +21,15 @@
#include "KML_Object"
-using namespace osgEarth;
-
-struct KML_LineStyle : public KML_Object
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, Style& style, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_LineStyle : public KML_Object
+ {
+ virtual void scan( const Config& conf, Style& style, KMLContext& cx );
+ };
+
+} //namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_LINESTYLE
diff --git a/src/osgEarthDrivers/kml/KML_LineStyle.cpp b/src/osgEarthDrivers/kml/KML_LineStyle.cpp
index 76150e3..743d9c8 100644
--- a/src/osgEarthDrivers/kml/KML_LineStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_LineStyle.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_LineStyle"
+using namespace osgEarth_kml;
+
void
KML_LineStyle::scan( const Config& conf, Style& style, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_LinearRing b/src/osgEarthDrivers/kml/KML_LinearRing
index 56df748..3344de7 100644
--- a/src/osgEarthDrivers/kml/KML_LinearRing
+++ b/src/osgEarthDrivers/kml/KML_LinearRing
@@ -21,12 +21,16 @@
#include "KML_Geometry"
-using namespace osgEarth;
-
-struct KML_LinearRing : public KML_Geometry
+namespace osgEarth_kml
{
- virtual void parseStyle( const Config& conf, KMLContext& cs, Style& style );
- virtual void parseCoords( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_LinearRing : public KML_Geometry
+ {
+ virtual void parseStyle( const Config& conf, KMLContext& cs, Style& style );
+ virtual void parseCoords( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_LINEARRING
diff --git a/src/osgEarthDrivers/kml/KML_LinearRing.cpp b/src/osgEarthDrivers/kml/KML_LinearRing.cpp
index c073125..fc34a27 100644
--- a/src/osgEarthDrivers/kml/KML_LinearRing.cpp
+++ b/src/osgEarthDrivers/kml/KML_LinearRing.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_LinearRing"
+using namespace osgEarth_kml;
+
void
KML_LinearRing::parseStyle( const Config& conf, KMLContext& cs, Style& style )
{
diff --git a/src/osgEarthDrivers/kml/KML_Model b/src/osgEarthDrivers/kml/KML_Model
index 205ce55..39156c1 100644
--- a/src/osgEarthDrivers/kml/KML_Model
+++ b/src/osgEarthDrivers/kml/KML_Model
@@ -21,12 +21,16 @@
#include "KML_Geometry"
-using namespace osgEarth;
-
-struct KML_Model : public KML_Geometry
+namespace osgEarth_kml
{
- void parseCoords( const Config& conf, KMLContext& cx );
- void parseStyle(const Config& conf, KMLContext& cx, Style& style);
-};
+ using namespace osgEarth;
+
+ struct KML_Model : public KML_Geometry
+ {
+ void parseCoords( const Config& conf, KMLContext& cx );
+ void parseStyle(const Config& conf, KMLContext& cx, Style& style);
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_MODEL
diff --git a/src/osgEarthDrivers/kml/KML_Model.cpp b/src/osgEarthDrivers/kml/KML_Model.cpp
index 798f31d..9638fab 100644
--- a/src/osgEarthDrivers/kml/KML_Model.cpp
+++ b/src/osgEarthDrivers/kml/KML_Model.cpp
@@ -20,6 +20,7 @@
#include <osgEarthSymbology/ModelSymbol>
+using namespace osgEarth_kml;
using namespace osgEarth::Symbology;
void
diff --git a/src/osgEarthDrivers/kml/KML_MultiGeometry b/src/osgEarthDrivers/kml/KML_MultiGeometry
index 064701b..6bda743 100644
--- a/src/osgEarthDrivers/kml/KML_MultiGeometry
+++ b/src/osgEarthDrivers/kml/KML_MultiGeometry
@@ -21,11 +21,15 @@
#include "KML_Geometry"
-using namespace osgEarth;
-
-struct KML_MultiGeometry : public KML_Geometry
+namespace osgEarth_kml
{
- virtual void parseCoords( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_MultiGeometry : public KML_Geometry
+ {
+ virtual void parseCoords( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_MULTIGEOMETRY
diff --git a/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp b/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp
index 8a2c319..98bc3de 100644
--- a/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp
+++ b/src/osgEarthDrivers/kml/KML_MultiGeometry.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_MultiGeometry"
+using namespace osgEarth_kml;
+
void
KML_MultiGeometry::parseCoords( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_NetworkLink b/src/osgEarthDrivers/kml/KML_NetworkLink
index 1f70569..aa6952b 100644
--- a/src/osgEarthDrivers/kml/KML_NetworkLink
+++ b/src/osgEarthDrivers/kml/KML_NetworkLink
@@ -21,6 +21,7 @@
#include "KML_Object"
+using namespace osgEarth_kml;
using namespace osgEarth;
struct KML_NetworkLink : public KML_Object
diff --git a/src/osgEarthDrivers/kml/KML_NetworkLink.cpp b/src/osgEarthDrivers/kml/KML_NetworkLink.cpp
index 4de2386..b456e0a 100644
--- a/src/osgEarthDrivers/kml/KML_NetworkLink.cpp
+++ b/src/osgEarthDrivers/kml/KML_NetworkLink.cpp
@@ -26,6 +26,8 @@
#undef LC
#define LC "[KML_NetworkLink] "
+using namespace osgEarth_kml;
+
void
KML_NetworkLink::build( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_NetworkLinkControl b/src/osgEarthDrivers/kml/KML_NetworkLinkControl
index eb76e33..e906595 100644
--- a/src/osgEarthDrivers/kml/KML_NetworkLinkControl
+++ b/src/osgEarthDrivers/kml/KML_NetworkLinkControl
@@ -21,12 +21,16 @@
#include "KML_Object"
-using namespace osgEarth;
-
-struct KML_NetworkLinkControl : public KML_Object
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
- virtual void build( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_NetworkLinkControl : public KML_Object
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_NETWORKLINKCONTROL
diff --git a/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp b/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp
index e81783d..b27bdca 100644
--- a/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp
+++ b/src/osgEarthDrivers/kml/KML_NetworkLinkControl.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_NetworkLinkControl"
+using namespace osgEarth_kml;
+
void
KML_NetworkLinkControl::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_Object b/src/osgEarthDrivers/kml/KML_Object
index e195735..63c52ef 100644
--- a/src/osgEarthDrivers/kml/KML_Object
+++ b/src/osgEarthDrivers/kml/KML_Object
@@ -22,22 +22,26 @@
#include "KML_Common"
#include <osgEarthAnnotation/AnnotationData>
-using namespace osgEarth;
-using namespace osgEarth::Annotation;
-
-struct KML_Object
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx ) { }
-
- virtual void scan2( const Config& conf, KMLContext& cx ) { }
+ using namespace osgEarth;
+ using namespace osgEarth::Annotation;
+
+ struct KML_Object
+ {
+ virtual void scan( const Config& conf, KMLContext& cx ) { }
+
+ virtual void scan2( const Config& conf, KMLContext& cx ) { }
+
+ virtual void build( const Config& conf, KMLContext& cx, osg::Node* working );
- virtual void build( const Config& conf, KMLContext& cx, osg::Node* working );
+ virtual ~KML_Object() { }
- virtual ~KML_Object() { }
+ protected:
-protected:
+ AnnotationData* getOrCreateAnnotationData( osg::Node* node );
+ };
- AnnotationData* getOrCreateAnnotationData( osg::Node* node );
-};
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_OBJECT
diff --git a/src/osgEarthDrivers/kml/KML_Object.cpp b/src/osgEarthDrivers/kml/KML_Object.cpp
index a31c114..2b97a4c 100644
--- a/src/osgEarthDrivers/kml/KML_Object.cpp
+++ b/src/osgEarthDrivers/kml/KML_Object.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_Object"
+using namespace osgEarth_kml;
+
void
KML_Object::build( const Config& conf, KMLContext& cx, osg::Node* working )
{
diff --git a/src/osgEarthDrivers/kml/KML_Overlay b/src/osgEarthDrivers/kml/KML_Overlay
index 8674948..77f943c 100644
--- a/src/osgEarthDrivers/kml/KML_Overlay
+++ b/src/osgEarthDrivers/kml/KML_Overlay
@@ -22,12 +22,16 @@
#include "KML_Common"
#include "KML_Feature"
-using namespace osgEarth;
-
-struct KML_Overlay : public KML_Feature
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
- virtual void build( const Config& conf, KMLContext& cx, osg::Node* working );
-};
+ using namespace osgEarth;
+
+ struct KML_Overlay : public KML_Feature
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx, osg::Node* working );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_OVERLAY
diff --git a/src/osgEarthDrivers/kml/KML_Overlay.cpp b/src/osgEarthDrivers/kml/KML_Overlay.cpp
index cf1b13e..b1beb5d 100644
--- a/src/osgEarthDrivers/kml/KML_Overlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_Overlay.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_Overlay"
+using namespace osgEarth_kml;
+
void
KML_Overlay::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_PhotoOverlay b/src/osgEarthDrivers/kml/KML_PhotoOverlay
index e77bef3..a35cd32 100644
--- a/src/osgEarthDrivers/kml/KML_PhotoOverlay
+++ b/src/osgEarthDrivers/kml/KML_PhotoOverlay
@@ -22,12 +22,16 @@
#include "KML_Common"
#include "KML_Overlay"
-using namespace osgEarth;
-
-struct KML_PhotoOverlay : public KML_Overlay
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
- virtual void build( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_PhotoOverlay : public KML_Overlay
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_PHOTOOVERLAY
diff --git a/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp b/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp
index f2f72dd..d856c6f 100644
--- a/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_PhotoOverlay.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_PhotoOverlay"
+using namespace osgEarth_kml;
+
void
KML_PhotoOverlay::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_Placemark b/src/osgEarthDrivers/kml/KML_Placemark
index 6984179..fb85875 100644
--- a/src/osgEarthDrivers/kml/KML_Placemark
+++ b/src/osgEarthDrivers/kml/KML_Placemark
@@ -21,6 +21,7 @@
#include "KML_Feature"
+using namespace osgEarth_kml;
using namespace osgEarth;
struct KML_Placemark : public KML_Feature
diff --git a/src/osgEarthDrivers/kml/KML_Placemark.cpp b/src/osgEarthDrivers/kml/KML_Placemark.cpp
index add81e3..8e2c69b 100644
--- a/src/osgEarthDrivers/kml/KML_Placemark.cpp
+++ b/src/osgEarthDrivers/kml/KML_Placemark.cpp
@@ -30,6 +30,7 @@
#include <osg/Depth>
#include <osgDB/WriteFile>
+using namespace osgEarth_kml;
using namespace osgEarth::Features;
using namespace osgEarth::Annotation;
diff --git a/src/osgEarthDrivers/kml/KML_Point b/src/osgEarthDrivers/kml/KML_Point
index 698bf9f..b3a5b81 100644
--- a/src/osgEarthDrivers/kml/KML_Point
+++ b/src/osgEarthDrivers/kml/KML_Point
@@ -21,11 +21,15 @@
#include "KML_Geometry"
-using namespace osgEarth;
-
-struct KML_Point : public KML_Geometry
+namespace osgEarth_kml
{
- virtual void parseCoords( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_Point : public KML_Geometry
+ {
+ virtual void parseCoords( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_POINT
diff --git a/src/osgEarthDrivers/kml/KML_Point.cpp b/src/osgEarthDrivers/kml/KML_Point.cpp
index 642859d..944dc6c 100644
--- a/src/osgEarthDrivers/kml/KML_Point.cpp
+++ b/src/osgEarthDrivers/kml/KML_Point.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_Point"
+using namespace osgEarth_kml;
+
void
KML_Point::parseCoords( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_PolyStyle b/src/osgEarthDrivers/kml/KML_PolyStyle
index 50d73c0..04907f8 100644
--- a/src/osgEarthDrivers/kml/KML_PolyStyle
+++ b/src/osgEarthDrivers/kml/KML_PolyStyle
@@ -21,11 +21,15 @@
#include "KML_Object"
-using namespace osgEarth;
-
-struct KML_PolyStyle : public KML_Object
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, Style& style, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_PolyStyle : public KML_Object
+ {
+ virtual void scan( const Config& conf, Style& style, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_POLYSTYLE
diff --git a/src/osgEarthDrivers/kml/KML_PolyStyle.cpp b/src/osgEarthDrivers/kml/KML_PolyStyle.cpp
index 8228b92..a3fc042 100644
--- a/src/osgEarthDrivers/kml/KML_PolyStyle.cpp
+++ b/src/osgEarthDrivers/kml/KML_PolyStyle.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_PolyStyle"
+using namespace osgEarth_kml;
+
void
KML_PolyStyle::scan( const Config& conf, Style& style, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_Polygon b/src/osgEarthDrivers/kml/KML_Polygon
index 7a24326..781f6c4 100644
--- a/src/osgEarthDrivers/kml/KML_Polygon
+++ b/src/osgEarthDrivers/kml/KML_Polygon
@@ -21,12 +21,16 @@
#include "KML_Geometry"
-using namespace osgEarth;
-
-struct KML_Polygon : public KML_Geometry
+namespace osgEarth_kml
{
- virtual void parseStyle( const Config& conf, KMLContext& cx, Style& style);
- virtual void parseCoords( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_Polygon : public KML_Geometry
+ {
+ virtual void parseStyle( const Config& conf, KMLContext& cx, Style& style);
+ virtual void parseCoords( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_POLYGON
diff --git a/src/osgEarthDrivers/kml/KML_Polygon.cpp b/src/osgEarthDrivers/kml/KML_Polygon.cpp
index a5c17b8..b70a978 100644
--- a/src/osgEarthDrivers/kml/KML_Polygon.cpp
+++ b/src/osgEarthDrivers/kml/KML_Polygon.cpp
@@ -20,6 +20,8 @@
#include "KML_LinearRing"
#include <iterator>
+using namespace osgEarth_kml;
+
void
KML_Polygon::parseStyle(const Config& conf, KMLContext& cx, Style& style)
{
diff --git a/src/osgEarthDrivers/kml/KML_Root b/src/osgEarthDrivers/kml/KML_Root
index deb53bd..0ef7dee 100644
--- a/src/osgEarthDrivers/kml/KML_Root
+++ b/src/osgEarthDrivers/kml/KML_Root
@@ -21,13 +21,17 @@
#include "KML_Object"
-struct KML_Root
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
- virtual void scan2( const Config& conf, KMLContext& cx );
- virtual void build( const Config& conf, KMLContext& cx );
+ struct KML_Root
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+ virtual void scan2( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx );
- virtual ~KML_Root() { }
-};
+ virtual ~KML_Root() { }
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_SCHEMA
diff --git a/src/osgEarthDrivers/kml/KML_Root.cpp b/src/osgEarthDrivers/kml/KML_Root.cpp
index 713866a..a80d0ee 100644
--- a/src/osgEarthDrivers/kml/KML_Root.cpp
+++ b/src/osgEarthDrivers/kml/KML_Root.cpp
@@ -26,6 +26,8 @@
#include "KML_Placemark"
#include "KML_NetworkLinkControl"
+using namespace osgEarth_kml;
+
void
KML_Root::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_Schema b/src/osgEarthDrivers/kml/KML_Schema
index 89d5ea9..1d79094 100644
--- a/src/osgEarthDrivers/kml/KML_Schema
+++ b/src/osgEarthDrivers/kml/KML_Schema
@@ -22,11 +22,15 @@
#include "KML_Common"
#include "KML_Container"
-using namespace osgEarth;
-
-struct KML_Schema : public KML_Object
+namespace osgEarth_kml
{
+ using namespace osgEarth;
+
+ struct KML_Schema : public KML_Object
+ {
+
+ };
-};
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_SCHEMA
diff --git a/src/osgEarthDrivers/kml/KML_Schema.cpp b/src/osgEarthDrivers/kml/KML_Schema.cpp
index f9ac2b4..939c1e6 100644
--- a/src/osgEarthDrivers/kml/KML_Schema.cpp
+++ b/src/osgEarthDrivers/kml/KML_Schema.cpp
@@ -17,3 +17,5 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "KML_Schema"
+
+using namespace osgEarth_kml;
diff --git a/src/osgEarthDrivers/kml/KML_ScreenOverlay b/src/osgEarthDrivers/kml/KML_ScreenOverlay
index 1ba32fb..6adb5e3 100644
--- a/src/osgEarthDrivers/kml/KML_ScreenOverlay
+++ b/src/osgEarthDrivers/kml/KML_ScreenOverlay
@@ -22,12 +22,16 @@
#include "KML_Common"
#include "KML_Overlay"
-using namespace osgEarth;
-
-struct KML_ScreenOverlay : public KML_Overlay
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
- virtual void build( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_ScreenOverlay : public KML_Overlay
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+ virtual void build( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_SCREENOVERLAY
diff --git a/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp b/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp
index 72643e2..e717a98 100644
--- a/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp
+++ b/src/osgEarthDrivers/kml/KML_ScreenOverlay.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_ScreenOverlay"
+using namespace osgEarth_kml;
+
void
KML_ScreenOverlay::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_Style b/src/osgEarthDrivers/kml/KML_Style
index a28eed2..1a8d156 100644
--- a/src/osgEarthDrivers/kml/KML_Style
+++ b/src/osgEarthDrivers/kml/KML_Style
@@ -22,11 +22,15 @@
#include "KML_Common"
#include "KML_StyleSelector"
-using namespace osgEarth;
-
-struct KML_Style : public KML_StyleSelector
+namespace osgEarth_kml
{
- virtual void scan( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_Style : public KML_StyleSelector
+ {
+ virtual void scan( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_STYLE
diff --git a/src/osgEarthDrivers/kml/KML_Style.cpp b/src/osgEarthDrivers/kml/KML_Style.cpp
index dad6852..4d2c645 100644
--- a/src/osgEarthDrivers/kml/KML_Style.cpp
+++ b/src/osgEarthDrivers/kml/KML_Style.cpp
@@ -22,6 +22,8 @@
#include "KML_LineStyle"
#include "KML_PolyStyle"
+using namespace osgEarth_kml;
+
void
KML_Style::scan( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_StyleMap b/src/osgEarthDrivers/kml/KML_StyleMap
index 37438d7..3b421c1 100644
--- a/src/osgEarthDrivers/kml/KML_StyleMap
+++ b/src/osgEarthDrivers/kml/KML_StyleMap
@@ -22,11 +22,15 @@
#include "KML_Common"
#include "KML_StyleSelector"
-using namespace osgEarth;
-
-struct KML_StyleMap : public KML_StyleSelector
+namespace osgEarth_kml
{
- virtual void scan2( const Config& conf, KMLContext& cx );
-};
+ using namespace osgEarth;
+
+ struct KML_StyleMap : public KML_StyleSelector
+ {
+ virtual void scan2( const Config& conf, KMLContext& cx );
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_STYLEMAP
diff --git a/src/osgEarthDrivers/kml/KML_StyleMap.cpp b/src/osgEarthDrivers/kml/KML_StyleMap.cpp
index 9805657..7e5f308 100644
--- a/src/osgEarthDrivers/kml/KML_StyleMap.cpp
+++ b/src/osgEarthDrivers/kml/KML_StyleMap.cpp
@@ -18,6 +18,8 @@
*/
#include "KML_StyleMap"
+using namespace osgEarth_kml;
+
void
KML_StyleMap::scan2( const Config& conf, KMLContext& cx )
{
diff --git a/src/osgEarthDrivers/kml/KML_StyleSelector b/src/osgEarthDrivers/kml/KML_StyleSelector
index 23b51e8..286ae6e 100644
--- a/src/osgEarthDrivers/kml/KML_StyleSelector
+++ b/src/osgEarthDrivers/kml/KML_StyleSelector
@@ -21,10 +21,14 @@
#include "KML_Object"
-using namespace osgEarth;
-
-struct KML_StyleSelector : public KML_Object
+namespace osgEarth_kml
{
-};
+ using namespace osgEarth;
+
+ struct KML_StyleSelector : public KML_Object
+ {
+ };
+
+} // namespace osgEarth_kml
#endif // OSGEARTH_DRIVER_KML_KML_STYLESELECTOR
diff --git a/src/osgEarthDrivers/kml/ReaderWriterKML.cpp b/src/osgEarthDrivers/kml/ReaderWriterKML.cpp
index 5a223e7..66a8d19 100644
--- a/src/osgEarthDrivers/kml/ReaderWriterKML.cpp
+++ b/src/osgEarthDrivers/kml/ReaderWriterKML.cpp
@@ -33,6 +33,7 @@
using namespace osgEarth;
using namespace osgEarth::Drivers;
+using namespace osgEarth_kml;
//---------------------------------------------------------------------------
diff --git a/src/osgEarthDrivers/model_simple/SimpleModelOptions b/src/osgEarthDrivers/model_simple/SimpleModelOptions
index 55b5433..9c44e5c 100644
--- a/src/osgEarthDrivers/model_simple/SimpleModelOptions
+++ b/src/osgEarthDrivers/model_simple/SimpleModelOptions
@@ -22,6 +22,7 @@
#include <osgEarth/Common>
#include <osgEarth/ModelSource>
#include <osgEarth/URI>
+#include <osgEarth/ShaderUtils>
namespace osgEarth { namespace Drivers
{
@@ -41,6 +42,9 @@ namespace osgEarth { namespace Drivers
optional<osg::Vec3>& orientation() { return _orientation;}
const optional<osg::Vec3>& orientation() const { return _orientation;}
+
+ optional<ShaderPolicy>& shaderPolicy() { return _shaderPolicy; }
+ const optional<ShaderPolicy>& shaderPolicy() const { return _shaderPolicy; }
/**
If specified, use this node instead try to load from url
@@ -51,7 +55,10 @@ namespace osgEarth { namespace Drivers
public:
- SimpleModelOptions( const ConfigOptions& options=ConfigOptions() ) : ModelSourceOptions( options ) {
+ SimpleModelOptions( const ConfigOptions& options=ConfigOptions() )
+ : ModelSourceOptions( options ),
+ _shaderPolicy( SHADERPOLICY_GENERATE )
+ {
setDriver( "simple" );
fromConfig( _conf );
}
@@ -65,6 +72,11 @@ namespace osgEarth { namespace Drivers
conf.updateIfSet( "lod_scale", _lod_scale );
conf.updateIfSet( "location", _location );
conf.updateIfSet( "orientation", _orientation);
+
+ conf.addIfSet( "shader_policy", "disable", _shaderPolicy, SHADERPOLICY_DISABLE );
+ conf.addIfSet( "shader_policy", "inherit", _shaderPolicy, SHADERPOLICY_INHERIT );
+ conf.addIfSet( "shader_policy", "generate", _shaderPolicy, SHADERPOLICY_GENERATE );
+
conf.updateNonSerializable( "SimpleModelOptions::Node", _node.get() );
return conf;
}
@@ -81,6 +93,11 @@ namespace osgEarth { namespace Drivers
conf.getIfSet( "lod_scale", _lod_scale );
conf.getIfSet( "location", _location);
conf.getIfSet( "orientation", _orientation);
+
+ conf.getIfSet( "shader_policy", "disable", _shaderPolicy, SHADERPOLICY_DISABLE );
+ conf.getIfSet( "shader_policy", "inherit", _shaderPolicy, SHADERPOLICY_INHERIT );
+ conf.getIfSet( "shader_policy", "generate", _shaderPolicy, SHADERPOLICY_GENERATE );
+
_node = conf.getNonSerializable<osg::Node>( "SimpleModelOptions::Node" );
}
@@ -88,6 +105,7 @@ namespace osgEarth { namespace Drivers
optional<float> _lod_scale;
optional<osg::Vec3> _location;
optional<osg::Vec3> _orientation;
+ optional<ShaderPolicy> _shaderPolicy;
osg::ref_ptr<osg::Node> _node;
};
diff --git a/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp b/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp
index 0dfaed7..e4cb34d 100644
--- a/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp
+++ b/src/osgEarthDrivers/model_simple/SimpleModelSource.cpp
@@ -155,8 +155,17 @@ public:
// generate a shader program to render the model.
if ( result.valid() )
{
- ShaderGenerator gen;
- result->accept( gen );
+ if ( _options.shaderPolicy() == SHADERPOLICY_GENERATE )
+ {
+ ShaderGenerator gen;
+ result->accept( gen );
+ }
+ else if ( _options.shaderPolicy() == SHADERPOLICY_DISABLE )
+ {
+ result->getOrCreateStateSet()->setAttributeAndModes(
+ new osg::Program(),
+ osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE );
+ }
}
return result.release();
diff --git a/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer b/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer
index 8ff4421..e889b36 100644
--- a/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer
+++ b/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer
@@ -19,40 +19,44 @@
#ifndef OSGEARTH_DRIVER_OCEAN_SURFACE_ELEV_PROXY_IMAGE_LAYER
#define OSGEARTH_DRIVER_OCEAN_SURFACE_ELEV_PROXY_IMAGE_LAYER 1
-#include <osgEarth/Map>
+#include <osgEarth/MapFrame>
#include <osgEarth/ImageLayer>
-using namespace osgEarth;
-
-/**
- * A customized ImageLayer that taps into another Map, reads elevation
- * tiles, and converts them into heightmap-encoded images.
- */
-class ElevationProxyImageLayer : public osgEarth::ImageLayer
+namespace osgEarth_ocean_surface
{
-public:
+ using namespace osgEarth;
+
/**
- * Constucts a proxy layer
- * @param sourceMap Map from which to read heightfields
+ * A customized ImageLayer that taps into another Map, reads elevation
+ * tiles, and converts them into heightmap-encoded images.
*/
- ElevationProxyImageLayer( Map* sourceMap, const ImageLayerOptions& options );
+ class ElevationProxyImageLayer : public osgEarth::ImageLayer
+ {
+ public:
+ /**
+ * Constucts a proxy layer
+ * @param sourceMap Map from which to read heightfields
+ */
+ ElevationProxyImageLayer( Map* sourceMap, const ImageLayerOptions& options );
+
+ /** dtor */
+ virtual ~ElevationProxyImageLayer() { }
- /** dtor */
- virtual ~ElevationProxyImageLayer() { }
+ public: // ImageLayer
-public: // ImageLayer
+ virtual void initTileSource();
- virtual void initTileSource();
+ virtual bool isKeyValid( const TileKey& key ) const;
- virtual bool isKeyValid( const TileKey& key ) const;
+ virtual bool isCached( const TileKey& key ) const;
- virtual bool isCached( const TileKey& key ) const;
+ virtual GeoImage createImage( const TileKey& key, ProgressCallback* progress, bool forceFallback );
- virtual GeoImage createImage( const TileKey& key, ProgressCallback* progress, bool forceFallback );
+ private:
+ osg::observer_ptr<Map> _sourceMap;
+ MapFrame _mapf;
+ };
-private:
- osg::observer_ptr<Map> _sourceMap;
- MapFrame _mapf;
-};
+} // namespace osgEarth_ocean_surface
#endif // OSGEARTH_DRIVER_OCEAN_SURFACE_ELEV_PROXY_IMAGE_LAYER
diff --git a/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer.cpp b/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer.cpp
index 7082d52..365841f 100644
--- a/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer.cpp
+++ b/src/osgEarthDrivers/ocean_surface/ElevationProxyImageLayer.cpp
@@ -18,6 +18,7 @@
*/
#include "ElevationProxyImageLayer"
+using namespace osgEarth_ocean_surface;
using namespace osgEarth;
ElevationProxyImageLayer::ElevationProxyImageLayer( Map* sourceMap, const ImageLayerOptions& options ) :
@@ -32,6 +33,7 @@ void
ElevationProxyImageLayer::initTileSource()
{
_tileSourceInitAttempted = true;
+ _tileSourceInitFailed = true;
}
bool
diff --git a/src/osgEarthDrivers/ocean_surface/OceanCompositor b/src/osgEarthDrivers/ocean_surface/OceanCompositor
index bf456c9..a00126f 100644
--- a/src/osgEarthDrivers/ocean_surface/OceanCompositor
+++ b/src/osgEarthDrivers/ocean_surface/OceanCompositor
@@ -21,31 +21,35 @@
#include <osgEarth/TextureCompositor>
-using namespace osgEarth;
-
-/**
- * A custom texture compositor for rendering the ocean surface.
- */
-class OceanCompositor : public TextureCompositorTechnique
+namespace osgEarth_ocean_surface
{
-public:
- OceanCompositor() { }
+ using namespace osgEarth;
+
+ /**
+ * A custom texture compositor for rendering the ocean surface.
+ */
+ class OceanCompositor : public TextureCompositorTechnique
+ {
+ public:
+ OceanCompositor() { }
+
+ /** dtor */
+ virtual ~OceanCompositor() { }
- /** dtor */
- virtual ~OceanCompositor() { }
+ virtual bool requiresUnitTextureSpace() const { return true; }
- virtual bool requiresUnitTextureSpace() const { return true; }
+ virtual bool usesShaderComposition() const { return true; }
- virtual bool usesShaderComposition() const { return true; }
+ virtual void updateMasterStateSet( osg::StateSet* stateSet, const TextureLayout& layout ) const;
- virtual void updateMasterStateSet( osg::StateSet* stateSet, const TextureLayout& layout ) const;
+ virtual void applyLayerUpdate(osg::StateSet* stateSet,
+ UID layerUID,
+ const GeoImage& preparedImage,
+ const TileKey& tileKey,
+ const TextureLayout& layout,
+ osg::StateSet* parentStateSet) const;
+ };
- virtual void applyLayerUpdate(osg::StateSet* stateSet,
- UID layerUID,
- const GeoImage& preparedImage,
- const TileKey& tileKey,
- const TextureLayout& layout,
- osg::StateSet* parentStateSet) const;
-};
+} // namespace osgEarth_ocean_surface
#endif // OSGEARTH_DRIVER_OCEAN_SURFACE_COMPOSITOR
diff --git a/src/osgEarthDrivers/ocean_surface/OceanCompositor.cpp b/src/osgEarthDrivers/ocean_surface/OceanCompositor.cpp
index ee7c27f..ae87dc7 100644
--- a/src/osgEarthDrivers/ocean_surface/OceanCompositor.cpp
+++ b/src/osgEarthDrivers/ocean_surface/OceanCompositor.cpp
@@ -19,10 +19,11 @@
#include "OceanCompositor"
#include <osgEarth/ImageUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osg/Texture2D>
#include "OceanShaders"
+using namespace osgEarth_ocean_surface;
using namespace osgEarth;
void
@@ -36,9 +37,18 @@ OceanCompositor::updateMasterStateSet(osg::StateSet* stateSet,
vp->setName("osgEarth OceanCompositor");
stateSet->setAttributeAndModes( vp, 1 );
}
+
vp->installDefaultLightingShaders();
- vp->setShader( "osgearth_vert_setupColoring", new osg::Shader(osg::Shader::VERTEX, source_setupColoring) );
- vp->setShader( "osgearth_frag_applyColoring", new osg::Shader(osg::Shader::FRAGMENT, source_applyColoring ) );
+
+ vp->setShader(
+ "osgearth_vert_setupColoring",
+ new osg::Shader(osg::Shader::VERTEX, source_setupColoring),
+ osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
+
+ vp->setShader(
+ "osgearth_frag_applyColoring",
+ new osg::Shader(osg::Shader::FRAGMENT, source_applyColoring),
+ osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
}
namespace
diff --git a/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer b/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer
index 9f317d5..1f4f551 100644
--- a/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer
+++ b/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer
@@ -28,31 +28,35 @@
#include <osg/Image>
#include <osg/Uniform>
-using namespace osgEarth;
-using namespace osgEarth::Drivers;
-
-class OceanSurfaceContainer : public osg::Group,
- public MapNodeObserver
+namespace osgEarth_ocean_surface
{
-public:
- OceanSurfaceContainer( MapNode* mapNode, const OceanSurfaceOptions& options );
+ using namespace osgEarth;
+ using namespace osgEarth::Drivers;
+
+ class OceanSurfaceContainer : public osg::Group,
+ public MapNodeObserver
+ {
+ public:
+ OceanSurfaceContainer( MapNode* mapNode, const OceanSurfaceOptions& options );
+
+ /** dtor */
+ virtual ~OceanSurfaceContainer() { }
- /** dtor */
- virtual ~OceanSurfaceContainer() { }
+ void apply( const OceanSurfaceOptions& options );
- void apply( const OceanSurfaceOptions& options );
+ public:
+ MapNode* getMapNode() { return _parentMapNode.get(); }
+ void setMapNode( MapNode* mapNode );
-public:
- MapNode* getMapNode() { return _parentMapNode.get(); }
- void setMapNode( MapNode* mapNode );
+ private:
+ osg::observer_ptr<MapNode> _parentMapNode;
+ OceanSurfaceOptions _options;
+ osg::ref_ptr<osg::Uniform> _seaLevel, _lowFeather, _highFeather;
+ osg::ref_ptr<osg::Uniform> _baseColor;
-private:
- osg::observer_ptr<MapNode> _parentMapNode;
- OceanSurfaceOptions _options;
- osg::ref_ptr<osg::Uniform> _seaLevel, _lowFeather, _highFeather;
- osg::ref_ptr<osg::Uniform> _baseColor;
+ void rebuild();
+ };
- void rebuild();
-};
+} // namespace osgEarth_ocean_surface
#endif // OSGEARTH_DRIVER_OCEAN_SURFACE_CONTAINER
diff --git a/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer.cpp b/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer.cpp
index ccfbd0b..1c61ef2 100644
--- a/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer.cpp
+++ b/src/osgEarthDrivers/ocean_surface/OceanSurfaceContainer.cpp
@@ -20,10 +20,8 @@
#include "OceanCompositor"
#include "ElevationProxyImageLayer"
#include <osgEarth/Map>
-#include <osgEarth/ShaderComposition>
#include <osgEarth/TextureCompositor>
#include <osgEarthDrivers/osg/OSGOptions>
-//#include <osgEarthDrivers/engine_osgterrain/OSGTerrainOptions>
#include <osgEarthDrivers/engine_quadtree/QuadTreeTerrainEngineOptions>
#include <osg/CullFace>
@@ -32,6 +30,9 @@
#define LC "[OceanSurface] "
+using namespace osgEarth_ocean_surface;
+
+
OceanSurfaceContainer::OceanSurfaceContainer( MapNode* mapNode, const OceanSurfaceOptions& options ) :
_parentMapNode( mapNode ),
_options ( options )
@@ -80,6 +81,7 @@ OceanSurfaceContainer::rebuild()
// install an "elevation proxy" layer that reads elevation tiles from the
// parent map and turns them into encoded images for our shader to use.
ImageLayerOptions epo( "ocean-proxy" );
+ epo.cachePolicy() = CachePolicy::NO_CACHE;
epo.maxLevel() = *_options.maxLOD();
oceanMap->addImageLayer( new ElevationProxyImageLayer(_parentMapNode->getMap(), epo) );
diff --git a/src/osgEarthDrivers/ocean_surface/ReaderWriterOceanSurface.cpp b/src/osgEarthDrivers/ocean_surface/ReaderWriterOceanSurface.cpp
index 4def40f..37d7414 100644
--- a/src/osgEarthDrivers/ocean_surface/ReaderWriterOceanSurface.cpp
+++ b/src/osgEarthDrivers/ocean_surface/ReaderWriterOceanSurface.cpp
@@ -29,6 +29,7 @@
#undef LC
#define LC "[ReaderWriterOceanSurface] "
+using namespace osgEarth_ocean_surface;
using namespace osgEarth;
using namespace osgEarth::Drivers;
diff --git a/src/osgEarthDrivers/osg/OSGTileSource.cpp b/src/osgEarthDrivers/osg/OSGTileSource.cpp
index 030fa3e..b4a0846 100644
--- a/src/osgEarthDrivers/osg/OSGTileSource.cpp
+++ b/src/osgEarthDrivers/osg/OSGTileSource.cpp
@@ -143,7 +143,7 @@ public:
if ( !_image.valid() || key.getLevelOfDetail() > getMaxDataLevel() )
return NULL;
- GeoImage cropped = _image.crop( key.getExtent(), true, getPixelsPerTile(), getPixelsPerTile() );
+ GeoImage cropped = _image.crop( key.getExtent(), true, getPixelsPerTile(), getPixelsPerTile(), *_options.bilinearReprojection() );
return cropped.valid() ? cropped.takeImage() : 0L;
}
diff --git a/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp b/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp
index ddf6aad..cac28c5 100644
--- a/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp
+++ b/src/osgEarthFeatures/ExtrudeGeometryFilter.cpp
@@ -955,26 +955,8 @@ ExtrudeGeometryFilter::push( FeatureList& input, FilterContext& context )
groupStateSet->setAttributeAndModes( new osg::LineWidth(*_outlineSymbol->stroke()->width()), 1 );
}
-#if 0
- // if we have textures, install a shader to draw them
- if ( _wallSkinSymbol.valid() || _roofSkinSymbol.valid() )
- {
- osg::StateSet* stateSet = group->getOrCreateStateSet();
-
- VirtualProgram* vp = new VirtualProgram();
- vp->setName("ExtrudeGeomFilter");
- vp->installDefaultColoringShaders( 1 );
- stateSet->setAttributeAndModes( vp, osg::StateAttribute::ON );
-
- // a default empty texture will support any non-textured geometry
- osg::Texture2D* tex = new osg::Texture2D( ImageUtils::createEmptyImage() );
- tex->setUnRefImageDataAfterApply( false );
- stateSet->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
- stateSet->getOrCreateUniform("tex0", osg::Uniform::SAMPLER_2D)->set(0);
- }
-#endif
+#if 0 // now called from GeometryCompiler
-#if 1
// generate shaders to draw the geometry.
if ( Registry::capabilities().supportsGLSL() )
{
diff --git a/src/osgEarthFeatures/Feature.cpp b/src/osgEarthFeatures/Feature.cpp
index a84b0b9..7541182 100644
--- a/src/osgEarthFeatures/Feature.cpp
+++ b/src/osgEarthFeatures/Feature.cpp
@@ -437,7 +437,24 @@ Feature::getGeoJSON()
{
for (AttributeTable::const_iterator itr = getAttrs().begin(); itr != getAttrs().end(); ++itr)
- props[itr->first] = itr->second.getString();
+ {
+ if (itr->second.first == ATTRTYPE_INT)
+ {
+ props[itr->first] = itr->second.getInt();
+ }
+ else if (itr->second.first == ATTRTYPE_DOUBLE)
+ {
+ props[itr->first] = itr->second.getDouble();
+ }
+ else if (itr->second.first == ATTRTYPE_BOOL)
+ {
+ props[itr->first] = itr->second.getBool();
+ }
+ else
+ {
+ props[itr->first] = itr->second.getString();
+ }
+ }
}
root["properties"] = props;
@@ -486,4 +503,4 @@ void Feature::transform( const SpatialReference* srs )
getSRS()->transform( geom->asVector(), srs );
}
setSRS( srs );
-}
\ No newline at end of file
+}
diff --git a/src/osgEarthFeatures/FeatureModelGraph b/src/osgEarthFeatures/FeatureModelGraph
index 941c843..9a5882d 100644
--- a/src/osgEarthFeatures/FeatureModelGraph
+++ b/src/osgEarthFeatures/FeatureModelGraph
@@ -74,6 +74,11 @@ namespace osgEarth { namespace Features
void setStyles( StyleSheet* styles );
/**
+ * Session associated with this feature graph.
+ */
+ Session* getSession() { return _session; }
+
+ /**
* Mark the feature graph dirty and in need of regeneration
*/
void dirty();
@@ -85,6 +90,10 @@ namespace osgEarth { namespace Features
*/
void addPostMergeOperation( NodeOperation* op );
+ /**
+ * Access to the features levels
+ */
+ const std::vector<const FeatureLevel*>& getLevels() const { return _lodmap; };
public: // osg::Node
@@ -142,8 +151,6 @@ namespace osgEarth { namespace Features
void redraw();
- void installShaderMains();
-
private:
FeatureModelSourceOptions _options;
osg::ref_ptr<FeatureNodeFactory> _factory;
diff --git a/src/osgEarthFeatures/FeatureModelGraph.cpp b/src/osgEarthFeatures/FeatureModelGraph.cpp
index 18065df..66b5b74 100644
--- a/src/osgEarthFeatures/FeatureModelGraph.cpp
+++ b/src/osgEarthFeatures/FeatureModelGraph.cpp
@@ -27,7 +27,6 @@
#include <osgEarth/FadeEffect>
#include <osgEarth/NodeUtils>
#include <osgEarth/Registry>
-#include <osgEarth/ShaderComposition>
#include <osgEarth/ThreadingUtils>
#include <osg/CullFace>
@@ -124,9 +123,16 @@ struct osgEarthFeatureModelPseudoLoader : public osgDB::ReaderWriter
osg::ref_ptr<FeatureModelGraph> graph = getGraph(uid);
if ( graph.valid() )
- return ReadResult( graph->load( lod, x, y, uri ) );
- else
- return ReadResult::ERROR_IN_READING_FILE;
+ {
+ // Take a reference on the map to avoid map destruction during thread operation
+ osg::ref_ptr<const Map> map = graph->getSession()->getMap();
+ if (map.valid() == true)
+ {
+ return ReadResult( graph->load( lod, x, y, uri ) );
+ }
+ }
+
+ return ReadResult::ERROR_IN_READING_FILE;
}
static UID registerGraph( FeatureModelGraph* graph )
@@ -263,18 +269,25 @@ _pendingUpdate( false )
}
}
- // install base shader mains.
- if ( Registry::instance()->getCapabilities().supportsGLSL() )
- {
- installShaderMains();
- }
+ // Apply some default state. The options properties let you override the
+ // defaults, but we'll set some reasonable state if they are not set.
- // Set up the state set.
- // backface culling is ON by default. By the way, this is most definitely
- // necessary when shading with shadows.
osg::StateSet* stateSet = getOrCreateStateSet();
- stateSet->setMode( GL_CULL_FACE, 1 );
- stateSet->setMode( GL_BLEND, 1 );
+
+ // Set up backface culling. If the option is unset, enable it by default
+ // since shadowing requires it and it's a decent general-purpose setting
+ if ( _options.backfaceCulling().isSet() )
+ stateSet->setMode( GL_CULL_FACE, *_options.backfaceCulling() ? 1 : 0 );
+ else
+ stateSet->setMode( GL_CULL_FACE, 1 );
+
+ // Set up alpha blending. Enable it by default if not specified.
+ if ( _options.alphaBlending().isSet() )
+ stateSet->setMode( GL_BLEND, *_options.alphaBlending() ? 1 : 0 );
+ else
+ stateSet->setMode( GL_BLEND, 1 );
+
+ // Set up lighting, only if the option is set
if ( _options.enableLighting().isSet() )
stateSet->setMode( GL_LIGHTING, *_options.enableLighting() ? 1 : 0 );
@@ -297,12 +310,6 @@ FeatureModelGraph::~FeatureModelGraph()
}
void
-FeatureModelGraph::installShaderMains()
-{
- osg::StateSet* ss = this->getOrCreateStateSet();
-}
-
-void
FeatureModelGraph::dirty()
{
_dirty = true;
diff --git a/src/osgEarthFeatures/FeatureModelSource b/src/osgEarthFeatures/FeatureModelSource
index dbc85a1..d55024b 100644
--- a/src/osgEarthFeatures/FeatureModelSource
+++ b/src/osgEarthFeatures/FeatureModelSource
@@ -72,6 +72,14 @@ namespace osgEarth { namespace Features
optional<bool>& featureIndexing() { return _featureIndexing; }
const optional<bool>& featureIndexing() const { return _featureIndexing; }
+ /** Whether to activate backface culling (default = yes) */
+ optional<bool>& backfaceCulling() { return _backfaceCulling; }
+ const optional<bool>& backfaceCulling() const { return _backfaceCulling; }
+
+ /** Whether to activate alpha blending (default = yes) */
+ optional<bool>& alphaBlending() { return _alphaBlending; }
+ const optional<bool>& alphaBlending() const { return _alphaBlending; }
+
/** Explicity caching policy for data from the underlying feature source */
optional<CachePolicy>& cachePolicy() { return _cachePolicy; }
const optional<CachePolicy>& cachePolicy() const { return _cachePolicy; }
@@ -115,6 +123,8 @@ namespace osgEarth { namespace Features
optional<bool> _mergeGeometry;
optional<bool> _clusterCulling;
optional<bool> _featureIndexing;
+ optional<bool> _backfaceCulling;
+ optional<bool> _alphaBlending;
optional<CachePolicy> _cachePolicy;
optional<float> _fadeInDuration;
diff --git a/src/osgEarthFeatures/FeatureModelSource.cpp b/src/osgEarthFeatures/FeatureModelSource.cpp
index 3274c3e..c15af29 100644
--- a/src/osgEarthFeatures/FeatureModelSource.cpp
+++ b/src/osgEarthFeatures/FeatureModelSource.cpp
@@ -37,6 +37,8 @@ _maxGranularity_deg( 1.0 ),
_mergeGeometry ( false ),
_clusterCulling ( true ),
_featureIndexing ( false ),
+_backfaceCulling ( true ),
+_alphaBlending ( true ),
_fadeInDuration ( 0.0f )
{
fromConfig( _conf );
@@ -59,6 +61,8 @@ FeatureModelSourceOptions::fromConfig( const Config& conf )
conf.getIfSet( "merge_geometry", _mergeGeometry );
conf.getIfSet( "cluster_culling", _clusterCulling );
conf.getIfSet( "feature_indexing", _featureIndexing );
+ conf.getIfSet( "backface_culling", _backfaceCulling );
+ conf.getIfSet( "alpha_blending", _alphaBlending );
conf.getIfSet( "fade_in_duration", _fadeInDuration );
std::string gt = conf.value( "geometry_type" );
@@ -89,6 +93,8 @@ FeatureModelSourceOptions::getConfig() const
conf.updateIfSet( "merge_geometry", _mergeGeometry );
conf.updateIfSet( "cluster_culling", _clusterCulling );
conf.updateIfSet( "feature_indexing", _featureIndexing );
+ conf.updateIfSet( "backface_culling", _backfaceCulling );
+ conf.updateIfSet( "alpha_blending", _alphaBlending );
conf.updateIfSet( "fade_in_duration", _fadeInDuration );
if ( _geomTypeOverride.isSet() ) {
diff --git a/src/osgEarthFeatures/FeatureSource b/src/osgEarthFeatures/FeatureSource
index 11a1e10..9f5726d 100644
--- a/src/osgEarthFeatures/FeatureSource
+++ b/src/osgEarthFeatures/FeatureSource
@@ -32,6 +32,7 @@
#include <osgEarth/Cache>
#include <osgEarth/CachePolicy>
#include <osgEarth/URI>
+#include <osgEarth/Revisioning>
#include <osgDB/ReaderWriter>
#include <OpenThreads/Mutex>
diff --git a/src/osgEarthFeatures/Filter b/src/osgEarthFeatures/Filter
index 272810b..8aad80f 100644
--- a/src/osgEarthFeatures/Filter
+++ b/src/osgEarthFeatures/Filter
@@ -114,10 +114,10 @@ namespace osgEarth { namespace Features
};
#define OSGEARTH_REGISTER_FEATUREFILTER( CLASSNAME )\
- static RegisterFeatureFilterProxy<CLASSNAME> s_osgEarthRegisterFeatureFilterProxy_##CLASSNAME;
+ static osgEarth::Features::RegisterFeatureFilterProxy<CLASSNAME> s_osgEarthRegisterFeatureFilterProxy_##CLASSNAME;
#define OSGEARTH_REGISTER_SIMPLE_FEATUREFILTER( KEY, CLASSNAME)\
- static RegisterFeatureFilterProxy< SimpleFeatureFilterFactory<CLASSNAME> > s_osgEarthRegisterFeatureFilterProxy_##CLASSNAME##KEY(new SimpleFeatureFilterFactory<CLASSNAME>(#KEY));
+ static osgEarth::Features::RegisterFeatureFilterProxy< osgEarth::Features::SimpleFeatureFilterFactory<CLASSNAME> > s_osgEarthRegisterFeatureFilterProxy_##CLASSNAME##KEY(new osgEarth::Features::SimpleFeatureFilterFactory<CLASSNAME>(#KEY));
template<typename T>
diff --git a/src/osgEarthFeatures/GeometryCompiler b/src/osgEarthFeatures/GeometryCompiler
index dcb7b6f..8289c8a 100644
--- a/src/osgEarthFeatures/GeometryCompiler
+++ b/src/osgEarthFeatures/GeometryCompiler
@@ -77,6 +77,9 @@ namespace osgEarth { namespace Features
optional<bool>& useVertexBufferObjects() { return _useVertexBufferObjects;}
const optional<bool>& useVertexBufferObjects() const { return _useVertexBufferObjects;}
+ optional<ShaderPolicy>& shaderPolicy() { return _shaderPolicy; }
+ const optional<ShaderPolicy>& shaderPolicy() const { return _shaderPolicy; }
+
public:
Config getConfig() const;
@@ -93,6 +96,7 @@ namespace osgEarth { namespace Features
optional<double> _resampleMaxLength;
optional<bool> _ignoreAlt;
optional<bool> _useVertexBufferObjects;
+ optional<ShaderPolicy> _shaderPolicy;
void fromConfig( const Config& conf );
};
diff --git a/src/osgEarthFeatures/GeometryCompiler.cpp b/src/osgEarthFeatures/GeometryCompiler.cpp
index 6b3342b..957d905 100644
--- a/src/osgEarthFeatures/GeometryCompiler.cpp
+++ b/src/osgEarthFeatures/GeometryCompiler.cpp
@@ -25,6 +25,10 @@
#include <osgEarthFeatures/ScatterFilter>
#include <osgEarthFeatures/SubstituteModelFilter>
#include <osgEarthFeatures/TessellateOperator>
+#include <osgEarth/Registry>
+#include <osgEarth/Capabilities>
+#include <osgEarth/ShaderGenerator>
+#include <osgEarth/ShaderUtils>
#include <osg/MatrixTransform>
#include <osg/Timer>
#include <osgDB/WriteFile>
@@ -42,6 +46,7 @@ namespace
osg::ref_ptr<PointSymbol> s_defaultPointSymbol = new PointSymbol();
osg::ref_ptr<LineSymbol> s_defaultLineSymbol = new LineSymbol();
osg::ref_ptr<PolygonSymbol> s_defaultPolygonSymbol = new PolygonSymbol();
+ osg::ref_ptr<osg::Program> s_nullProgram = new osg::Program();
}
//-----------------------------------------------------------------------
@@ -53,7 +58,8 @@ _mergeGeometry ( false ),
_clustering ( false ),
_instancing ( false ),
_ignoreAlt ( false ),
-_useVertexBufferObjects( true )
+_useVertexBufferObjects( true ),
+_shaderPolicy ( SHADERPOLICY_GENERATE )
{
fromConfig(_conf);
}
@@ -70,6 +76,10 @@ GeometryCompilerOptions::fromConfig( const Config& conf )
conf.getIfSet ( "geo_interpolation", "great_circle", _geoInterp, GEOINTERP_GREAT_CIRCLE );
conf.getIfSet ( "geo_interpolation", "rhumb_line", _geoInterp, GEOINTERP_RHUMB_LINE );
conf.getIfSet ( "use_vbo", _useVertexBufferObjects);
+
+ conf.getIfSet( "shader_policy", "disable", _shaderPolicy, SHADERPOLICY_DISABLE );
+ conf.getIfSet( "shader_policy", "inherit", _shaderPolicy, SHADERPOLICY_INHERIT );
+ conf.getIfSet( "shader_policy", "generate", _shaderPolicy, SHADERPOLICY_GENERATE );
}
Config
@@ -85,6 +95,10 @@ GeometryCompilerOptions::getConfig() const
conf.addIfSet ( "geo_interpolation", "great_circle", _geoInterp, GEOINTERP_GREAT_CIRCLE );
conf.addIfSet ( "geo_interpolation", "rhumb_line", _geoInterp, GEOINTERP_RHUMB_LINE );
conf.addIfSet ( "use_vbo", _useVertexBufferObjects);
+
+ conf.addIfSet( "shader_policy", "disable", _shaderPolicy, SHADERPOLICY_DISABLE );
+ conf.addIfSet( "shader_policy", "inherit", _shaderPolicy, SHADERPOLICY_INHERIT );
+ conf.addIfSet( "shader_policy", "generate", _shaderPolicy, SHADERPOLICY_GENERATE );
return conf;
}
@@ -417,18 +431,32 @@ GeometryCompiler::compile(FeatureList& workingSet,
}
}
- // Finally, optimize the stateset-sharing in the group.
+ // Common state set cache?
+ osg::ref_ptr<StateSetCache> sscache;
if ( sharedCX.getSession() )
+ sscache = sharedCX.getSession()->getStateSetCache();
+ else
+ sscache = new StateSetCache();
+
+ // Generate shaders, if necessary
+ if (Registry::capabilities().supportsGLSL())
{
- sharedCX.getSession()->getStateSetCache()->optimize( resultGroup.get() );
- //OE_INFO << LC << "state set cache size = " << sharedCX.getSession()->getStateSetCache()->size() << std::endl;
- }
- else
- {
- StateSetCache tempCache;
- tempCache.optimize( resultGroup.get() );
+ if ( _options.shaderPolicy() == SHADERPOLICY_GENERATE )
+ {
+ ShaderGenerator gen( 0L );
+ resultGroup->accept( gen );
+ }
+ else if ( _options.shaderPolicy() == SHADERPOLICY_DISABLE )
+ {
+ resultGroup->getOrCreateStateSet()->setAttributeAndModes(
+ s_nullProgram,
+ osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE );
+ }
}
+ // Optimize stateset sharing.
+ sscache->optimize( resultGroup.get() );
+
//osgDB::writeNodeFile( *(resultGroup.get()), "out.osg" );
diff --git a/src/osgEarthFeatures/Session b/src/osgEarthFeatures/Session
index 1b39387..921b60a 100644
--- a/src/osgEarthFeatures/Session
+++ b/src/osgEarthFeatures/Session
@@ -25,6 +25,8 @@
#include <osgEarthSymbology/StyleSheet>
#include <osgEarth/StateSetCache>
#include <osgEarth/ThreadingUtils>
+#include <osgEarth/MapInfo>
+#include <osgEarth/MapFrame>
#include <osgEarth/Map>
namespace osgEarth { namespace Features
@@ -72,6 +74,11 @@ namespace osgEarth { namespace Features
*/
const MapInfo& getMapInfo() const { return _mapInfo; }
+ /**
+ * Gets the map related to this session. Be carefull, this is held by an osg::observer_ptr and may be NULL
+ */
+ const Map* getMap() const { return _map.get(); }
+
/** The style sheet governing this session. */
void setStyles( StyleSheet* value );
StyleSheet* styles() const { return _styles.get(); }
diff --git a/src/osgEarthFeatures/SubstituteModelFilter.cpp b/src/osgEarthFeatures/SubstituteModelFilter.cpp
index 4640c9e..d92baf8 100644
--- a/src/osgEarthFeatures/SubstituteModelFilter.cpp
+++ b/src/osgEarthFeatures/SubstituteModelFilter.cpp
@@ -20,7 +20,7 @@
#include <osgEarthFeatures/FeatureSourceIndexNode>
#include <osgEarthSymbology/MeshConsolidator>
#include <osgEarth/ECEF>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/ShaderGenerator>
#include <osgEarth/DrawInstanced>
#include <osgEarth/Registry>
@@ -273,11 +273,14 @@ SubstituteModelFilter::process(const FeatureList& features,
attachPoint->getOrCreateStateSet()->setAttributeAndModes( p, osg::StateAttribute::ON );
}
+#if 0 // now called from GeometryCompiler
+
// Generate shader code to render the models
StateSetCache* cache = context.getSession() ? context.getSession()->getStateSetCache() : 0L;
ShaderGenerator gen( cache );
attachPoint->accept( gen );
+#endif
return true;
}
diff --git a/src/osgEarthFeatures/TessellateOperator b/src/osgEarthFeatures/TessellateOperator
index 959bfa8..e3f43dc 100644
--- a/src/osgEarthFeatures/TessellateOperator
+++ b/src/osgEarthFeatures/TessellateOperator
@@ -32,6 +32,29 @@ namespace osgEarth { namespace Features
*/
class OSGEARTHFEATURES_EXPORT TessellateOperator
{
+ public: // static methods
+
+ /**
+ * Tessellates a straight line into multiple segments.
+ */
+ static void tessellateLinear(
+ const osg::Vec3d& p0,
+ const osg::Vec3d& p1,
+ unsigned parts,
+ std::vector<osg::Vec3d>& out );
+
+ /**
+ * Tessellates a geographic line (great circle or rhumb) between
+ * two geographic points (long,lat,alt) into multiple segments along
+ * a spheroid.
+ */
+ static void tessellateGeo(
+ const osg::Vec3d& p0,
+ const osg::Vec3d& p1,
+ unsigned parts,
+ GeoInterpolation interp,
+ std::vector<osg::Vec3d>& out );
+
public:
/**
* Constructs a new tessellation operator.
diff --git a/src/osgEarthFeatures/TessellateOperator.cpp b/src/osgEarthFeatures/TessellateOperator.cpp
index 7d04536..3665a13 100644
--- a/src/osgEarthFeatures/TessellateOperator.cpp
+++ b/src/osgEarthFeatures/TessellateOperator.cpp
@@ -25,56 +25,55 @@ using namespace osgEarth::Symbology;
//------------------------------------------------------------------------
-namespace
+void
+TessellateOperator::tessellateLinear( const osg::Vec3d& p0, const osg::Vec3d& p1, unsigned parts, Vec3dVector& out )
{
- void tessellateLinear( const osg::Vec3d& p0, const osg::Vec3d& p1, unsigned parts, Vec3dVector& out )
+ osg::Vec3d vec = (p1-p0)/double(parts);
+ out.push_back( p0 );
+ for( unsigned i=1; i<parts; ++i )
{
- osg::Vec3d vec = (p1-p0)/double(parts);
- out.push_back( p0 );
- for( unsigned i=1; i<parts; ++i )
- {
- out.push_back( p0 + vec*double(i) );
- }
+ out.push_back( p0 + vec*double(i) );
}
+}
- void tessellateGeo( const osg::Vec3d& p0, const osg::Vec3d& p1, unsigned parts, GeoInterpolation interp, Vec3dVector& out )
- {
- double step = 1.0/double(parts);
- double zdelta = p1.z() - p0.z();
-
- out.push_back( p0 );
+void
+TessellateOperator::tessellateGeo( const osg::Vec3d& p0, const osg::Vec3d& p1, unsigned parts, GeoInterpolation interp, Vec3dVector& out )
+{
+ double step = 1.0/double(parts);
+ double zdelta = p1.z() - p0.z();
- for( unsigned i=1; i<parts; ++i )
- {
- double t = step*double(i);
- osg::Vec3d p;
+ out.push_back( p0 );
- if ( interp == GEOINTERP_GREAT_CIRCLE )
- {
- double lat, lon;
- GeoMath::interpolate(
- osg::DegreesToRadians(p0.y()), osg::DegreesToRadians(p0.x()),
- osg::DegreesToRadians(p1.y()), osg::DegreesToRadians(p1.x()),
- t,
- lat, lon );
- p.set( osg::RadiansToDegrees(lon), osg::RadiansToDegrees(lat), p0.z() + t*zdelta );
- }
- else // GEOINTERP_RHUMB_LINE
- {
- double lat1 = osg::DegreesToRadians(p0.y()), lon1 = osg::DegreesToRadians(p1.x());
- double lat2 = osg::DegreesToRadians(p1.y()), lon2 = osg::DegreesToRadians(p1.x());
+ for( unsigned i=1; i<parts; ++i )
+ {
+ double t = step*double(i);
+ osg::Vec3d p;
- double distance = GeoMath::rhumbDistance( lat1, lon1, lat2, lon2 );
- double bearing = GeoMath::rhumbBearing( lat1, lon1, lat2, lon2 );
+ if ( interp == GEOINTERP_GREAT_CIRCLE )
+ {
+ double lat, lon;
+ GeoMath::interpolate(
+ osg::DegreesToRadians(p0.y()), osg::DegreesToRadians(p0.x()),
+ osg::DegreesToRadians(p1.y()), osg::DegreesToRadians(p1.x()),
+ t,
+ lat, lon );
+ p.set( osg::RadiansToDegrees(lon), osg::RadiansToDegrees(lat), p0.z() + t*zdelta );
+ }
+ else // GEOINTERP_RHUMB_LINE
+ {
+ double lat1 = osg::DegreesToRadians(p0.y()), lon1 = osg::DegreesToRadians(p1.x());
+ double lat2 = osg::DegreesToRadians(p1.y()), lon2 = osg::DegreesToRadians(p1.x());
- double lat3, lon3;
- GeoMath::rhumbDestination(lat1, lon1, bearing, distance, lat3, lon3);
+ double distance = GeoMath::rhumbDistance( lat1, lon1, lat2, lon2 );
+ double bearing = GeoMath::rhumbBearing( lat1, lon1, lat2, lon2 );
- p.set( osg::RadiansToDegrees(lon3), osg::RadiansToDegrees(lat3), p0.z() + t*zdelta );
- }
+ double lat3, lon3;
+ GeoMath::rhumbDestination(lat1, lon1, bearing, distance, lat3, lon3);
- out.push_back(p);
+ p.set( osg::RadiansToDegrees(lon3), osg::RadiansToDegrees(lat3), p0.z() + t*zdelta );
}
+
+ out.push_back(p);
}
}
diff --git a/src/osgEarthQt/AnnotationDialogs.cpp b/src/osgEarthQt/AnnotationDialogs.cpp
index 8325fa9..af877cd 100644
--- a/src/osgEarthQt/AnnotationDialogs.cpp
+++ b/src/osgEarthQt/AnnotationDialogs.cpp
@@ -1082,4 +1082,4 @@ void AddEllipseDialog::onFillColorButtonClicked()
updateButtonColorStyle(_fillColorButton, color);
}
-}
\ No newline at end of file
+}
diff --git a/src/osgEarthQt/AnnotationToolbar.cpp b/src/osgEarthQt/AnnotationToolbar.cpp
index 8b5ee89..4b9c0f6 100644
--- a/src/osgEarthQt/AnnotationToolbar.cpp
+++ b/src/osgEarthQt/AnnotationToolbar.cpp
@@ -175,4 +175,4 @@ void AnnotationToolbar::onAddFinished(int result)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/osgEarthQt/DataManager.cpp b/src/osgEarthQt/DataManager.cpp
index d0a9b7a..6dd6f47 100644
--- a/src/osgEarthQt/DataManager.cpp
+++ b/src/osgEarthQt/DataManager.cpp
@@ -19,6 +19,7 @@
#include <osgEarthQt/DataManager>
#include <osgEarth/Map>
+#include <osgEarth/MapModelChange>
#include <osgEarth/MapNode>
using namespace osgEarth::QtGui;
diff --git a/src/osgEarthQt/TerrainProfileWidget.cpp b/src/osgEarthQt/TerrainProfileWidget.cpp
index ac78b4d..fdeb971 100644
--- a/src/osgEarthQt/TerrainProfileWidget.cpp
+++ b/src/osgEarthQt/TerrainProfileWidget.cpp
@@ -285,4 +285,4 @@ void TerrainProfileWidget::drawProfileLine()
}
refreshViews();
-}
\ No newline at end of file
+}
diff --git a/src/osgEarthSymbology/Expression.cpp b/src/osgEarthSymbology/Expression.cpp
index 16a7cce..2cc18c1 100644
--- a/src/osgEarthSymbology/Expression.cpp
+++ b/src/osgEarthSymbology/Expression.cpp
@@ -78,18 +78,53 @@ NumericExpression::init()
{
_vars.clear();
_rpn.clear();
- StringTokenizer tokenizer( "", "" );
- tokenizer.addDelims( "[],()%*/+-", true );
- tokenizer.addQuotes( "'\"", true );
- tokenizer.keepEmpties() = false;
+
+ StringTokenizer variablesTokenizer( "", "" );
+ variablesTokenizer.addDelims( "[]", true );
+ variablesTokenizer.addQuotes( "'\"", true );
+ variablesTokenizer.keepEmpties() = false;
+
+ StringTokenizer operandTokenizer( "", "" );
+ operandTokenizer.addDelims( ",()%*/+-", true );
+ operandTokenizer.addQuotes( "'\"", true );
+ operandTokenizer.keepEmpties() = false;
+
+ StringVector variablesTokens;
+ variablesTokenizer.tokenize( _src, variablesTokens );
StringVector t;
- tokenizer.tokenize( _src, t );
- //tokenize(_src, t, "[],()%*/+-", "'\"", false, true);
+ bool invar = false;
+ for( unsigned i=0; i<variablesTokens.size(); ++i )
+ {
+ if ( variablesTokens[i] == "[" && !invar )
+ {
+ // Start variable, add "[" token
+ invar = true;
+ t.push_back(variablesTokens[i]);
+ }
+ else if ( variablesTokens[i] == "]" && invar )
+ {
+ // End variable, add "]" token
+ invar = false;
+ t.push_back(variablesTokens[i]);
+ }
+ else if ( invar )
+ {
+ // Variable, add variable token
+ t.push_back(variablesTokens[i]);
+ }
+ else
+ {
+ // Operands, tokenize it and add tokens
+ StringVector operandTokens;
+ operandTokenizer.tokenize( variablesTokens[i], operandTokens );
+ t.insert(t.end(), operandTokens.begin(), operandTokens.end());
+ }
+ }
// identify tokens:
AtomVector infix;
- bool invar = false;
+ invar = false;
for( unsigned i=0; i<t.size(); ++i ) {
if ( t[i] == "[" && !invar ) {
invar = true;
diff --git a/src/osgEarthSymbology/SLD.cpp b/src/osgEarthSymbology/SLD.cpp
index b304912..47ba905 100644
--- a/src/osgEarthSymbology/SLD.cpp
+++ b/src/osgEarthSymbology/SLD.cpp
@@ -148,6 +148,11 @@ SLDReader::readStyleFromCSSParams( const Config& conf, Style& sc )
if (!text) text = sc.getOrCreateSymbol<TextSymbol>();
text->halo()->color() = htmlColorToVec4f( value );
}
+ else if ( match(key, "text-halo-offset") )
+ {
+ if (!text) text = sc.getOrCreateSymbol<TextSymbol>();
+ text->haloOffset() = as<float>(value, 0.07f);
+ }
else if ( match(key, "text-remove-duplicate-labels") )
{
if (!text) text = sc.getOrCreateSymbol<TextSymbol>();
diff --git a/src/osgEarthSymbology/Skins.cpp b/src/osgEarthSymbology/Skins.cpp
index 900508f..26b77bc 100644
--- a/src/osgEarthSymbology/Skins.cpp
+++ b/src/osgEarthSymbology/Skins.cpp
@@ -19,7 +19,6 @@
#include <osgEarthSymbology/Skins>
#include <osgEarth/StringUtils>
#include <osgEarth/ImageUtils>
-#include <osgEarth/ShaderComposition>
#include <osgEarth/Registry>
#include <osg/BlendFunc>
diff --git a/src/osgEarthSymbology/TextSymbol b/src/osgEarthSymbology/TextSymbol
index bd9c6dd..2b511b7 100644
--- a/src/osgEarthSymbology/TextSymbol
+++ b/src/osgEarthSymbology/TextSymbol
@@ -33,12 +33,12 @@ namespace osgEarth { namespace Symbology
class OSGEARTHSYMBOLOGY_EXPORT TextSymbol : public Symbol
{
public:
- enum Encoding {
+ enum Encoding {
ENCODING_ASCII,
ENCODING_UTF8,
ENCODING_UTF16,
- ENCODING_UTF32
- };
+ ENCODING_UTF32
+ };
// note: these are identical to the values in osgText::Text::AlignmentType
enum Alignment {
@@ -78,6 +78,10 @@ namespace osgEarth { namespace Symbology
optional<Stroke>& halo() { return _halo; }
const optional<Stroke>& halo() const { return _halo; }
+ /** Text outline offset */
+ optional<float>& haloOffset() { return _haloOffset; }
+ const optional<float>& haloOffset() const { return _haloOffset; }
+
/** Name of text font. */
optional<std::string>& font() { return _font; }
const optional<std::string>& font() const { return _font; }
@@ -125,6 +129,7 @@ namespace osgEarth { namespace Symbology
protected:
optional<Fill> _fill;
optional<Stroke> _halo;
+ optional<float> _haloOffset;
optional<std::string> _font;
optional<float> _size;
optional<StringExpression> _content;
@@ -132,7 +137,7 @@ namespace osgEarth { namespace Symbology
optional<bool> _removeDuplicateLabels;
optional<osg::Vec2s> _pixelOffset;
optional<std::string> _provider;
- optional<Encoding> _encoding;
+ optional<Encoding> _encoding;
optional<Alignment> _alignment;
optional<bool> _declutter;
};
diff --git a/src/osgEarthSymbology/TextSymbol.cpp b/src/osgEarthSymbology/TextSymbol.cpp
index c29eac1..08f0834 100644
--- a/src/osgEarthSymbology/TextSymbol.cpp
+++ b/src/osgEarthSymbology/TextSymbol.cpp
@@ -25,6 +25,7 @@ TextSymbol::TextSymbol( const Config& conf ) :
Symbol ( conf ),
_fill ( Fill( 1, 1, 1, 1 ) ),
_halo ( Stroke( 0.3, 0.3, 0.3, 1) ),
+_haloOffset ( 0.07f ),
_size ( 16.0f ),
_removeDuplicateLabels( false ),
_alignment ( ALIGN_BASE_LINE ),
@@ -42,6 +43,7 @@ TextSymbol::getConfig() const
conf.key() = "text";
conf.addObjIfSet( "fill", _fill );
conf.addObjIfSet( "halo", _halo );
+ conf.addIfSet( "halo_offset", _haloOffset );
conf.addIfSet( "font", _font );
conf.addIfSet( "size", _size );
conf.addObjIfSet( "content", _content );
@@ -53,16 +55,6 @@ TextSymbol::getConfig() const
conf.addIfSet( "encoding", "utf16", _encoding, ENCODING_UTF16 );
conf.addIfSet( "encoding", "utf32", _encoding, ENCODING_UTF32 );
-#if 0
- conf.addIfSet( "halign", "left", _halign, HALIGN_LEFT );
- conf.addIfSet( "halign", "center", _halign, HALIGN_CENTER );
- conf.addIfSet( "halign", "right", _halign, HALIGN_RIGHT );
-
- conf.addIfSet( "valign", "top", _valign, VALIGN_TOP );
- conf.addIfSet( "valign", "center", _valign, VALIGN_CENTER );
- conf.addIfSet( "valign", "bottom", _valign, VALIGN_BOTTOM );
-#endif
-
conf.addIfSet( "alignment", "left_top", _alignment, ALIGN_LEFT_TOP );
conf.addIfSet( "alignment", "left_center", _alignment, ALIGN_LEFT_CENTER );
conf.addIfSet( "alignment", "left_bottom", _alignment, ALIGN_LEFT_BOTTOM );
@@ -80,18 +72,6 @@ TextSymbol::getConfig() const
conf.addIfSet( "alignment", "right_bottom_base_line", _alignment, ALIGN_RIGHT_BOTTOM_BASE_LINE );
conf.addIfSet( "alignment", "base_line", _alignment, ALIGN_BASE_LINE );
-#if 0
- conf.addIfSet( "rotate_to_screen", _rotateToScreen );
- conf.addIfSet( "size_mode", "screen", _sizeMode, SIZEMODE_SCREEN );
- conf.addIfSet( "size_mode", "object", _sizeMode, SIZEMODE_OBJECT );
- conf.addIfSet( "line_orientation", "parallel", _lineOrientation, LINEORIENTATION_PARALLEL );
- conf.addIfSet( "line_orientation", "perpendicular", _lineOrientation, LINEORIENTATION_PERPENDICULAR );
- conf.addIfSet( "line_orientation", "horizontal", _lineOrientation, LINEORIENTATION_HORIZONTAL );
- conf.addIfSet( "line_placement", "along_line", _linePlacement, LINEPLACEMENT_ALONG_LINE );
- conf.addIfSet( "line_placement", "centroid", _linePlacement, LINEPLACEMENT_CENTROID );
- conf.addIfSet( "theme", _theme );
-#endif
-
conf.addIfSet( "declutter", _declutter );
conf.addIfSet( "provider", _provider );
@@ -107,6 +87,7 @@ TextSymbol::mergeConfig( const Config& conf )
{
conf.getObjIfSet( "fill", _fill );
conf.getObjIfSet( "halo", _halo );
+ conf.getIfSet( "halo_offset", _haloOffset );
conf.getIfSet( "font", _font );
conf.getIfSet( "size", _size );
conf.getObjIfSet( "content", _content );
@@ -135,18 +116,6 @@ TextSymbol::mergeConfig( const Config& conf )
conf.getIfSet( "alignment", "right_bottom_base_line", _alignment, ALIGN_RIGHT_BOTTOM_BASE_LINE );
conf.getIfSet( "alignment", "base_line" , _alignment, ALIGN_BASE_LINE );
-#if 0
- conf.getIfSet( "rotate_to_screen", _rotateToScreen );
- conf.getIfSet( "size_mode", "screen", _sizeMode, SIZEMODE_SCREEN );
- conf.getIfSet( "size_mode", "object", _sizeMode, SIZEMODE_OBJECT );
- conf.getIfSet( "line_orientation", "parallel", _lineOrientation, LINEORIENTATION_PARALLEL );
- conf.getIfSet( "line_orientation", "perpendicular", _lineOrientation, LINEORIENTATION_PERPENDICULAR );
- conf.getIfSet( "line_orientation", "horizontal", _lineOrientation, LINEORIENTATION_HORIZONTAL );
- conf.getIfSet( "line_placement", "along_line", _linePlacement, LINEPLACEMENT_ALONG_LINE );
- conf.getIfSet( "line_placement", "centroid", _linePlacement, LINEPLACEMENT_CENTROID );
- conf.getIfSet( "theme", _theme );
-#endif
-
conf.getIfSet( "declutter", _declutter );
conf.getIfSet( "provider", _provider );
diff --git a/src/osgEarthUtil/BrightnessContrastColorFilter.cpp b/src/osgEarthUtil/BrightnessContrastColorFilter.cpp
index 5ff497b..fa8ef57 100644
--- a/src/osgEarthUtil/BrightnessContrastColorFilter.cpp
+++ b/src/osgEarthUtil/BrightnessContrastColorFilter.cpp
@@ -19,7 +19,7 @@
* Original author: Thomas Lerman
*/
#include <osgEarthUtil/BrightnessContrastColorFilter>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/StringUtils>
#include <osgEarth/ThreadingUtils>
#include <osg/Program>
diff --git a/src/osgEarthUtil/CMYKColorFilter.cpp b/src/osgEarthUtil/CMYKColorFilter.cpp
index 28c3d98..c7f871c 100644
--- a/src/osgEarthUtil/CMYKColorFilter.cpp
+++ b/src/osgEarthUtil/CMYKColorFilter.cpp
@@ -19,7 +19,7 @@
* Original author: Thomas Lerman
*/
#include <osgEarthUtil/CMYKColorFilter>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/StringUtils>
#include <osgEarth/ThreadingUtils>
#include <osg/Program>
diff --git a/src/osgEarthUtil/ChromaKeyColorFilter.cpp b/src/osgEarthUtil/ChromaKeyColorFilter.cpp
index 3b32f8e..b088a66 100644
--- a/src/osgEarthUtil/ChromaKeyColorFilter.cpp
+++ b/src/osgEarthUtil/ChromaKeyColorFilter.cpp
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <osgEarthUtil/ChromaKeyColorFilter>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/StringUtils>
#include <osgEarth/ThreadingUtils>
#include <osg/Program>
@@ -151,7 +151,7 @@ Config
ChromaKeyColorFilter::getConfig() const
{
osg::Vec3f val = getColor();
- Config conf("rgb");
+ Config conf("chroma_key");
conf.add( "r", val[0] );
conf.add( "g", val[1] );
conf.add( "b", val[2] );
diff --git a/src/osgEarthUtil/Controls b/src/osgEarthUtil/Controls
index 89f9366..1c3482b 100644
--- a/src/osgEarthUtil/Controls
+++ b/src/osgEarthUtil/Controls
@@ -828,7 +828,8 @@ namespace osgEarth { namespace Util { namespace Controls
bool _contextDirty;
bool _updatePending;
- std::map<osgGA::GUIEventHandler*, osgViewer::View*> _eventHandlersMap;
+ typedef std::map< osg::observer_ptr<osgGA::GUIEventHandler>, osg::observer_ptr<osgViewer::View> > EventHandlersMap;
+ EventHandlersMap _eventHandlersMap;
osg::ref_ptr<ControlNodeBin> _controlNodeBin;
diff --git a/src/osgEarthUtil/Controls.cpp b/src/osgEarthUtil/Controls.cpp
index 1d83b0d..80c3195 100644
--- a/src/osgEarthUtil/Controls.cpp
+++ b/src/osgEarthUtil/Controls.cpp
@@ -1090,17 +1090,17 @@ HSliderControl::draw( const ControlContext& cx, DrawableList& out )
g->setVertexArray( verts );
(*verts)[0].set( rx, vph - ry, 0 );
- (*verts)[1].set( rx + rw, vph - ry, 0 );
+ (*verts)[1].set( rx, vph - (ry + rh), 0 );
(*verts)[2].set( rx + rw, vph - (ry + rh), 0 );
- (*verts)[3].set( rx, vph - (ry + rh), 0 );
+ (*verts)[3].set( rx + rw, vph - ry, 0 );
g->addPrimitiveSet( new osg::DrawArrays( GL_LINE_LOOP, 0, 4 ) );
float hx = rx + rw * ( (_value-_min)/(_max-_min) );
(*verts)[4].set( hx-4, vph - ry + 3, 0 );
- (*verts)[5].set( hx+4, vph - ry + 3, 0 );
+ (*verts)[5].set( hx-4, vph - (ry + rh + 3), 0 );
(*verts)[6].set( hx+4, vph - (ry + rh + 3), 0 );
- (*verts)[7].set( hx-4, vph - (ry + rh + 3), 0 );
+ (*verts)[7].set( hx+4, vph - ry + 3, 0 );
g->addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 4, 4 ) );
osg::Vec4Array* c = new osg::Vec4Array(1);
@@ -2497,14 +2497,16 @@ ControlCanvas::~ControlCanvas()
OpenThreads::ScopedLock<OpenThreads::Mutex> lock( _viewCanvasMapMutex );
_viewCanvasMap.erase( _context._view );
- // commented out: causing a crash on exit
-#if 0
- std::map<osgGA::GUIEventHandler*, osgViewer::View*>::iterator itr;
+ EventHandlersMap::iterator itr;
for (itr = _eventHandlersMap.begin(); itr != _eventHandlersMap.end(); ++itr)
{
- itr->second->removeEventHandler(itr->first);
+ osgGA::GUIEventHandler* pGUIEventHandler = itr->first.get();
+ osgViewer::View* pView = itr->second.get();
+ if ( (pView != NULL) && (pGUIEventHandler != NULL) )
+ {
+ pView->removeEventHandler(pGUIEventHandler);
+ }
}
-#endif
}
void
diff --git a/src/osgEarthUtil/EarthManipulator b/src/osgEarthUtil/EarthManipulator
index df50c9c..0b7b92e 100644
--- a/src/osgEarthUtil/EarthManipulator
+++ b/src/osgEarthUtil/EarthManipulator
@@ -24,9 +24,9 @@
#include <osgEarth/Viewpoint>
#include <osgEarth/GeoData>
#include <osgEarth/Revisioning>
+#include <osgEarth/Terrain>
#include <osg/Timer>
#include <osgGA/CameraManipulator>
-#include <osgEarth/Terrain>
#include <map>
#include <list>
#include <utility>
diff --git a/src/osgEarthUtil/EarthManipulator.cpp b/src/osgEarthUtil/EarthManipulator.cpp
index 3a719c3..92239e7 100644
--- a/src/osgEarthUtil/EarthManipulator.cpp
+++ b/src/osgEarthUtil/EarthManipulator.cpp
@@ -2017,6 +2017,42 @@ EarthManipulator::zoom( double dx, double dy )
}
+namespace
+{
+ // osg::View::getCameraContainingPosition has a bug in it. If the camera's current event
+ // state is not up to date (after a window resize, for example), it still uses that event
+ // state to get the window's current size instead of using the Viewport.
+ //
+ // This version works around that
+
+ const osg::Camera*
+ getCameraContainingPosition(osgViewer::View* view, float x, float y, float& out_local_x, float& out_local_y)
+ {
+ osg::Camera* camera = view->getCamera();
+ osg::Viewport* viewport = camera->getViewport();
+
+ if ( camera->getGraphicsContext() && viewport )
+ {
+ double new_x = x;
+ double new_y = y;
+
+ const double epsilon = 0.5;
+
+ if (
+ new_x >= (viewport->x()-epsilon) && new_y >= (viewport->y()-epsilon) &&
+ new_x < (viewport->x()+viewport->width()-1.0+epsilon) && new_y <= (viewport->y()+viewport->height()-1.0+epsilon) )
+ {
+ out_local_x = new_x;
+ out_local_y = new_y;
+ return camera;
+ }
+ }
+
+ return view->getCameraContainingPosition(x, y, out_local_x, out_local_y);
+ }
+}
+
+
bool
EarthManipulator::screenToWorld(float x, float y, osg::View* theView, osg::Vec3d& out_coords ) const
{
@@ -2030,7 +2066,7 @@ EarthManipulator::screenToWorld(float x, float y, osg::View* theView, osg::Vec3d
return false;
float local_x, local_y = 0.0;
- const osg::Camera* camera = view->getCameraContainingPosition(x, y, local_x, local_y);
+ const osg::Camera* camera = getCameraContainingPosition(view, x, y, local_x, local_y);
if ( !camera )
return false;
@@ -2157,6 +2193,9 @@ EarthManipulator::handlePointAction( const Action& action, float mx, float my, o
osg::Vec3d pointVP;
here.getSRS()->transformFromWorld(point, pointVP);
+
+ //OE_NOTICE << "X=" << pointVP.x() << ", Y=" << pointVP.y() << std::endl;
+
here.setFocalPoint( pointVP );
double duration_s = action.getDoubleOption(OPTION_DURATION, 1.0);
diff --git a/src/osgEarthUtil/ElevationManager b/src/osgEarthUtil/ElevationManager
index 6f2eeaa..4829f99 100644
--- a/src/osgEarthUtil/ElevationManager
+++ b/src/osgEarthUtil/ElevationManager
@@ -20,8 +20,7 @@
#define OSGEARTHUTIL_ELEVATION_MANAGER_H
#include <osgEarthUtil/Common>
-#include <osgEarth/Map>
-#include <osgEarth/MapNode>
+#include <osgEarth/MapFrame>
namespace osgEarth { namespace Util
{
diff --git a/src/osgEarthUtil/ExampleResources.cpp b/src/osgEarthUtil/ExampleResources.cpp
index ea3028a..f551831 100644
--- a/src/osgEarthUtil/ExampleResources.cpp
+++ b/src/osgEarthUtil/ExampleResources.cpp
@@ -381,6 +381,7 @@ AnnotationGraphControlFactory::create(osg::Node* graph,
osgViewer::View* view) const
{
AnnoControlBuilder builder( view );
+ builder.setNodeMaskOverride(~0);
if ( graph )
graph->accept( builder );
@@ -456,6 +457,7 @@ MapNodeHelper::parse(MapNode* mapNode,
osg::Group* root,
Control* userControl ) const
{
+ // this is a dubious move.
if ( !root )
root = mapNode;
@@ -629,7 +631,17 @@ MapNodeHelper::parse(MapNode* mapNode,
// Install an auto clip plane clamper
if ( useAutoClip )
{
- view->getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode) );
+#if 0
+ HorizonClipNode* hcn = new HorizonClipNode( mapNode );
+ if ( mapNode->getNumParents() == 1 )
+ {
+ osg::Group* parent = mapNode->getParent(0);
+ hcn->addChild( mapNode );
+ parent->replaceChild( mapNode, hcn );
+ }
+#else
+ mapNode->addCullCallback( new AutoClipPlaneCullCallback(mapNode) );
+#endif
}
root->addChild( canvas );
diff --git a/src/osgEarthUtil/GammaColorFilter.cpp b/src/osgEarthUtil/GammaColorFilter.cpp
index 13d8477..1f53a58 100644
--- a/src/osgEarthUtil/GammaColorFilter.cpp
+++ b/src/osgEarthUtil/GammaColorFilter.cpp
@@ -19,7 +19,7 @@
* Original author: Thomas Lerman
*/
#include <osgEarthUtil/GammaColorFilter>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/StringUtils>
#include <osgEarth/ThreadingUtils>
#include <osg/Program>
@@ -147,4 +147,4 @@ GammaColorFilter::getConfig() const
conf.add("b", rgb[2]);
}
return conf;
-}
\ No newline at end of file
+}
diff --git a/src/osgEarthUtil/HSLColorFilter.cpp b/src/osgEarthUtil/HSLColorFilter.cpp
index a784922..7efd4a2 100644
--- a/src/osgEarthUtil/HSLColorFilter.cpp
+++ b/src/osgEarthUtil/HSLColorFilter.cpp
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <osgEarthUtil/HSLColorFilter>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/StringUtils>
#include <osgEarth/ThreadingUtils>
#include <osg/Program>
diff --git a/src/osgEarthUtil/RGBColorFilter.cpp b/src/osgEarthUtil/RGBColorFilter.cpp
index e002321..cc53e3f 100644
--- a/src/osgEarthUtil/RGBColorFilter.cpp
+++ b/src/osgEarthUtil/RGBColorFilter.cpp
@@ -19,7 +19,7 @@
* Original author: Thomas Lerman
*/
#include <osgEarthUtil/RGBColorFilter>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/StringUtils>
#include <osgEarth/ThreadingUtils>
#include <osg/Program>
diff --git a/src/osgEarthUtil/ShadowUtils.cpp b/src/osgEarthUtil/ShadowUtils.cpp
index ae5d3d2..0dbfcfa 100644
--- a/src/osgEarthUtil/ShadowUtils.cpp
+++ b/src/osgEarthUtil/ShadowUtils.cpp
@@ -21,7 +21,7 @@
#include <osgEarth/MapNode>
#include <osgEarth/NodeUtils>
#include <osgEarth/Notify>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/TextureCompositor>
#include <osgEarth/Registry>
@@ -128,37 +128,39 @@ ShadowUtils::setUpShadows(osgShadow::ShadowedScene* sscene, osg::Group* root)
std::stringstream buf;
buf << "#version " << GLSL_VERSION_STR << "\n";
- buf << "varying vec4 colorAmbientEmissive;\n";
- buf << "varying vec4 shadow_TexCoord0;\n";
+#ifdef OSG_GLES2_AVAILABLE
+ buf << "precision mediump float;\n";
+#endif
+ buf << "varying vec4 oe_shadow_ambient;\n";
+ buf << "varying vec4 oe_shadow_TexCoord0;\n";
if ( su1 >= 0 )
- buf << "varying vec4 shadow_TexCoord1;\n";
+ buf << "varying vec4 oe_shadow_TexCoord1;\n";
- buf << "void osgearth_vert_setupShadowCoords()\n";
+ buf << "void oe_shadow_setupShadowCoords()\n";
buf << "{\n";
buf << " vec4 position4 = gl_ModelViewMatrix * gl_Vertex;\n";
- buf << " shadow_TexCoord0.s = dot( position4, gl_EyePlaneS[" << su <<"]);\n";
- buf << " shadow_TexCoord0.t = dot( position4, gl_EyePlaneT[" << su <<"]);\n";
- buf << " shadow_TexCoord0.p = dot( position4, gl_EyePlaneR[" << su <<"]);\n";
- buf << " shadow_TexCoord0.q = dot( position4, gl_EyePlaneQ[" << su <<"]);\n";
+ buf << " oe_shadow_TexCoord0.s = dot( position4, gl_EyePlaneS[" << su <<"]);\n";
+ buf << " oe_shadow_TexCoord0.t = dot( position4, gl_EyePlaneT[" << su <<"]);\n";
+ buf << " oe_shadow_TexCoord0.p = dot( position4, gl_EyePlaneR[" << su <<"]);\n";
+ buf << " oe_shadow_TexCoord0.q = dot( position4, gl_EyePlaneQ[" << su <<"]);\n";
if (su1 >= 0)
{
- buf << " shadow_TexCoord1.s = dot( position4, gl_EyePlaneS[" << su1 <<"]);\n";
- buf << " shadow_TexCoord1.t = dot( position4, gl_EyePlaneT[" << su1 <<"]);\n";
- buf << " shadow_TexCoord1.p = dot( position4, gl_EyePlaneR[" << su1 <<"]);\n";
- buf << " shadow_TexCoord1.q = dot( position4, gl_EyePlaneQ[" << su1 <<"]);\n";
+ buf << " oe_shadow_TexCoord1.s = dot( position4, gl_EyePlaneS[" << su1 <<"]);\n";
+ buf << " oe_shadow_TexCoord1.t = dot( position4, gl_EyePlaneT[" << su1 <<"]);\n";
+ buf << " oe_shadow_TexCoord1.p = dot( position4, gl_EyePlaneR[" << su1 <<"]);\n";
+ buf << " oe_shadow_TexCoord1.q = dot( position4, gl_EyePlaneQ[" << su1 <<"]);\n";
}
- buf << " colorAmbientEmissive = gl_FrontLightModelProduct.sceneColor\n";
- buf << " + gl_FrontLightProduct[0].ambient;\n";
- //buf << " colorAmbientEmissive = gl_LightModel.ambient + gl_FrontLightProduct[0].ambient; \n";
- //buf << " colorAmbientEmissive = gl_FrontLightProduct[0].ambient; \n";
- buf << "}\n";
+
+ // the ambient lighting will control the intensity of the shadow.
+ buf << " oe_shadow_ambient = gl_FrontLightProduct[0].ambient; \n"
+ << "}\n";
std::string setupShadowCoords;
setupShadowCoords = buf.str();
vp->setFunction(
- "osgearth_vert_setupShadowCoords",
+ "oe_shadow_setupShadowCoords",
setupShadowCoords,
ShaderComp::LOCATION_VERTEX_POST_LIGHTING,
-1.0 );
@@ -166,40 +168,46 @@ ShadowUtils::setUpShadows(osgShadow::ShadowedScene* sscene, osg::Group* root)
std::stringstream buf2;
buf2 <<
"#version " << GLSL_VERSION_STR << "\n"
+#ifdef OSG_GLES2_AVAILABLE
+ "precision mediump float;\n"
+#endif
"uniform sampler2DShadow shadowTexture;\n"
- "varying vec4 shadow_TexCoord0;\n";
+ "varying vec4 oe_shadow_TexCoord0;\n";
if (su1 >= 0)
{
// bound by vdsm
buf2 << "uniform sampler2DShadow shadowTexture1;\n";
- buf2 << "varying vec4 shadow_TexCoord1;\n";
+ buf2 << "varying vec4 oe_shadow_TexCoord1;\n";
}
buf2 <<
- "varying vec4 colorAmbientEmissive;\n"
- "varying vec4 osg_FrontColor;\n"
- "varying vec4 osg_FrontSecondaryColor;\n"
- "void osgearth_frag_applyLighting( inout vec4 color )\n"
+ "varying vec4 oe_shadow_ambient;\n"
+
+ "void oe_shadow_applyLighting( inout vec4 color )\n"
"{\n"
" float alpha = color.a;\n"
- " float shadowFac = shadow2DProj( shadowTexture, shadow_TexCoord0).r;\n";
+ " float shadowFac = shadow2DProj( shadowTexture, oe_shadow_TexCoord0).r;\n";
if (su1 > 0)
{
- buf2 << " shadowFac *= shadow2DProj( shadowTexture1, shadow_TexCoord1).r;\n";
+ buf2 << " shadowFac *= shadow2DProj( shadowTexture1, oe_shadow_TexCoord1).r;\n";
}
+
+ // calculate the shadowed color and mix if with the lit color based on the
+ // ambient lighting. The 0.5 is a multiplier that darkens the shadow in
+ // proportion to ambient light. It should probably be a uniform.
buf2 <<
- " vec4 diffuseLight = mix(colorAmbientEmissive, osg_FrontColor, shadowFac);\n"
- " color = color * diffuseLight + osg_FrontSecondaryColor * shadowFac;\n"
+ " vec4 colorInFullShadow = color * oe_shadow_ambient; \n"
+ " color = mix(colorInFullShadow, color, shadowFac); \n"
" color.a = alpha;\n"
"}\n";
std::string fragApplyLighting;
fragApplyLighting = buf2.str();
- // override the terrain engine's default lighting shader:
- vp->setShader("osgearth_frag_applyLighting",
- new osg::Shader(osg::Shader::FRAGMENT, fragApplyLighting),
- osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
+ vp->setFunction(
+ "oe_shadow_applyLighting",
+ fragApplyLighting,
+ osgEarth::ShaderComp::LOCATION_FRAGMENT_POST_LIGHTING );
setShadowUnit(sscene, su);
diff --git a/src/osgEarthUtil/SkyNode.cpp b/src/osgEarthUtil/SkyNode.cpp
index d93359f..37b450d 100644
--- a/src/osgEarthUtil/SkyNode.cpp
+++ b/src/osgEarthUtil/SkyNode.cpp
@@ -19,7 +19,7 @@
#include <osgEarthUtil/SkyNode>
#include <osgEarthUtil/StarData>
-#include <osgEarth/ShaderComposition>
+#include <osgEarth/VirtualProgram>
#include <osgEarthUtil/LatLongFormatter>
#include <osgEarth/NodeUtils>
#include <osgEarth/MapNode>
@@ -788,12 +788,45 @@ SkyNode::traverse( osg::NodeVisitor& nv )
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>( &nv );
if ( cv )
{
+ // If there's a custom projection matrix clamper installed, remove it temporarily.
+ // We dont' want it mucking with our sky elements.
+ osg::ref_ptr<osg::CullSettings::ClampProjectionMatrixCallback> cb = cv->getClampProjectionMatrixCallback();
+ cv->setClampProjectionMatrixCallback( 0L );
+
osg::View* view = cv->getCurrentCamera()->getView();
PerViewDataMap::iterator i = _perViewData.find( view );
if ( i != _perViewData.end() )
{
+#if 0
+ // adjust the light color based on the eye point and the sun position.
+ float aMin = 0.1f;
+ float aMax = 0.9f;
+ float dMin = -0.5f;
+ float dMax = 0.5f;
+
+ osg::Vec3 eye = cv->getViewPoint();
+ eye.normalize();
+
+ osg::Vec3 sun = i->second._lightPos;
+ sun.normalize();
+
+ // clamp to valid range:
+ float d = osg::clampBetween(eye * sun, dMin, dMax);
+
+ // remap to [0..1]:
+ d = (d-dMin) / (dMax-dMin);
+
+ // map to ambient level:
+ float diff = aMin + d * (aMax-aMin);
+
+ i->second._light->setDiffuse( osg::Vec4(diff,diff,diff,1.0) );
+#endif
+
i->second._cullContainer->accept( nv );
}
+
+ // restore a custom clamper.
+ if ( cb.valid() ) cv->setClampProjectionMatrixCallback( cb.get() );
}
else
@@ -860,7 +893,7 @@ SkyNode::attach( osg::View* view, int lightNum )
data._starsMatrix = _defaultPerViewData._starsMatrix;
data._starsXform->setMatrix( _defaultPerViewData._starsMatrix );
data._starsXform->addChild( _stars.get() );
- data._cullContainer->addChild( data._starsXform.get() );
+ data._cullContainer->addChild( data._starsXform.get() );
data._starsVisible = _defaultPerViewData._starsVisible;
data._starsXform->setNodeMask( data._starsVisible ? ~0 : 0 );
@@ -1154,79 +1187,81 @@ SkyNode::makeAtmosphere( const osg::EllipsoidModel* em )
// configure the state set:
set->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
- //set->setMode( GL_CULL_FACE, osg::StateAttribute::ON );
- set->setMode( GL_CULL_FACE, osg::StateAttribute::OFF );
+ set->setAttributeAndModes( new osg::CullFace(osg::CullFace::BACK), osg::StateAttribute::ON );
//set->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
set->setAttributeAndModes( new osg::Depth( osg::Depth::LESS, 0, 1, false ) ); // no depth write
+ set->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false) ); // no zbuffer
set->setAttributeAndModes( new osg::BlendFunc( GL_ONE, GL_ONE ), osg::StateAttribute::ON );
- // next, create and add the shaders:
- osg::Program* program = new osg::Program();
- osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, Stringify()
- << s_versionString
- << s_mathUtils
- << s_atmosphereVertexDeclarations
- << s_atmosphereVertexShared
- << s_atmosphereVertexMain );
- program->addShader( vs );
-
- osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, Stringify()
- << s_versionString
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ // next, create and add the shaders:
+ osg::Program* program = new osg::Program();
+ osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, Stringify()
+ << s_versionString
+ << s_mathUtils
+ << s_atmosphereVertexDeclarations
+ << s_atmosphereVertexShared
+ << s_atmosphereVertexMain );
+ program->addShader( vs );
+
+ osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, Stringify()
+ << s_versionString
#ifdef OSG_GLES2_AVAILABLE
- << "precision highp float;\n"
+ << "precision highp float;\n"
#endif
- << s_mathUtils
- << s_atmosphereFragmentDeclarations
- //<< s_atmosphereFragmentShared
- << s_atmosphereFragmentMain );
- program->addShader( fs );
-
- set->setAttributeAndModes( program, osg::StateAttribute::ON );
-
- // apply the uniforms:
- float r_wl = ::powf( .65f, 4.0f );
- float g_wl = ::powf( .57f, 4.0f );
- float b_wl = ::powf( .475f, 4.0f );
- osg::Vec3 RGB_wl( 1.0f/r_wl, 1.0f/g_wl, 1.0f/b_wl );
- float Kr = 0.0025f;
- float Kr4PI = Kr * 4.0f * osg::PI;
- float Km = 0.0015f;
- float Km4PI = Km * 4.0f * osg::PI;
- float ESun = 15.0f;
- float MPhase = -.095f;
- float RayleighScaleDepth = 0.25f;
- int Samples = 2;
- float Weather = 1.0f;
-
- float Scale = 1.0f / (_outerRadius - _innerRadius);
-
- // TODO: replace this with a UBO.
-
- set->getOrCreateUniform( "atmos_v3InvWavelength", osg::Uniform::FLOAT_VEC3 )->set( RGB_wl );
- set->getOrCreateUniform( "atmos_fInnerRadius", osg::Uniform::FLOAT )->set( _innerRadius );
- set->getOrCreateUniform( "atmos_fInnerRadius2", osg::Uniform::FLOAT )->set( _innerRadius * _innerRadius );
- set->getOrCreateUniform( "atmos_fOuterRadius", osg::Uniform::FLOAT )->set( _outerRadius );
- set->getOrCreateUniform( "atmos_fOuterRadius2", osg::Uniform::FLOAT )->set( _outerRadius * _outerRadius );
- set->getOrCreateUniform( "atmos_fKrESun", osg::Uniform::FLOAT )->set( Kr * ESun );
- set->getOrCreateUniform( "atmos_fKmESun", osg::Uniform::FLOAT )->set( Km * ESun );
- set->getOrCreateUniform( "atmos_fKr4PI", osg::Uniform::FLOAT )->set( Kr4PI );
- set->getOrCreateUniform( "atmos_fKm4PI", osg::Uniform::FLOAT )->set( Km4PI );
- set->getOrCreateUniform( "atmos_fScale", osg::Uniform::FLOAT )->set( Scale );
- set->getOrCreateUniform( "atmos_fScaleDepth", osg::Uniform::FLOAT )->set( RayleighScaleDepth );
- set->getOrCreateUniform( "atmos_fScaleOverScaleDepth", osg::Uniform::FLOAT )->set( Scale / RayleighScaleDepth );
- set->getOrCreateUniform( "atmos_g", osg::Uniform::FLOAT )->set( MPhase );
- set->getOrCreateUniform( "atmos_g2", osg::Uniform::FLOAT )->set( MPhase * MPhase );
- set->getOrCreateUniform( "atmos_nSamples", osg::Uniform::INT )->set( Samples );
- set->getOrCreateUniform( "atmos_fSamples", osg::Uniform::FLOAT )->set( (float)Samples );
- set->getOrCreateUniform( "atmos_fWeather", osg::Uniform::FLOAT )->set( Weather );
+ << s_mathUtils
+ << s_atmosphereFragmentDeclarations
+ //<< s_atmosphereFragmentShared
+ << s_atmosphereFragmentMain );
+ program->addShader( fs );
+
+ set->setAttributeAndModes( program, osg::StateAttribute::ON );
+
+ // apply the uniforms:
+ float r_wl = ::powf( .65f, 4.0f );
+ float g_wl = ::powf( .57f, 4.0f );
+ float b_wl = ::powf( .475f, 4.0f );
+ osg::Vec3 RGB_wl( 1.0f/r_wl, 1.0f/g_wl, 1.0f/b_wl );
+ float Kr = 0.0025f;
+ float Kr4PI = Kr * 4.0f * osg::PI;
+ float Km = 0.0015f;
+ float Km4PI = Km * 4.0f * osg::PI;
+ float ESun = 15.0f;
+ float MPhase = -.095f;
+ float RayleighScaleDepth = 0.25f;
+ int Samples = 2;
+ float Weather = 1.0f;
+
+ float Scale = 1.0f / (_outerRadius - _innerRadius);
+
+ // TODO: replace this with a UBO.
+
+ set->getOrCreateUniform( "atmos_v3InvWavelength", osg::Uniform::FLOAT_VEC3 )->set( RGB_wl );
+ set->getOrCreateUniform( "atmos_fInnerRadius", osg::Uniform::FLOAT )->set( _innerRadius );
+ set->getOrCreateUniform( "atmos_fInnerRadius2", osg::Uniform::FLOAT )->set( _innerRadius * _innerRadius );
+ set->getOrCreateUniform( "atmos_fOuterRadius", osg::Uniform::FLOAT )->set( _outerRadius );
+ set->getOrCreateUniform( "atmos_fOuterRadius2", osg::Uniform::FLOAT )->set( _outerRadius * _outerRadius );
+ set->getOrCreateUniform( "atmos_fKrESun", osg::Uniform::FLOAT )->set( Kr * ESun );
+ set->getOrCreateUniform( "atmos_fKmESun", osg::Uniform::FLOAT )->set( Km * ESun );
+ set->getOrCreateUniform( "atmos_fKr4PI", osg::Uniform::FLOAT )->set( Kr4PI );
+ set->getOrCreateUniform( "atmos_fKm4PI", osg::Uniform::FLOAT )->set( Km4PI );
+ set->getOrCreateUniform( "atmos_fScale", osg::Uniform::FLOAT )->set( Scale );
+ set->getOrCreateUniform( "atmos_fScaleDepth", osg::Uniform::FLOAT )->set( RayleighScaleDepth );
+ set->getOrCreateUniform( "atmos_fScaleOverScaleDepth", osg::Uniform::FLOAT )->set( Scale / RayleighScaleDepth );
+ set->getOrCreateUniform( "atmos_g", osg::Uniform::FLOAT )->set( MPhase );
+ set->getOrCreateUniform( "atmos_g2", osg::Uniform::FLOAT )->set( MPhase * MPhase );
+ set->getOrCreateUniform( "atmos_nSamples", osg::Uniform::INT )->set( Samples );
+ set->getOrCreateUniform( "atmos_fSamples", osg::Uniform::FLOAT )->set( (float)Samples );
+ set->getOrCreateUniform( "atmos_fWeather", osg::Uniform::FLOAT )->set( Weather );
+ }
// A nested camera isolates the projection matrix calculations so the node won't
// affect the clip planes in the rest of the scene.
osg::Camera* cam = new osg::Camera();
cam->getOrCreateStateSet()->setRenderBinDetails( BIN_ATMOSPHERE, "RenderBin" );
cam->setRenderOrder( osg::Camera::NESTED_RENDER );
- //cam->setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES );
- cam->setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES );
+ cam->setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES );
cam->addChild( geode );
_atmosphere = cam;
@@ -1255,20 +1290,23 @@ SkyNode::makeSun()
// set->setAttributeAndModes( new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), osg::StateAttribute::ON );
// create shaders
- osg::Program* program = new osg::Program();
- osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, Stringify()
- << s_versionString
- << s_sunVertexSource );
- program->addShader( vs );
- osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, Stringify()
- << s_versionString
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ osg::Program* program = new osg::Program();
+ osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, Stringify()
+ << s_versionString
+ << s_sunVertexSource );
+ program->addShader( vs );
+ osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, Stringify()
+ << s_versionString
#ifdef OSG_GLES2_AVAILABLE
- << "precision highp float;\n"
+ << "precision highp float;\n"
#endif
- << s_mathUtils
- << s_sunFragmentSource );
- program->addShader( fs );
- set->setAttributeAndModes( program, osg::StateAttribute::ON );
+ << s_mathUtils
+ << s_sunFragmentSource );
+ program->addShader( fs );
+ set->setAttributeAndModes( program, osg::StateAttribute::ON );
+ }
// make the sun's transform:
// todo: move this?
@@ -1322,21 +1360,24 @@ SkyNode::makeMoon()
#ifdef OSG_GLES2_AVAILABLE
- set->addUniform(new osg::Uniform("moonTex", 0));
-
- // create shaders
- osg::Program* program = new osg::Program();
- osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, Stringify()
- << s_versionString
- << "precision highp float;\n"
- << s_moonVertexSource );
- program->addShader( vs );
- osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, Stringify()
- << s_versionString
- << "precision highp float;\n"
- << s_moonFragmentSource );
- program->addShader( fs );
- set->setAttributeAndModes( program, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ set->addUniform(new osg::Uniform("moonTex", 0));
+
+ // create shaders
+ osg::Program* program = new osg::Program();
+ osg::Shader* vs = new osg::Shader( osg::Shader::VERTEX, Stringify()
+ << s_versionString
+ << "precision highp float;\n"
+ << s_moonVertexSource );
+ program->addShader( vs );
+ osg::Shader* fs = new osg::Shader( osg::Shader::FRAGMENT, Stringify()
+ << s_versionString
+ << "precision highp float;\n"
+ << s_moonFragmentSource );
+ program->addShader( fs );
+ set->setAttributeAndModes( program, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
+ }
#endif
// make the moon's transform:
@@ -1397,9 +1438,6 @@ SkyNode::makeStars(const std::string& starFile)
osg::Node* starNode = buildStarGeometry(stars);
- //AddCallbackToDrawablesVisitor visitor(_starRadius);
- //starNode->accept(visitor);
-
_stars = starNode;
}
@@ -1437,13 +1475,16 @@ SkyNode::buildStarGeometry(const std::vector<StarData>& stars)
osg::StateSet* sset = geometry->getOrCreateStateSet();
- sset->setTextureAttributeAndModes( 0, new osg::PointSprite(), osg::StateAttribute::ON );
- sset->setMode( GL_VERTEX_PROGRAM_POINT_SIZE, osg::StateAttribute::ON );
+ if ( Registry::capabilities().supportsGLSL() )
+ {
+ sset->setTextureAttributeAndModes( 0, new osg::PointSprite(), osg::StateAttribute::ON );
+ sset->setMode( GL_VERTEX_PROGRAM_POINT_SIZE, osg::StateAttribute::ON );
- osg::Program* program = new osg::Program;
- program->addShader( new osg::Shader(osg::Shader::VERTEX, s_createStarVertexSource()) );
- program->addShader( new osg::Shader(osg::Shader::FRAGMENT, s_createStarFragmentSource()) );
- sset->setAttributeAndModes( program, osg::StateAttribute::ON );
+ osg::Program* program = new osg::Program;
+ program->addShader( new osg::Shader(osg::Shader::VERTEX, s_createStarVertexSource()) );
+ program->addShader( new osg::Shader(osg::Shader::FRAGMENT, s_createStarFragmentSource()) );
+ sset->setAttributeAndModes( program, osg::StateAttribute::ON );
+ }
sset->setRenderBinDetails( BIN_STARS, "RenderBin");
sset->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), osg::StateAttribute::ON );
diff --git a/src/osgEarthUtil/SpatialData.cpp b/src/osgEarthUtil/SpatialData.cpp
index 20a7067..6a45dd6 100644
--- a/src/osgEarthUtil/SpatialData.cpp
+++ b/src/osgEarthUtil/SpatialData.cpp
@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <osgEarthUtil/SpatialData>
+#include <osgEarth/Registry>
#include <osgUtil/CullVisitor>
#include <osg/PolygonOffset>
#include <osg/Polytope>
@@ -44,8 +45,7 @@ namespace
return row*xdim + col;
}
-
- static osgText::Font* s_font = 0L;
+
osg::Geode* makeClusterGeode( const GeoExtent& cellExtent, unsigned num )
{
@@ -66,10 +66,8 @@ namespace
t->setCharacterSizeMode( osgText::TextBase::SCREEN_COORDS );
t->setCharacterSize( 22.0f );
t->setAutoRotateToScreen( true );
-
- if ( !s_font )
- s_font = osgText::readFontFile( "arialbd.ttf" );
- t->setFont( s_font );
+
+ t->setFont( osgEarth::Registry::instance()->getDefaultFont() );
t->setBackdropType( osgText::Text::OUTLINE );
t->setColor( osg::Vec4(1,1,1,1) );
diff --git a/src/osgEarthUtil/TMSPackager b/src/osgEarthUtil/TMSPackager
index b63de0d..e58ebfc 100644
--- a/src/osgEarthUtil/TMSPackager
+++ b/src/osgEarthUtil/TMSPackager
@@ -39,7 +39,7 @@ namespace osgEarth { namespace Util
* Constructs a new packager.
* @param profile Profile of packaged tile data (required)
*/
- TMSPackager( const Profile* outProfile );
+ TMSPackager( const Profile* outProfile, osgDB::Options* imageWriteOptions);
/** dtor */
virtual ~TMSPackager() { }
@@ -153,6 +153,7 @@ namespace osgEarth { namespace Util
unsigned _maxLevel;
std::vector<GeoExtent> _extents;
osg::ref_ptr<const Profile> _outProfile;
+ osg::ref_ptr<osgDB::Options> _imageWriteOptions;
};
} } // namespace osgEarth::Util
diff --git a/src/osgEarthUtil/TMSPackager.cpp b/src/osgEarthUtil/TMSPackager.cpp
index bd96dec..2907262 100644
--- a/src/osgEarthUtil/TMSPackager.cpp
+++ b/src/osgEarthUtil/TMSPackager.cpp
@@ -30,14 +30,15 @@ using namespace osgEarth::Util;
using namespace osgEarth;
-TMSPackager::TMSPackager(const Profile* outProfile) :
-_outProfile ( outProfile ),
-_maxLevel ( 5 ),
-_verbose ( false ),
-_overwrite ( false ),
-_keepEmptyImageTiles ( false ),
+TMSPackager::TMSPackager(const Profile* outProfile, osgDB::Options* imageWriteOptions) :
+_outProfile ( outProfile ),
+_maxLevel ( 99 ),
+_verbose ( false ),
+_overwrite ( false ),
+_keepEmptyImageTiles( false ),
_subdivideSingleColorImageTiles ( false ),
-_abortOnError ( true )
+_abortOnError ( true ),
+_imageWriteOptions (imageWriteOptions)
{
//nop
}
@@ -126,7 +127,7 @@ TMSPackager::packageImageTile(ImageLayer* layer,
// dump it to disk
osgDB::makeDirectoryForFile( path );
- tileOK = osgDB::writeImageFile( *final.get(), path );
+ tileOK = osgDB::writeImageFile( *final.get(), path, _imageWriteOptions);
if ( _verbose )
{
diff --git a/tests/annotation.earth b/tests/annotation.earth
index d252338..ae63859 100644
--- a/tests/annotation.earth
+++ b/tests/annotation.earth
@@ -72,6 +72,7 @@ osgEarth Sample - Annotations
stroke-width: 3;
extrusion-height: 30000;
</style>
+ <lighting>false</lighting>
</feature>
<local_geometry>
@@ -83,6 +84,7 @@ osgEarth Sample - Annotations
fill: #00ff00;
stroke: #ffff00;
</style>
+ <lighting>false</lighting>
</local_geometry>
<model>
@@ -95,6 +97,7 @@ osgEarth Sample - Annotations
<alpha>1.0</alpha>
<geometry>POLYGON((-81 26, -80.5 26, -80.5 26.5, -81 26.5))</geometry>
</imageoverlay>
+
<label text="image overlay">
<position lat="26" long="-81" />
</label>
diff --git a/tests/boston.earth b/tests/boston.earth
index c70e0fa..7e71775 100644
--- a/tests/boston.earth
+++ b/tests/boston.earth
@@ -56,6 +56,7 @@ to extruded buildings.
extrusion-height: 3.5 * max([story_ht_], 1);
extrusion-flatten: true;
extrusion-wall-style: building-wall;
+ extrusion-wall-gradient: 0.8;
extrusion-roof-style: building-rooftop;
altitude-clamping: none;
}
@@ -73,9 +74,7 @@ to extruded buildings.
fill: #ffffff;
}
</style>
- </styles>
-
- <lighting>true</lighting>
+ </styles>
</model>
<external>
diff --git a/tests/feature_extrude.earth b/tests/feature_extrude.earth
index 8d40d25..871b9a8 100644
--- a/tests/feature_extrude.earth
+++ b/tests/feature_extrude.earth
@@ -24,11 +24,12 @@ Footprint Extrusion using the "feature_geom" driver.
<styles>
<style type="text/css">
buildings {
- extrusion-height: 15;
- extrusion-flatten: true;
- fill: #ff7f2f;
- altitude-clamping: terrain;
- altitude-resolution: 0.001;
+ fill: #ff7f2f;
+ extrusion-height: 15;
+ extrusion-flatten: true;
+ extrusion-wall-gradient: 0.7;
+ altitude-clamping: terrain;
+ altitude-resolution: 0.001;
}
</style>
</styles>
diff --git a/tests/feature_model_scatter.earth b/tests/feature_model_scatter.earth
index b62cd91..088a137 100644
--- a/tests/feature_model_scatter.earth
+++ b/tests/feature_model_scatter.earth
@@ -13,7 +13,7 @@ is randomized, but it is randomized exactly the same way each time.
<!-- Our features layer. The "feature_geom" driver will analyze the
style sheet and determine how to render the feature data. -->
- <model name="trees" driver="feature_geom">
+ <model name="trees" driver="feature_geom" enabled="true">
<!-- Feature data set to load. This is a set of polygons representing
the public parks in Washington DC -->
@@ -31,6 +31,9 @@ is randomized, but it is randomized exactly the same way each time.
real features anyway. -->
<feature_indexing>false</feature_indexing>
+ <!-- Fade in new tiles over one second. -->
+ <fade_in_duration>1.0</fade_in_duration>
+
<!-- The stylesheet will describe how to render the feature data. In this case
we indicate model substitution with density-based scattering. The "density"
units are instances-per-sqkm. -->
diff --git a/tests/feature_scripted_styling_2.earth b/tests/feature_scripted_styling_2.earth
index 69e428e..2602096 100644
--- a/tests/feature_scripted_styling_2.earth
+++ b/tests/feature_scripted_styling_2.earth
@@ -1,8 +1,7 @@
<!--
osgEarth Sample
-This one demonstrates how to read feature data from a shapefile and "drape" it
-on the map using the overlay technique.
+Demonstrates how to select a style name using javascript.
-->
<map name="Feature Overlay Demo" type="geocentric" version="2">
diff --git a/tests/gdal_tiff.earth b/tests/gdal_tiff.earth
index 0613eb0..82534a5 100644
--- a/tests/gdal_tiff.earth
+++ b/tests/gdal_tiff.earth
@@ -8,6 +8,4 @@ Demonstrates the simplest possible use of the GDAL driver to load a GeoTIFF imag
<url>../data/world.tif</url>
<caching_policy usage="no_cache"/>
</image>
-
- <options lighting="false"/>
</map>
diff --git a/tests/min_max_resolutions.earth b/tests/min_max_resolutions.earth
index f5d643d..f674a42 100644
--- a/tests/min_max_resolutions.earth
+++ b/tests/min_max_resolutions.earth
@@ -12,12 +12,12 @@ Please note that usage of Yahoo! map data is subject to Yahoo!'s terms of servic
<!-- this level will be visible at lower resolutions -->
<image name="yahoo_sat" driver="yahoo">
<dataset>satellite</dataset>
- <max_level_resolution>4891</max_level_resolution>
+ <max_resolution>4891</max_resolution>
</image>
<!-- this level will be visible at higher resolutions -->
<image name="yahoo_maps" driver="yahoo">
- <min_level_resolution>2445</min_level_resolution>
+ <min_resolution>2445</min_resolution>
</image>
</image>
diff --git a/tests/readymap.earth b/tests/readymap.earth
index ddc5555..627c18c 100644
--- a/tests/readymap.earth
+++ b/tests/readymap.earth
@@ -21,4 +21,8 @@ http://readymap.org
<url>http://readymap.org/readymap/tiles/1.0.0/9/</url>
</elevation>
+ <options>
+ <terrain normalize_edges="true"/>
+ </options>
+
</map>
diff --git a/tests/wms_naip.earth b/tests/wms_naip.earth
deleted file mode 100644
index 4029c0e..0000000
--- a/tests/wms_naip.earth
+++ /dev/null
@@ -1,13 +0,0 @@
-<!--
-osgEarth Sample.
-Access to the USGS Seamless WMS Server - NAIP Dataset
--->
-<map>
- <image name="naip" driver="wms" version="2">
- <url>http://isse.cr.usgs.gov/arcgis/services/Combined/USGS_EDC_Ortho_NAIP/MapServer/WMSServer?transparent=true</url>
- <srs>EPSG:4326</srs>
- <tile_size>256</tile_size>
- <layers>0</layers>
- <format>png</format>
- </image>
-</map>
--
osgEarth terrain rendering toolkit
More information about the Pkg-grass-devel
mailing list