一、前言
之前版本使用相机后期处理实现,参见相机后期处理实现指北针,当开启对数深度缓存后,指北针就显示不正常了,本人感觉这种实现有点太繁琐、太耗性能了,后续维护起来也不方便,故采用osg原生图形界面的方式实现。
二、效果

以下图片可自行换成自己的


三、实现
VDCompassUseCanvas.h
cpp
/***********************************************************************
* 功能:指北针(使用界面canvas实现)
* 作者:xxx
* 历史:2026年2月12日09:55:35新建。
***********************************************************************/
#pragma once
#include <osgEarth/Controls>
#include <osgViewer/Viewer>
class VDCompassUseCanvas :public osgEarth::Util::Controls::ControlCanvas
{
public:
VDCompassUseCanvas(osgViewer::Viewer *view);
~VDCompassUseCanvas();
void SetHeading(const double &heading);
private:
osg::ref_ptr<osgEarth::Util::Controls::ImageControl> m_pImageControl = nullptr;
};
VDCompassUseCanvas.cpp
cpp
#include "VDCompassUseCanvas.h"
#include <osgDB/ReadFile>
#include <QCoreApplication>
VDCompassUseCanvas::VDCompassUseCanvas(osgViewer::Viewer *view)
{
if (!view) {
OE_FATAL << "create compass error,viewer is invalid." << std::endl;
}
else {
getOrCreate(view);
//绘制背景
osg::ref_ptr<osg::Image> imageBG = osgDB::readImageFile((QCoreApplication::applicationDirPath() + QString("\\data\\image\\compass-b4.png")).toStdString());
if (imageBG.valid())
{
osg::ref_ptr<osgEarth::Util::Controls::ImageControl> imageControl = new osgEarth::Util::Controls::ImageControl(imageBG.get());
imageControl->setHorizAlign(osgEarth::Util::Controls::Control::ALIGN_RIGHT);
imageControl->setFixSizeForRotation(true);
imageControl->setSize(100, 100);
addControl(imageControl.get());
}
//绘制指针
osg::ref_ptr<osg::Image> image = osgDB::readImageFile((QCoreApplication::applicationDirPath() + QString("\\data\\image\\compass-p2.png")).toStdString());
if (image.valid())
{
m_pImageControl = new osgEarth::Util::Controls::ImageControl(image.get());
m_pImageControl->setHorizAlign(osgEarth::Util::Controls::Control::ALIGN_RIGHT);
m_pImageControl->setFixSizeForRotation(true);
m_pImageControl->setSize(100, 100);
addControl(m_pImageControl.get());
}
}
}
VDCompassUseCanvas::~VDCompassUseCanvas()
{
OE_NOTICE << "~VDCompassUseCanvas" << std::endl;
}
void VDCompassUseCanvas::SetHeading(const double &heading)
{
if (m_pImageControl.valid())
m_pImageControl->setRotation(osgEarth::Angular((heading), osgEarth::Units::DEGREES));
}
原创不易,记得点赞加关注哦,我会持续分享实用的功能(:-