目录
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();
}
需要此相机的视图矩阵和主相机的一样。