OsgEarth下给地球添加网格、鹰眼

void QtGuiAppEarth::slotGride()
{
	if (ui.actionGride->isChecked())
	{
		if (m_pGraticule == nullptr)
		{
			m_pGraticule = new osgEarth::Util::GeodeticGraticule(m_GViewer->getMapNode());
			// 颜色设置为红色
			osgEarth::Util::GeodeticGraticuleOptions op = m_pGraticule->getOptions();
			op.lineStyle()->getOrCreate<osgEarth::Util::LineSymbol>()->stroke()->color().set(1, 0, 0, 1);
			m_pGraticule->setOptions(op);
			m_GViewer->getRoot()->addChild(m_pGraticule);
		}
	}
	else
	{
		if (m_pGraticule)
		{
			m_GViewer->getRoot()->removeChild(m_pGraticule);
			m_pGraticule = nullptr;
		}
	}
}
#ifndef RADARMAP_H
#define RADARMAP_H

#include "framehandle.h"
#include "graphicsview.h"

class RadarMap : public QObject
{
	Q_OBJECT

public:
	RadarMap(GraphicsView* view, QObject *parent = nullptr);
	~RadarMap();

	void setGeomtry(int x = 20, int y = 20, int width = 320, int height = 180)
	{
		m_iX = x; m_iY = y; m_iWidth = width; m_iHeight = height;
	}

	void enableMap();
	void disableMap();

private slots:
	void slotFrameViewport(const osg::Vec3d& pos);

private:
	void createMap();
	// 根据世界坐标去经纬度坐标
	osg::Vec3d getLonLat(const osg::Vec3d& worldPos);

private:
	// 显示的区域
	int m_iX;
	int m_iY;
	int m_iWidth;
	int m_iHeight;

	// HUD相机
	osg::ref_ptr<osg::Camera> m_pHUDCamera;
	GraphicsView* m_pOSGViewer;
	osg::ref_ptr<osg::Group> m_pGroup;
	FrameHandle* m_pFrameHandle;

	// 十字架,显示当前视点位置
	osg::ref_ptr<osg::Geode> m_pGeodeCross;
	osg::ref_ptr<osg::Vec3dArray> m_pVertexCross;
};

#endif // RADARMAP_H
#include "radarmap.h"

RadarMap::RadarMap(GraphicsView* view, QObject* parent/* = nullptr*/)
	: m_pOSGViewer(view), QObject(parent)
{
	m_pHUDCamera = nullptr;
	m_pGroup = new osg::Group;
	m_pOSGViewer->getRoot()->addChild(m_pGroup);//添加到大的视图中
	m_pFrameHandle = new FrameHandle;
	m_pGeodeCross = nullptr;
	setGeomtry();
}

RadarMap::~RadarMap()
{

}

void RadarMap::enableMap()
{
	if (m_pHUDCamera == nullptr)
	{
		createMap();
	}
	m_pGroup->addChild(m_pHUDCamera);
	m_pOSGViewer->getOSGViewer()->addEventHandler(m_pFrameHandle);
	connect(m_pFrameHandle, SIGNAL(signalFrameViewport(const osg::Vec3d&)),
		this, SLOT(slotFrameViewport(const osg::Vec3d&)));
}

void RadarMap::disableMap()
{
	if (m_pHUDCamera)
	{
		m_pGroup->removeChild(m_pHUDCamera);
		m_pHUDCamera = nullptr;
		disconnect(m_pFrameHandle, SIGNAL(signalFrameViewport(const osg::Vec3d&)),
			this, SLOT(slotFrameViewport(const osg::Vec3d&)));
		m_pOSGViewer->getOSGViewer()->removeEventHandler(m_pFrameHandle);
	}
}

