查看: 2977|回复: 7

请教关于鹰眼图的问题~

[复制链接]

该用户从未签到

发表于 2010-5-28 22:15:44 | 显示全部楼层 |阅读模式
想在场景漫游器的基础上再做个类似鹰眼图的功能,在屏幕的边缘显示小地图,实时显示此时漫游者所处的位置,后期再加上地图。想想应该不难,可是做起来却遇到了问题。劳驾大牛指点一二~不胜感激~

思路如下:
在main()函数中设置一个PositionAttitudeTransform节点,添加将来要在俯视图中显示的箭头作为其子节点,之后设置回调,在回调函数中创建一个事件访问器并初始化,之后会调用虚函数handle,事件触发的类型为osgGA::FRAME,也就是每一帧更改pos的位置,在handle函数中通过viewer->getCamera()->getViewMatrixAslookat()获得主相机的位置,然后进行世界坐标系到辅相机的模型、投影、视口变换,调整为可以在小视口显示的坐标。(这里用的变换函数是书上的一段程序改的)

参考了坛子里一个老帖子,大概也是这样的思路
原帖如下:http://www.osgchina.org/bbs/redirect.php?tid=1714&goto=lastpost
但是其中最关键的PlayerCallback却没有写

=====================================
现在的问题是
1.漫游器没有问题,但是小视口中却没有箭头显示,应该是自己坐标和矩阵变换的地方有什么问题。。。可是主相机得到的坐标应该是世界坐标对吧?世界坐标应该是在辅相机的模型视图矩阵和投影矩阵以及视口的基础上进行的变换啊
2.getViewMatrixAsOrtho2D(left,right,bottom,up)相当于是将z方向的深度限制在[-1,1]之间而得到的俯视效果吧?
源码添加如下 Travel_Test.rar (2.62 MB, 下载次数: 147)

该用户从未签到

发表于 2010-5-29 10:07:29 | 显示全部楼层
问题好像在相机

该用户从未签到

发表于 2010-5-29 16:16:46 | 显示全部楼层
没有时间看您的代码,,不过,鹰眼有很多种实现的方式,,我用的比较多的还是HUD来实现的~~~至于箭头不显示,,可能是因为您设置的投影矩阵和矩阵变换过程有问题,,或许您可以测试下~~···

该用户从未签到

 楼主| 发表于 2010-5-29 20:12:44 | 显示全部楼层
2# wangjunchao
谢了~
很可能就是相机有问题,正在钻研和修改中
代码估计也没有人看,我应该把问题具体一点,呵呵

该用户从未签到

 楼主| 发表于 2010-5-29 21:54:36 | 显示全部楼层
本帖最后由 sunpent 于 2010-5-29 21:57 编辑

[url=http://www.osgchina.org/bbs/redirect.php?
goto=findpost&pid=20272&ptid=3622]3#[/url] FlySky

谢谢FlySky
自己的代码很乱,相信给谁都不愿意看的,下面把问题具体一些:
main函数的部分:

  1. osg::ref_ptr<osg::Node> arrow = osgDB::readNodeFile( "arrow.osg" );
  2. osg::ref_ptr<osg:ositionAttitudeTransform> pat = new osg:ositionAttitudeTransform;
  3. pat->addChild( arrow.get() );
  4. osg::ref_ptr<osg::Camera> eagleeye = createHUDCamera( new osg::Viewport(10,10,320,240), osg::Vec4d(-10,10,-10,10));
  5. eagleeye->addChild( pat.get() );
  6. pat->setEventCallback( new MyEventCallback(eagleeye) );
  7. root->addChild(eagleeye.get());
复制代码
现在HUD可以正常读出箭头,但是一旦启用回调函数,就显示不了了,应该是坐标变换的问题。这里有一点不明白,在回调函数里可以通过
viewer ->getCamera() ->getViewMatrixAsLookAt(ex_pos, cent, up) 得到现在主相机的位置,接着仿照您书中第二章的“程序清单2.2”完成世界坐标到屏幕坐标的变换,这里也有链接
http://www.osgchina.org/bbs/view ... =%D7%F8%B1%EA%CF%B5

