void TileModelFactory::buildElevation(const TileKey& key, const MapFrame& frame, bool accumulate, TileModel* model, ProgressCallback* progress) { const MapInfo& mapInfo = frame.getMapInfo(); const osgEarth::ElevationInterpolation& interp = frame.getMapOptions().elevationInterpolation().get(); // Request a heightfield from the map, falling back on lower resolution tiles // if necessary (fallback=true) osg::ref_ptr<osg::HeightField> hf; bool isFallback = false; if (_hfCache->getOrCreateHeightField(frame, key, accumulate, hf, isFallback, SAMPLE_FIRST_VALID, interp, progress)) { model->_elevationData = TileModel::ElevationData( hf, GeoLocator::createForKey( key, mapInfo ), isFallback ); // Edge normalization: requires adjacency information if ( _terrainOptions.normalizeEdges() == true ) { for( int x=-1; x<=1; x++ ) { for( int y=-1; y<=1; y++ ) { if ( x != 0 || y != 0 ) { TileKey nk = key.createNeighborKey(x, y); if ( nk.valid() ) { osg::ref_ptr<osg::HeightField> hf; if (_hfCache->getOrCreateHeightField(frame, nk, accumulate, hf, isFallback, SAMPLE_FIRST_VALID, interp, progress) ) { model->_elevationData.setNeighbor( x, y, hf.get() ); } } } } } // parent too. if ( key.getLOD() > 0 ) { osg::ref_ptr<osg::HeightField> hf; if ( _hfCache->getOrCreateHeightField(frame, key.createParentKey(), accumulate, hf, isFallback, SAMPLE_FIRST_VALID, interp, progress) ) { model->_elevationData.setParent( hf.get() ); } } } } }
void TileModelFactory::buildNormalMap(const TileKey& key, const MapFrame& frame, bool accumulate, TileModel* model, ProgressCallback* progress) { const MapInfo& mapInfo = frame.getMapInfo(); const osgEarth::ElevationInterpolation& interp = frame.getMapOptions().elevationInterpolation().get(); // Request a heightfield from the map, falling back on lower resolution tiles // if necessary (fallback=true) osg::ref_ptr<osg::HeightField> hf; osg::ref_ptr<osg::HeightField> parentHF; osg::ref_ptr<const TileModel> parentModel; bool isFallback = false; unsigned minNormalLOD = _terrainOptions.minNormalMapLOD().isSet() ? _terrainOptions.minNormalMapLOD().get() : 0u; if ( key.getLOD() >= minNormalLOD ) { // look up the parent's heightfield to use as a template TileKey parentKey = key.createParentKey(); if ( accumulate ) { osg::ref_ptr<TileNode> parentNode; if (_liveTiles->get(parentKey, parentNode)) { parentModel = parentNode->getTileModel(); parentHF = parentModel->_normalData.getHeightField(); if ( parentHF->getNumColumns() == EMPTY_NORMAL_MAP_SIZE ) parentHF = 0L; } } // Make a new heightfield: if (_normalHFCache->getOrCreateHeightField(frame, key, parentHF.get(), hf, isFallback, SAMPLE_FIRST_VALID, interp, progress)) { if ( isFallback && parentModel.valid() ) { model->_normalData = parentModel->_normalData; model->_normalData._fallbackData = true; } else { model->_normalData = TileModel::NormalData( hf, GeoLocator::createForKey( key, mapInfo ), isFallback ); } } } else { // empty HF must be at least 2x2 for normal texture gen to work hf = HeightFieldUtils::createReferenceHeightField( key.getExtent(), EMPTY_NORMAL_MAP_SIZE, EMPTY_NORMAL_MAP_SIZE, true ); model->_normalData = TileModel::NormalData( hf, GeoLocator::createForKey( key, mapInfo ), false ); } if ( isFallback && parentModel.valid() ) { model->_normalTexture = parentModel->_normalTexture.get(); } else { model->generateNormalTexture(); } }
void TileModelFactory::buildElevation(const TileKey& key, const MapFrame& frame, bool accumulate, bool buildTexture, TileModel* model, ProgressCallback* progress) { const MapInfo& mapInfo = frame.getMapInfo(); const osgEarth::ElevationInterpolation& interp = frame.getMapOptions().elevationInterpolation().get(); // Request a heightfield from the map, falling back on lower resolution tiles // if necessary (fallback=true) osg::ref_ptr<osg::HeightField> hf; bool isFallback = false; // look up the parent's heightfield to use as a template osg::ref_ptr<osg::HeightField> parentHF; TileKey parentKey = key.createParentKey(); if ( accumulate ) { osg::ref_ptr<TileNode> parentNode; if (_liveTiles->get(parentKey, parentNode)) { parentHF = parentNode->getTileModel()->_elevationData.getHeightField(); if ( _debug && key.getLOD() > 0 && !parentHF.valid() ) { OE_NOTICE << LC << "Could not find a parent tile HF for " << key.str() << "\n"; } } } // Make a new heightfield: if (_meshHFCache->getOrCreateHeightField(frame, key, parentHF.get(), hf, isFallback, SAMPLE_FIRST_VALID, interp, progress)) { model->_elevationData = TileModel::ElevationData( hf, GeoLocator::createForKey( key, mapInfo ), isFallback ); // Edge normalization: requires adjacency information if ( _terrainOptions.normalizeEdges() == true ) { for( int x=-1; x<=1; x++ ) { for( int y=-1; y<=1; y++ ) { if ( x != 0 || y != 0 ) { TileKey neighborKey = key.createNeighborKey(x, y); if ( neighborKey.valid() ) { osg::ref_ptr<osg::HeightField> neighborParentHF; if ( accumulate ) { TileKey neighborParentKey = neighborKey.createParentKey(); if (neighborParentKey == parentKey) { neighborParentHF = parentHF; } else { osg::ref_ptr<TileNode> neighborParentNode; if (_liveTiles->get(neighborParentKey, neighborParentNode)) { neighborParentHF = neighborParentNode->getTileModel()->_elevationData.getHeightField(); } } } // only pull the tile if we have a valid parent HF for it -- otherwise // you might get a flat tile when upsampling data. if ( neighborParentHF.valid() ) { osg::ref_ptr<osg::HeightField> hf; if (_meshHFCache->getOrCreateHeightField(frame, neighborKey, neighborParentHF.get(), hf, isFallback, SAMPLE_FIRST_VALID, interp, progress) ) { model->_elevationData.setNeighbor( x, y, hf.get() ); } } } } } } // parent too. if ( parentHF.valid() ) { model->_elevationData.setParent( parentHF.get() ); } } if ( buildTexture ) { model->generateElevationTexture(); } } }