void RadarMap::slotFrameViewport(const osg::Vec3d& pos)
{
	if (m_pGeodeCross == nullptr)
	{
		m_pGeodeCross = new osg::Geode;
		osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
		// 使用VBO,每帧实时的修改数据
		pGeometry->setUseVertexBufferObjects(true);
		m_pVertexCross = new osg::Vec3dArray;
		pGeometry->setVertexArray(m_pVertexCross);
		osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array;
		normal->push_back(osg::Vec3(0, 0, 1));
		pGeometry->setNormalArray(normal, osg::Array::BIND_OVERALL);
		osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
		color->push_back(osg::Vec4(0.8, 0.8, 0.8, 1));
		pGeometry->setColorArray(color, osg::Array::BIND_OVERALL);
		pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 4));

		m_pGeodeCross->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
		m_pGeodeCross->getOrCreateStateSet()->setAttribute(
			new osg::LineWidth(0.5), osg::StateAttribute::ON);
		m_pGeodeCross->addDrawable(pGeometry);
		m_pHUDCamera->addChild(m_pGeodeCross);
	}
	osg::Vec3d mapPos = getLonLat(pos);
	// 经纬度是-180~180,-90~90,保证算出的是0~360和0~180
	double x = (mapPos.x() + 180.0) * m_iWidth / 360.0;
	double y = (mapPos.y() + 90.0) * m_iHeight / 180.0;

	// 更新缓冲区数据
	m_pVertexCross->clear();
	m_pVertexCross->push_back(osg::Vec3d(x, y - 5, 0));
	m_pVertexCross->push_back(osg::Vec3d(x, y + 5, 0));
	m_pVertexCross->push_back(osg::Vec3d(x - 5, y, 0));
	m_pVertexCross->push_back(osg::Vec3d(x + 5, y, 0));
	m_pVertexCross->dirty();
}

void RadarMap::createMap()
{
	m_pHUDCamera = new osg::Camera;

	// 设置投影矩阵
	m_pHUDCamera->setProjectionMatrixAsOrtho2D(m_iX, m_iWidth, m_iY, m_iHeight);

	// 设置视口矩阵
	m_pHUDCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
	m_pHUDCamera->setViewMatrix(osg::Matrix::identity());

	// 只清除深度缓冲区
	m_pHUDCamera->setClearMask(GL_DEPTH_BUFFER_BIT);

	// 设置HUD相机在主相机之后渲染
	m_pHUDCamera->setRenderOrder(osg::Camera::POST_RENDER);

	// HUD相机不获取Event的焦点
	m_pHUDCamera->setAllowEventFocus(false);
	m_pHUDCamera->setViewport(m_iX, m_iY, m_iWidth, m_iHeight);

	// 增加HUD相机的渲染内容,即map
	osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;

	// 创建纹理
	osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
	{
		// 顶点
		osg::ref_ptr<osg::Vec3Array> verArray = new osg::Vec3Array;
		verArray->push_back(osg::Vec3(0, 0, -1));
		verArray->push_back(osg::Vec3(m_iWidth, 0, -1));
		verArray->push_back(osg::Vec3(m_iWidth, m_iHeight, -1));
		verArray->push_back(osg::Vec3(0, m_iHeight, -1));
		pGeometry->setVertexArray(verArray);
		// 纹理坐标
		osg::ref_ptr<osg::Vec2Array> textArray = new osg::Vec2Array;
		textArray->push_back(osg::Vec2(0, 0));
		textArray->push_back(osg::Vec2(1, 0));
		textArray->push_back(osg::Vec2(1, 1));
		textArray->push_back(osg::Vec2(0, 1));
		pGeometry->setTexCoordArray(0, textArray);
		// 法线,指向用户,即y轴
		osg::ref_ptr < osg::Vec3Array> normal = new osg::Vec3Array;
		normal->push_back(osg::Vec3(0, 1, 0));
		pGeometry->setNormalArray(normal);
		pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
		// 指定绘制方式
		pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
		// 纹理图片
		osg::ref_ptr<osg::Image> image = osgDB::readImageFile(
			"./Images/image_formats/png/world.png");// E:\osg\data\Images\image_formats\png
		if (image)
		{
			osg::ref_ptr<osg::Texture2D> text2D = new osg::Texture2D;
			text2D->setImage(image);
			text2D->setDataVariance(osg::Object::DYNAMIC);

			pGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(
				0, text2D, osg::StateAttribute::ON);
		}
	}

	// 创建HUD相机的边框
	osg::ref_ptr<osg::Geometry> pGeoBorder = new osg::Geometry;
	{
		// 顶点
		osg::ref_ptr<osg::Vec3Array> verBorder = new osg::Vec3Array;
		verBorder->push_back(osg::Vec3(1.0, 1.0, 0));
		verBorder->push_back(osg::Vec3(m_iWidth - 1.0, 1.0, 0));
		verBorder->push_back(osg::Vec3(m_iWidth - 1.0, m_iHeight - 1.0, 0));
		verBorder->push_back(osg::Vec3(1.0, m_iHeight - 1.0, 0));
		pGeoBorder->setVertexArray(verBorder);
		// 法线
		osg::ref_ptr<osg::Vec3Array> normalBorder = new osg::Vec3Array;
		normalBorder->push_back(osg::Vec3(0.0, 0.0, 1.0));
		pGeoBorder->setNormalArray(normalBorder, osg::Array::BIND_OVERALL);
		// 颜色
		osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
		color->push_back(osg::Vec4(1, 0.8, 0, 1));
		pGeoBorder->setColorArray(color);
		pGeoBorder->addPrimitiveSet(new osg::DrawArrays(osg::DrawArrays::LINE_LOOP, 0, 4));
		pGeoBorder->getOrCreateStateSet()->setAttribute(new osg::LineWidth(2), osg::StateAttribute::ON);
	}
	pGeode->addDrawable(pGeometry);
	pGeode->addDrawable(pGeoBorder);
	pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

	m_pHUDCamera->addChild(pGeode);
}

