diff --git a/examples/osgdem/DataSet.cpp b/examples/osgdem/DataSet.cpp new file mode 100644 index 000000000..daf991f84 --- /dev/null +++ b/examples/osgdem/DataSet.cpp @@ -0,0 +1,1628 @@ +/* -*-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 "DataSet.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "cpl_string.h" +#include + +DataSet::SourceData* DataSet::SourceData::readData(Source* source) +{ + if (!source) return 0; + + + switch(source->getType()) + { + case(Source::IMAGE): + case(Source::HEIGHT_FIELD): + { + GDALDataset* gdalDataSet = (GDALDataset*)GDALOpen(source->getFileName().c_str(),GA_ReadOnly); + if (gdalDataSet) + { + SourceData* data = new SourceData(source); + data->_gdalDataSet = gdalDataSet; + + data->_numValuesX = gdalDataSet->GetRasterXSize(); + data->_numValuesY = gdalDataSet->GetRasterYSize(); + data->_numValuesZ = gdalDataSet->GetRasterCount(); + data->_hasGCPs = gdalDataSet->GetGCPCount()!=0; + + const char* pszSourceSRS = gdalDataSet->GetProjectionRef(); + if (!pszSourceSRS || strlen(pszSourceSRS)==0) pszSourceSRS = gdalDataSet->GetGCPProjection(); + + data->_cs = new osgTerrain::CoordinateSystem(pszSourceSRS); + + double geoTransform[6]; + if (gdalDataSet->GetGeoTransform(geoTransform)==CE_None) + { + data->_geoTransform.set( geoTransform[1], geoTransform[4], 0.0, 0.0, + geoTransform[2], geoTransform[5], 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + geoTransform[0], geoTransform[3], 0.0, 1.0); + + data->_extents.init(); + data->_extents.expandBy( osg::Vec3(0.0,0.0,0.0)*data->_geoTransform); + data->_extents.expandBy( osg::Vec3(data->_numValuesX,data->_numValuesY,0.0)*data->_geoTransform); + + } + else if (gdalDataSet->GetGCPCount()>0 && gdalDataSet->GetGCPProjection()) + { + std::cout << " Using GCP's"<< std::endl; + + + /* -------------------------------------------------------------------- */ + /* Create a transformation object from the source to */ + /* destination coordinate system. */ + /* -------------------------------------------------------------------- */ + void *hTransformArg = + GDALCreateGenImgProjTransformer( gdalDataSet, pszSourceSRS, + NULL, pszSourceSRS, + TRUE, 0.0, 1 ); + + if ( hTransformArg == NULL ) + { + std::cout<<" failed to create transformer"<_geoTransform.set( adfDstGeoTransform[1], adfDstGeoTransform[4], 0.0, 0.0, + adfDstGeoTransform[2], adfDstGeoTransform[5], 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + adfDstGeoTransform[0], adfDstGeoTransform[3], 0.0, 1.0); + + data->_extents.init(); + data->_extents.expandBy( osg::Vec3(0.0,0.0,0.0)*data->_geoTransform); + data->_extents.expandBy( osg::Vec3(nPixels,nLines,0.0)*data->_geoTransform); + + } + else + { + std::cout << " No GeoTransform or GCP's - unable to compute position in space"<< std::endl; + + } + return data; + } + } + case(Source::MODEL): + { + osg::Node* model = osgDB::readNodeFile(source->getFileName().c_str()); + if (model) + { + SourceData* data = new SourceData(source); + data->_model = model; + data->_extents.expandBy(model->getBound()); + } + + } + break; + } + + return 0; +} + +osg::BoundingBox DataSet::SourceData::getExtents(const osgTerrain::CoordinateSystem* cs) const +{ + if (_cs==cs) return _extents; + if (_cs.valid() && cs) + { + if (*_cs == *cs) return _extents; + + if (_gdalDataSet) + { + + std::cout<<"Projecting bounding volume for "<<_source->getFileName()<getProjectionRef().c_str(), + NULL, cs->getProjectionRef().c_str(), + TRUE, 0.0, 1 ); + + if (!hTransformArg) + { + std::cout<<" failed to create transformer"<getFileName()<getProjectionRef().c_str(), + NULL, cs->getProjectionRef().c_str(), + TRUE, 0.0, 1 ); + + if (!hTransformArg) + { + std::cout<<" failed to create transformer"<getType()) + { + case(Source::IMAGE): + readImage(destination); + break; + case(Source::HEIGHT_FIELD): + readHeightField(destination); + break; + case(Source::MODEL): + readModels(destination); + break; + } +} + +void DataSet::SourceData::readImage(DestinationData& destination) +{ + if (destination._image.valid()) + { + osg::BoundingBox s_bb = getExtents(destination._cs.get()); + + osg::BoundingBox d_bb = destination._extents; + + osg::BoundingBox intersect_bb(s_bb.intersect(d_bb)); + if (!intersect_bb.valid()) + { + std::cout<<"Reading image but it does not intesection destination - ignoring"<s()*(intersect_bb.xMin()-d_bb.xMin())/(d_bb.xMax()-d_bb.xMin())),0); + int destY = osg::maximum((int)floorf((float)destination._image->t()*(intersect_bb.yMin()-d_bb.yMin())/(d_bb.yMax()-d_bb.yMin())),0); + int destWidth = osg::minimum((int)ceilf((float)destination._image->s()*(intersect_bb.xMax()-d_bb.xMin())/(d_bb.xMax()-d_bb.xMin())),(int)destination._image->s())-destX; + int destHeight = osg::minimum((int)ceilf((float)destination._image->t()*(intersect_bb.yMax()-d_bb.yMin())/(d_bb.yMax()-d_bb.yMin())),(int)destination._image->t())-destY; + + std::cout<<" copying from "<GetRasterCount(); + GDALRasterBand* bandGray = 0; + GDALRasterBand* bandRed = 0; + GDALRasterBand* bandGreen = 0; + GDALRasterBand* bandBlue = 0; + GDALRasterBand* bandAlpha = 0; + + for(int b=1;b<=numBands;++b) + { + GDALRasterBand* band = _gdalDataSet->GetRasterBand(b); + if (band->GetColorInterpretation()==GCI_GrayIndex) bandGray = band; + else if (band->GetColorInterpretation()==GCI_RedBand) bandRed = band; + else if (band->GetColorInterpretation()==GCI_GreenBand) bandGreen = band; + else if (band->GetColorInterpretation()==GCI_BlueBand) bandBlue = band; + else if (band->GetColorInterpretation()==GCI_AlphaBand) bandAlpha = band; + else bandGray = band; + } + + + GDALRasterBand* bandSelected = 0; + if (!bandSelected && bandGray) bandSelected = bandGray; + else if (!bandSelected && bandAlpha) bandSelected = bandAlpha; + else if (!bandSelected && bandRed) bandSelected = bandRed; + else if (!bandSelected && bandGreen) bandSelected = bandGreen; + else if (!bandSelected && bandBlue) bandSelected = bandBlue; + + if (bandRed && bandGreen && bandBlue) + { + // RGB + + unsigned int numBytesPerPixel = 1; + GDALDataType targetGDALType = GDT_Byte; + + int pixelSpace=3*numBytesPerPixel; + int lineSpace=-destination._image->getRowSizeInBytes(); + + unsigned char* imageData = destination._image->data(destX,destY+destHeight-1); + std::cout << "reading RGB"<RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,(void*)(imageData+0),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); + bandGreen->RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,(void*)(imageData+1),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); + bandBlue->RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,(void*)(imageData+2),destWidth,destHeight,targetGDALType,pixelSpace,lineSpace); + + } + + + } +} + +void DataSet::SourceData::readHeightField(DestinationData& destination) +{ + if (destination._heightField.valid()) + { + std::cout<<"Reading height field"<getNumColumns()*(intersect_bb.xMin()-d_bb.xMin())/(d_bb.xMax()-d_bb.xMin())),0); + int destY = osg::maximum((int)floorf((float)destination._heightField->getNumRows()*(intersect_bb.yMin()-d_bb.yMin())/(d_bb.yMax()-d_bb.yMin())),0); + int destWidth = osg::minimum((int)ceilf((float)destination._heightField->getNumColumns()*(intersect_bb.xMax()-d_bb.xMin())/(d_bb.xMax()-d_bb.xMin())),(int)destination._heightField->getNumColumns())-destX; + int destHeight = osg::minimum((int)ceilf((float)destination._heightField->getNumRows()*(intersect_bb.yMax()-d_bb.yMin())/(d_bb.yMax()-d_bb.yMin())),(int)destination._heightField->getNumRows())-destY; + + std::cout<<" copying from "<GetRasterCount(); + GDALRasterBand* bandGray = 0; + GDALRasterBand* bandRed = 0; + GDALRasterBand* bandGreen = 0; + GDALRasterBand* bandBlue = 0; + GDALRasterBand* bandAlpha = 0; + + for(int b=1;b<=numBands;++b) + { + GDALRasterBand* band = _gdalDataSet->GetRasterBand(b); + if (band->GetColorInterpretation()==GCI_GrayIndex) bandGray = band; + else if (band->GetColorInterpretation()==GCI_RedBand) bandRed = band; + else if (band->GetColorInterpretation()==GCI_GreenBand) bandGreen = band; + else if (band->GetColorInterpretation()==GCI_BlueBand) bandBlue = band; + else if (band->GetColorInterpretation()==GCI_AlphaBand) bandAlpha = band; + else bandGray = band; + } + + + GDALRasterBand* bandSelected = 0; + if (!bandSelected && bandGray) bandSelected = bandGray; + else if (!bandSelected && bandAlpha) bandSelected = bandAlpha; + else if (!bandSelected && bandRed) bandSelected = bandRed; + else if (!bandSelected && bandGreen) bandSelected = bandGreen; + else if (!bandSelected && bandBlue) bandSelected = bandBlue; + + float heightRatio = 1.0/65536; + + if (bandSelected) + { + // raad the data. + osg::HeightField* hf = destination._heightField.get(); + void* floatdata = (void*)(&(hf->getHeight(destX,destY+destHeight-1))); // start at the top + + unsigned int numBytesPerZvalue = 4; + int lineSpace=-(hf->getNumColumns()*numBytesPerZvalue); //and work down (note - sign) + + bandSelected->RasterIO(GF_Read,windowX,_numValuesY-(windowY+windowHeight),windowWidth,windowHeight,floatdata,destWidth,destHeight,GDT_Float32,numBytesPerZvalue,lineSpace); + + bool doFlip = false; + if (doFlip) + { + // now need to flip since the OSG's origin is in lower left corner. + std::cout<<"flipping"<getNumRows()-1; + for(unsigned int r=0;rgetNumColumns();++c) + { + float temp = hf->getHeight(c,r); + hf->setHeight(c,r,hf->getHeight(c,copy_r)*heightRatio); + hf->setHeight(c,copy_r,temp*heightRatio); + } + } + } + else + { + for(int r=destY;rsetHeight(c,r,hf->getHeight(c,r)*heightRatio); + } + } + } + } + + + } +} + +void DataSet::SourceData::readModels(DestinationData& destination) +{ + if (_model.valid()) + { + std::cout<<"Raading model"<_extents.xMax()-_sourceData->_extents.xMin())/(double)_sourceData->_numValuesX; + double dy = (_sourceData->_extents.yMax()-_sourceData->_extents.yMin())/(double)_sourceData->_numValuesY; + + setSortValue( sqrt( dx*dx + dy*dy ) ); + } +} + +void DataSet::Source::loadSourceData() +{ + std::cout<<"DataSet::Source::loadSourceData() "<<_filename<_hasGCPs) return true; + + // coordinate system are the same. + if (_sourceData->_cs == cs) return false; + + if (_sourceData->_cs.valid() && cs) + { + return (*(_sourceData->_cs) != *cs); + } + return false; +} + +DataSet::Source* DataSet::Source::doReproject(osgTerrain::CoordinateSystem* cs,const std::string& filename) const +{ + // return nothing when repoject is inappropriate. + if (!_sourceData) return 0; + if (_type==MODEL) return 0; + + std::cout<<"reprojecting to file "<_gdalDataSet,_sourceData->_cs->getProjectionRef().c_str(), + NULL, cs->getProjectionRef().c_str(), + TRUE, 0.0, 1 ); + + if (!hTransformArg) + { + std::cout<<" failed to create transformer"<_gdalDataSet, + GDALGenImgProjTransform, hTransformArg, + adfDstGeoTransform, &nPixels, &nLines ) + != CE_None ) + { + std::cout<<" failed to create warp"<_gdalDataSet,1)); + + +/* --------------------------------------------------------------------- */ +/* Create the file */ +/* --------------------------------------------------------------------- */ + + GDALDatasetH hDstDS = GDALCreate( hDriver, filename.c_str(), nPixels, nLines, + GDALGetRasterCount(_sourceData->_gdalDataSet), eDT, + 0 ); + + if( hDstDS == NULL ) + return NULL; + +/* -------------------------------------------------------------------- */ +/* Write out the projection definition. */ +/* -------------------------------------------------------------------- */ + GDALSetProjection( hDstDS, cs->getProjectionRef().c_str() ); + GDALSetGeoTransform( hDstDS, adfDstGeoTransform ); + + +// Set up the transformer along with the new datasets. + + hTransformArg = + GDALCreateGenImgProjTransformer( _sourceData->_gdalDataSet,_sourceData->_cs->getProjectionRef().c_str(), + hDstDS, cs->getProjectionRef().c_str(), + TRUE, 0.0, 1 ); + + GDALTransformerFunc pfnTransformer = GDALGenImgProjTransform; + + + std::cout<<"Setting projection "<getProjectionRef()<_gdalDataSet,1) ); + if( hCT != NULL ) + GDALSetRasterColorTable( GDALGetRasterBand(hDstDS,1), hCT ); + +/* -------------------------------------------------------------------- */ +/* Setup warp options. */ +/* -------------------------------------------------------------------- */ + GDALWarpOptions *psWO = GDALCreateWarpOptions(); + + psWO->hSrcDS = _sourceData->_gdalDataSet; + psWO->hDstDS = hDstDS; + + psWO->pfnTransformer = pfnTransformer; + psWO->pTransformerArg = hTransformArg; + + psWO->pfnProgress = GDALTermProgress; + +/* -------------------------------------------------------------------- */ +/* Setup band mapping. */ +/* -------------------------------------------------------------------- */ + psWO->nBandCount = GDALGetRasterCount(_sourceData->_gdalDataSet); + psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int)); + psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int)); + + for(int i = 0; i < psWO->nBandCount; i++ ) + { + psWO->panSrcBands[i] = i+1; + psWO->panDstBands[i] = i+1; + } + +/* -------------------------------------------------------------------- */ +/* Initialize and execute the warp. */ +/* -------------------------------------------------------------------- */ + GDALWarpOperation oWO; + + if( oWO.Initialize( psWO ) == CE_None ) + { + oWO.ChunkAndWarpImage( 0, 0, + GDALGetRasterXSize( hDstDS ), + GDALGetRasterYSize( hDstDS ) ); + } + + std::cout<<"new projection is "<_filename = filename; + newSource->_temporaryFile = true; + newSource->_cs = cs; + newSource->_geoTransform.set( adfDstGeoTransform[1], adfDstGeoTransform[4], 0.0, 0.0, + adfDstGeoTransform[2], adfDstGeoTransform[5], 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + adfDstGeoTransform[0], adfDstGeoTransform[3], 0.0, 1.0); + + newSource->_extents.init(); + newSource->_extents.expandBy( osg::Vec3(0.0,0.0,0.0)*newSource->_geoTransform); + newSource->_extents.expandBy( osg::Vec3(nPixels,nLines,0.0)*newSource->_geoTransform); + + // reload the newly created file. + newSource->loadSourceData(); + + SourceData* newData = newSource->_sourceData.get(); + + // override the values in the new source data. + newData->_cs = cs; + newData->_extents = newSource->_extents; + newData->_geoTransform = newSource->_geoTransform; + + + return newSource; +} + +void DataSet::Source::buildOverviews() +{ + return; + + if (_sourceData.valid() && _sourceData->_gdalDataSet ) + { + + int anOverviewList[4] = { 2, 4, 8, 16 }; + GDALBuildOverviews( _sourceData->_gdalDataSet, "AVERAGE", 4, anOverviewList, 0, NULL, + GDALTermProgress/*GDALDummyProgress*/, NULL ); + + } +} + + +DataSet::DestinationTile::DestinationTile(): + _imagery_maxNumColumns(4096), + _imagery_maxNumRows(4096), + _imagery_maxSourceResolutionX(0.0f), + _imagery_maxSourceResolutionY(0.0f), + _terrain_maxNumColumns(1024), + _terrain_maxNumRows(1024), + _terrain_maxSourceResolutionX(0.0f), + _terrain_maxSourceResolutionY(0.0f) +{ + for(int i=0;igetSourceData(); + if (data && (*itr)->getType()!=Source::MODEL) + { + SpatialProperties sp = data->computeSpatialProperties(_cs.get()); + + if (sp._numValuesX!=0 && sp._numValuesY!=0) + { + float sourceResolutionX = (sp._extents.xMax()-sp._extents.xMin())/(float)sp._numValuesX; + float sourceResolutionY = (sp._extents.yMax()-sp._extents.yMin())/(float)sp._numValuesY; + + switch((*itr)->getType()) + { + case(Source::IMAGE): + if (_imagery_maxSourceResolutionX==0.0f) _imagery_maxSourceResolutionX=sourceResolutionX; + else _imagery_maxSourceResolutionX=osg::minimum(_imagery_maxSourceResolutionX,sourceResolutionX); + if (_imagery_maxSourceResolutionY==0.0f) _imagery_maxSourceResolutionY=sourceResolutionY; + else _imagery_maxSourceResolutionY=osg::minimum(_imagery_maxSourceResolutionY,sourceResolutionY); + break; + case(Source::HEIGHT_FIELD): + if (_terrain_maxSourceResolutionX==0.0f) _terrain_maxSourceResolutionX=sourceResolutionX; + else _terrain_maxSourceResolutionX=osg::minimum(_terrain_maxSourceResolutionX,sourceResolutionX); + if (_terrain_maxSourceResolutionY==0.0f) _terrain_maxSourceResolutionY=sourceResolutionY; + else _terrain_maxSourceResolutionY=osg::minimum(_terrain_maxSourceResolutionY,sourceResolutionY); + break; + default: + break; + } + } + } + } +} + +void DataSet::DestinationTile::allocate() +{ + + if (_imagery_maxSourceResolutionX!=0.0f && _imagery_maxSourceResolutionY!=0.0f && + _imagery_maxNumColumns!=0 && _imagery_maxNumRows!=0) + { + + unsigned int numColumnsAtFullRes = 1+(unsigned int)ceilf((_extents.xMax()-_extents.xMin())/_imagery_maxSourceResolutionX); + unsigned int numRowsAtFullRes = 1+(unsigned int)ceilf((_extents.yMax()-_extents.yMin())/_imagery_maxSourceResolutionY); + unsigned int texture_numColumns = osg::minimum(_imagery_maxNumColumns,numColumnsAtFullRes); + unsigned int texture_numRows = osg::minimum(_imagery_maxNumRows,numRowsAtFullRes); + + double texture_dx = (_extents.xMax()-_extents.xMin())/(double)(texture_numColumns-1); + double texture_dy = (_extents.yMax()-_extents.yMin())/(double)(texture_numRows-1); + + _imagery = new DestinationData; + _imagery->_cs = _cs; + _imagery->_extents = _extents; + _imagery->_geoTransform.set(texture_dx, 0.0, 0.0,0.0, + 0.0, -texture_dy, 0.0,0.0, + 0.0, 0.0, 1.0,1.0, + _extents.xMin(), _extents.yMax(), 0.0,1.0); + _imagery->_image = new osg::Image; + _imagery->_image->allocateImage(texture_numColumns,texture_numRows,1,GL_RGB,GL_UNSIGNED_BYTE); + } + + if (_terrain_maxSourceResolutionX!=0.0f && _terrain_maxSourceResolutionY!=0.0f && + _terrain_maxNumColumns!=0 && _terrain_maxNumRows!=0) + { + unsigned int numColumnsAtFullRes = 1+(unsigned int)ceilf((_extents.xMax()-_extents.xMin())/_terrain_maxSourceResolutionX); + unsigned int numRowsAtFullRes = 1+(unsigned int)ceilf((_extents.yMax()-_extents.yMin())/_terrain_maxSourceResolutionY); + unsigned int dem_numColumns = osg::minimum(_terrain_maxNumColumns,numColumnsAtFullRes); + unsigned int dem_numRows = osg::minimum(_terrain_maxNumRows,numRowsAtFullRes); + + double dem_dx = (_extents.xMax()-_extents.xMin())/(double)(dem_numColumns-1); + double dem_dy = (_extents.yMax()-_extents.yMin())/(double)(dem_numRows-1); + + _terrain = new DestinationData; + _terrain->_cs = _cs; + _terrain->_extents = _extents; + _terrain->_geoTransform.set(dem_dx, 0.0, 0.0,0.0, + 0.0, -dem_dy, 0.0,0.0, + 0.0, 0.0, 1.0,1.0, + _extents.xMin(), _extents.yMax(), 0.0,1.0); + _terrain->_heightField = new osg::HeightField; + _terrain->_heightField->allocate(dem_numColumns,dem_numRows); + _terrain->_heightField->setOrigin(osg::Vec3(_extents.xMin(),_extents.yMin(),0.0f)); + _terrain->_heightField->setXInterval(dem_dx); + _terrain->_heightField->setYInterval(dem_dy); + + float xMax = _terrain->_heightField->getOrigin().x()+_terrain->_heightField->getXInterval()*(float)(dem_numColumns-1); + std::cout<<"ErrorX = "<_heightField->getOrigin().y()+_terrain->_heightField->getYInterval()*(float)(dem_numRows-1); + std::cout<<"ErrorY = "<_neighbour[(i+4)%NUMBER_OF_POSITIONS]!=this) + { + std::cout<<"Error:: Tile "< TileCornerPair; + typedef std::vector TileCornerList; + + TileCornerList cornersToProcess; + DestinationTile* tile=0; + + cornersToProcess.push_back(TileCornerPair(this,position)); + + tile = _neighbour[(position-1)%NUMBER_OF_POSITIONS]; + if (tile) cornersToProcess.push_back(TileCornerPair(tile,(Position)((position+2)%NUMBER_OF_POSITIONS))); + + tile = _neighbour[(position)%NUMBER_OF_POSITIONS]; + if (tile) cornersToProcess.push_back(TileCornerPair(tile,(Position)((position+4)%NUMBER_OF_POSITIONS))); + + tile = _neighbour[(position+1)%NUMBER_OF_POSITIONS]; + if (tile) cornersToProcess.push_back(TileCornerPair(tile,(Position)((position+6)%NUMBER_OF_POSITIONS))); + + // make all these tiles as equalised upfront before we return. + TileCornerList::iterator itr; + for(itr=cornersToProcess.begin(); + itr!=cornersToProcess.end(); + ++itr) + { + TileCornerPair& tcp = *itr; + tcp.first->_equalized[tcp.second] = true; + } + + // if there is only one valid corner to process then there is nothing to equalize against so return. + if (cornersToProcess.size()==1) return; + + typedef std::pair ImageCornerPair; + typedef std::vector ImageCornerList; + + typedef std::pair HeightFieldCornerPair; + typedef std::vector HeightFieldCornerList; + + ImageCornerList imagesToProcess; + HeightFieldCornerList heightFieldsToProcess; + + for(itr=cornersToProcess.begin(); + itr!=cornersToProcess.end(); + ++itr) + { + TileCornerPair& tcp = *itr; + if (tcp.first->_imagery.valid() && tcp.first->_imagery->_image.valid()) + { + imagesToProcess.push_back(ImageCornerPair(tcp.first->_imagery->_image.get(),tcp.second)); + } + + if (tcp.first->_terrain.valid() && tcp.first->_terrain->_heightField.valid()) + { + heightFieldsToProcess.push_back(HeightFieldCornerPair(tcp.first->_terrain->_heightField.get(),tcp.second)); + } + } + + if (imagesToProcess.size()>1) + { + int red = 0; + int green = 0; + int blue = 0; + // accumulate colours. + ImageCornerList::iterator iitr; + for(iitr=imagesToProcess.begin(); + iitr!=imagesToProcess.end(); + ++iitr) + { + ImageCornerPair& icp = *iitr; + unsigned char* data=0; + switch(icp.second) + { + case LEFT_BELOW: + data = icp.first->data(0,0); + break; + case BELOW_RIGHT: + data = icp.first->data(icp.first->s()-1,0); + break; + case RIGHT_ABOVE: + data = icp.first->data(icp.first->s()-1,icp.first->t()-1); + break; + case ABOVE_LEFT: + data = icp.first->data(0,icp.first->t()-1); + break; + default : + break; + } + red += *(data++); + green += *(data++); + blue += *(data); + } + + // divide them. + red /= imagesToProcess.size(); + green /= imagesToProcess.size(); + blue /= imagesToProcess.size(); + // apply colour to corners. + for(iitr=imagesToProcess.begin(); + iitr!=imagesToProcess.end(); + ++iitr) + { + ImageCornerPair& icp = *iitr; + unsigned char* data=0; + switch(icp.second) + { + case LEFT_BELOW: + data = icp.first->data(0,0); + break; + case BELOW_RIGHT: + data = icp.first->data(icp.first->s()-1,0); + break; + case RIGHT_ABOVE: + data = icp.first->data(icp.first->s()-1,icp.first->t()-1); + break; + case ABOVE_LEFT: + data = icp.first->data(0,icp.first->t()-1); + break; + default : + break; + } + *(data++) = red; + *(data++) = green; + *(data) = blue; + } + + } + + if (heightFieldsToProcess.size()>1) + { + float height = 0; + // accumulate heights. + HeightFieldCornerList::iterator hitr; + for(hitr=heightFieldsToProcess.begin(); + hitr!=heightFieldsToProcess.end(); + ++hitr) + { + HeightFieldCornerPair& hfcp = *hitr; + switch(hfcp.second) + { + case LEFT_BELOW: + height += hfcp.first->getHeight(0,0); + break; + case BELOW_RIGHT: + height += hfcp.first->getHeight(hfcp.first->getNumColumns()-1,0); + break; + case RIGHT_ABOVE: + height += hfcp.first->getHeight(hfcp.first->getNumColumns()-1,hfcp.first->getNumRows()-1); + break; + case ABOVE_LEFT: + height += hfcp.first->getHeight(0,hfcp.first->getNumRows()-1); + break; + default : + break; + } + } + + // divide them. + height /= heightFieldsToProcess.size(); + + // apply height to corners. + for(hitr=heightFieldsToProcess.begin(); + hitr!=heightFieldsToProcess.end(); + ++hitr) + { + HeightFieldCornerPair& hfcp = *hitr; + switch(hfcp.second) + { + case LEFT_BELOW: + hfcp.first->setHeight(0,0,height); + break; + case BELOW_RIGHT: + hfcp.first->setHeight(hfcp.first->getNumColumns()-1,0,height); + break; + case RIGHT_ABOVE: + hfcp.first->setHeight(hfcp.first->getNumColumns()-1,hfcp.first->getNumRows()-1,height); + break; + case ABOVE_LEFT: + hfcp.first->setHeight(0,hfcp.first->getNumRows()-1,height); + break; + default : + break; + } + } + } + +} + +void DataSet::DestinationTile::equalizeEdge(Position position) +{ + // don't need to equalize if already done. + if (_equalized[position]) return; + + DestinationTile* tile2 = _neighbour[position]; + Position position2 = (Position)((position+4)%NUMBER_OF_POSITIONS); + + _equalized[position] = true; + + // no neighbour of this edge so nothing to equalize. + if (!tile2) return; + + tile2->_equalized[position2]=true; + + osg::Image* image1 = _imagery.valid()?_imagery->_image.get():0; + osg::Image* image2 = tile2->_imagery.valid()?tile2->_imagery->_image.get():0; + + if (image1 && image2 && + image1->getPixelFormat()==image2->getPixelFormat() && + image1->getDataType()==image2->getDataType() && + image1->getPixelFormat()==GL_RGB && + image1->getDataType()==GL_UNSIGNED_BYTE) + { + unsigned char* data1 = 0; + unsigned char* data2 = 0; + unsigned int delta1 = 0; + unsigned int delta2 = 0; + int num = 0; + + switch(position) + { + case LEFT: + data1 = image1->data(0,1); // LEFT hand side + delta1 = image1->getRowSizeInBytes(); + data2 = image2->data(image2->s()-1,1); // RIGHT hand side + delta2 = image2->getRowSizeInBytes(); + num = (image1->t()==image2->t())?image2->t()-2:0; // note miss out corners. + break; + case BELOW: + data1 = image1->data(1,0); // BELOW hand side + delta1 = 3; + data2 = image2->data(1,image2->t()-1); // ABOVE hand side + delta2 = 3; + num = (image1->s()==image2->s())?image2->s()-2:0; // note miss out corners. + break; + case RIGHT: + data1 = image1->data(image2->s()-1,1); // LEFT hand side + delta1 = image1->getRowSizeInBytes(); + data2 = image2->data(0,1); // RIGHT hand side + delta2 = image2->getRowSizeInBytes(); + num = (image1->t()==image2->t())?image2->t()-2:0; // note miss out corners. + break; + case ABOVE: + data1 = image1->data(1,image2->t()-1); // ABOVE hand side + delta1 = 3; + data2 = image2->data(1,0); // BELOW hand side + delta2 = 3; + num = (image1->s()==image2->s())?image2->s()-2:0; // note miss out corners. + break; + default : + break; + } + + for(int i=0;i_heightField.get():0; + osg::HeightField* heightField2 = tile2->_terrain.valid()?tile2->_terrain->_heightField.get():0; + + if (heightField1 && heightField2) + { + float* data1 = 0; + float* data2 = 0; + unsigned int delta1 = 0; + unsigned int delta2 = 0; + int num = 0; + + switch(position) + { + case LEFT: + data1 = &(heightField1->getHeight(0,1)); // LEFT hand side + delta1 = heightField1->getNumColumns(); + data2 = &(heightField2->getHeight(heightField2->getNumColumns()-1,1)); // LEFT hand side + delta2 = heightField2->getNumColumns(); + num = (heightField1->getNumRows()==heightField2->getNumRows())?heightField1->getNumRows()-2:0; // note miss out corners. + break; + case BELOW: + data1 = &(heightField1->getHeight(1,0)); // BELOW hand side + delta1 = 1; + data2 = &(heightField2->getHeight(1,heightField2->getNumRows()-1)); // ABOVE hand side + delta2 = 1; + num = (heightField1->getNumColumns()==heightField2->getNumColumns())?heightField1->getNumColumns()-2:0; // note miss out corners. + break; + case RIGHT: + data1 = &(heightField1->getHeight(heightField1->getNumColumns()-1,1)); // LEFT hand side + delta1 = heightField1->getNumColumns(); + data2 = &(heightField2->getHeight(0,1)); // LEFT hand side + delta2 = heightField2->getNumColumns(); + num = (heightField1->getNumRows()==heightField2->getNumRows())?heightField1->getNumRows()-2:0; // note miss out corners. + break; + case ABOVE: + data1 = &(heightField1->getHeight(1,heightField1->getNumRows()-1)); // ABOVE hand side + delta1 = 1; + data2 = &(heightField2->getHeight(1,0)); // BELOW hand side + delta2 = 1; + num = (heightField1->getNumColumns()==heightField2->getNumColumns())?heightField1->getNumColumns()-2:0; // note miss out corners. + break; + default : + break; + } + + for(int i=0;i_heightField.valid()) + { + osg::Geode* geode = new osg::Geode; + geode->addDrawable(new osg::ShapeDrawable(_terrain->_heightField.get())); + + if (_imagery.valid() && _imagery->_image.valid()) + { + std::string imageName(_name+".rgb"); + _imagery->_image->setFileName(imageName.c_str()); + osgDB::writeImageFile(*_imagery->_image,_imagery->_image->getFileName().c_str()); + + osg::StateSet* stateset = geode->getOrCreateStateSet(); + osg::Texture2D* texture = new osg::Texture2D(_imagery->_image.get()); + texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP); + texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP); + stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); + } + + return geode; + } + else + { + return 0; + } +} + +void DataSet::DestinationTile::readFrom(CompositeSource* sourceGraph) +{ + for(CompositeSource::iterator itr(sourceGraph);itr.valid();++itr) + { + SourceData* data = (*itr)->getSourceData(); + if (data) + { + if (_imagery.valid()) data->read(*_imagery); + if (_terrain.valid()) data->read(*_terrain); + } + } +} + +void DataSet::CompositeDestination::readFrom(CompositeSource* sourceGraph) +{ + // handle leaves + for(TileList::iterator titr=_tiles.begin(); + titr!=_tiles.end(); + ++titr) + { + (*titr)->readFrom(sourceGraph); + } + + // handle chilren + for(ChildList::iterator citr=_children.begin(); + citr!=_children.end(); + ++citr) + { + (*citr)->readFrom(sourceGraph); + } +} + +void DataSet::CompositeDestination::equalizeBoundaries() +{ + // handle leaves + for(TileList::iterator titr=_tiles.begin(); + titr!=_tiles.end(); + ++titr) + { + (*titr)->equalizeBoundaries(); + } + + // handle chilren + for(ChildList::iterator citr=_children.begin(); + citr!=_children.end(); + ++citr) + { + (*citr)->equalizeBoundaries(); + } + +} + + +osg::Node* DataSet::CompositeDestination::createScene() +{ + if (_children.empty() && _tiles.empty()) return 0; + + typedef std::vector NodeList; + NodeList nodes; + + // handle leaves + for(TileList::iterator titr=_tiles.begin(); + titr!=_tiles.end(); + ++titr) + { + osg::Node* node = (*titr)->createScene(); + if (node) nodes.push_back(node); + } + + // handle chilren + for(ChildList::iterator citr=_children.begin(); + citr!=_children.end(); + ++citr) + { + osg::Node* node = (*citr)->createScene(); + if (node) nodes.push_back(node); + } + + if (nodes.empty()) return 0; + if (nodes.size()==1) return nodes.front(); + + osg::Group* group = new osg::Group; + for(NodeList::iterator nitr=nodes.begin(); + nitr!=nodes.end(); + ++nitr) + { + group->addChild(*nitr); + } + return group; + +} + +/////////////////////////////////////////////////////////////////////////////// + +DataSet::DataSet() +{ + init(); + + _defaultColour.set(0.5f,0.5f,1.0f,1.0f); +} + +void DataSet::init() +{ + static bool s_initialized = false; + if (!s_initialized) + { + s_initialized = true; + GDALAllRegister(); + } +} + +void DataSet::addSource(Source* source) +{ + if (!source) return; + + if (!_sourceGraph.valid()) _sourceGraph = new CompositeSource; + + _sourceGraph->_sourceList.push_back(source); +} + +void DataSet::addSource(CompositeSource* composite) +{ + if (!composite) return; + + if (!_sourceGraph.valid()) _sourceGraph = new CompositeSource; + + _sourceGraph->_children.push_back(composite); +} + +void DataSet::loadSources() +{ + for(CompositeSource::iterator itr(_sourceGraph.get());itr.valid();++itr) + { + (*itr)->loadSourceData(); + } +} + +void DataSet::computeDestinationGraphFromSources() +{ + + // ensure we have a valid coordinate system + if (!_coordinateSystem) + { + for(CompositeSource::iterator itr(_sourceGraph.get());itr.valid();++itr) + { + SourceData* sd = (*itr)->getSourceData(); + if (sd) + { + if (sd->_cs.valid()) + { + _coordinateSystem = sd->_cs; + break; + } + } + } + } + + + // get the extents of the sources and + osg::BoundingBox extents(_extents); + if (!extents.valid()) + { + for(CompositeSource::iterator itr(_sourceGraph.get());itr.valid();++itr) + { + SourceData* sd = (*itr)->getSourceData(); + if (sd) extents.expandBy(sd->getExtents(_coordinateSystem.get())); + } + } + + // then create the destinate graph accordingly. + + _destinationGraph = new CompositeDestination; + _destinationGraph->_cs = _coordinateSystem; + _destinationGraph->_extents = extents; + + bool singleTile = false; + if (singleTile) + { + int imageSize = 4096; + int terrainSize = 1024; + + DestinationTile* tile = new DestinationTile; + tile->_name = _tileBasename; + tile->_cs = _destinationGraph->_cs; + tile->_extents = _destinationGraph->_extents; + tile->setMaximumImagerySize(imageSize,imageSize); + tile->setMaximumTerrainSize(terrainSize,terrainSize); + tile->computeMaximumSourceResolution(_sourceGraph.get()); + tile->allocate(); + _destinationGraph->_tiles.push_back(tile); + } + else + { + + + float xCenter = (extents.xMin()+extents.xMax())*0.5f; + float yCenter = (extents.yMin()+extents.yMax())*0.5f; + + + int imageSize = 2048; + int terrainSize = 512; + + + DestinationTile* top_left_tile = 0; + DestinationTile* top_right_tile = 0; + DestinationTile* bottom_left_tile = 0; + DestinationTile* bottom_right_tile = 0; + + { + DestinationTile* tile = new DestinationTile; + tile->_name = _tileBasename+"_0"; + tile->_cs = _destinationGraph->_cs; + tile->_extents.set(extents.xMin(),extents.yMin(),extents.zMin(),xCenter,yCenter,extents.zMax()); + tile->setMaximumImagerySize(imageSize,imageSize); + tile->setMaximumTerrainSize(terrainSize,terrainSize); + tile->computeMaximumSourceResolution(_sourceGraph.get()); + tile->allocate(); + _destinationGraph->_tiles.push_back(tile); + bottom_left_tile = tile; + } + + { + DestinationTile* tile = new DestinationTile; + tile->_name = _tileBasename+"_1"; + tile->_cs = _destinationGraph->_cs; + tile->_extents.set(xCenter,extents.yMin(),extents.zMin(),extents.xMax(),yCenter,extents.zMax()); + tile->setMaximumImagerySize(imageSize,imageSize); + tile->setMaximumTerrainSize(terrainSize,terrainSize); + tile->computeMaximumSourceResolution(_sourceGraph.get()); + tile->allocate(); + _destinationGraph->_tiles.push_back(tile); + bottom_right_tile = tile; + } + + { + DestinationTile* tile = new DestinationTile; + tile->_name = _tileBasename+"_2"; + tile->_cs = _destinationGraph->_cs; + tile->_extents.set(extents.xMin(),yCenter,extents.zMin(),xCenter,extents.yMax(),extents.zMax()); + tile->setMaximumImagerySize(imageSize,imageSize); + tile->setMaximumTerrainSize(terrainSize,terrainSize); + tile->computeMaximumSourceResolution(_sourceGraph.get()); + tile->allocate(); + _destinationGraph->_tiles.push_back(tile); + top_left_tile = tile; + } + + { + DestinationTile* tile = new DestinationTile; + tile->_name = _tileBasename+"_3"; + tile->_cs = _destinationGraph->_cs; + tile->_extents.set(xCenter,yCenter,extents.zMin(),extents.xMax(),extents.yMax(),extents.zMax()); + tile->setMaximumImagerySize(imageSize,imageSize); + tile->setMaximumTerrainSize(terrainSize,terrainSize); + tile->computeMaximumSourceResolution(_sourceGraph.get()); + tile->allocate(); + _destinationGraph->_tiles.push_back(tile); + top_right_tile = tile; + } + + // now get each tile to point to each other. + top_left_tile->setNeighbours(0,0,bottom_left_tile,bottom_right_tile,top_right_tile,0,0,0); + top_right_tile->setNeighbours(top_left_tile,bottom_left_tile,bottom_right_tile,0,0,0,0,0); + bottom_left_tile->setNeighbours(0,0,0,0,bottom_right_tile,top_right_tile,top_left_tile,0); + bottom_right_tile->setNeighbours(bottom_left_tile,0,0,0,0,0,top_right_tile,top_left_tile); + + top_left_tile->checkNeighbouringTiles(); + top_right_tile->checkNeighbouringTiles(); + bottom_left_tile->checkNeighbouringTiles(); + bottom_right_tile->checkNeighbouringTiles(); + + + } +} + +template +struct DerefLessFunctor +{ + bool operator () (const T& lhs, const T& rhs) + { + return lhs->getSortValue() > rhs->getSortValue(); + } +}; + +void DataSet::CompositeSource::setSortValueFromSourceDataResolution() +{ + for(SourceList::iterator sitr=_sourceList.begin();sitr!=_sourceList.end();++sitr) + { + (*sitr)->setSortValueFromSourceDataResolution(); + } + + + for(ChildList::iterator citr=_children.begin();citr!=_children.end();++citr) + { + (*citr)->setSortValueFromSourceDataResolution(); + } +} + +void DataSet::CompositeSource::sort() +{ + // sort the sources. + std::sort(_sourceList.begin(),_sourceList.end(),DerefLessFunctor< osg::ref_ptr >()); + + // sort the composite sources internal data + for(ChildList::iterator itr=_children.begin();itr!=_children.end();++itr) + { + (*itr)->sort(); + } + + // source the sources themselves + std::sort(_children.begin(),_children.end(),DerefLessFunctor< osg::ref_ptr >()); + +} + +void DataSet::updateSourcesForDestinationGraphNeeds() +{ + + std::cout<<"Using Source Iterator itr"<getFileName()<get(); + if (source->needReproject(_coordinateSystem.get())) + { + // do the reprojection to a tempory file. + std::string newFileName = temporyFilePrefix + osgDB::getStrippedName(source->getFileName()) + ".tif"; + + Source* newSource = source->doReproject(_coordinateSystem.get(),newFileName); + + // replace old source by new one. + if (newSource) *itr = newSource; + } + } + } + + // do sampling of data to required values. + { + for(CompositeSource::iterator itr(_sourceGraph.get());itr.valid();++itr) + { + Source* source = itr->get(); + source->buildOverviews(); + } + } + + // sort the sources so that the lowest res tiles are drawn first. + { + for(CompositeSource::iterator itr(_sourceGraph.get());itr.valid();++itr) + { + Source* source = itr->get(); + source->setSortValueFromSourceDataResolution(); + std::cout<<"sort "<getFileName()<<" value "<getSortValue()<sort(); + } + +} + +void DataSet::populateDestinationGraphFromSources() +{ + // for each DestinationTile populate it. + _destinationGraph->readFrom(_sourceGraph.get()); + + // for each DestinationTile equalize the boundaries so they all fit each other without gaps. + _destinationGraph->equalizeBoundaries(); +} + + +void DataSet::createDestination() +{ + + std::cout<<"new DataSet::createDestination()"<createScene(); +} + +void DataSet::writeDestination(const std::string& filename) +{ + std::cout<<"DataSet::writeDestination("< +#include +#include +#include +#include + +#include + +#include + +class DataSet : public osg::Referenced +{ + public: + + class Source; + + + struct SpatialProperties + { + SpatialProperties(): + _numValuesX(0), + _numValuesY(0), + _numValuesZ(0) {} + + SpatialProperties(const SpatialProperties& sp): + _cs(sp._cs), + _geoTransform(sp._geoTransform), + _extents(sp._extents), + _numValuesX(sp._numValuesX), + _numValuesY(sp._numValuesY), + _numValuesZ(sp._numValuesZ) {} + + + SpatialProperties& operator = (const SpatialProperties& sp) + { + if (&sp==this) return *this; + + _cs = sp._cs; + _geoTransform = sp._geoTransform; + _extents = sp._extents; + _numValuesX = sp._numValuesX; + _numValuesY = sp._numValuesY; + _numValuesZ = sp._numValuesZ; + + return *this; + } + + osg::ref_ptr _cs; + osg::Matrixd _geoTransform; + osg::BoundingBox _extents; + unsigned int _numValuesX; + unsigned int _numValuesY; + unsigned int _numValuesZ; + }; + + struct DestinationData : public osg::Referenced, SpatialProperties + { + + DestinationData(): + _minDistance(0.0), + _maxDistance(FLT_MAX) {} + + + typedef std::vector< osg::ref_ptr > ModelList; + + float _minDistance; + float _maxDistance; + + osg::ref_ptr _image; + osg::ref_ptr _heightField; + ModelList _models; + }; + + struct SourceData : public osg::Referenced, public SpatialProperties + { + + SourceData(Source* source=0): + _source(source), + _hasGCPs(false), + _gdalDataSet(0) {} + + + virtual ~SourceData() + { + if (_gdalDataSet) GDALClose(_gdalDataSet); + } + + static SourceData* readData(Source* source); + + osg::BoundingBox getExtents(const osgTerrain::CoordinateSystem* cs) const; + + SpatialProperties computeSpatialProperties(osgTerrain::CoordinateSystem* cs) const; + + void read(DestinationData& destination); + + void readImage(DestinationData& destination); + void readHeightField(DestinationData& destination); + void readModels(DestinationData& destination); + + Source* _source; + + bool _hasGCPs; + + osg::ref_ptr _model; + GDALDataset* _gdalDataSet; + }; + + + class Source : public osg::Referenced, public SpatialProperties + { + public: + + enum Type + { + IMAGE, + HEIGHT_FIELD, + MODEL + }; + + enum ParameterPolicy + { + PREFER_CONFIG_SETTINGS, + PREFER_FILE_SETTINGS + }; + + Source(): + _type(IMAGE), + _sortValue(0.0), + _temporaryFile(false), + _coordinateSystemPolicy(PREFER_FILE_SETTINGS), + _geoTransformPolicy(PREFER_FILE_SETTINGS) + {} + + Source(Type type, const std::string& filename): + _type(type), + _sortValue(0.0), + _filename(filename), + _temporaryFile(false), + _coordinateSystemPolicy(PREFER_FILE_SETTINGS), + _geoTransformPolicy(PREFER_FILE_SETTINGS) + {} + + void setSortValue(double s) { _sortValue = s; } + double getSortValue() const { return _sortValue; } + + void setSortValueFromSourceDataResolution(); + + void setType(Type type) { _type = type; } + Type getType() const { return _type; } + + void setFileName(const std::string& filename) { _filename = filename; } + const std::string& getFileName() const { return _filename; } + + void setTemporaryFile(bool temporaryFile) { _temporaryFile = temporaryFile; } + bool getTemporaryFile() const { return _temporaryFile; } + + void setCoordinateSystemPolicy(ParameterPolicy policy) { _coordinateSystemPolicy = policy; } + void setCoordinateSystem(osgTerrain::CoordinateSystem* cs) { _cs = cs; } + osgTerrain::CoordinateSystem* getCoordinateSystem() { return _cs.get(); } + + + void setGeoTransformPolicy(ParameterPolicy policy) { _geoTransformPolicy = policy; } + + void setGeoTransform(osg::Matrixd& transform) { _geoTransform = transform; } + osg::Matrixd& getGeoTransform() { return _geoTransform; } + + + void setSourceData(SourceData* data) { _sourceData = data; if (_sourceData.valid()) _sourceData->_source = this; } + SourceData* getSourceData() { return _sourceData.get(); } + + void loadSourceData(); + + bool needReproject(const osgTerrain::CoordinateSystem* cs) const; + + Source* doReproject(osgTerrain::CoordinateSystem* cs, const std::string& filename) const; + + void buildOverviews(); + + protected: + + + Type _type; + + double _sortValue; + + std::string _filename; + bool _temporaryFile; + + ParameterPolicy _coordinateSystemPolicy; + ParameterPolicy _geoTransformPolicy; + + osg::ref_ptr _sourceData; + + }; + + enum CompositeType + { + GROUP, + LEVEL_OF_DETAIL + }; + + class CompositeSource : public osg::Referenced, public SpatialProperties + { + public: + + CompositeSource() {}; + + typedef std::vector< osg::ref_ptr > SourceList; + typedef std::vector< osg::ref_ptr< CompositeSource> > ChildList; + + void setSortValue(double s) { _sortValue = s; } + double getSortValue() const { return _sortValue; } + + void setSortValueFromSourceDataResolution(); + + void sort(); + + class iterator + { + public: + + + iterator(CompositeSource* composite) + { + if (composite) + { + _positionStack.push_back(IteratorPosition(composite)); + advance(); + } + } + + iterator(const iterator& rhs): + _positionStack(rhs._positionStack) {} + + iterator& operator = (const iterator& rhs) + { + if (&rhs==this) return *this; + _positionStack = rhs._positionStack; + } + + bool valid() const + { + return !_positionStack.empty() && _positionStack.back().valid(); + } + + osg::ref_ptr& operator *() + { + return valid()?_positionStack.back().currentSource():_nullSource; + } + + osg::ref_ptr* operator ->() + { + return valid()?&(_positionStack.back().currentSource()):&_nullSource; + } + + iterator& operator++() + { + advance(); + return *this; + } + + iterator operator++(int) + { + iterator tmp=*this; + advance(); + return tmp; + } + + bool advance() + { + if (_positionStack.empty()) return false; + + // simple advance to the next source + if (_positionStack.back().advance()) + { + if (_positionStack.back().currentSource().valid()) return true; + + if (_positionStack.back().currentChild()) + { + std::cout<<"Pushing IteratorPosition"<& currentSource() + { + return (_index>=0 && _index < (int)_composite->_sourceList.size())?_composite->_sourceList[_index]:_nullSource; + } + + CompositeSource* currentChild() + { + return (_index < (int)_composite->_sourceList.size())?0: + (_index-_composite->_sourceList.size() < _composite->_children.size())?(_composite->_children[_index-_composite->_sourceList.size()].get()):0; + } + + bool valid() const + { + return _composite && + _index >= 0 && + _index < (int)(_composite->_sourceList.size()+_composite->_children.size()); + } + + bool advance() + { + if (_index+1 < (int)(_composite->_sourceList.size()+_composite->_children.size())) + { + ++_index; + return valid(); + } + return false; + } + + CompositeSource* _composite; + int _index; + osg::ref_ptr _nullSource; + }; + + typedef std::vector PositionStack; + PositionStack _positionStack; + osg::ref_ptr _nullSource; + }; + + + + CompositeType _type; + SourceList _sourceList; + ChildList _children; + float _sortValue; + }; + + + + class DestinationTile : public osg::Referenced, public SpatialProperties + { + public: + + + enum Position + { + LEFT = 0, + LEFT_BELOW = 1, + BELOW = 2, + BELOW_RIGHT = 3, + RIGHT = 4, + RIGHT_ABOVE = 5, + ABOVE = 6, + ABOVE_LEFT = 7, + NUMBER_OF_POSITIONS = 8 + }; + + + DestinationTile(); + + void setNeighbours(DestinationTile* left, DestinationTile* left_below, + DestinationTile* below, DestinationTile* below_right, + DestinationTile* right, DestinationTile* right_above, + DestinationTile* above, DestinationTile* above_left); + + void checkNeighbouringTiles(); + + void setMaximumImagerySize(unsigned int maxNumColumns,unsigned int maxNumRows) + { + _imagery_maxNumColumns = maxNumColumns; + _imagery_maxNumRows = maxNumRows; + } + + void setMaximumTerrainSize(unsigned int maxNumColumns,unsigned int maxNumRows) + { + _terrain_maxNumColumns = maxNumColumns; + _terrain_maxNumRows = maxNumRows; + } + + void computeMaximumSourceResolution(CompositeSource* sourceGraph); + + void allocate(); + + void readFrom(CompositeSource* sourceGraph); + + void equalizeCorner(Position position); + void equalizeEdge(Position position); + + + void equalizeBoundaries(); + + osg::Node* createScene(); + + + std::string _name; + + osg::ref_ptr _imagery; + osg::ref_ptr _terrain; + osg::ref_ptr _models; + + DestinationTile* _neighbour[8]; + bool _equalized[8]; + + + unsigned int _imagery_maxNumColumns; + unsigned int _imagery_maxNumRows; + float _imagery_maxSourceResolutionX; + float _imagery_maxSourceResolutionY; + + unsigned int _terrain_maxNumColumns; + unsigned int _terrain_maxNumRows; + float _terrain_maxSourceResolutionX; + float _terrain_maxSourceResolutionY; + + }; + + class CompositeDestination : public osg::Referenced, public SpatialProperties + { + public: + + void readFrom(CompositeSource* sourceGraph); + + void equalizeBoundaries(); + + osg::Node* createScene(); + + typedef std::vector< osg::ref_ptr > TileList; + typedef std::vector< osg::ref_ptr > ChildList; + + CompositeType _type; + TileList _tiles; + ChildList _children; + }; + + public: + + + DataSet(); + + void addSource(Source* source); + void addSource(CompositeSource* composite); + + void loadSources(); + + void setDestinationCoordinateSystem(osgTerrain::CoordinateSystem* cs) { _coordinateSystem = cs; } + void setDestinationExtents(const osg::BoundingBox& extents) { _extents = extents; } + void setDestinationGeoTransform(const osg::Matrixd& geoTransform) { _geoTransform = geoTransform; } + + void setDestinationTileBaseName(const std::string& basename) { _tileBasename = basename; } + void setDestinationTileExtension(const std::string& extension) { _tileExtension = _tileExtension; } + + + void computeDestinationGraphFromSources(); + void updateSourcesForDestinationGraphNeeds(); + void populateDestinationGraphFromSources(); + + void createDestination(); + + void writeDestination(const std::string& filename); + + osg::Node* getDestinationRootNode() { return _rootNode.get(); } + + + protected: + + virtual ~DataSet() {} + + void init(); + + osg::ref_ptr _sourceGraph; + + osg::ref_ptr _destinationGraph; + + osg::ref_ptr _coordinateSystem; + osg::Matrixd _geoTransform; + osg::BoundingBox _extents; + std::string _tileBasename; + std::string _tileExtension; + osg::Vec4 _defaultColour; + + + osg::ref_ptr _rootNode; + +}; + +#endif diff --git a/examples/osgdem/GNUmakefile b/examples/osgdem/GNUmakefile index dfbbd656d..df7325073 100644 --- a/examples/osgdem/GNUmakefile +++ b/examples/osgdem/GNUmakefile @@ -2,9 +2,10 @@ TOPDIR = ../.. include $(TOPDIR)/Make/makedefs CXXFILES =\ + DataSet.cpp\ osgdem.cpp\ -LIBS += -losgProducer -lProducer -losgFX -losgGL2 -losgText -losgGA -losgDB -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) +LIBS += -losgProducer -lProducer -losgTerrain -losgFX -losgGL2 -losgText -losgGA -losgDB -losgUtil -losg -lgdal $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) INSTFILES = \ $(CXXFILES)\ diff --git a/examples/osgdem/GNUmakefile.inst b/examples/osgdem/GNUmakefile.inst index b2c0aaba7..1d6d959af 100644 --- a/examples/osgdem/GNUmakefile.inst +++ b/examples/osgdem/GNUmakefile.inst @@ -4,7 +4,7 @@ include $(TOPDIR)/Make/makedefs CXXFILES =\ osgdem.cpp\ -LIBS += -losgProducer -lProducer -losgFX -losgGL2 -losgDB -losgText -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) +LIBS += -losgProducer -lProducer -losgTerrain -losgFX -losgGL2 -losgDB -losgText -losgUtil -losg $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) EXEC = osgdem diff --git a/examples/osgdem/osgdem.cpp b/examples/osgdem/osgdem.cpp index 9aa012fd7..5f6b053e0 100644 --- a/examples/osgdem/osgdem.cpp +++ b/examples/osgdem/osgdem.cpp @@ -28,850 +28,12 @@ #include +#include "DataSet.h" -float VERTICAL_SIZE = 0.0005; - -class GraphicsContext { - public: - GraphicsContext() - { - rs = new Producer::RenderSurface; - rs->setWindowRectangle(0,0,1,1); - rs->useBorder(false); - rs->useConfigEventThread(false); - rs->realize(); - std::cout<<"Realized window"< rs; -}; - -osg::Image* createNormalMap(osg::HeightField* grid) -{ - osg::Image* image = new osg::Image; - image->allocateImage(grid->getNumColumns(),grid->getNumRows(),1,GL_RGB,GL_BYTE); - - char* ptr = (char*) image->data(); - for(unsigned int r=0;rgetNumRows();++r) - { - for(unsigned int c=0;cgetNumColumns();++c) - { - osg::Vec3 normal = grid->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); - } - } - - return image; - -} - - -template< typename T> -osg::HeightField* _createHeightField(osg::Image* image, float zScale) -{ - unsigned char* ptr = image->data(); - unsigned int rowSizeInBytes = image->getRowSizeInBytes(); - unsigned int pixelSizeInBits = image->getPixelSizeInBits(); - unsigned int pixelSizeInBytes = pixelSizeInBits/8; - - unsigned int numColumns = image->s(); - unsigned int numRows = image->t(); - - osg::HeightField* grid = new osg::HeightField; - grid->allocateGrid(numColumns,numRows); - - for(unsigned int r=0;rsetHeight(c,r,zScale*(float)(*((T*)ptr_in_row))); - ptr_in_row += pixelSizeInBytes; - } - ptr += rowSizeInBytes; - } - - return grid; -} - -osg::HeightField* createHeightField(osg::Image* image, const osg::Vec3& origin, const osg::Vec3& size) -{ - osg::HeightField* grid = new osg::HeightField; - switch(image->getDataType()) - { - case(GL_UNSIGNED_BYTE): grid = _createHeightField(image,size.z()); break; - case(GL_BYTE): grid = _createHeightField(image,size.z()); break; - case(GL_UNSIGNED_SHORT): grid = _createHeightField(image,size.z()); break; - case(GL_SHORT): grid = _createHeightField(image,size.z()); break; - case(GL_UNSIGNED_INT): grid = _createHeightField(image,size.z()); break; - case(GL_INT): grid = _createHeightField(image,size.z()); break; - case(GL_FLOAT): grid = _createHeightField(image,size.z()); break; - } - grid->setOrigin(origin); - grid->setXInterval(size.x()/(float)(image->s()-1)); - grid->setYInterval(size.y()/(float)(image->s()-1)); - - return grid; - -} - -osg::Node* createTile(osg::HeightField* grid, - unsigned int columnBegin, unsigned int columnEnd, - unsigned int rowBegin, unsigned int rowEnd, - float xTexCoordBegin, float xTexCoordEnd, - float yTexCoordBegin, float yTexCoordEnd, - unsigned int targetNumPolygonsPerTile) -{ - - - int numPolys = (columnEnd-columnBegin)*(rowEnd-rowBegin)*2; - int numColumns, numRows; - bool oneToOneMapping = numPolys<=targetNumPolygonsPerTile; - if (oneToOneMapping) - { - numColumns = (columnEnd-columnBegin)+1; - numRows = (rowEnd-rowBegin)+1; - } - else - { - numColumns = (int)sqrtf((float)targetNumPolygonsPerTile/2.0) + 1; - numRows = targetNumPolygonsPerTile/(2*(numColumns)-1) + 1; - } - - bool createSkirt = true; - - - int numVerticesInBody = numColumns*numRows; - int numVerticesInSkirt = createSkirt ? numColumns*2 + numRows*2 - 4 : 0; - int numVertices = numVerticesInBody+numVerticesInSkirt; - - osg::Vec3 skirtVector(0.0f,0.0f,-0.003f); - - - osg::Geometry* geometry = new osg::Geometry; - - osg::Vec3Array& v = *(new osg::Vec3Array(numVertices)); - osg::Vec2Array& t = *(new osg::Vec2Array(numVertices)); - osg::UByte4Array& color = *(new osg::UByte4Array(1)); - - color[0].set(255,255,255,255); - - - int vi=0; - int r,c; - if (!oneToOneMapping) - { - for(r=0;rgetOrigin()+osg::Vec3(grid->getXInterval()*(float)col, - grid->getYInterval()*(float)row, - grid->getHeight(col,row)); - t[vi].x() = xTexCoordBegin + (xTexCoordEnd-xTexCoordBegin)*(float)(col-columnBegin)/(float)(columnEnd-columnBegin); - t[vi].y() = yTexCoordBegin + (yTexCoordEnd-yTexCoordBegin)*(float)(row-rowBegin)/(float)(rowEnd-rowBegin); - - ++vi; - } - } - } - else - { - for(r=rowBegin;r<=rowEnd;++r) - { - for(c=columnBegin;c<=columnEnd;++c) - { - v[vi] = grid->getOrigin()+osg::Vec3(grid->getXInterval()*c, - grid->getYInterval()*r, - grid->getHeight(c,r)); - t[vi].x() = xTexCoordBegin + (xTexCoordEnd-xTexCoordBegin)*(float)(c-columnBegin)/(float)(columnEnd-columnBegin); - t[vi].y() = yTexCoordBegin + (yTexCoordEnd-yTexCoordBegin)*(float)(r-rowBegin)/(float)(rowEnd-rowBegin); - - ++vi; - } - } - } - - - - geometry->setVertexArray(&v); - geometry->setColorArray(&color); - geometry->setColorBinding(osg::Geometry::BIND_OVERALL); - geometry->setTexCoordArray(0,&t); - geometry->setTexCoordArray(1,&t); - - bool pickOutDiagonals = true; - if (pickOutDiagonals) - { - osg::DrawElementsUShort& drawElements = *(new osg::DrawElementsUShort(GL_TRIANGLES,2*3*(numColumns-1)*(numRows-1))); - geometry->addPrimitiveSet(&drawElements); - int ei=0; - for(r=0;raddPrimitiveSet(&drawElements); - int ei=0; - for(c=0;c0) - { - osg::DrawElementsUShort& skirtDrawElements = *(new osg::DrawElementsUShort(GL_QUAD_STRIP,2*numVerticesInSkirt+2)); - geometry->addPrimitiveSet(&skirtDrawElements); - int ei=0; - int firstSkirtVertexIndex = vi; - // create bottom skirt vertices - r=0; - for(c=0;c0;--c) - { - skirtDrawElements[ei++] = (r)*numColumns+c; - skirtDrawElements[ei++] = vi; - v[vi] = v[(r)*numColumns+c]+skirtVector; - t[vi++] = t[(r)*numColumns+c]; - } - // create left skirt vertices - c=0; - for(r=numRows-1;r>0;--r) - { - skirtDrawElements[ei++] = (r)*numColumns+c; - skirtDrawElements[ei++] = vi; - v[vi] = v[(r)*numColumns+c]+skirtVector; - t[vi++] = t[(r)*numColumns+c]; - } - skirtDrawElements[ei++] = 0; - skirtDrawElements[ei++] = firstSkirtVertexIndex; - } - - - - - osgUtil::TriStripVisitor tsv; - tsv.stripify(*geometry); -// -// osgUtil::SmoothingVisitor sv; -// sv.smooth(*geometry); - - osg::Vec4Array& tsgTangentArray = *(new osg::Vec4Array(1)); - osg::Vec4Array& tsgBinormalArray = *(new osg::Vec4Array(1)); - osg::Vec4Array& tsgNormalArray = *(new osg::Vec4Array(1)); - tsgTangentArray[0].set(1.0f,0.0f,0.0f,0.0f); - tsgBinormalArray[0].set(0.0f,1.0f,0.0f,0.0f); - tsgNormalArray[0].set(0.0f,0.0f,1.0f,0.0f); - geometry->setVertexAttribData(6, osg::Geometry::ArrayData(&tsgTangentArray, osg::Geometry::BIND_OVERALL,GL_FALSE)); - geometry->setVertexAttribData(7, osg::Geometry::ArrayData(&tsgBinormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE)); - geometry->setVertexAttribData(15, osg::Geometry::ArrayData(&tsgNormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE)); - - //geometry->setUseVertexBufferObjects(true); - - geometry->setUseDisplayList(false); - geometry->setUseVertexBufferObjects(false); - - osg::Geode* geode = new osg::Geode; - geode->addDrawable(geometry); - - return geode; - -} - - -osg::Node* createQuadTree(osg::HeightField* grid, - unsigned int columnBegin, unsigned int columnEnd, - unsigned int rowBegin, unsigned int rowEnd, - float xTexCoordBegin, float xTexCoordEnd, - float yTexCoordBegin, float yTexCoordEnd, - unsigned int targetNumPolygonsPerTile, - unsigned int numLevels) -{ - unsigned int numPolys = (columnEnd-columnBegin)*(rowEnd-rowBegin)*2; - - - std::cout << "createQuadTree "<getBound().radius()*4.0f; - float max_visible_distance = 1e7; - - unsigned int columnCenter = (columnBegin + columnEnd)/2; - unsigned int rowCenter = (rowBegin + rowEnd)/2; - float xTexCoordCenter = xTexCoordBegin+ - (xTexCoordEnd-xTexCoordBegin)*((float)(columnCenter-columnBegin)/(float)(columnEnd-columnBegin)); - float yTexCoordCenter = yTexCoordBegin+ - (yTexCoordEnd-yTexCoordBegin)*((float)(rowCenter-rowBegin)/(float)(rowEnd-rowBegin)); - - osg::Group* group = new osg::Group; - group->addChild(createQuadTree(grid, - columnBegin, columnCenter, - rowBegin, rowCenter, - xTexCoordBegin, xTexCoordCenter, - yTexCoordBegin, yTexCoordCenter, - targetNumPolygonsPerTile, - numLevels-1)); - - group->addChild(createQuadTree(grid, - columnCenter, columnEnd, - rowBegin, rowCenter, - xTexCoordCenter, xTexCoordEnd, - yTexCoordBegin, yTexCoordCenter, - targetNumPolygonsPerTile, - numLevels-1)); - - group->addChild(createQuadTree(grid, - columnCenter, columnEnd, - rowCenter, rowEnd, - xTexCoordCenter, xTexCoordEnd, - yTexCoordCenter, yTexCoordEnd, - targetNumPolygonsPerTile, - numLevels-1)); - - group->addChild(createQuadTree(grid, - columnBegin, columnCenter, - rowCenter, rowEnd, - xTexCoordBegin, xTexCoordCenter, - yTexCoordCenter, yTexCoordEnd, - targetNumPolygonsPerTile, - numLevels-1)); - - osg::LOD* lod = new osg::LOD; - lod->addChild(tile,cut_off_distance,max_visible_distance); - lod->addChild(group,0.0f,cut_off_distance); - - return lod; - - } -} - - -template< typename T> -void populate_z(osg::Image* image, const osg::Vec3& zAxis,osg::Vec3Array& v) -{ - unsigned char* ptr = image->data(); - unsigned int rowSizeInBytes = image->getRowSizeInBytes(); - unsigned int pixelSizeInBits = image->getPixelSizeInBits(); - unsigned int pixelSizeInBytes = pixelSizeInBits/8; - - unsigned int numColumns = image->s(); - unsigned int numRows = image->t(); - for(unsigned int r=0,vi=0;r(image->getUserData()); - - unsigned int numColumns = image->s(); - unsigned int numRows = image->t(); - unsigned int r; - unsigned int c; - - osg::Geode* geode = new osg::Geode; - - bool useGeometry = true; - if (useGeometry) - { - - osg::Geometry* geometry = new osg::Geometry; - - osg::Vec3Array& v = *(new osg::Vec3Array(numColumns*numRows)); - //osg::Vec3Array& n = *(new osg::Vec3Array(numColumns*numRows)); - osg::Vec2Array& t = *(new osg::Vec2Array(numColumns*numRows)); - osg::UByte4Array& color = *(new osg::UByte4Array(1)); - - color[0].set(255,255,255,255); - - -#if 0 - osg::Vec2 tex_orig(0.0f,0.0f); - - float rowTexDelta = 1.0f/(float)(numRows-1); - float columnTexDelta = 1.0f/(float)(numColumns-1); -#else - - osg::Vec2 tex_orig(origin.x(),origin.y()); - - float columnTexDelta = xAxis.length()/(float)(numColumns-1); - float rowTexDelta = yAxis.length()/(float)(numRows-1); -#endif - - if (texCoordRange) - { -// tex_orig.set(texCoordRange->_x,texCoordRange->_y); -// rowTexDelta = texCoordRange->_h/(float)(numRows-1); -// columnTexDelta = texCoordRange->_w/(float)(numColumns-1); - - std::cout<<"setting tex values to use texCoordRange"<getDataType()) - { - case(GL_UNSIGNED_BYTE): populate_z(image,zAxis,v); break; - case(GL_BYTE): populate_z(image,zAxis,v); break; - case(GL_UNSIGNED_SHORT): populate_z(image,zAxis,v); break; - case(GL_SHORT): populate_z(image,zAxis,v); break; - case(GL_UNSIGNED_INT): populate_z(image,zAxis,v); break; - case(GL_INT): populate_z(image,zAxis,v); break; - case(GL_FLOAT): populate_z(image,zAxis,v); break; - } - - geometry->setVertexArray(&v); - //geometry->setNormalArray(&n); - //geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX); - geometry->setColorArray(&color); - geometry->setColorBinding(osg::Geometry::BIND_OVERALL); - geometry->setTexCoordArray(0,&t); - geometry->setTexCoordArray(1,&t); - - - for(r=0;raddPrimitiveSet(&drawElements); - int ei=0; - for(c=0;csetVertexAttribData(6, osg::Geometry::ArrayData(&tsgTangentArray, osg::Geometry::BIND_OVERALL,GL_FALSE)); - geometry->setVertexAttribData(7, osg::Geometry::ArrayData(&tsgBinormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE)); - geometry->setVertexAttribData(15, osg::Geometry::ArrayData(&tsgNormalArray, osg::Geometry::BIND_OVERALL,GL_FALSE)); - - //geometry->setUseVertexBufferObjects(true); - - geometry->setUseDisplayList(false); - geometry->setUseVertexBufferObjects(false); - - geode->addDrawable(geometry); - } - else - { - - osg::HeightField* grid = createHeightField(image,origin,osg::Vec3(xAxis.length(),yAxis.length(),zAxis.length())); - - geode->addDrawable(new osg::ShapeDrawable(grid)); - } - - return geode; -} - -osg::Node* computeGeometry(osg::Image* image, const osg::Vec3& origin, const osg::Vec3& size) -{ - return computeGeometry(image,origin,osg::Vec3(size.x(),0.0f,0.0f),osg::Vec3(0.0f,size.y(),0.0f),osg::Vec3(0.0f,0.0f,size.z())); -} - -osg::Node* createTile(const std::string& filename, double x, double y, double w,double h) -{ - - osg::ref_ptr options = new osgDB::ImageOptions; - options->_sourceImageWindowMode = osgDB::ImageOptions::RATIO_WINDOW; - options->_sourceRatioWindow.set(x,1-(y+h),w,h); - - options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW; - options->_destinationPixelWindow.set(0,0,20,20); - - osgDB::Registry::instance()->setOptions(options.get()); - osg::Image* image = osgDB::readImageFile(filename.c_str()); - if (image) - { - - return computeGeometry(image,osg::Vec3(x,y,0.0),osg::Vec3(w,h,VERTICAL_SIZE)); - - } - else - { - return 0; - } -} - -osg::Node* createTileAndRecurse(const std::string& filename, const std::string& basename, const std::string& extension, unsigned int noTilesX, unsigned int noTilesY, double x, double y, double w,double h, unsigned int numLevelsLeft) -{ - - osg::Group* group = new osg::Group; - - double dx = w / (double) noTilesX; - double dy = h / (double) noTilesY; - - - if (numLevelsLeft>0) - { - - float cut_off_distance = 4.0f*dy; - float max_visible_distance = 1e7; - - // create current layer, and write to disk. - unsigned int numTiles = 0; - double lx = x; - for(unsigned i=0;i node = createTileAndRecurse(filename,lbasename,extension,2,2,lx,ly,dx,dy,numLevelsLeft-1); - osgDB::writeNodeFile(*node, lbasename+extension); - } - - // create PagedLOD for tile. - osg::PagedLOD* pagedlod = new osg::PagedLOD; - osg::Node* tile = createTile(filename,lx,ly,dx,dy); - pagedlod->addChild(tile, cut_off_distance,max_visible_distance); - pagedlod->setRange(1,0.0f,cut_off_distance); - pagedlod->setFileName(1,lbasename+extension); - pagedlod->setCenter(tile->getBound().center()); - - group->addChild(pagedlod); - - // increment number of tiles. - ++numTiles; - } - - } - - } - else - { - double lx = x; - for(unsigned i=0;iaddChild(createTile(filename,lx,ly,dx,dy)); - } - } - } - - - return group; - -} - -bool createWorld(const std::string& inputFile, const std::string& baseName, const std::string& diffuseTextureName,unsigned int numLevels) -{ - - osgDB::ReaderWriter* readerWriter = osgDB::Registry::instance()->getReaderWriterForExtension("gdal"); - if (!readerWriter) - { - std::cout<<"Error: GDAL plugin not available, cannot preceed with database creation"< options = new osgDB::ImageOptions; - options->_sourceImageWindowMode = osgDB::ImageOptions::RATIO_WINDOW; - options->_sourceRatioWindow.set(0,0,1,1); - - options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW; - options->_destinationPixelWindow.set(0,0,bumpMapSizeWidth,bumpMapSizeHeight); - - osgDB::Registry::instance()->setOptions(options.get()); - - bool useImage = false; - if (useImage) - { - osg::Image* image = osgDB::readImageFile(inputFile.c_str()); - if (image) - { - osg::HeightField* grid = createHeightField(image,osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(1.0,1.0,VERTICAL_SIZE)); - normalMap = createNormalMap(grid); - normalMap->setFileName("normalmap.rgb"); - osgDB::writeImageFile(*normalMap,"normalmap.rgb"); - - -// scene = createQuadTree(grid, -// 0, grid->getNumColumns()-1, -// 0, grid->getNumRows()-1, -// 0.0f, 1.0f, -// 0.0f, 1.0f, -// 2000, numLevels); - - - - } - } - else - { - osg::HeightField* grid = osgDB::readHeightFieldFile(inputFile.c_str()); - if (grid) - { - osg::HeightField::HeightList& hlist = grid->getHeightList(); - for(osg::HeightField::HeightList::iterator itr=hlist.begin(); - itr!=hlist.end(); - ++itr) - { - (*itr) *= VERTICAL_SIZE; - } - - normalMap = createNormalMap(grid); - normalMap->setFileName("normalmap.rgb"); - osgDB::writeImageFile(*normalMap,"normalmap.rgb"); - -// osg::Geode* geode = new osg::Geode; -// geode->addDrawable(new osg::ShapeDrawable(grid)); -// -// scene = geode; - scene = createQuadTree(grid, - 0, grid->getNumColumns()-1, - 0, grid->getNumRows()-1, - 0.0f, 1.0f, - 0.0f, 1.0f, - 2000, numLevels); - - } - } - } - - // generate diffuse map - osg::Image* diffuseMap = 0; -// { -// osg::ref_ptr options = new osgDB::ImageOptions; -// options->_sourceImageWindowMode = osgDB::ImageOptions::RATIO_WINDOW; -// options->_sourceRatioWindow.set(0,0,1,1); -// -// options->_destinationImageWindowMode = osgDB::ImageOptions::PIXEL_WINDOW; -// options->_destinationPixelWindow.set(0,0,2048,2048); -// -// osgDB::Registry::instance()->setOptions(options.get()); -// diffuseMap = osgDB::readImageFile(inputFile.c_str()); -// if (diffuseMap) -// { -// diffuseMap->setFileName("diffuse.rgb"); -// osgDB::writeImageFile(*diffuseMap,"diffuse.rgb"); -// } -// -// } - - //diffuseMap = osgDB::readImageFile(diffuseTextureName.c_str()); - diffuseMap = new osg::Image; - diffuseMap->setFileName(diffuseTextureName.c_str()); - - - - osg::Texture2D* diffuseMapTexture = new osg::Texture2D(diffuseMap); - osg::Texture2D* normalMapTexture = new osg::Texture2D(normalMap); - - // create osgFX::BumpingMapping - osg::ref_ptr bumpMap = new osgFX::BumpMapping; - bumpMap->setLightNumber(0); - bumpMap->setNormalMapTextureUnit(0); - bumpMap->setDiffuseTextureUnit(1); - bumpMap->selectTechnique(1); - bumpMap->setOverrideDiffuseTexture(diffuseMapTexture); - bumpMap->setOverrideNormalMapTexture(normalMapTexture); - - bumpMap->addChild(scene.get()); - -#ifdef USE_PREPARE - bumpMap->prepareChildren(); -#endif - - osg::ref_ptr group = new osg::Group; - - - group->addChild(bumpMap.get()); - - osg::StateSet* stateset = group->getOrCreateStateSet(); - stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON); - - osgDB::writeNodeFile(*group, baseName); - - } - else - { - - osg::ref_ptr group = new osg::Group; - group->addChild(createTileAndRecurse(inputFile, base, extension, 2,2, 0.0, 0.0, 1.0, 1.0, numLevels)); - - osg::StateSet* stateset = group->getOrCreateStateSet(); - stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON); - - osgDB::writeNodeFile(*group, baseName); - - } - - osg::Timer_t end_tick = timer.tick(); - std::cout << "Time to create world "< int main( int argc, char **argv ) { - // use an ArgumentParser object to manage the program arguments. osg::ArgumentParser arguments(&argc,argv); @@ -879,24 +41,67 @@ int main( int argc, char **argv ) arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName()); arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models."); arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); - arguments.getApplicationUsage()->addCommandLineOption("-i ","Specify the input file to process"); + arguments.getApplicationUsage()->addCommandLineOption("-d ","Specify the digital elevation map input file to process"); + arguments.getApplicationUsage()->addCommandLineOption("-t ","Specify the texture map input file to process"); + arguments.getApplicationUsage()->addCommandLineOption("-m ","Specify the 3D database model input file to process"); arguments.getApplicationUsage()->addCommandLineOption("-o ","Specify the output master file to generate"); arguments.getApplicationUsage()->addCommandLineOption("-l ","Specify the number of PagedLOD levels to generate"); + arguments.getApplicationUsage()->addCommandLineOption("-e ","Extents of the model to generate"); arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); - std::string inputFile; - while (arguments.read("-i",inputFile)) {} + if (arguments.argc()<=1) + { + arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); + return 1; + } + + // create DataSet. + osg::ref_ptr dataset = new DataSet; + + std::string filename; + while (arguments.read("-d",filename)) + { + if (!filename.empty()) dataset->addSource(new DataSet::Source(DataSet::Source::HEIGHT_FIELD,filename)); + } - std::string basename("output.ive"); - while (arguments.read("-o",basename)) {} + while (arguments.read("-t",filename)) + { + if (!filename.empty()) dataset->addSource(new DataSet::Source(DataSet::Source::IMAGE,filename)); + } + + while (arguments.read("-m",filename)) + { + if (!filename.empty()) dataset->addSource(new DataSet::Source(DataSet::Source::MODEL,filename)); + } + + float x,y,w,h; + while (arguments.read("-e",x,y,w,h)) + { + dataset->setDestinationExtents(osg::BoundingBox(x,y,0.0f,x+w,y+h,0.0f)); + } + + dataset->setDestinationTileBaseName("output"); + dataset->setDestinationTileExtension(".ive"); + + std::string outputFileName("output.ive"); + while (arguments.read("-o",outputFileName)) + { + std::string path = osgDB::getFilePath(outputFileName); + std::string base = path.empty()?osgDB::getStrippedName(outputFileName): + path +'/'+ osgDB::getStrippedName(outputFileName); + std::string extension = '.'+osgDB::getLowerCaseFileExtension(outputFileName); + + dataset->setDestinationTileBaseName(base); + dataset->setDestinationTileExtension(extension); + + } float numLevels; while (arguments.read("-l",numLevels)) {} - while (arguments.read("-v",VERTICAL_SIZE)) {} + float verticalScale; + while (arguments.read("-v",verticalScale)) {} - std::string diffuseTextureName("lz.ive"); - while (arguments.read("-t",diffuseTextureName)) {} // if user request help write it out to cout. if (arguments.read("-h") || arguments.read("--help")) @@ -915,18 +120,11 @@ int main( int argc, char **argv ) return 1; } -// if (arguments.argc()<=1) -// { -// arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); -// return 1; -// } + dataset->loadSources(); - - - // create a graphics context to allow us to use OpenGL to compress textures. - GraphicsContext gfx; - - createWorld(inputFile,basename,diffuseTextureName,(unsigned int)numLevels); + dataset->createDestination(); + + dataset->writeDestination(outputFileName); return 0; }