查看: 13513|回复: 11

关于用setViewMatrixAsLookAt改变相机位置和朝向无效的问题

[复制链接]

该用户从未签到

发表于 2011-5-29 10:21:47 | 显示全部楼层 |阅读模式
各位大侠早,想请教大家一个关于用setViewMatrixAsLookAt改变相机位置和朝向无效的问题,具体情况如下:
    (1)我首先仿照FreeSouth的那个CSouth漫游器写了一个 CTravelManipulator漫游器,然后用
  1. mViewer->setCameraManipulator(new CTravelManipulator(mViewer));
复制代码

      设置漫游器;同时在仿真循环中采用如下代码进行仿真循环
  1. while(!viewer->done())
  2. {
  3. osg->PreFrameUpdate();
  4. viewer->frame();
  5. osg->PostFrameUpdate();
  6. Sleep(10); // 让其它程也占用CPU,放出10MS
  7. }
复制代码


    (2)由于需要,我需要对viewer添加响应时间,因此在setCameraManipulator后立即进行那个如下设置:
  1. mViewer->addEventHandler(new CMouseHandler(mViewer,camera.get()));
复制代码

    这个CMouseHandler类是从public osgGA::GUIEventHandler类继承下来的,在这个类的handle函数中,我希望将传进来的camera的位置进行调整,主要是改变相机的位置、朝向这两个属性,改变的代码如下:

  1. currentcamera ->setViewMatrixAsLookAt(cameraEyeNew,toCenterNew,cameraUpNew);
复制代码

上面的cameraEyeNew,toCenterNew,cameraUpNew都是我根据需要重新计算过的新的值。

    (3)问题:按照如上设置,通过断点跟踪程序,发现handler函数中的setViewMatrixAsLookAt虽然执行了,但是相机的位置并没有发生变化。我在论坛搜了一下,可能的原因是我这边的设置又被漫游器给重置了,因此没有效果。那我想请问的是:
            1、是不是一定要写一个camera的更新回调才能改变camera的位置呢?我要的功能是,鼠标双击后根据鼠标当前所在位置去设置camera的位置和朝向,用回调不知道该怎么写。。。。
            2、有没有一种设置方法,使得我在handle函数中可以顺利地用setViewMatrixAsLookAt改变相机的位置和朝向呢?


       谢谢各位大侠~~~

该用户从未签到

发表于 2017-3-23 20:09:28 | 显示全部楼层
GetViewer()->getCameraManipulator()->setByInverseMatrix(viewMatrix),亲测有效

该用户从未签到

 楼主| 发表于 2011-5-29 10:22:17 | 显示全部楼层
自己顶一下先~~

该用户从未签到

发表于 2011-5-29 12:02:37 | 显示全部楼层
这个问题我是遇到过的,当设置viewer->cameraManipulator()后,setViewAtLookAt是不起作用的,你在你自己写的操作器中改变观察矩阵的值就可以了,使用相机回调也是可以的

该用户从未签到

发表于 2011-5-29 12:04:43 | 显示全部楼层
我现在怀疑在你的view中不只有一个camera

该用户从未签到

 楼主| 发表于 2011-5-29 14:05:02 | 显示全部楼层
回复 4# wangjunchao


    我只设置了一个camera,不可能有多个

该用户从未签到

 楼主| 发表于 2011-5-29 14:05:35 | 显示全部楼层
回复 3# garyliyong


    我用相机事件回调来试试看

该用户从未签到

 楼主| 发表于 2011-5-29 15:15:37 | 显示全部楼层
本帖最后由 lanxun1988 于 2011-5-29 15:17 编辑

回复 3# garyliyong


    您好,非常感谢您的指导。我根据我的理解,我需要在相机的事件回调中用setViewMatrixAsLookAt进行设置。我的几个重要代码如下:
    (1)首先定义了一个class CCameraEventCallback :public osg::NodeCallback 的相机回调类,类中几个重要的代码是这样的:

  1. virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
  2. {
  3.   if(nv->getVisitorType()==osg::NodeVisitor::EVENT_VISITOR)
  4.   {
  5.    osg::ref_ptr<osgGA::EventVisitor> ev = dynamic_cast<osgGA::EventVisitor*> (nv);
  6.    if(ev)
  7.    {
  8.     osgGA::GUIActionAdapter* aa = ev->getActionAdapter();
  9.     osgGA::EventQueue::Events& events = ev->getEvents();
  10.     for(osgGA::EventQueue::Events::iterator itr = events.begin();itr != events.end();++itr)
  11.     {
  12.      handle(*(*itr),*(aa),node  )//这个里面去改相机的位置
  13.   }
  14.    }
  15.   }
  16. }
