我在《OSG加載傾斜攝影數據》這篇博文中論述瞭如何經過OSG生成一個總體的索引文件,經過這個索引文件來正確顯示ContextCapture(Smart3D)生成的傾斜攝影模型數據。這類傾斜攝影模型數據通常都會有個元數據metadata.xml,經過這個元數據,能夠將其正確顯示在osgEarth的數字地球上。html
metadata.xml中的內容通常以下所示:
node
SRS就是空間座標參考的意思,ENU表示是東北天站心座標系,站心點的經緯度座標爲(108.9594, 34.2196)。這個站心點對應的應該是傾斜攝影模型的中心點,那麼思路就很簡單了,只須要平移旋轉這個傾斜攝影模型,使模型的中心點對應於站心點。這實際上是個地心座標系於站心座標系轉換的問題:
ios
在osgEarth中能夠不用關心這個問題,其直接封裝了一個類osgEarth::GeoTransform,能夠直接經過這個類的接口來加載傾斜攝影模型:web
std::string filePath = "D:/Data/scene/Dayanta/Data.osgb"; osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filePath); osg::ref_ptr<osgEarth::GeoTransform> xform = new osgEarth::GeoTransform(); xform->addChild(node); xform->setTerrain(mapNode->getTerrain()); osgEarth::GeoPoint point(map->getSRS(), 108.9594, 34.2196, -410); //使用絕對高,正高 xform->setPosition(point); osg::ref_ptr<osgEarth::ModelLayer> modelLayer = new osgEarth::ModelLayer("oblic", xform); map->addLayer(modelLayer);
給osgEarth::GeoTransform傳入的osgEarth::GeoPoint就是站心點。不過這種類型的metadata.xml彷佛都沒有給出準確的高程值,因此須要本身調整高程來貼地。可能由於我這裏試用的傾斜攝影數據都是網上找的,不太可能給出準確的地理座標。緩存
另一點要注意的是直接讀取加載的傾斜攝影模型是沒有顏色信息的,這點和OSG還不太同樣,在幫助文檔裏面論述了這個問題:
學習
因此必定要記得加上着色器渲染,不然傾斜攝影模型會變成白模:ui
osgEarth::Registry::shaderGenerator().run(node);
有的metadata.xml裏面的內容是這樣的:
url
這個元數據的意思是這個傾斜攝影模型是根據EPSG編號爲2384的空間參考座標系下構建的。簡單查了一下這個座標系應該是xian80高斯克呂格平面投影直角座標系,由於是用於三維數據,因此加上一個高程造成一個三維立體直角座標系。嚴格意義上來說,是須要將地球展成這個立體直角座標系,將這個傾斜攝影模型放置到SRSOrigin的地理位置纔是最準確的。可是通常的投影東向和北向的方向是不會變的,仍然能夠將SRSOrigin的地理位置當成一個站心位置,只不過這個站心位置再也不是經緯度而是EPSG:2384的平面座標值(加上高程)。spa
因此像這種類型的數據,只須要將SRSOrigin的地理位置值轉換成經緯度值,就變成2.1中描述的狀況了。.net
具體的實現代碼以下:
#include <Windows.h> #include <iostream> #include <string> #include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgEarth/MapNode> #include <osgEarthDrivers/gdal/GDALOptions> #include <osgEarthDrivers/cache_filesystem/FileSystemCache> #include <osgEarth/ImageLayer> #include <osgEarth/Viewpoint> #include <osgEarth/GeoTransform> #include <osgEarth/ModelLayer> #include <osgEarth/Registry> #include <osgEarthUtil/EarthManipulator> #include <gdal_priv.h> using namespace std; void AddModel(osg::ref_ptr<osgEarth::Map> map, osg::ref_ptr<osgEarth::MapNode> mapNode) { // std::string filePath = "D:/Data/scene/Dayanta/Data.osgb"; osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filePath); osg::ref_ptr<osgEarth::GeoTransform> xform = new osgEarth::GeoTransform(); xform->addChild(node); xform->setTerrain(mapNode->getTerrain()); osgEarth::GeoPoint point(map->getSRS(), 108.9594, 34.2196, -410); //使用絕對高,正高 xform->setPosition(point); osg::ref_ptr<osgEarth::ModelLayer> modelLayer = new osgEarth::ModelLayer("oblic", xform); map->addLayer(modelLayer); osgEarth::Registry::shaderGenerator().run(node); } int main() { CPLSetConfigOption("GDAL_DATA", "D:/Work/OSGNewBuild/OpenSceneGraph-3.6.4/3rdParty/x64/gdal-data"); //string wktString = "EPSG:3857"; //web墨卡託投影 //string wktString = "EPSG:4326"; //wgs84 osgEarth::ProfileOptions profileOpts; //profileOpts.srsString() = wktString; //osgEarth::Bounds bs(535139, 3365107, 545139, 3375107); //osgEarth::Bounds bs(73, 3, 135, 53); //profileOpts.bounds() = bs; //地圖配置:設置緩存目錄 osgEarth::Drivers::FileSystemCacheOptions cacheOpts; string cacheDir = "D:/Work/OSGNewBuild/tmp"; cacheOpts.rootPath() = cacheDir; // osgEarth::MapOptions mapOpts; mapOpts.cache() = cacheOpts; //mapOpts.coordSysType() = osgEarth::MapOptions::CSTYPE_PROJECTED; mapOpts.profile() = profileOpts; //建立地圖節點 osg::ref_ptr<osgEarth::Map> map = new osgEarth::Map(mapOpts); osg::ref_ptr<osgEarth::MapNode> mapNode = new osgEarth::MapNode(map); osgEarth::Drivers::GDALOptions gdal; //gdal.url() = "D:/Work/OSGNewBuild/osgearth-2.10.1/data/world.tif"; //gdal.url() = "D:/Work/SinianGIS/bin/Resource/BlueMarbleNASA.jpg"; gdal.url() = "D:/Work/SinianGIS/bin/Resource/baseMap.jpg"; osg::ref_ptr<osgEarth::ImageLayer> imgLayer = new osgEarth::ImageLayer("BlueMarble", gdal); map->addLayer(imgLayer); AddModel(map, mapNode); osgViewer::Viewer viewer; viewer.getCamera()->setClearColor(osg::Vec4(0, 0, 0, 0)); viewer.setSceneData(mapNode); osg::ref_ptr< osgEarth::Util::EarthManipulator> mainManipulator = new osgEarth::Util::EarthManipulator; viewer.setCameraManipulator(mainManipulator); osgEarth::Viewpoint vp; osgEarth::GeoPoint newPoint(map->getSRS(), 108.9594, 34.2196, 0); vp.focalPoint() = newPoint; vp.heading() = 0; vp.pitch() = -90; vp.range() = 1000; mainManipulator->setViewpoint(vp); viewer.setUpViewInWindow(100, 100, 800, 600); return viewer.run(); }
運行結果以下: