查看: 2511|回复: 9

osg在切换视点过程中屏幕坐标在转换为世界坐标的问题

[复制链接]

该用户从未签到

发表于 2014-8-27 22:22:42 | 显示全部楼层 |阅读模式
本帖最后由 hisong7 于 2014-8-27 22:48 编辑

Hi,大家好,请大家帮忙,困扰了好几天了:

        我现在把视点切换(移动相机)到场景中,然后把屏幕上每个点计算它的世界坐标并保存起来,然后再次变换视点,然后根据之前保存的世界坐标计算它们在屏幕上的坐标,按理说如果切换视点变化很小,应该此时计算出来的屏幕坐标有很多是在屏幕内的(实际观察也应当如此),但是我在计算之后却发觉,我把视点切换之后,得到出来的全部屏幕坐标却远远不再屏幕坐标范围之内,这是怎么回事呢?

     
  1. //计算移动相机前整个屏幕的世界坐标,保存在m_worldPoints里
  2. void MouseEvent::calcCurWorldPoint()
  3. {
  4.         m_worldPoints->clear();
  5.         osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(mAA);
  6.         osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
  7.         osgViewer::Renderer *render = dynamic_cast<osgViewer::Renderer*>(camera->getRenderer());
  8.         osgUtil::SceneView *sceneView = render->getSceneView(0);

  9.         QFile txt_file("F://worldC.txt");
  10.         txt_file.open(QIODevice::WriteOnly | QIODevice::Text);
  11.         QTextStream txt_file_stream(&txt_file);
  12.         for(int i = 0; i < 640; i++){    //width
  13.                 for (int j = 0; j < 480; j++)//height
  14.                 {
  15.                         osg::Vec3 world;
  16.                         osg::Vec3 screen(i, j, 0);
  17.                         if(sceneView->projectWindowIntoObject(screen, world))//得到世界坐标
  18.                                 {
  19.                                         m_worldPoints->push_back(world);
  20.                         }else{
  21.                                 printf("project fail");
  22.                         }
  23.                 }
  24.         }
  25.         printf("calcCurWorldPoint done\n");
  26. }

  27. //计算移动视点后的屏幕坐标,却发觉已经便宜了屏幕很多
  28. void MouseEvent::calcAfterScreenPoint()
  29. {
  30.        
  31.         m_screenPoints->clear();
  32.         osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(mAA);
  33.         osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
  34.         osgViewer::Renderer *render = dynamic_cast<osgViewer::Renderer*>(camera->getRenderer());
  35.         osgUtil::SceneView *sceneView = render->getSceneView(0);

  36.         sceneView->projectObjectIntoWindow(mObject, mWindow);

  37.         QFile txt_file("F://screenC.txt");
  38.         txt_file.open(QIODevice::WriteOnly | QIODevice::Text);
  39.         QTextStream txt_file_stream(&txt_file);
  40.         int count = 0;
  41.         for (int i = 0; i < 640; i++)
  42.         {
  43.                 for (int j = 0; j < 480; j++)
  44.                 {
  45.                         osg::Vec3 window, tmpWindow;
  46.                         osg::Vec3 tmpWorld = m_worldPoints->at(count);
  47.                         sceneView->projectObjectIntoWindow(tmpWorld, tmpWindow);//得到屏幕坐标
  48.                         window = osg::Vec3(tmpWindow.x(), tmpWindow.y(), 0);
  49.                         m_screenPoints->push_back(window);
  50.                         count++;
  51.                         //printf("%d: after trans: %f, %f ",count, window.x(), window.y());
  52.                         //txt_file_stream << (int)(window.x() + 0.5f) << " " << (int)(window.y() + 0.5f) << "\n";//写入结果
  53.                 }
  54.         }

  55.         printf("calcAfterScreenPoint done\n");
  56. }
复制代码



计算当前屏幕到世界坐标

计算当前屏幕到世界坐标

变换视点后的截屏,计算之前保存的世界坐标在当前视上的位置

变换视点后的截屏,计算之前保存的世界坐标在当前视上的位置

该用户从未签到

 楼主| 发表于 2014-8-27 22:30:24 | 显示全部楼层
