osg中实现窗体右下角绘制坐标轴且能随场景转动一致

本文档介绍了如何在3D场景中创建一个始终位于右下角且不受缩放和平移影响的坐标轴显示。通过使用osg库中的HUD技术,创建了一个名为`HUDAxis`的类,该类继承自`osg::Camera`,并设置了正交投影矩阵以消除缩放效果,并调整视图矩阵使其固定在窗口右下角。在主相机视图矩阵的基础上,实现了坐标轴模型的固定位置显示。代码示例展示了如何将坐标轴模型与主相机结合,以及在osgViewer中设置和运行。

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

目录

1. 功能需求      

2. 实现方法方法


1. 功能需求      

      在场景左下角显示一个表示当前场景坐标系,它只对相机旋转有反应,对场景缩放和移动不起效果,如下(右下角坐标轴模型很小,需要仔细看):

2. 实现方法方法

        将一个坐标轴模型节点放在一个Projection下或放在Matrixtransform下设置为绝对坐标模式,然后再回调剔除移动变换。采用了三维中的HUD技术,关于什么是HUD技术,参见:OSG中的创建HUD

代码实现如下:

#include<osg/Geometry>
#include<osg/Geode>
#include<osgViewer/Viewer>
#include<osgViewer/ViewerEventHandlers>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include<osg/DrawPixels>
#include<osg/PositionAttitudeTransform>
#include<osg/computeBoundsVisitor>
#include<osg/MatrixTransform>
#include<osg/ShapeDrawable>
#include<osg/Shape>
#include<osg/PolygonMode>
#include<osg/NodeVisitor>
class HUDAxis :public osg::Camera
{
public:
	HUDAxis();
	HUDAxis(const HUDAxis& copy, osg::CopyOp copyOp = osg::CopyOp::SHALLOW_COPY);
	META_Node(osg, HUDAxis);
	inline void setMainCamera(Camera* camera)
	{
		_mainCamera = camera;
	}
	virtual void traverse(osg::NodeVisitor& nv);
protected:
	virtual ~HUDAxis();
	osg::observer_ptr<Camera> _mainCamera;
};



HUDAxis::HUDAxis()
{
	//可以在这直接读取axes.osgt;
	// this->addChild(osgDB::readNodeFile("axes.osgt"));
}

HUDAxis::HUDAxis(const HUDAxis& copy, osg::CopyOp copyOp /* = CopyOp::SHALLOW_COPY */) :Camera(copy, copyOp),
_mainCamera(copy._mainCamera)
{

}

// 每次回调时,该函数就会被执行
void HUDAxis::traverse(osg::NodeVisitor& nv)
{
	double fovy, aspectRatio, vNear, vFar;
	_mainCamera->getProjectionMatrixAsPerspective(fovy, aspectRatio, vNear, vFar);

	// 改为正投影,正投影不会随相机的拉近拉远而放大、缩小,这样就剔除了缩放效果,
	this->setProjectionMatrixAsOrtho(-10.0 * aspectRatio, 10.0 * aspectRatio, -10.0, 10.0, vNear, vFar); //设置投影矩阵,使缩放不起效果

	osg::Vec3 trans(8.5 * aspectRatio, -8.5, -8.0);// 让坐标轴模型位于窗体右下角。
	if (_mainCamera.valid())
	{
		osg::Matrix matrix = _mainCamera->getViewMatrix();//改变视图矩阵,让移动位置固定

		// 让移动固定,即始终位于窗体右下角,否则鼠标左键按住模型可以拖动或按空格键时模型会动
		matrix.setTrans(trans);
		this->setViewMatrix(matrix);
	}
	osg::Camera::traverse(nv);
}

HUDAxis::~HUDAxis()
{

}

void main()
{
	osg::ref_ptr<osgViewer::Viewer> spViewer = new osgViewer::Viewer;

	auto pCow = osgDB::readNodeFile("cow.osg");
	if (nullptr == pCow)
	{
		OSG_WARN << "cow node is null!";
		return;
	}

	// 如果没有坐标轴模型的osg文件,用cow.osg代替验证也行,都一样的,只是模型不同而已。
	osg::ref_ptr<osg::Node> spAxes = osgDB::readNodeFile("axes.osgt");
	if (nullptr == spAxes)
	{
		OSG_WARN << "Axes node is null!";
		return;
	}

	auto pRoot = new osg::Group;
	pRoot->addChild(pCow);

	// 使用这个类代码 /
	osg::ref_ptr<HUDAxis> hudAxes = new HUDAxis;
	pRoot->addChild(hudAxes);
	hudAxes->addChild(spAxes);

	osg::ref_ptr<osg::Camera> spCamera = spViewer->getCamera();
	spViewer->setUpViewInWindow(100, 100, 800, 600); // 窗体左上角位于在屏幕(100, 100)处,宽度为800,高度为600
	hudAxes->setMainCamera(spCamera);
	hudAxes->setRenderOrder(osg::Camera::POST_RENDER);  // 坐标轴最后渲染,即在所有其它三维场景前面
	hudAxes->setClearMask(GL_DEPTH_BUFFER_BIT);       // 关闭深度缓冲
	hudAxes->setAllowEventFocus(false);               // 禁止鼠标、键盘事件
	hudAxes->setReferenceFrame(osg::Transform::ABSOLUTE_RF); // 绝对参考帧
	spViewer->setSceneData(pRoot);

	spViewer->run();
}

需要此相机的视图矩阵和主相机的一样。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值