OpenGL相机矩阵转OpenSceneGraph相机视图同步问题求助
问题
我有一个OpenGL项目,希望将其中的相机矩阵同步到OpenSceneGraph(OSG)相机,以保持两者视图一致。
获取OpenGL相机位置的代码如下:
GLdouble camera_pos[3]; double rationZoom = // RatioZoom int* iViewport = // the ViewPort double* projetMatrix = // Projection Matrix double* modelMatrix = // ModelView matrix // screenCenter is the position of my model. double screenCenterX = // The center in x Axis double screenCenterY = // The center in y Axis gluUnProject((iViewport[2] - iViewport[0]) / 2, (iViewport[3] - iViewport[1]) / 2, 0.0, modelMatrix, projetMatrix, iViewport, &camera_pos[0], &camera_pos[1], &camera_pos[2]); //Camera_pos is the position X,Y,Z of my camera.
在OSG中设置相机的代码如下:
// i use a zoom ration to have the same distance. double X = ((camera_pos[0]/2) - ((screenCenterX)))/rationZoom; double Y = ((camera_pos[1]/2) - ((screenCenterY)))/rationZoom; double Z = ((camera_pos[2]/2)) / rationZoom; osg::Vec3 updateCameraPosition(X, Y, Z); osg::Matrix matrixCameraPosition; matrixCameraPosition.setTrans(updateCameraPosition); // Yes, for the center i invert the position matrix of the camera osg::Matrix matrixCameraCenter; matrixCameraCenter.invert(matrixCameraPosition); osg::Vec3f eye(matrixCameraPosition.getTrans()); osg::Vec3f up(0, 0, 1); osg::Vec3f centre = osg::Vec3f(matrixCameraCenter.getTrans().x(), matrixCameraCenter.getTrans().y(), matrixCameraCenter.getTrans().z()); // And a set the view into the camera nodeCamera->setViewMatrixAsLookAt(eye, centre, up);
初始位置设置无问题,但平移OpenGL项目中的模型后,两者视图不再一致。我了解到OpenGL坐标系为X左、Y上、Z后,OSG坐标系为X左、Y后、Z上,怀疑是坐标系差异导致问题,是否需要将OSG的up向量改为Y轴方向?
解决方案
问题根源是坐标系映射错误加上目标点(center)计算逻辑错误,调整方案如下:
- 修正坐标系映射
OpenGL与OSG的轴对应关系:
- OpenGL X ↔ OSG X(方向一致:左)
- OpenGL Y(上) ↔ OSG Z(上)
- OpenGL Z(后) ↔ OSG Y(后)
需要按此对应关系转换相机位置和模型中心坐标:
// 转换OpenGL相机位置到OSG坐标系 double osg_cam_x = camera_pos[0]; double osg_cam_y = camera_pos[2]; // OpenGL Z轴 → OSG Y轴 double osg_cam_z = camera_pos[1]; // OpenGL Y轴 → OSG Z轴 // 转换模型中心到OSG坐标系(假设screenCenter是OpenGL XY平面的中心,Z=0) double osg_center_x = screenCenterX; double osg_center_y = 0.0; // OpenGL模型Z=0对应OSG Y=0 double osg_center_z = screenCenterY; // OpenGL模型Y → OSG Z
修正目标点计算逻辑
原代码通过反转相机位置矩阵获取center是错误的——OSG的setViewMatrixAsLookAt需要的是相机看向的目标点(即OpenGL中的模型中心),直接使用转换后的模型中心即可,无需反转矩阵。确认up向量
OpenGL的默认向上方向是Y轴(0,1,0),对应OSG的Z轴(0,0,1),所以up向量设置为osg::Vec3f(0, 0, 1)是正确的,不需要改为Y轴方向。移除多余的坐标除法
原代码中camera_pos[0]/2这类无依据的除法会导致坐标偏移,直接移除即可。
最终的OSG相机设置代码:
// 坐标转换 double osg_cam_x = camera_pos[0]; double osg_cam_y = camera_pos[2]; double osg_cam_z = camera_pos[1]; double osg_center_x = screenCenterX; double osg_center_y = 0.0; double osg_center_z = screenCenterY; // 应用缩放比例 osg::Vec3 eye(osg_cam_x / rationZoom, osg_cam_y / rationZoom, osg_cam_z / rationZoom); osg::Vec3 centre(osg_center_x / rationZoom, osg_center_y / rationZoom, osg_center_z / rationZoom); osg::Vec3 up(0, 0, 1); // 设置视图矩阵 nodeCamera->setViewMatrixAsLookAt(eye, centre, up);
调整后,平移模型时OSG相机就能正确同步OpenGL的视图。
内容的提问来源于stack exchange,提问作者Dada
相关产品推荐
相关产品推荐

