From 01cbfd6715d39923a0f5f4acd51379d7bd9f9620 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 5 Apr 2004 15:39:33 +0000 Subject: [PATCH] Added local transform support. Fixed skirt generation to work during geocentric transformations. Fixed output of image files so that compressed textures are turned off when external image files are required. --- include/osgTerrain/CoordinateSystem | 45 +++++++ src/osgTerrain/DataSet.cpp | 179 +++++++++++++++++++--------- 2 files changed, 167 insertions(+), 57 deletions(-) diff --git a/include/osgTerrain/CoordinateSystem b/include/osgTerrain/CoordinateSystem index 82b6c6ad6..03aa0a7d1 100644 --- a/include/osgTerrain/CoordinateSystem +++ b/include/osgTerrain/CoordinateSystem @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -79,6 +80,50 @@ class EllipsodeTransform height = p/cos(latitude) - N; } + inline void computeLocalToWorldTransform(double latitude, double longitude, double height, osg::Matrixd& localToWorld) const + { + double X, Y, Z; + convertLatLongHeightToXYZ(latitude,longitude,height,X,Y,Z); + + localToWorld.makeTranslate(X,Y,Z); + + // normalize X,Y,Z + double inverse_length = 1.0/sqrt(X*X + Y*Y + Z*Z); + X *= inverse_length; + Y *= inverse_length; + Z *= inverse_length; + + double length_XY = sqrt(X*X + Y*Y); + double inverse_length_XY = 1.0/length_XY; + + // Vx = |(-Y,X,0)| + localToWorld(0,0) = -Y*inverse_length_XY; + localToWorld(0,1) = X*inverse_length_XY; + localToWorld(0,2) = 0.0; + + // Vy = /(-Z*X/(sqrt(X*X+Y*Y), -Z*Y/(sqrt(X*X+Y*Y),sqrt(X*X+Y*Y))| + double Vy_x = -Z*X*inverse_length_XY; + double Vy_y = -Z*Y*inverse_length_XY; + double Vy_z = length_XY; + inverse_length = 1.0/sqrt(Vy_x*Vy_x + Vy_y*Vy_y + Vy_z*Vy_z); + localToWorld(1,0) = Vy_x*inverse_length; + localToWorld(1,1) = Vy_y*inverse_length; + localToWorld(1,2) = Vy_z*inverse_length; + + // Vz = (X,Y,Z) + localToWorld(2,0) = X; + localToWorld(2,1) = Y; + localToWorld(2,2) = Z; + } + + osg::Vec3 computeGavitationVector(double X, double Y, double Z) const + { + osg::Vec3 normal(-X,-Y,-Z); + normal.normalize(); + return normal; + } + + protected: void computeCoefficients() diff --git a/src/osgTerrain/DataSet.cpp b/src/osgTerrain/DataSet.cpp index 86866026e..79d88810e 100644 --- a/src/osgTerrain/DataSet.cpp +++ b/src/osgTerrain/DataSet.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -625,7 +626,7 @@ void DataSet::SourceData::readHeightField(DestinationData& destination) else { std::cout<<"We have no Scale"<getConvertFromGeographicToGeocentric()*/) ? 1.0f/111319.0f : 1.0f; } std::cout<<"********* getLinearUnits = "<setMaxAnisotropy(8); stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); - if (_dataSet->getTextureType()==COMPRESSED_TEXTURE) + bool inlineImageFile = _dataSet->getDestinationTileExtension()==".ive"; + + if (inlineImageFile && _dataSet->getTextureType()==COMPRESSED_TEXTURE) { texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT3_COMPRESSION); @@ -1815,7 +1818,7 @@ osg::StateSet* DataSet::DestinationTile::createStateSet() } - if (_dataSet->getDestinationTileExtension()!=".ive") + if (!inlineImageFile) { std::cout<<"Writing out imagery to "<_image,_imagery->_image->getFileName().c_str()); @@ -1872,6 +1875,18 @@ osg::Node* DataSet::DestinationTile::createHeightField() } + +static osg::Vec3 computeLocalPosition(const osg::Matrixd& localToWorld, double X, double Y, double Z) +{ + X -= localToWorld(3,0); + Y -= localToWorld(3,1); + Z -= localToWorld(3,2); + return osg::Vec3(X*localToWorld(0,0) + Y*localToWorld(0,1) + Z*localToWorld(0,2), + X*localToWorld(1,0) + Y*localToWorld(1,1) + Z*localToWorld(1,2), + X*localToWorld(2,0) + Y*localToWorld(2,1) + Z*localToWorld(2,2)); +} + + osg::Node* DataSet::DestinationTile::createPolygonal() { std::cout<<"--------- DataSet::DestinationTile::createDrawableGeometry() ------------- "<getConvertFromGeographicToGeocentric(); - if (needConversion) std::cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> need to do conversion <<<<<<<<<<<<<<<<<<<< "<getEllipsodeTransform(); + bool mapLatLongsToXYZ = _dataSet->getConvertFromGeographicToGeocentric(); + bool useLocalToTileTransform = _dataSet->getUseLocalTileTransform(); + + if (useLocalToTileTransform) + { + if (mapLatLongsToXYZ) + { + double midLong = grid->getOrigin().x()+grid->getXInterval()*((double)(numColumns-1))*0.5; + double midLat = grid->getOrigin().y()+grid->getYInterval()*((double)(numRows-1))*0.5; + double midZ = grid->getOrigin().z(); + et.computeLocalToWorldTransform(osg::DegreesToRadians(midLat),osg::DegreesToRadians(midLong),midZ,localToWorld); + + double minLong = grid->getOrigin().x(); + double minLat = grid->getOrigin().y(); + + double minX,minY,minZ; + et.convertLatLongHeightToXYZ(osg::DegreesToRadians(minLat),osg::DegreesToRadians(minLong),midZ,minX,minY,minZ); + + double midX,midY; + et.convertLatLongHeightToXYZ(osg::DegreesToRadians(midLat),osg::DegreesToRadians(midLong),midZ,midX,midY,midZ); + + double length = sqrt((midX-minX)*(midX-minX) + (midY-minY)*(midY-minY)); + + skirtVector.set(0.0f,0.0f,-length*skirtRatio); + } + else + { + double midX = grid->getOrigin().x()+grid->getXInterval()*((double)(numColumns-1))*0.5; + double midY = grid->getOrigin().y()+grid->getYInterval()*((double)(numRows-1))*0.5; + double midZ = grid->getOrigin().z(); + localToWorld.makeTranslate(midX,midY,midZ); + skirtVector.set(0.0f,0.0f,-_extents.radius()*skirtRatio); + } + } + else if (mapLatLongsToXYZ) + { + // no local to tile transform + mapping from lat+longs to XYZ so we need to use + // a rotatated skirt vector - use the gravity vector. + double midLong = grid->getOrigin().x()+grid->getXInterval()*((double)(numColumns-1))*0.5; + double midLat = grid->getOrigin().y()+grid->getYInterval()*((double)(numRows-1))*0.5; + double midZ = grid->getOrigin().z(); + double X,Y,Z; + et.convertLatLongHeightToXYZ(osg::DegreesToRadians(midLat),osg::DegreesToRadians(midLong),midZ,X,Y,Z); + osg::Vec3 gravitationVector = et.computeGavitationVector(X,Y,Z); + gravitationVector.normalize(); + skirtVector = gravitationVector * _extents.radius()* skirtRatio; + } + else + { + skirtVector.set(0.0f,0.0f,-_extents.radius()*skirtRatio); + } unsigned int vi=0; unsigned int r,c; - if (needConversion) + // populate the vertex/normal/texcoord arrays from the grid. + double orig_X = grid->getOrigin().x(); + double delta_X = grid->getXInterval(); + double orig_Y = grid->getOrigin().y(); + double delta_Y = grid->getYInterval(); + double orig_Z = grid->getOrigin().z(); + + for(r=0;rgetOrigin().x(); - double delta_longitude = grid->getXInterval(); + for(c=0;cgetHeight(c,r); - double orig_latitude = grid->getOrigin().y(); - double delta_latitude = grid->getYInterval(); - - double orig_height = grid->getOrigin().z(); - - osgTerrain::EllipsodeTransform& et = _dataSet->getEllipsodeTransform(); - - for(r=0;rgetHeight(c,r); - double X,Y,Z; - - et.convertLatLongHeightToXYZ(osg::DegreesToRadians(latitude),osg::DegreesToRadians(longitude),height, + if (mapLatLongsToXYZ) + { + et.convertLatLongHeightToXYZ(osg::DegreesToRadians(Y),osg::DegreesToRadians(X),Z, X,Y,Z); - + } +#if 1 + if (useLocalToTileTransform) + { + v[vi] = computeLocalPosition(localToWorld,X,Y,Z); + } + else +#endif + { v[vi].set(X,Y,Z); + } - // note normal will need rotating. - if (n) (*n)[vi] = grid->getNormal(c,r); + // note normal will need rotating. + if (n) (*n)[vi] = grid->getNormal(c,r); - t[vi].x() = (c==numColumns-1)? 1.0f : (float)(c)/(float)(numColumns-1); - t[vi].y() = (r==numRows-1)? 1.0f : (float)(r)/(float)(numRows-1); + t[vi].x() = (c==numColumns-1)? 1.0f : (float)(c)/(float)(numColumns-1); + t[vi].y() = (r==numRows-1)? 1.0f : (float)(r)/(float)(numRows-1); - ++vi; - } - } - } - else - { - for(r=0;rgetVertex(c,r); - - if (n) (*n)[vi] = grid->getNormal(c,r); - - t[vi].x() = (c==numColumns-1)? 1.0f : (float)(c)/(float)(numColumns-1); - t[vi].y() = (r==numRows-1)? 1.0f : (float)(r)/(float)(numRows-1); - - ++vi; - } - } + ++vi; + } } //geometry->setUseDisplayList(false); @@ -2035,9 +2091,8 @@ osg::Node* DataSet::DestinationTile::createPolygonal() } } - osgUtil::SmoothingVisitor sv; - sv.smooth(*geometry); - +// osgUtil::SmoothingVisitor sv; +// sv.smooth(*geometry); if (numVerticesInSkirt>0) { @@ -2089,7 +2144,7 @@ osg::Node* DataSet::DestinationTile::createPolygonal() skirtDrawElements[ei++] = firstSkirtVertexIndex; } -#if 1 +#if 0 osgUtil::TriStripVisitor tsv; tsv.stripify(*geometry); #endif @@ -2110,8 +2165,18 @@ osg::Node* DataSet::DestinationTile::createPolygonal() osg::Geode* geode = new osg::Geode; geode->addDrawable(geometry); - - return geode; + + if (useLocalToTileTransform) + { + osg::MatrixTransform* mt = new osg::MatrixTransform; + mt->setMatrix(localToWorld); + mt->addChild(geode); + return mt; + } + else + { + return geode; + } } void DataSet::DestinationTile::readFrom(CompositeSource* sourceGraph)