我们在使用OSG编程时,经常会自定义操作器实现自己想要的操作功能。我在实现二维图像转换为360度全景图像的过程中发现OSG自带的一些操作器都没有自己想要的旋转和缩放操作,所以只能自己定义操作器。参考了网上有的一些代码,再结合自己的实际情况修改之后实现的。参考代码的网址:https://blog.csdn.net/mj511099781/article/details/46051453。该网址用的是正射投影setProjectionMatrixAsOrtho,而我使用的是透射投影setProjectionMatrixAsFrustum。自己修改缩放部分的代码如下:
//自定义响应鼠标的事件
bool CRotateGlider::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
switch (ea.getEventType())
{
// 如果是滚轮事件
case osgGA::GUIEventAdapter::SCROLL:
{
_scale = 1.0;
bool flag = false;
osgViewer::View* pViewer = dynamic_cast<osgViewer::View*>(&aa);
osg::ref_ptr<osg::Camera> m_pCamera = pViewer->getCamera();
osg::Vec3 ptWorldBefore, ptWorldAfter; // 修改投影矩阵前后鼠标位置对应的世界坐标点
float x1 = ea.getX(), y1 = ea.getY();
osg::Vec3 vecWindow1(x1, y1, 0.0);
{
// 计算修改投影矩阵前
// 获取当前运算矩阵
osg::Matrix VPW = m_pCamera->getViewMatrix() *
m_pCamera->getProjectionMatrix() *
(m_pCamera->getViewport())->computeWindowMatrix();
osg::Matrix inverseVPW;
inverseVPW.invert(VPW);
// 矩阵运算获得世界坐标
ptWorldBefore = vecWindow1 * inverseVPW;
}
double dFactor = 1;
switch (ea.getScrollingMotion())
{
case osgGA::GUIEventAdapter::SCROLL_UP: // 鼠标滚轮向上放大
{
dFactor = 1.2;
}
break;
case osgGA::GUIEventAdapter::SCROLL_DOWN: // 鼠标滚轮向下缩小
{
dFactor = 0.8;
}
break;
default:
break;
}
double dL, dR, dT, dB, dZ, dF;
m_pCamera->getProjectionMatrixAsFrustum(dL, dR, dB, dT, dZ, dF);
double width, height;
width = dR - dL;
height = dT - dB;
dR = width * dFactor;
dT = height * dFactor;
m_pCamera->setProjectionMatrixAsFrustum(-dR * 0.5, dR * 0.5, -dT * 0.5, dT * 0.5, dZ, dF);
{
// 计算修改投影矩阵后
// 获取当前运算矩阵
osg::Matrix VPW = m_pCamera->getViewMatrix() *
m_pCamera->getProjectionMatrix() *
(m_pCamera->getViewport())->computeWindowMatrix();
osg::Matrix inverseVPW;
inverseVPW.invert(VPW);
// 矩阵运算获得世界坐标
ptWorldAfter = vecWindow1 * inverseVPW;
}
osg::Vec3 vecMove = ptWorldBefore - ptWorldAfter;
//panModel(vecMove.x(), vecMove.y(), vecMove.z());
return false;
}
break;
default:
break;
}
return false;
}