复制代码

    上面的handle的具体代码是:
  1. bool CCameraEventCallback::handle(const osgGA::GUIEventAdapter& ea ,osgGA::GUIActionAdapter& aa,osg::Node* node)
  2. {
  3. switch(ea.getEventType())
  4. {
  5. case osgGA::GUIEventAdapter::DOUBLECLICK://如果是鼠标双击事件
  6. if(ea.getButton()==1)//确保是鼠标左键双击
  7. {
  8. osg::Vec3 cameraEye;
  9. osg::Vec3 toCenter;
  10. osg::Vec3 cameraUp;//这些变量用来保存camera的各个参数
  11. //自己写的那个漫游器类的初始化为
  12. // m_vPosition = osg::Vec3(0.0f,-70.0f,0.0f);
  13. // m_vRotation = osg::Vec3(osg::PI_2,0.0f,0.0f);


  14. dynamic_cast<osg::Camera*>(node)->getViewMatrixAsLookAt(cameraEye,toCenter,cameraUp);//获取当前camera的各个参数
  15. //断点后发现cameraEye确实是(0.0f,-70.0f,0.0f)
  16. dynamic_cast<osg::Camera*>(node)->setViewMatrixAsLookAt(osg::Vec3(cameraEye.x(),cameraEye.y()+50,cameraEye.z()),toCenter,cameraUp);//只是想让这个cameraEye的y变大一点,也就是感觉上相机往前进了一些
  17. AfxMessageBox("双击事件捕获到了");//这个是我来测试双击事件有没有捕获到的
  18. }
  19. break;
  20. default:
  21. break;
  22. }
  23. return false;
  24. }
复制代码


    (3)另外,相机初始时候是这样设置的
  1. mViewer->addSlave(camera.get());

  2. mViewer->setCameraManipulator(new CTravelManipulator(mViewer));

  3. camera->setEventCallback(new CCameraEventCallback());//用camera来设置事件回调,因此handle函数中的node其实就是这个camera

  4. mViewer->setSceneData(mRoot.get());
复制代码


    但是很悲催的是,相机的位置依旧没有改变。。。。不知道我哪里理解错了。。。。。至于您说的第一种去漫游器里面改变matrix的值的方法,我不知道具体该如何操作。。。。。麻烦您了

该用户从未签到

发表于 2011-5-29 20:24:35 | 显示全部楼层
回复 7# lanxun1988

   你不是看过freesouth的csouth类吗?如果想改变相机的位置,只要根据你的要求,设置m_rotation,m_positon的值就可以了,你的要求是拉近,只要设置m_position.y()+50就可以了,你试试。关于第一个方法,我目前是这样解决的就是viewer->getManipulator()->setHomePosition(eye,enter,up),viewer->home();另外setViewMatrixlookat在setcameraManilulator(NULL)会起作用的,至于为什么,我没有得到明确的答案,也没有找到很好的解决方法。

该用户从未签到

发表于 2011-5-30 10:39:18 | 显示全部楼层
handler函数中的setViewMatrixAsLookAt
看起来您完全没有理解漫游器的编写方法……最重要的是重写虚函数getMatrix()和getInverseMatrix(),因为系统会在每帧自动调用后者来设置主相机,这个函数没有重写的话,任何handle()中的设置都毫无意义

该用户从未签到

发表于 2012-9-15 09:43:36 | 显示全部楼层
lanxun1988 发表于 2011-5-29 15:15
回复 3# garyliyong

你好,你用相机回调设置相机位置的问题有没有解决?我也遇到了同样的问题,谢谢分享

该用户从未签到

发表于 2017-3-24 16:34:54 | 显示全部楼层
我之前遇到这种情况,原因是有其他操作器,在没有操作器的情况下setViewMatrixAsLookAt就是好用的,你可以试一下viewer()->setCameraManipulator(NULL) 之后在setViewMatrixAsLookAt就是好用的,如果想要在具体某个操作器下移动相机,参考array大大的办法
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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