osg实现地球并在指定经纬度放置一个飞机模型(非osgEarth方式)

博客展示了与osg和osgEarth相关的代码及其呈现的效果,聚焦于信息技术领域中这两个技术的实际应用呈现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码如下:

#include<osgViewer/Viewer>
#include<osgGA/TrackBallManipulator>
#include<osg/Shape>
#include<osg/ShapeDrawable>
#include<osg/Texture2D>
#include<osgDB/readFile>
#include<osg/MatrixTransform>
#include<osg/PositionAttitudeTransform>
int main(int argc, char*argv[])
{
	osg::ArgumentParser arguments(&argc, argv);

    osgViewer::Viewer viewer(arguments);
	viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
	viewer.setRunFrameScheme(osgViewer::Viewer::CONTINUOUS);
	viewer.setCameraManipulator(new osgGA::TrackballManipulator);

	osg::ref_ptr<osg::Group> m_spRoot = new osg::Group;

    // 精细度设置
    osg::TessellationHints* hints = new osg::TessellationHints;

    hints->setDetailRatio(5.0f);

    // 新建半径为WGS84参考半径的球。即地球半径为6356752.3142米
    osg::ShapeDrawable* sd = new osg::ShapeDrawable(
        new osg::Sphere(osg::Vec3(0.0, 0.0, 0.0), osg::WGS_84_RADIUS_POLAR), hints);

    osg::Geode* geode = new osg::Geode;
    geode->addDrawable(sd);

    // 添加全球的纹理,图片的OSG资源Data中的图片,即使下载osg时附带的图片、模型数据资源文件夹下的图片
    geode->getOrCreateStateSet()->setTextureAttributeAndModes(0,

        /*注意:这里需要读取jpg,故请保证jpg插件存在,否则读取jpg会失败。
        关于怎么编译jpg插件到osg,请参见:https://blog.youkuaiyun.com/danshiming/article/details/115412956
        */
        new osg::Texture2D(osgDB::readImageFile(R"(E:\osg\OpenSceneGraph-Data\Images\land_shallow_topo_2048.jpg)")));

    // 经纬度坐标处理
    osg::ref_ptr<osg::CoordinateSystemNode> spCsn = new osg::CoordinateSystemNode;

    // 设置地球坐标系统为WGS_84,即:经纬度、高程坐标系。
    auto pEllModel = new osg::EllipsoidModel();
    spCsn->setEllipsoidModel(pEllModel);
    spCsn->addChild(geode);

    osg::ref_ptr<osg::Group> spModelRoot = new osg::Group; // 模型根节点

    osg::ref_ptr<osg::MatrixTransform> spMatrixTrans = new osg::MatrixTransform;

    // 读取j-10飞机模型
    auto pNode = osgDB::readNodeFile(R"(E:\osg\OpenSceneGraph-Data\glider.osg)");
    spMatrixTrans->addChild(pNode);
    auto matrix = spMatrixTrans->getMatrix();
    matrix.makeScale(osg::Vec3(10000000, 10000000, 10000000)); // 将飞机放大些,否则和地球相比大小,看不见。
    spMatrixTrans->setMatrix(matrix);

    // 设置飞机在地球的经纬度位置。即将经纬度高程坐标转为地心地固坐标系
    double x, y, z; // 分别表示离地球球心的 x, y, z距离,单位为米。

    // 下面函数参数是以弧度、米为单位的。飞机在北京上空
    pEllModel->convertLatLongHeightToXYZ(osg::DegreesToRadians(39.6), osg::DegreesToRadians(116.35), 1000000, x, y, z);

    osg::ref_ptr<osg::PositionAttitudeTransform> spPosition = new osg::PositionAttitudeTransform;
    spPosition->addChild(spMatrixTrans);

    spModelRoot->addChild(spPosition);

    spCsn->addChild(spModelRoot);
    m_spRoot->addChild(spCsn);

    viewer.getCamera()->setNearFarRatio(0.00001f);
    viewer.setSceneData(m_spRoot);
    
    viewer.run();
}

效果如下:

OpenSceneGraph (简称 OSG)一个开源的高性能 3D 图形库,用于创建复杂且交互式的三维场景。要在 OSG实现地球模型(通常使用球体几何)旋转移动到特定经纬度,你需要做以下几步: 1. 创建球体模型:首先,你需要创建一个代表地球表面的球体几何体。这可以通过osg::Geode和osg::Shape来完成。 ```cpp osg::Geode* geode = new osg::Geode(); osg::Sphere sphere(0, 0, 0, osg::PI * 2, osg::PI / 180 * 60); // 地球半径约为6371公里,这里用一个小一点的值简化 osg::Drawable* drawable = new osg::ShapeDrawable(sphere); geode->addDrawable(drawable); ``` 2. 经纬度转换为三维坐标:使用球体的极坐标系,你需要将经纬度转换为三维位置。这可能涉及到一些数学计算,比如使用经纬度计算地球表面上对应的经线和纬线交点的直角坐标。 ```cpp double latitude = yourLatitude; // 用户输入的纬度 double longitude = yourLongitude; // 用户输入的经度 // 计算XYZ坐标,这依赖于地球的半径和其他参数,这里不提供完整的转换公式,但你可以查找相关算法或库如 GeographicLib 或者使用在线工具生成坐标 osg::Vec3 earthPosition(latitudeRad, longitudeRad, 0); ``` 3. 设置模型的位置和旋转:然后,你可以设置这个地理坐标作为模型的位置,以及适当的旋转使其指向正确的方向。 ```cpp osg::Matrixd rotation = osg::rotate(osg::DegreeToRadian(-longitude), osg::Vec3(0, 1, 0)); // 左手法则决定顺时针还是逆时针旋转 rotation *= osg::rotate(osg::DegreeToRadian(-latitude), osg::Vec3(1, 0, 0)); // 旋转地轴 geode->setTransform(rotation); geode->setPosition(earthPosition); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值