osg::Vec3d RadarMap::getLonLat(const osg::Vec3d& worldPos)
{
	osg::Vec3d vecPos = osg::Vec3d();
	if (m_pOSGViewer)
	{
		m_pOSGViewer->getSRS()->getEllipsoid()->convertXYZToLatLongHeight(
			worldPos.x(), worldPos.y(), worldPos.z(), vecPos.y(), vecPos.x(), vecPos.z());
		vecPos.x() = osg::RadiansToDegrees(vecPos.x());
		vecPos.y() = osg::RadiansToDegrees(vecPos.y());
	}
	return vecPos;
}

 

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
osgEarth是一个开源的地理信息系统(GIS)开发工具包,可以与OpenSceneGraph(OSG)一同使用,用于创建和渲染三维地球场景。 osgEarth使用了波束(Tile)的概念来管理地球表面的数据。波束是一种方式,将地球表面划分为不同大小和级别的网格块,每个网格块也称为一个波束。每个波束都有一个唯一的标识符,用于在渲染时加载和显示对应的地理数据。 通过使用波束的方式,osgEarth能够实现地球表面的分级加载和细节控制。较远离相机的区域可以使用较低分辨率的波束,以保持渲染效率,而相机附近的区域则可以使用高分辨率的波束,以展现更多的细节。这种分级加载和细节控制的机制使得osgEarth能够在真实感和效率之间取得平衡。 osgEarth还支持多种类型的地理数据,包括栅格数据、矢量数据和影像数据等。这些数据可以与波束进行关联,在渲染时根据需要加载和显示相应的数据。同时,osgEarth还提供了丰富的地理数据处理和渲染功能,包括地形地貌生成、纹理贴图、灯光效果等,以及与其他GIS工具的集成能力。 总之,osgEarth通过使用波束的方式来管理和加载地球表面的数据,实现了地球场景的分级加载和细节控制。它是一个强大的GIS开发工具包,能够帮助开发人员创建逼真的三维地球场景,并且具备丰富的地理数据处理和渲染功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海亲王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值