From acb2ed177ce106b9c09ae9edf606877e5712dd3a Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 11 May 2007 18:25:06 +0000 Subject: [PATCH] Added ValidDataOperator base class and NoDataValue and ValidRange subclasses, and support for it in osgTerrain::Layer and GeometryTechniqnue. --- examples/osgterrain/osgterrain.cpp | 4 + include/osgTerrain/Layer | 37 +++++- include/osgTerrain/ValidDataOperator | 70 +++++++++++ src/osgTerrain/CMakeLists.txt | 1 + src/osgTerrain/GeometryTechnique.cpp | 173 ++++++++++++++------------- src/osgTerrain/Layer.cpp | 2 +- 6 files changed, 204 insertions(+), 83 deletions(-) create mode 100644 include/osgTerrain/ValidDataOperator diff --git a/examples/osgterrain/osgterrain.cpp b/examples/osgterrain/osgterrain.cpp index 1cf72f650..a4aff48b9 100644 --- a/examples/osgterrain/osgterrain.cpp +++ b/examples/osgterrain/osgterrain.cpp @@ -81,6 +81,7 @@ int main(int argc, char** argv) osg::ref_ptr terrain = new osgTerrain::TerrainNode; osg::ref_ptr locator = new osgTerrain::EllipsoidLocator(-osg::PI, -osg::PI*0.5, 2.0*osg::PI, osg::PI, 0.0); + osg::ref_ptr validDataOperator = new osgTerrain::NoDataValue(0.0); unsigned int layerNum = 0; @@ -136,6 +137,7 @@ int main(int argc, char** argv) hfl->setHeightField(hf.get()); hfl->setLocator(locator.get()); + hfl->setValidDataOperator(validDataOperator.get()); if (offset!=0.0f || scale!=1.0f) { @@ -167,6 +169,7 @@ int main(int argc, char** argv) osg::ref_ptr imageLayer = new osgTerrain::ImageLayer; imageLayer->setImage(image.get()); imageLayer->setLocator(locator.get()); + imageLayer->setValidDataOperator(validDataOperator.get()); if (offset!=0.0f || scale!=1.0f) { @@ -198,6 +201,7 @@ int main(int argc, char** argv) osg::ref_ptr imageLayer = new osgTerrain::ImageLayer; imageLayer->setImage(image.get()); imageLayer->setLocator(locator.get()); + imageLayer->setValidDataOperator(validDataOperator.get()); if (offset!=0.0f || scale!=1.0f) { diff --git a/include/osgTerrain/Layer b/include/osgTerrain/Layer index 33e7abb2c..027f3b4d3 100644 --- a/include/osgTerrain/Layer +++ b/include/osgTerrain/Layer @@ -19,6 +19,7 @@ #include #include +#include namespace osgTerrain { @@ -38,6 +39,11 @@ class OSGTERRAIN_EXPORT Layer : public osg::Object Locator* getLocator() { return _locator.get(); } const Locator* getLocator() const { return _locator.get(); } + void setValidDataOperator(ValidDataOperator* validDataOp) { _validDataOperator = validDataOp; } + ValidDataOperator* getValidDataOperator() { return _validDataOperator.get(); } + const ValidDataOperator* getValidDataOperator() const { return _validDataOperator.get(); } + + virtual unsigned int getNumColumns() const { return 0; } virtual unsigned int getNumRows() const { return 0; } @@ -46,11 +52,37 @@ class OSGTERRAIN_EXPORT Layer : public osg::Object virtual bool transform(float offset, float scale) { return false; } + virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, float& /*value*/) const { return false; } virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec2& /*value*/) const { return false; } virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec3& /*value*/) const { return false; } virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec4& /*value*/) const { return false; } + inline bool getValidValue(unsigned int i, unsigned int j, float& value) const + { + if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true; + return false; + } + + inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec2& value) const + { + if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true; + return false; + } + + inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec3& value) const + { + if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true; + return false; + } + + inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec4& value) const + { + if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true; + return false; + } + + inline void computeIndices(double ndc_x, double ndc_y, unsigned int& i, unsigned int& j, double& ir, double& jr) { ndc_x *= double(getNumColumns()-1); @@ -115,8 +147,9 @@ class OSGTERRAIN_EXPORT Layer : public osg::Object virtual ~Layer(); - osg::ref_ptr _locator; - osg::Vec4 _defaultValue; + osg::ref_ptr _locator; + osg::ref_ptr _validDataOperator; + osg::Vec4 _defaultValue; }; diff --git a/include/osgTerrain/ValidDataOperator b/include/osgTerrain/ValidDataOperator new file mode 100644 index 000000000..799a9a593 --- /dev/null +++ b/include/osgTerrain/ValidDataOperator @@ -0,0 +1,70 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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_VALIDDATAOPERATOR +#define OSGTERRAIN_VALIDDATAOPERATOR 1 + +#include + +namespace osgTerrain { + +struct ValidDataOperator : public osg::Referenced +{ + virtual bool operator() (float value) const { return true; } + virtual bool operator() (const osg::Vec2& value) const { return operator()(value.x()) && operator()(value.y()) ; } + virtual bool operator() (const osg::Vec3& value) const { return operator()(value.x()) && operator()(value.y()) && operator()(value.z()); } + virtual bool operator() (const osg::Vec4& value) const { return operator()(value.x()) && operator()(value.y()) && operator()(value.z()) && operator()(value.w()); } +}; + +struct ValidRange : public ValidDataOperator +{ + ValidRange(float minValue, float maxValue): + _minValue(minValue), + _maxValue(maxValue) {} + + void setRange(float minValue, float maxValue) + { + _minValue = minValue; + _maxValue = maxValue; + } + + void setMinValue(float minValue) { _minValue = minValue; } + float getMinValue() const { return _minValue; } + + void setMaxValue(float maxValue) { _maxValue = maxValue; } + float getMaxValue() const { return _maxValue; } + + virtual bool operator() (float value) const { return value>=_minValue && value<=_maxValue; } + + float _minValue, _maxValue; +}; + + +struct NoDataValue : public ValidDataOperator +{ + NoDataValue(float value): + _value(value) {} + + void setNoDataValue(float value) { _value = value; } + float getValue() const { return _value; } + + virtual bool operator() (float value) const { return value!=_value; } + + float _value; +}; + +} + +#endif + + diff --git a/src/osgTerrain/CMakeLists.txt b/src/osgTerrain/CMakeLists.txt index 6ddcbbaa1..7d6c695db 100644 --- a/src/osgTerrain/CMakeLists.txt +++ b/src/osgTerrain/CMakeLists.txt @@ -13,6 +13,7 @@ SET(LIB_PUBLIC_HEADERS ${HEADER_PATH}/TerrainNode ${HEADER_PATH}/TerrainTechnique ${HEADER_PATH}/GeometryTechnique + ${HEADER_PATH}/ValidDataOperator ${HEADER_PATH}/Version ) diff --git a/src/osgTerrain/GeometryTechnique.cpp b/src/osgTerrain/GeometryTechnique.cpp index a3ac7b73e..f261c4006 100644 --- a/src/osgTerrain/GeometryTechnique.cpp +++ b/src/osgTerrain/GeometryTechnique.cpp @@ -142,12 +142,12 @@ void GeometryTechnique::init() unsigned int numVertices = numRows * numColumns; // allocate and assign vertices - osg::Vec3Array* _vertices = new osg::Vec3Array(numVertices); + osg::Vec3Array* _vertices = new osg::Vec3Array; if (_terrainGeometry.valid()) _terrainGeometry->setVertices(_vertices); if (_geometry.valid()) _geometry->setVertexArray(_vertices); // allocate and assign normals - osg::Vec3Array* _normals = new osg::Vec3Array(numVertices); + osg::Vec3Array* _normals = new osg::Vec3Array; if (_terrainGeometry.valid()) _terrainGeometry->setNormals(_normals); if (_geometry.valid()) { @@ -169,14 +169,14 @@ void GeometryTechnique::init() color_index = texcoord_index; ++texcoord_index; - _texcoords = new osg::Vec2Array(numVertices); + _texcoords = new osg::Vec2Array; if (_terrainGeometry.valid()) _terrainGeometry->setTexCoords(color_index, _texcoords); if (_geometry.valid()) _geometry->setTexCoordArray(color_index, _texcoords); } - osg::FloatArray* _elevations = new osg::FloatArray(numVertices); + osg::FloatArray* _elevations = new osg::FloatArray; osg::TransferFunction1D* tf = dynamic_cast(colorTF); if (tf) { @@ -194,6 +194,10 @@ void GeometryTechnique::init() } } + if (_vertices) _vertices->reserve(numVertices); + if (_texcoords) _texcoords->reserve(numVertices); + if (_elevations) _elevations->reserve(numVertices); + if (_normals) _normals->reserve(numVertices); // allocate and assign color osg::Vec4Array* _colors = new osg::Vec4Array(1); @@ -205,6 +209,10 @@ void GeometryTechnique::init() _geometry->setColorArray(_colors); _geometry->setColorBinding(osg::Geometry::BIND_OVERALL); } + + + typedef std::vector Indices; + Indices indices(numColumns*numRows, -1); // populate vertex and tex coord arrays unsigned int j; @@ -214,47 +222,59 @@ void GeometryTechnique::init() { unsigned int iv = j*numColumns + i; osg::Vec3d ndc( ((double)i)/(double)(numColumns-1), ((double)j)/(double)(numRows-1), 0.0); + + bool validValue = true; + if (elevationLayer) { float value = 0.0f; - elevationLayer->getValue(i,j, value); + validValue = elevationLayer->getValidValue(i,j, value); // osg::notify(osg::NOTICE)<<"i="<addPrimitiveSet(elements); + int i10 = i00+1; + int i11 = i01+1; - if (_geometry.valid()) _geometry->addPrimitiveSet(elements); - } - } - else - { - osg::notify(osg::NOTICE)<<"New tesselation"<reserve((numRows-1) * (numColumns-1) * 6); - - if (_terrainGeometry.valid()) _terrainGeometry->addPrimitiveSet(elements); - if (_geometry.valid()) _geometry->addPrimitiveSet(elements); - - for(j=0; j=0) ++numValid; + if (i01>=0) ++numValid; + if (i10>=0) ++numValid; + if (i11>=0) ++numValid; + + if (numValid==4) { - unsigned int i00; - unsigned int i01; - if (swapOrientation) - { - i01 = j*numColumns + i; - i00 = i01+numColumns; - } - else - { - i00 = j*numColumns + i; - i01 = i00+numColumns; - } - - unsigned int i10 = i00+1; - unsigned int i11 = i01+1; - float e00 = (*_elevations)[i00]; float e10 = (*_elevations)[i10]; float e01 = (*_elevations)[i01]; float e11 = (*_elevations)[i11]; - + if (fabsf(e00-e11)push_back(i01); @@ -345,9 +349,18 @@ void GeometryTechnique::init() elements->push_back(i11); } } + else if (numValid==3) + { + if (i00>=0) elements->push_back(i00); + if (i01>=0) elements->push_back(i01); + if (i11>=0) elements->push_back(i11); + if (i10>=0) elements->push_back(i10); + } + } } + bool containsTransparency = false; if (colorLayer) diff --git a/src/osgTerrain/Layer.cpp b/src/osgTerrain/Layer.cpp index 0879a2c0d..143179a15 100644 --- a/src/osgTerrain/Layer.cpp +++ b/src/osgTerrain/Layer.cpp @@ -187,7 +187,7 @@ bool ImageLayer::getValue(unsigned int i, unsigned int j, float& value) const return false; } - return false; + return true; } bool ImageLayer::getValue(unsigned int i, unsigned int j, osg::Vec2& value) const