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

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

目录

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();
}

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

在OpenSceneGraph (OSG) 中,Camera HUD (Head-Up Display) 是一种常用的增强现实功能,它通常会在摄像机视图中显示辅助信息,如坐标轴、网格等。如果你想要在右下角绘制一个坐标系,你需要进行以下步骤: 1. **创建HUD Node**:首先,在你的场景中创建一个osg::ref_ptr<osg::Group> 或 osg::Node作为你的坐标系容器。 2. **添加CoordinateFrame**:使用`osgUtil::Camera::getOrCreate hudCamera()`创建一个专门用于绘图的小窗口摄像机,并在其节点树上添加一个`osgViewer::GraphicsView::addCoordinateFrame`,这将在指定位置(通常是视口中心)显示默认的三维坐标轴。 ```cpp osg::ref_ptr<osg::Camera> hudCamera = osgUtil::Camera::getOrCreateHudCamera(); osgViewer::GraphicsView* hudView = static_cast<osgViewer::GraphicsView*>(view->getImplementation()); hudView->addCoordinateFrame(hudCamera.get(), osg::Vec3d(0.5, -0.5, 0)); // 设置坐标系在右下角 ``` 3. **调整坐标系大小和位置**:你可以通过设置`osgGA::TrackballManipulator`或者其他操纵器的属性,改变坐标系的大小和显示位置。例如,可以调整`osgGA::GUIEventHandler`中设置的坐标轴显示范围。 4. **固定坐标系**:如果你想让坐标系永远固定在屏幕右下角,可以在`updateCameraProjectionMatrix`方法里手动计算变换矩阵,将坐标系的位置移动到合适的位置。 5. **显示**:最后,记得在每次视口更新(`View::frame`或`Viewer::frame`)后更新这个坐标系,让它跟随摄像机的视角变化。 ```cpp // 在帧更新函数中 if (!hudView) return; // 获取坐标系节点 osg::Node* hudNode = hudCamera->getDrawable()->asNodeIf(); if (hudNode) { // 这里做你的坐标系位置和大小调整 } ```
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值