根据第一帧图得到的屏幕坐标
  1. -71452 -57162
  2. -71449 -57158
  3. -71451 -57158
  4. -71453 -57159
  5. -71450 -57155
  6. -71452 -57156
  7. -71448 -57152
  8. -71450 -57153
  9. -71453 -57154
  10. -71449 -57150
  11. -71451 -57150
  12. -71453 -57151
  13. -71450 -57148
  14. -71451 -57148
  15. -71448 -57144
  16. -71450 -57145
  17. -71452 -57146
  18. -71449 -57142
  19. -71451 -57142
  20. -71453 -57143
  21. -71449 -57139
  22. -71452 -57140
  23. -71447 -57136
  24. -71450 -57137
  25. -71452 -57138
  26. -71448 -57133
  27. -71450 -57134
  28. -71453 -57135
  29. -71449 -57131
  30. -71451 -57132
  31. -71448 -57128
  32. -71450 -57129
  33. -71452 -57129
  34. -71448 -57126
  35. -71450 -57126
  36. -71453 -57127
  37. -71449 -57123
  38. -71451 -57124
  39. -71447 -57120
  40. -71450 -57121
  41. -71452 -57121
  42. -71448 -57117
  43. -71450 -57118
  44. -71453 -57119
复制代码

该用户从未签到

发表于 2014-8-28 21:13:06 | 显示全部楼层

看osgUtil::SceneView的projectWindowIntoObject的注释,该函数的使用是有限制的。你应该能调查到。
一般都是实时获取相关矩阵自己计算变换矩阵。,没遇到这种变换错误。

该用户从未签到

 楼主| 发表于 2014-8-29 00:11:10 | 显示全部楼层
cenfer 发表于 2014-8-28 21:13
看osgUtil::SceneView的projectWindowIntoObject的注释,该函数的使用是有限制的。你应该能调查到。
一 ...

谢谢回复。我使用
  1. projectWindowIntoObject
复制代码

是在MouseEvent中
  1. bool MouseEvent::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
  2. {
  3.         mAA = &aa;
  4. }
复制代码

这样在
  1.         osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(mAA);
  2.         osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
  3.         osgViewer::Renderer *render = dynamic_cast<osgViewer::Renderer*>(camera->getRenderer());
  4.         osgUtil::SceneView *sceneView = render->getSceneView(0);
  5.         sceneView->projectWindowIntoObject(screen, mObject);
复制代码

应该能保证我使用的到的变换矩阵是当前最新的矩阵的吧。

如果这样不行,我如何能得到当前相机的各个变换矩阵呢?

该用户从未签到

 楼主| 发表于 2014-8-29 00:32:09 | 显示全部楼层
cenfer 发表于 2014-8-28 21:13
看osgUtil::SceneView的projectWindowIntoObject的注释,该函数的使用是有限制的。你应该能调查到。
一 ...

我使用相机自己计算变换矩阵,还是一样的问题,设置了断点跟踪到vpw矩阵,发觉在相机视点变换后,这个vpw是变化的
  1.         osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(mAA);
  2.         osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
  3.         osgViewer::Renderer *render = dynamic_cast<osgViewer::Renderer*>(camera->getRenderer());
  4.         osgUtil::SceneView *sceneView = render->getSceneView(0);
  5.         osg::Matrix VPW = camera->getViewMatrix()*camera->getProjectionMatrix() * camera->getViewport()->computeWindowMatrix();
复制代码

该用户从未签到

 楼主| 发表于 2014-8-29 16:03:58 | 显示全部楼层
把相机计算远近平面的模式设置为
  1. viewer.getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
复制代码

就ok了
设置为
  1. //viewer.getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
复制代码

也是不行,请高手解释这三种方式有什么区别吖?
  1. DO_NOT_COMPUTE_NEAR_FAR        
  2. COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES        
  3. COMPUTE_NEAR_FAR_USING_PRIMITIVES
复制代码

该用户从未签到

发表于 2014-8-29 18:58:20 | 显示全部楼层
hisong7 发表于 2014-8-29 16:03
把相机计算远近平面的模式设置为

就ok了

大体意思就是 需不需要自动调整裁剪面的距离。
只能推测:
你目前的计算方式不能保证变换矩阵为最新,计算的时机早于裁剪面自动调整了。

该用户从未签到

发表于 2014-8-29 19:05:06 | 显示全部楼层
不要获得Renderer
直接算
osg::Matrix vpm = view->getCamera()->getViewMatrix() *
view->getCamera()->getProjectionMatrix() *
view->getCamera()->getViewport()->computeWindowMatrix();
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表