diff --git a/include/osgTerrain/GeometryPool b/include/osgTerrain/GeometryPool index 98f31a3e9..9d5c23fa2 100644 --- a/include/osgTerrain/GeometryPool +++ b/include/osgTerrain/GeometryPool @@ -27,6 +27,33 @@ namespace osgTerrain { extern OSGTERRAIN_EXPORT const osgTerrain::Locator* computeMasterLocator(const osgTerrain::TerrainTile* tile); + +class OSGTERRAIN_EXPORT SharedGeometry : public osg::Geometry +{ + public: + SharedGeometry(); + + SharedGeometry(const SharedGeometry&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osgTerrain, SharedGeometry); + + typedef std::vector VertexToHeightFieldMapping; + + void setVertexToHeightFieldMapping(const VertexToHeightFieldMapping& vthfm) { _vertexToHeightFieldMapping = vthfm; } + + VertexToHeightFieldMapping& getVertexToHeightFieldMapping() { return _vertexToHeightFieldMapping; } + const VertexToHeightFieldMapping& getVertexToHeightFieldMapping() const { return _vertexToHeightFieldMapping; } + + using osg::Geometry::supports; + using osg::Geometry::accept; + +protected: + + virtual ~SharedGeometry(); + + VertexToHeightFieldMapping _vertexToHeightFieldMapping; +}; + class OSGTERRAIN_EXPORT GeometryPool : public osg::Referenced { public: @@ -61,7 +88,7 @@ class OSGTERRAIN_EXPORT GeometryPool : public osg::Referenced int ny; }; - typedef std::map< GeometryKey, osg::ref_ptr > GeometryMap; + typedef std::map< GeometryKey, osg::ref_ptr > GeometryMap; bool createKeyForTile(TerrainTile* tile, GeometryKey& key); @@ -77,7 +104,7 @@ class OSGTERRAIN_EXPORT GeometryPool : public osg::Referenced osg::ref_ptr getOrCreateProgram(LayerTypes& layerTypes); - osg::ref_ptr getOrCreateGeometry(osgTerrain::TerrainTile* tile); + osg::ref_ptr getOrCreateGeometry(osgTerrain::TerrainTile* tile); osg::ref_ptr getTileSubgraph(osgTerrain::TerrainTile* tile); @@ -107,9 +134,13 @@ class OSGTERRAIN_EXPORT HeightFieldDrawable : public osg::Drawable osg::HeightField* getHeightField() { return _heightField.get(); } const osg::HeightField* getHeightField() const { return _heightField.get(); } - void setGeometry(osg::Geometry* geom) { _geometry = geom; } - osg::Geometry* getGeometry() { return _geometry.get(); } - const osg::Geometry* getGeometry() const { return _geometry.get(); } + void setGeometry(SharedGeometry* geom) { _geometry = geom; } + SharedGeometry* getGeometry() { return _geometry.get(); } + const SharedGeometry* getGeometry() const { return _geometry.get(); } + + void setVertices(osg::Vec3Array* vertices) { _vertices = vertices; } + osg::Vec3Array* getVertices() { return _vertices.get(); } + const osg::Vec3Array* getVertices() const { return _vertices.get(); } virtual void drawImplementation(osg::RenderInfo& renderInfo) const; virtual void compileGLObjects(osg::RenderInfo& renderInfo) const; @@ -129,13 +160,13 @@ class OSGTERRAIN_EXPORT HeightFieldDrawable : public osg::Drawable virtual bool supports(const osg::PrimitiveIndexFunctor&) const { return true; } virtual void accept(osg::PrimitiveIndexFunctor&) const; - - protected: - osg::ref_ptr _heightField; - osg::ref_ptr _geometry; + virtual ~HeightFieldDrawable(); + osg::ref_ptr _heightField; + osg::ref_ptr _geometry; + osg::ref_ptr _vertices; }; diff --git a/src/osgTerrain/GeometryPool.cpp b/src/osgTerrain/GeometryPool.cpp index 8f2357c69..df4b827d9 100644 --- a/src/osgTerrain/GeometryPool.cpp +++ b/src/osgTerrain/GeometryPool.cpp @@ -87,10 +87,7 @@ bool GeometryPool::createKeyForTile(TerrainTile* tile, GeometryKey& key) return true; } -static int numberGeometryCreated = 0; -static int numberSharedGeometry = 0; - -osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::TerrainTile* tile) +osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::TerrainTile* tile) { OpenThreads::ScopedLock lock(_geometryMapMutex); @@ -100,16 +97,15 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai GeometryMap::iterator itr = _geometryMap.find(key); if (itr != _geometryMap.end()) { - - ++numberSharedGeometry; -// OSG_NOTICE<<"Sharing geometry "<second.get()<<", number shared = "<second.get(); } - osg::ref_ptr geometry = new osg::Geometry; + osg::ref_ptr geometry = new SharedGeometry; _geometryMap[key] = geometry; + SharedGeometry::VertexToHeightFieldMapping& vthfm = geometry->getVertexToHeightFieldMapping(); + + osg::ref_ptr vertices = new osg::Vec3Array; geometry->setVertexArray(vertices.get()); @@ -133,6 +129,7 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai vertices->reserve(numVertices); normals->reserve(numVertices); texcoords->reserve(numVertices); + vthfm.reserve(numVertices); double c_mult = 1.0/static_cast(nx-1); double r_mult = 1.0/static_cast(ny-1); @@ -179,6 +176,7 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai double skirtRatio = 0.02; double skirtHeight = -diagonalLength*skirtRatio; + // set up the vertex data { // bottom row for skirt @@ -191,6 +189,7 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai normals->push_back(normal); texcoords->push_back(osg::Vec4(pos.x(), pos.y(), 1.0f, 1.0f)); locationCoords.push_back(osg::Vec4d(pos.x(), pos.y(),c_mult, r_mult)); + vthfm.push_back(0*nx + c); } // main body @@ -206,6 +205,7 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai normals->push_back(normal); texcoords->push_back(osg::Vec4(pos.x(), pos.y(), 1.0f, 1.0f)); locationCoords.push_back(osg::Vec4d(pos.x(), pos.y(),c_mult, r_mult)); + vthfm.push_back(r*nx + 0); } pos.z() = 0; @@ -216,6 +216,7 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai normals->push_back(normal); texcoords->push_back(osg::Vec4(pos.x(), pos.y(), 1.0f, 1.0f)); locationCoords.push_back(osg::Vec4d(pos.x(), pos.y(),c_mult, r_mult)); + vthfm.push_back(r*nx + c); } // end skirt vertex @@ -226,6 +227,7 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai normals->push_back(normal); texcoords->push_back(osg::Vec4(pos.x(), pos.y(), 1.0f, 1.0f)); locationCoords.push_back(osg::Vec4d(pos.x(), pos.y(),c_mult, r_mult)); + vthfm.push_back((r+1)*nx-1); } } @@ -240,6 +242,7 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai normals->push_back(normal); texcoords->push_back(osg::Vec4(pos.x(), pos.y(), 1.0f, 1.0f)); locationCoords.push_back(osg::Vec4d(pos.x(), pos.y(),c_mult, r_mult)); + vthfm.push_back((ny-1)*nx + c); } } @@ -436,8 +439,6 @@ osg::ref_ptr GeometryPool::getOrCreateGeometry(osgTerrain::Terrai //osgDB::writeNodeFile(*geometry, "geometry.osgt"); - - ++ numberGeometryCreated; // OSG_NOTICE<<"Creating new geometry "< GeometryPool::getOrCreateGeometry(osgTerrain::Terrai osg::ref_ptr GeometryPool::getTileSubgraph(osgTerrain::TerrainTile* tile) { // create or reuse Geometry - osg::ref_ptr geometry = getOrCreateGeometry(tile); + osg::ref_ptr geometry = getOrCreateGeometry(tile); osg::ref_ptr hfDrawable = new HeightFieldDrawable(); @@ -489,37 +490,57 @@ osg::ref_ptr GeometryPool::getTileSubgraph(osgTerrain::Ter } } - osg::Vec3Array* vertices = dynamic_cast(geometry->getVertexArray()); - osg::Vec3Array* normals = dynamic_cast(geometry->getNormalArray()); - if (hf && vertices && normals && (vertices->size()==normals->size())) + osg::Vec3Array* shared_vertices = dynamic_cast(geometry->getVertexArray()); + osg::Vec3Array* shared_normals = dynamic_cast(geometry->getNormalArray()); + osg::FloatArray* heights = hf->getFloatArray(); + const SharedGeometry::VertexToHeightFieldMapping& vthfm = geometry->getVertexToHeightFieldMapping(); + + if (hf && shared_vertices && shared_normals && (shared_vertices->size()==shared_normals->size())) { - unsigned int nr = hf->getNumRows(); - unsigned int nc = hf->getNumColumns(); - - osg::BoundingBox bb; - osg::FloatArray* heights = hf->getFloatArray(); - - for(unsigned int r=0; rsize()) { - for(unsigned int c=0; csize(); + osg::ref_ptr vertices = new osg::Vec3Array; + vertices->resize(numVertices); + + for(unsigned int i=0; isetVertices(vertices.get()); + } + else + { + // Setting local bounding + unsigned int nr = hf->getNumRows(); + unsigned int nc = hf->getNumColumns(); + + osg::BoundingBox bb; + + for(unsigned int r=0; rsetInitialBound(bb); + // OSG_NOTICE<<"Assigning initial bound ("<getBoundingBox(); + //OSG_NOTICE<<" getBoundingBox ("<setInitialBound(bb); - // OSG_NOTICE<<"Assigning initial bound ("<getBoundingBox(); - //OSG_NOTICE<<" getBoundingBox ("< stateset = transform->getOrCreateStateSet(); // apply colour layers @@ -756,6 +777,29 @@ void GeometryPool::applyLayers(osgTerrain::TerrainTile* tile, osg::StateSet* sta } } + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// SharedGeometry +// +SharedGeometry::SharedGeometry() +{ +// setSupportsDisplayList(false); +} + +SharedGeometry::SharedGeometry(const SharedGeometry& rhs,const osg::CopyOp& copyop): + osg::Geometry(rhs, copyop), + _vertexToHeightFieldMapping(rhs._vertexToHeightFieldMapping) +{ +// setSupportsDisplayList(false); +} + +SharedGeometry::~SharedGeometry() +{ +} + + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// // // HeightFieldDrawable @@ -768,11 +812,16 @@ HeightFieldDrawable::HeightFieldDrawable() HeightFieldDrawable::HeightFieldDrawable(const HeightFieldDrawable& rhs,const osg::CopyOp& copyop): osg::Drawable(rhs, copyop), _heightField(rhs._heightField), - _geometry(rhs._geometry) + _geometry(rhs._geometry), + _vertices(rhs._vertices) { setSupportsDisplayList(false); } +HeightFieldDrawable::~HeightFieldDrawable() +{ +} + void HeightFieldDrawable::drawImplementation(osg::RenderInfo& renderInfo) const { if (_geometry.valid()) _geometry->draw(renderInfo); @@ -805,10 +854,39 @@ void HeightFieldDrawable::accept(osg::Drawable::ConstAttributeFunctor& caf) cons void HeightFieldDrawable::accept(osg::PrimitiveFunctor& pf) const { - if (_geometry) _geometry->accept(pf); + // use the cached vertex positions for PrimitiveFunctor operations + if (!_geometry) return; + + if (_vertices.valid()) + { + pf.setVertexArray(_vertices->size(), &((*_vertices)[0])); + for(osg::Geometry::PrimitiveSetList::const_iterator itr = _geometry->getPrimitiveSetList().begin(); + itr != _geometry->getPrimitiveSetList().end(); + ++itr) + { + (*itr)->accept(pf); + } + } + else + { + _geometry->accept(pf); + } } void HeightFieldDrawable::accept(osg::PrimitiveIndexFunctor& pif) const { - if (_geometry) _geometry->accept(pif); + if (_vertices.valid()) + { + pif.setVertexArray(_vertices->size(), &((*_vertices)[0])); + for(osg::Geometry::PrimitiveSetList::const_iterator itr = _geometry->getPrimitiveSetList().begin(); + itr != _geometry->getPrimitiveSetList().end(); + ++itr) + { + (*itr)->accept(pif); + } + } + else + { + _geometry->accept(pif); + } }