1. 换算时的投影矩阵和视图矩阵应该要相应改成鹰眼图的相机,视口也是最终显示的小视口吧?

2. 倘若上述过程得到了正确的相机在小视口中的坐标,我想直接通过pat->setPosition应该就可以完成位置变化了吧?

3. 用compositeViewer和这样addchild一个相机应该是一个道理吧。您那里有没有类似的实现鹰眼图的例子可以参考下呢?

谢谢了~

该用户从未签到

发表于 2010-5-30 00:44:58 | 显示全部楼层
并不是因为您的代码太乱而没有看,因为我个人时间上抽不出来阅读您的整个程序,理解代码执行的流程~~HUD显示的问题是,,必须是会针对几何体进行回调,,这样就不会出现问题~~~~~~

该用户从未签到

 楼主| 发表于 2010-5-30 17:34:39 | 显示全部楼层
几何体是指必须是geometry对象么?

还有一个问题啊,一般的鹰眼图的例子是直接修改场景中节点的世界坐标,然后在俯视图中也可以看到相应的变化。这个呢,加了个漫游器,除了虚拟的相机就是场景了,直接俯视投影的话因为不存在表现相机的节点,另外如果漫游的场景是在密闭的室内的话,投影也看不到这个节点
所以,所以我就想最终变化的还是在viewport中更改箭头的位置。。。我觉得只要计算出相应的世界坐标到视口的变换就行。
不知道这么表述清楚没?

唉。。。我再看看吧~
好无助啊

该用户从未签到

 楼主| 发表于 2010-5-30 21:28:19 | 显示全部楼层
本帖最后由 sunpent 于 2010-5-30 21:54 编辑

为什么我改用多视景器添加第二个view,通过赋值cameraClient =view2->getCamera(),再使用HUD,设置camera的投影矩阵等等,读出来的图形却并非俯视,而是平视呢?但是通过getViewMatrixAslookat()得到的相机位置却是俯视的?!。。。很不解啊,请教下诸位,谢谢了!问题很可能就在这儿。

  1. osg::ref_ptr<osgViewer::View> view2= new osgViewer::View;
  2. viewer->addView(view2.get());

  3. osg::ref_ptr<osg:ositionAttitudeTransform> pat = new osg:ositionAttitudeTransform;
  4. pat->addChild( cow.get() );
  5. view2->setSceneData(pat.get());
  6. osg::ref_ptr<osg::Camera> cameraClient = new osg::Camera;
  7. cameraClient = view2->getCamera();
  8. //pat->setEventCallback( new MyEventCallback(cameraClient.get(),view1.get()) );

  9. cameraClient->setViewport(new osg::Viewport(10,10, traits->width/2, traits->height/2));
  10. cameraClient->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
  11. cameraClient->setProjectionMatrixAsOrtho2D(-30,30,-30,30);
  12. cameraClient->
  13. cameraClient->setRenderOrder( osg::Camera:OST_RENDER);
  14. cameraClient->setClearMask( GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);

  15. osg::Vec3 _pos,_cent,_up;
  16. std:fstream os("eagleeye_Camera.txt");
  17. os<<"";
  18. cameraClient->getViewMatrixAsLookAt(_pos,_cent,_up);
  19. os<<"pos "<<_pos._v[0]<<" "<<_pos._v[1]<<" "<<_pos._v[2]<<std::endl;
  20. os<<"center "<<_cent._v[0]<<" "<<_cent._v[1]<<" "<<_cent._v[2]<<std::endl;
  21. os<<"up direction "<<_up._v[0]<<" "<<_up._v[1]<<" "<<_up._v[2]<<std::endl;

  22. cameraClient->setGraphicsContext(gc.get());
  23. view2->setCameraManipulator(new osgGA::TrackballManipulator);
复制代码
输出的文本中的信息为:
pos 0 0 0
center 0 0 -1
up direction 0 1 0


再添一句,我现在就是想得到一个俯视的相机cameraClient,在这个cameraClient下漫游器的主相机可以到达的每个点都能够在cameraClient最后显示的视口中有对应的坐标。
那么怎么修改现在cameraClient的投影矩阵呢?。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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