osgEarth示例分析——osgearth_transform

前言

osgearth_transform示例,是控制三维坐标轴的示例。通过控制面板的滑块,进而控制坐标轴的经度、纬度、高度、俯仰角、偏航角、旋转等操作。

执行效果

执行命令 :osgearth_transformd.exe earth_image\world.earth

 

Lat南北移动
Long东西移动
Alt /Zero上下移动 / 高度置零
Heading绕Z轴旋转
Pitch绕X轴旋转
Roll绕Y轴旋转
Relative Z由于没有加载高程数据,所以无法看到效果

代码分析

本节代码的重点:控制视点、以及在地球上如何操作模型的移动、旋转。

#include <osg/PositionAttitudeTransform>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/ExampleResources>
#include <osgEarthUtil/Controls>
#include <osgEarth/GeoTransform>
#include <osgEarth/MapNode>

#define LC "[osgearth_transform] "


using namespace osgEarth;
using namespace osgEarth::Util;

namespace ui = osgEarth::Util::Controls;

int
usage(const char* name)
{
    OE_NOTICE 
        << "\nUsage: " << name << " file.earth" << std::endl;

    return 0;
}

struct App
{
    const osgEarth::SpatialReference* srs;// 坐标系
    osgEarth::GeoTransform*           geo;// 接受地理空间坐标的变换节点。
    osg::PositionAttitudeTransform*   pat;// 节点姿态控制

	// 水平滑块控件
    ui::HSliderControl* uiLat;			// 控制纬度
    ui::HSliderControl* uiLon;			// 控制经度
    ui::HSliderControl* uiAlt;			// 控制高度
    ui::HSliderControl* uiHeading;		// 偏航角
    ui::HSliderControl* uiPitch;		// 俯仰角
    ui::HSliderControl* uiRoll;			// 旋转角
    ui::CheckBoxControl* uiRelativeZ;	// 相对值Z还是绝对值Z

    void apply()
    {
		// altMode 指示如何解释Z坐标。地形之上的高度,还是绝对高度
        AltitudeMode altMode = uiRelativeZ->getValue() ? ALTMODE_RELATIVE : ALTMODE_ABSOLUTE;

		// 根据传入值,创建pos
        GeoPoint pos(
            srs,
            uiLon->getValue(), uiLat->getValue(), uiAlt->getValue(),
            altMode);

		// 将坐标点pos添加到变换节点geo
        geo->setPosition( pos );

		// 四元数
        osg::Quat ori =
            osg::Quat(osg::DegreesToRadians(uiRoll->getValue()),    osg::Vec3(0,1,0)) *		// 角度和方向
            osg::Quat(osg::DegreesToRadians(uiPitch->getValue()),   osg::Vec3(1,0,0)) *
            osg::Quat(osg::DegreesToRadians(uiHeading->getValue()), osg::Vec3(0,0,-1));

		// 设置节点姿态
        pat->setAttitude( ori );
    }
};

struct Apply : public ui::ControlEventHandler
{
    Apply(App& app) : _app(app) { }
    void onValueChanged(ui::Control* control) {
        _app.apply();
    }
    App& _app;
};

// 高度置零
struct ZeroAlt : public ui::ControlEventHandler {
    ZeroAlt(App& app) : _app(app) { }
    void onClick(ui::Control* control) {
        _app.uiAlt->setValue(0.0f);
        _app.apply();
    }
    App& _app;
};

// 创建控制面板的UI界面
ui::Control* makeUI(App& app)
{
    ui::Grid* grid = new ui::Grid();
    grid->setBackColor(0,0,0,0.5);

    grid->setControl(0, 0, new ui::LabelControl("Lat:"));
    grid->setControl(0, 1, new ui::LabelControl("Long:"));
    grid->setControl(0, 2, new ui::LabelControl("Alt:"));
    grid->setControl(0, 3, new ui::LabelControl("Heading:"));
    grid->setControl(0, 4, new ui::LabelControl("Pitch:"));
    grid->setControl(0, 5, new ui::LabelControl("Roll:"));
    grid->setControl(0, 6, new ui::LabelControl("Relative Z:"));

	// 设置滑块的起止值与当前值,添加Apply事件方法
    app.uiLat = grid->setControl(1, 0, new ui::HSliderControl(40.0f, 50.0f, 44.7433f, new Apply(app)));
    grid->setControl(2, 0, new LabelControl(app.uiLat));// 添加标签,标签内容会随着app的apply方法更改而更改
    app.uiLon = grid->setControl(1, 1, new ui::HSliderControl(6.0f, 8.0f, 7.0f, new Apply(app)));
    grid->setControl(2, 1, new LabelControl(app.uiLon));
    app.uiAlt = grid->setControl(1, 2, new ui::HSliderControl(-3000.0f, 100000.0f, 25000.0f, new Apply(app)));
    grid->setControl(2, 2, new LabelControl(app.uiAlt));
    grid->setControl(3, 2, new ButtonControl("Zero", new ZeroAlt(app)));// 置零按钮
    app.uiHeading = grid->setControl(1, 3, new ui::HSliderControl(-180.0f, 180.0f, 0.0f, new Apply(app)));
    grid->setControl(2, 3, new LabelControl(app.uiHeading));
    app.uiPitch   = grid->setControl(1, 4, new ui::HSliderControl(-90.0f, 90.0f, 0.0f, new Apply(app)));
    grid->setControl(2, 4, new LabelControl(app.uiPitch));
    app.uiRoll    = grid->setControl(1, 5, new ui::HSliderControl(-180.0f, 180.0f, 0.0f, new Apply(app)));
    grid->setControl(2, 5, new LabelControl(app.uiRoll));
    app.uiRelativeZ = grid->setControl(1, 6, new ui::CheckBoxControl(true, new Apply(app))); app.uiRelativeZ->setWidth(15.0f);
    grid->setControl(2, 6, new LabelControl(app.uiRelativeZ));

    app.uiLat->setHorizFill(true, 700.0f);
    return grid;
}

