From 023d2254abbb0b2eb784ca22e6494d79c73602cf Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 25 Nov 2003 19:42:35 +0000 Subject: [PATCH] Early development work on osgTerrain. --- include/osgTerrain/CoordinateSystem | 96 +++++++++++++++++++++++ include/osgTerrain/Export | 37 +++++++++ include/osgTerrain/GeoMipMapRenderer | 49 ++++++++++++ include/osgTerrain/Renderer | 60 ++++++++++++++ include/osgTerrain/Terrain | 112 +++++++++++++++++++++++++++ src/osgTerrain/CoordinateSystem.cpp | 53 +++++++++++++ src/osgTerrain/GNUmakefile | 19 +++++ src/osgTerrain/GeoMipMapRenderer.cpp | 49 ++++++++++++ src/osgTerrain/Renderer.cpp | 31 ++++++++ src/osgTerrain/Terrain.cpp | 112 +++++++++++++++++++++++++++ 10 files changed, 618 insertions(+) create mode 100644 include/osgTerrain/CoordinateSystem create mode 100644 include/osgTerrain/Export create mode 100644 include/osgTerrain/GeoMipMapRenderer create mode 100644 include/osgTerrain/Renderer create mode 100644 include/osgTerrain/Terrain create mode 100644 src/osgTerrain/CoordinateSystem.cpp create mode 100644 src/osgTerrain/GNUmakefile create mode 100644 src/osgTerrain/GeoMipMapRenderer.cpp create mode 100644 src/osgTerrain/Renderer.cpp create mode 100644 src/osgTerrain/Terrain.cpp diff --git a/include/osgTerrain/CoordinateSystem b/include/osgTerrain/CoordinateSystem new file mode 100644 index 000000000..47e161f69 --- /dev/null +++ b/include/osgTerrain/CoordinateSystem @@ -0,0 +1,96 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGTERRAIN_COORDINATESYSTEM +#define OSGTERRAIN_COORDINATESYSTEM 1 + +#include +#include +#include + +#include + +namespace osgTerrain +{ + +/** CoordinateSystem encapsulate the coordinate system that associated with objects in a scene.*/ +class CoordinateSystem : public osg::Object +{ + public: + + CoordinateSystem(); + + CoordinateSystem(const std::string& projectionRef); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + CoordinateSystem(const CoordinateSystem&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgTerrain,CoordinateSystem); + + inline bool operator == (const CoordinateSystem& cs) const + { + if (this == &cs) return true; + if (_projectionRef == cs._projectionRef) return true; + return false; + } + + inline bool operator != (const CoordinateSystem& cs) const + { + return !(*this==cs); + } + + /** Set the CoordinateSystem projection reference string, should be stored in OpenGIS Well Know Text form.*/ + void setProjectionRef(const std::string& projectionRef) { _projectionRef = projectionRef; } + + /** Get the CoordinateSystem projection reference string.*/ + const std::string& getProjectionRef() const { return _projectionRef; } + + + /** CoordinateTransformation is a helper class for transforming between two different CoodinateSystems. + * To use, simply constructor a CoordinateSystem::CoordinateTransformation convertor(sourceCS,destinateCS) + * and then convert indiviual points via v_destination = convert(v_source), or the + * CoordinateTransformation.convert(ptr,num) method when handling arrays of Vec2/Vec3's.*/ + class CoordinateTransformation : public osg::Referenced + { + public: + + static CoordinateTransformation* createCoordinateTransformation(const CoordinateSystem& source, const CoordinateSystem& destination); + + static void setCoordinateTransformationPrototpe(CoordinateTransformation* ct); + + virtual osg::Vec2 operator () (const osg::Vec2& source) const = 0; + virtual osg::Vec3 operator () (const osg::Vec3& source) const = 0; + + virtual bool transform(unsigned int numPoints, osg::Vec2* vec2ptr) const = 0; + virtual bool transform(unsigned int numPoints, osg::Vec3* vec3ptr) const = 0; + + protected: + + CoordinateTransformation() {} + virtual ~CoordinateTransformation() {} + + virtual CoordinateTransformation* cloneCoordinateTransformation(const CoordinateSystem& source, const CoordinateSystem& destination) const = 0; + + }; + + protected: + + virtual ~CoordinateSystem() {} + + + std::string _projectionRef; + +}; + +} +#endif diff --git a/include/osgTerrain/Export b/include/osgTerrain/Export new file mode 100644 index 000000000..b4d3eb47f --- /dev/null +++ b/include/osgTerrain/Export @@ -0,0 +1,37 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGTERRAIN_EXPORT_ +#define OSGTERRAIN_EXPORT_ 1 + +#if defined(_MSC_VER) + #pragma warning( disable : 4244 ) + #pragma warning( disable : 4251 ) + #pragma warning( disable : 4267 ) + #pragma warning( disable : 4275 ) + #pragma warning( disable : 4290 ) + #pragma warning( disable : 4786 ) + #pragma warning( disable : 4305 ) +#endif + +#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) + # ifdef OSGTERRAIN_LIBRARY + # define OSGTERRAIN_EXPORT __declspec(dllexport) + # else + # define OSGTERRAIN_EXPORT __declspec(dllimport) + # endif /* OSGTERRAIN_LIBRARY */ +#else + # define OSGTERRAIN_EXPORT +#endif + +#endif diff --git a/include/osgTerrain/GeoMipMapRenderer b/include/osgTerrain/GeoMipMapRenderer new file mode 100644 index 000000000..7e65d7b7b --- /dev/null +++ b/include/osgTerrain/GeoMipMapRenderer @@ -0,0 +1,49 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGTERRAIN_GEOMIPMAPRENDERER +#define OSGTERRAIN_GEOMIPMAPRENDERER 1 + +#include + +namespace osgTerrain { + +class OSGTERRAIN_EXPORT GeoMipMapRenderer : public Renderer +{ + public: + + GeoMipMapRenderer(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + GeoMipMapRenderer(const GeoMipMapRenderer&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgTerrain,GeoMipMapRenderer) + + virtual void initialize(); + + virtual void terrainHasBeenModified(); + + virtual void update(osgUtil::UpdateVisitor* nv); + + virtual void cull(osgUtil::CullVisitor* nv); + + protected: + + virtual ~GeoMipMapRenderer(); + + +}; + +} + +#endif diff --git a/include/osgTerrain/Renderer b/include/osgTerrain/Renderer new file mode 100644 index 000000000..bbab75d05 --- /dev/null +++ b/include/osgTerrain/Renderer @@ -0,0 +1,60 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGTERRAIN_Renderer +#define OSGTERRAIN_Renderer 1 + +#include + +#include +#include + +#include + +namespace osgTerrain { + +class Terrain; + +class OSGTERRAIN_EXPORT Renderer : public osg::Object +{ + public: + + Renderer(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + Renderer(const Renderer&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + Terrain* getTerrain() { return _terrain; } + const Terrain* getTerrain() const { return _terrain; } + + virtual void initialize() = 0; + + virtual void terrainHasBeenModified() = 0; + + virtual void update(osgUtil::UpdateVisitor* nv) = 0; + + virtual void cull(osgUtil::CullVisitor* nv) = 0; + + protected: + + virtual ~Renderer(); + + friend class osgTerrain::Terrain; + + Terrain* _terrain; + +}; + +} + +#endif diff --git a/include/osgTerrain/Terrain b/include/osgTerrain/Terrain new file mode 100644 index 000000000..3ac8f6906 --- /dev/null +++ b/include/osgTerrain/Terrain @@ -0,0 +1,112 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGTERRAIN_TERRAIN +#define OSGTERRAIN_TERRAIN 1 + +#include +#include + +#include +#include + +namespace osgTerrain { + +/** Terrain provides a framework for loosly coupling height field data with height rendering algorithms. + * This allows renderer's to be pluged in at runtime.*/ +class OSGTERRAIN_EXPORT Terrain : public osg::Group +{ + public: + + Terrain(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + Terrain(const Terrain&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osgTerrain, Terrain); + + virtual void traverse(osg::NodeVisitor& nv); + + + /** Set the coordinates system associated with this Terrain*/ + void setCoordinateSystem(CoordinateSystem* cs) { _coordinateSystem = cs; } + + /** Get the coordinates system associated with this Terrain*/ + CoordinateSystem* getCoordinateSystem() { return _coordinateSystem.get(); } + + /** Get the const coordinates system associated with this Terrain*/ + const CoordinateSystem* getCoordinateSystem() const { return _coordinateSystem.get(); } + + + /** Set the HeightField for this Terrain. + * If a Renderer is attached then this will be notified.*/ + void setHeightField(osg::HeightField* heightField); + + /** Get the HeightField.*/ + osg::HeightField* getHeightField() { return _heightField.get(); } + + /** Get the const HeightField.*/ + const osg::HeightField* getHeightField() const { return _heightField.get(); } + + /** Tell the Renderer that the height field has been modified, so + * that any cached data will need updating*/ + void haveModifiedHeightField(); + + /** Set the Renderer*/ + void setRenderer(osgTerrain::Renderer* renderer); + + /** Get the Renderer*/ + Renderer* getRenderer() { return _renderer.get(); } + + /** Get the const Renderer*/ + const Renderer* getRenderer() const { return _renderer.get(); } + + + void setBaseTextureImage(osg::Image* image) { _baseTextureImage = image; } + osg::Image* getBaseTextureImage() { return _baseTextureImage.get(); } + const osg::Image* getBaseTextureImage() const { return _baseTextureImage.get(); } + + void setDetailTextureImage(osg::Image* image) { _detailTextureImage = image; } + osg::Image* getDetailTextureImage() { return _detailTextureImage.get(); } + const osg::Image* getDetailTextureImage() const { return _detailTextureImage.get(); } + + void setCloudShadowTextureImage(osg::Image* image) { _cloudShadowTextureImage = image; } + osg::Image* getCloudShadowTextureImage() { return _cloudShadowTextureImage.get(); } + const osg::Image* getCloudShadowTextureImage() const { return _cloudShadowTextureImage.get(); } + + void setNormalMapImage(osg::Image* image) { _normalMapImage = image ; } + osg::Image* getNormalMapImage() { return _normalMapImage.get(); } + const osg::Image* getNormalMapImage() const { return _normalMapImage.get(); } + + void computeNormalMap(); + + + protected: + + virtual ~Terrain(); + + + osg::ref_ptr _coordinateSystem; + osg::ref_ptr _heightField; + osg::ref_ptr _renderer; + + osg::ref_ptr _baseTextureImage; + osg::ref_ptr _detailTextureImage; + osg::ref_ptr _cloudShadowTextureImage; + osg::ref_ptr _normalMapImage; + +}; + +} + +#endif diff --git a/src/osgTerrain/CoordinateSystem.cpp b/src/osgTerrain/CoordinateSystem.cpp new file mode 100644 index 000000000..12a96432f --- /dev/null +++ b/src/osgTerrain/CoordinateSystem.cpp @@ -0,0 +1,53 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#include + +using namespace osgTerrain; + +CoordinateSystem::CoordinateSystem() +{ +} + +CoordinateSystem::CoordinateSystem(const std::string& projectionRef): + _projectionRef(projectionRef) +{ +} + +CoordinateSystem::CoordinateSystem(const CoordinateSystem& cs,const osg::CopyOp& copyop): + Object(cs,copyop), + _projectionRef(cs._projectionRef) +{ +} + + +osg::ref_ptr& getCoordinateTransformationPrototypePtr() +{ + static osg::ref_ptr s_coordinateSystemPrototype; + return s_coordinateSystemPrototype; +} + + +CoordinateSystem::CoordinateTransformation* CoordinateSystem::CoordinateTransformation::createCoordinateTransformation(const CoordinateSystem& source, const CoordinateSystem& destination) +{ + if (getCoordinateTransformationPrototypePtr().valid()) + { + getCoordinateTransformationPrototypePtr()->cloneCoordinateTransformation(source, destination); + } + return 0L; +} + +void CoordinateSystem::CoordinateTransformation::setCoordinateTransformationPrototpe(CoordinateTransformation* ct) +{ + getCoordinateTransformationPrototypePtr() = ct; +} diff --git a/src/osgTerrain/GNUmakefile b/src/osgTerrain/GNUmakefile new file mode 100644 index 000000000..091af9534 --- /dev/null +++ b/src/osgTerrain/GNUmakefile @@ -0,0 +1,19 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + + +CXXFILES = \ + CoordinateSystem.cpp\ + Terrain.cpp\ + Renderer.cpp\ + GeoMipMapRenderer.cpp\ + + +DEF += -DOSGTERRAIN_LIBRARY + +LIBS += -losgDB -losg $(GL_LIBS) $(OTHER_LIBS) + +TARGET_BASENAME = osgTerrain +LIB = $(LIB_PREFIX)$(TARGET_BASENAME).$(LIB_EXT) + +include $(TOPDIR)/Make/makerules diff --git a/src/osgTerrain/GeoMipMapRenderer.cpp b/src/osgTerrain/GeoMipMapRenderer.cpp new file mode 100644 index 000000000..36ce0500b --- /dev/null +++ b/src/osgTerrain/GeoMipMapRenderer.cpp @@ -0,0 +1,49 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#include +#include + +using namespace osgTerrain; + +GeoMipMapRenderer::GeoMipMapRenderer() +{ +} + +/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ +GeoMipMapRenderer::GeoMipMapRenderer(const GeoMipMapRenderer& renderer,const osg::CopyOp& copyop): + Renderer(renderer,copyop) +{ +} + +GeoMipMapRenderer::~GeoMipMapRenderer() +{ +} + +void GeoMipMapRenderer::initialize() +{ +} + +void GeoMipMapRenderer::terrainHasBeenModified() +{ +} + +void GeoMipMapRenderer::update(osgUtil::UpdateVisitor* nv) +{ + if (getTerrain()) nv->traverse(*getTerrain()); +} + +void GeoMipMapRenderer::cull(osgUtil::CullVisitor* nv) +{ + if (getTerrain()) getTerrain()->osg::Group::traverse(*nv); +} diff --git a/src/osgTerrain/Renderer.cpp b/src/osgTerrain/Renderer.cpp new file mode 100644 index 000000000..b752e5373 --- /dev/null +++ b/src/osgTerrain/Renderer.cpp @@ -0,0 +1,31 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#include + +using namespace osgTerrain; + +Renderer::Renderer(): + _terrain(0) +{ +} + +Renderer::Renderer(const Renderer& renderer,const osg::CopyOp& copyop): + osg::Object(renderer,copyop), + _terrain(0) +{ +} + +Renderer::~Renderer() +{ +} diff --git a/src/osgTerrain/Terrain.cpp b/src/osgTerrain/Terrain.cpp new file mode 100644 index 000000000..8e8380a40 --- /dev/null +++ b/src/osgTerrain/Terrain.cpp @@ -0,0 +1,112 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ + +#include +#include + +using namespace osgTerrain; + +Terrain::Terrain() +{ + setNumChildrenRequiringUpdateTraversal(1); +} + +Terrain::Terrain(const Terrain& terrain,const osg::CopyOp& copyop): + Group(terrain,copyop), + _heightField(terrain._heightField) +{ + setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); + if (terrain.getRenderer()) setRenderer(dynamic_cast(terrain.getRenderer()->cloneType())); +} + +Terrain::~Terrain() +{ +} + +void Terrain::traverse(osg::NodeVisitor& nv) +{ + // if app traversal update the frame count. + if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) + { + // if no renderer exists that default to using the GeoMipMapRenderer + if (!getRenderer()) setRenderer(new GeoMipMapRenderer); + + osgUtil::UpdateVisitor* uv = dynamic_cast(&nv); + if (getRenderer() && uv) + { + getRenderer()->update(uv); + return; + } + + } + else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) + { + osgUtil::CullVisitor* cv = dynamic_cast(&nv); + if (getRenderer() && cv) + { + getRenderer()->cull(cv); + return; + } + } + + // otherwise fallback to the Group::traverse() + osg::Group::traverse(nv); +} + +void Terrain::setHeightField(osg::HeightField* heightField) +{ + _heightField = heightField; + if (_renderer.valid()) _renderer->initialize(); +} + +void Terrain::haveModifiedHeightField() +{ + if (_renderer.valid()) _renderer->terrainHasBeenModified(); +} + +void Terrain::setRenderer(osgTerrain::Renderer* renderer) +{ + // need to figure out how to ensure that only one renderer is + // used between terrain nodes... issue a warning? + _renderer = renderer; + + if (_renderer.valid()) + { + _renderer->_terrain = this; + _renderer->initialize(); + } +} + +void Terrain::computeNormalMap() +{ + if (_heightField.valid()) + { + osg::Image* image = new osg::Image; + image->allocateImage(_heightField->getNumColumns(),_heightField->getNumRows(),1,GL_RGB,GL_BYTE); + + char* ptr = (char*) image->data(); + for(unsigned int r=0;r<_heightField->getNumRows();++r) + { + for(unsigned int c=0;c<_heightField->getNumColumns();++c) + { + osg::Vec3 normal = _heightField->getNormal(c,r); + (*ptr++) = (char)((normal.x()+1.0)*0.5*255); + (*ptr++) = (char)((normal.y()+1.0)*0.5*255); + (*ptr++) = (char)((normal.z()+1.0)*0.5*255); + } + } + + setNormalMapImage(image); + + } +}