Added ValidDataOperator base class and NoDataValue and ValidRange subclasses, and

support for it in osgTerrain::Layer and GeometryTechniqnue.
This commit is contained in:
Robert Osfield 2007-05-11 18:25:06 +00:00
parent e72ec7bb15
commit acb2ed177c
6 changed files with 204 additions and 83 deletions

View File

@ -81,6 +81,7 @@ int main(int argc, char** argv)
osg::ref_ptr<osgTerrain::TerrainNode> terrain = new osgTerrain::TerrainNode;
osg::ref_ptr<osgTerrain::Locator> locator = new osgTerrain::EllipsoidLocator(-osg::PI, -osg::PI*0.5, 2.0*osg::PI, osg::PI, 0.0);
osg::ref_ptr<osgTerrain::ValidDataOperator> 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<osgTerrain::ImageLayer> 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<osgTerrain::ImageLayer> imageLayer = new osgTerrain::ImageLayer;
imageLayer->setImage(image.get());
imageLayer->setLocator(locator.get());
imageLayer->setValidDataOperator(validDataOperator.get());
if (offset!=0.0f || scale!=1.0f)
{

View File

@ -19,6 +19,7 @@
#include <osg/Array>
#include <osgTerrain/Locator>
#include <osgTerrain/ValidDataOperator>
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> _locator;
osg::Vec4 _defaultValue;
osg::ref_ptr<Locator> _locator;
osg::ref_ptr<ValidDataOperator> _validDataOperator;
osg::Vec4 _defaultValue;
};

View File

@ -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 <osgTerrain/Export>
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

View File

@ -13,6 +13,7 @@ SET(LIB_PUBLIC_HEADERS
${HEADER_PATH}/TerrainNode
${HEADER_PATH}/TerrainTechnique
${HEADER_PATH}/GeometryTechnique
${HEADER_PATH}/ValidDataOperator
${HEADER_PATH}/Version
)

View File

@ -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<osg::TransferFunction1D*>(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<int> 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="<<i<<" j="<<j<<" z="<<value<<std::endl;
ndc.z() = value;
}
osg::Vec3d model;
masterLocator->convertLocalToModel(ndc, model);
(*_vertices)[iv] = model - centerModel;
if (colorLayer)
if (validValue)
{
if (colorLocator!= masterLocator)
indices[iv] = _vertices->size();
osg::Vec3d model;
masterLocator->convertLocalToModel(ndc, model);
(*_vertices).push_back(model - centerModel);
if (colorLayer)
{
osg::Vec3d color_ndc;
Locator::convertLocalCoordBetween(*masterLocator, ndc, *colorLocator, color_ndc);
(*_texcoords)[iv].set(color_ndc.x(), color_ndc.y());
}
else
{
(*_texcoords)[iv].set(ndc.x(), ndc.y());
if (colorLocator!= masterLocator)
{
osg::Vec3d color_ndc;
Locator::convertLocalCoordBetween(*masterLocator, ndc, *colorLocator, color_ndc);
(*_texcoords).push_back(osg::Vec2(color_ndc.x(), color_ndc.y()));
}
else
{
(*_texcoords).push_back(osg::Vec2(ndc.x(), ndc.y()));
}
}
}
if (_elevations)
{
(*_elevations).push_back((ndc.z()-minHeight)*scaleHeight);
}
if (_elevations)
// compute the local normal
osg::Vec3d ndc_one( (double)i/(double)(numColumns-1), (double)j/(double)(numColumns-1), 1.0);
osg::Vec3d model_one;
masterLocator->convertLocalToModel(ndc_one, model_one);
model_one = model_one - model;
model_one.normalize();
(*_normals).push_back(model_one);
}
else
{
(*_elevations)[iv] = (ndc.z()-minHeight)*scaleHeight;
indices[iv] = -1;
}
// compute the local normal
osg::Vec3d ndc_one( (double)i/(double)(numColumns-1), (double)j/(double)(numColumns-1), 1.0);
osg::Vec3d model_one;
masterLocator->convertLocalToModel(ndc_one, model_one);
model_one = model_one - model;
model_one.normalize();
(*_normals)[iv] = model_one;
}
}
@ -263,67 +283,51 @@ void GeometryTechnique::init()
bool optimizeOrientations = _elevations!=0;
bool swapOrientation = !(masterLocator->orientationOpenGL());
if (!optimizeOrientations)
osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLES);
elements->reserve((numRows-1) * (numColumns-1) * 6);
if (_terrainGeometry.valid()) _terrainGeometry->addPrimitiveSet(elements);
if (_geometry.valid()) _geometry->addPrimitiveSet(elements);
for(j=0; j<numRows-1; ++j)
{
osg::notify(osg::NOTICE)<<"Old tesselation"<<std::endl;
for(j=0; j<numRows-1; ++j)
for(unsigned int i=0; i<numColumns-1; ++i)
{
osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLE_STRIP, numColumns*2);
for(unsigned int i=0; i<numColumns; ++i)
int i00;
int i01;
if (swapOrientation)
{
unsigned int iv = j*numColumns + i;
if (swapOrientation)
{
(*elements)[i*2] = iv + numColumns;
(*elements)[i*2+1] = iv;
}
else
{
(*elements)[i*2+1] = iv + numColumns;
(*elements)[i*2] = iv;
}
i01 = j*numColumns + i;
i00 = i01+numColumns;
}
else
{
i00 = j*numColumns + i;
i01 = i00+numColumns;
}
if (_terrainGeometry.valid()) _terrainGeometry->addPrimitiveSet(elements);
int i10 = i00+1;
int i11 = i01+1;
if (_geometry.valid()) _geometry->addPrimitiveSet(elements);
}
}
else
{
osg::notify(osg::NOTICE)<<"New tesselation"<<std::endl;
osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(GL_TRIANGLES);
elements->reserve((numRows-1) * (numColumns-1) * 6);
if (_terrainGeometry.valid()) _terrainGeometry->addPrimitiveSet(elements);
if (_geometry.valid()) _geometry->addPrimitiveSet(elements);
for(j=0; j<numRows-1; ++j)
{
for(unsigned int i=0; i<numColumns-1; ++i)
// remap indices to final vertex positions
i00 = indices[i00];
i01 = indices[i01];
i10 = indices[i10];
i11 = indices[i11];
unsigned int numValid = 0;
if (i00>=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)<fabsf(e01-e10))
{
elements->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)

View File

@ -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