int
main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);

    // help?
    if ( arguments.read("--help") )
        return usage(argv[0]);

    osgViewer::Viewer viewer(arguments);
    EarthManipulator* em = new EarthManipulator();// 默认操作器
    viewer.setCameraManipulator( em );

    // load an earth file, and support all or our example command-line options
    // and earth file <external> tags    
    osg::Node* earth = MapNodeHelper().load( arguments, &viewer );
    MapNode* mapNode = MapNode::get(earth);
    if (!mapNode)
        return usage(argv[0]);

    // load the model file into the local coordinate frame, which will be
    // +X=east, +Y=north, +Z=up. 模型一定要放大很多倍,才能容易发现,模型初始位置位于欧洲的某一处高山位置。
    osg::ref_ptr<osg::Node> model = osgDB::readRefNodeFile("axes.osgt.(10000).scale.osgearth_shadergen");
    if (!model.valid())
        return usage(argv[0]);

    osg::Group* root = new osg::Group();
    root->addChild( earth );
    
	// 这个结构体设计的有点不合理
    App app;
    app.srs = mapNode->getMapSRS();
    app.geo = new GeoTransform();
    app.pat = new osg::PositionAttitudeTransform();// 位置和姿态
    app.pat->addChild( model.get() );// 添加模型
    app.geo->addChild( app.pat );

    // Place your GeoTransform under the map node and it will automatically support clamping.
    // If you don't do this, you must call setTerrain to get terrain clamping.
    mapNode->addChild( app.geo );
    
    viewer.setSceneData( root );
    viewer.getCamera()->setNearFarRatio(0.00002);
    viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);

	// 创建控制面板
    ui::ControlCanvas::getOrCreate(&viewer)->addControl( makeUI(app) );
    app.apply();// 遍历节点

    osgEarth::Viewpoint vp;// 视点控制
    vp.setNode( app.geo );
    vp.heading()->set( -45.0, Units::DEGREES );// 偏航角
    vp.pitch()->set( -20.0, Units::DEGREES );// 俯仰角
    vp.range()->set( model->getBound().radius()*10.0, Units::METERS );// 模型可见范围
    em->setViewpoint( vp );

    return viewer.run();
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在 Visual Studio 2022 中使用 osgEarth示例: 1. 安装 osgEarth 首先需要在你的系统中安装 osgEarth。可以从官网下载安装包进行安装,也可以使用 CMake 进行源码编译安装。 2. 创建一个 osgEarth 应用程序 在 Visual Studio 2022 中创建一个新的 C++ 控制台应用程序项目。然后,将 osgEarth 的 include 和 library 路径添加到项目中: - 右键单击项目,选择“属性”。 - 在“VC++ 目录”中添加包含路径和库路径。 - 在“链接器 -> 输入”中添加 osgEarth 的库文件。 3. 创建一个 osgEarth 地图节点 在应用程序中创建一个 osgEarth 地图节点,并将其添加到场景图中: ```cpp #include <osgEarth/MapNode> #include <osgEarthUtil/EarthManipulator> int main(int argc, char** argv) { // 初始化 osgEarthosgEarth::initialize(); // 创建一个 osgEarth 地图节点 osg::ref_ptr<osgEarth::MapNode> mapNode = osgEarth::MapNode::create(osgEarth::MapNodeOptions()); // 创建一个 osgEarth 视图并添加地图节点 osg::ref_ptr<osgViewer::View> view = new osgViewer::View; view->setSceneData(mapNode); // 设置地球操纵器 osg::ref_ptr<osgEarth::Util::EarthManipulator> manipulator = new osgEarth::Util::EarthManipulator; view->setCameraManipulator(manipulator); // 显示视图 osgViewer::Viewer viewer; viewer.addView(view); return viewer.run(); } ``` 以上代码创建了一个 osgEarth 地图节点,并使用 EarthManipulator 对其进行控制。注意要在程序结束前调用 osgEarth::shutdown(),以释放资源。 4. 运行应用程序 点击“生成”按钮编译应用程序,并运行应用程序。如果一切正常,应该可以看到一个 osgEarth 地球视图。 以上是在 Visual Studio 2022 中使用 osgEarth 的简单示例。根据需要,还可以使用 osgEarth 的其他功能来创建更复杂的地图应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值