主要是希望在切换的时候保持等距的转换,即使在发生缩放后。
首先osg中有获取与设置投影矩阵的方法,因此简单的转换如下:
case osgGA::GUIEventAdapter::DOUBLECLICK:
{
if (m_isPerspective)
{
double left,right,bottom,top,zNear, zFar;
m_pViewer->getCamera()->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar);
m_pViewer->getCamera()->setProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar);
}
else
{
double left, right, bottom, top, zNear, zFar;
m_pViewer->getCamera()->getProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar);
m_pViewer->getCamera()->setProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar);
}
m_isPerspective = !m_isPerspective;
}
return false;
这部分写在了自定义的漫游器的handle方法中,在写demo测试的时候呈现的效果已经是等距的了,但是放到实际项目中却不行,发现实际项目中在创建camera的时候初始化了透视投影矩阵:
setProjectionMatrixAsPerspective(30.0f, double(traits->width) / double(traits->height), 1.0f, 1000.0f);
然后感觉 转换效果和 近平面与_distance的比值 有关 :
初始化时的近平面设置为了1.0,因此比值刚好是_distance,修改后的切换如下:
if (m_isPerspective)
{
m_pViewer->getCamera()->getProjectionMatrixAsFrustum(m_left, m_right, m_bottom, m_top, m_zNear, m_zFar);
double v = _distance / m_zNear;
m_pViewer->getCamera()->setProjectionMatrixAsOrtho(m_left * v, m_right * v, m_bottom * v, m_top * v, m_zNear, m_zFar);
}
else
{
double left, right, bottom, top, zNear, zFar;
m_pViewer->getCamera()->getProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar);
double distance = left / m_left * zNear;
m_pViewer->getCamera()->setProjectionMatrixAsFrustum(m_left, m_right, m_bottom, m_top, m_zNear, m_zFar);
_distance = distance;
}
m_isPerspective = !m_isPerspective;
正交投影下的缩放我是通过修改投影矩阵的方式,没有去修改_distance,因此切换到透视投影的时候需要计算_distance并设置。