查看: 2938|回复: 7

OSG Camera 视点变动事件监听

[复制链接]

该用户从未签到

发表于 2012-12-28 17:32:51 | 显示全部楼层 |阅读模式
在osg之中,当我需要对Camera的视点变动事件进行响应的时候,该怎么办呢?
比如:我需要时常使用camera的eye pos值来设置一个Uniform变量的值,以实现某一特殊的效果,这时Camera的方位变换事件就得被一个UniformCallback处理来对Uniform值进行实时调整,遇到这种情况,我们一般的做法是
1.从Camera类派生出一个子类,并重载setViewMatrix()函数:
  1. bool CameraExt::setViewMatrix(const osg::Matrixf & matrix)
  2. {
  3.    Camera::setViewMatrix(matrix);
  4.    //向事件队列里面发送消息
  5.   osg::ref_ptr<osgViewer::View> view = dynamic_cast<osgViewer::View>(getView());
  6. if(view == NULL)
  7. {
  8.   osg::notify(osg::FITAL)<<"Failed to get and convert the view ..."<<std::endl;
  9. }
  10. osg::ref_ptr<osgGA::EventQueue> eq = view->getEventQueue();
  11. //向EventQueue中发送消息
  12. eq -> addEvent(new CameraPosChangeEvent());
  13. }
复制代码
下面是CameraPosChangeEvent()类的简单实现
  1. class CameraPosChangeEvent:public osgGa::GUIEventAdapter
  2. {
  3. public:
  4.    CameraPosChangeEvent()
  5.    {
  6.      setEventType(osgGA::GUIEventAdapter::USER);//我们自定义的事件
  7.    }
  8.    void setCameraPos(osg::Vec3 & pos)
  9.    {
  10.        _cameraPos = pos;
  11.     }
  12.     const osg::Vec3& getCameraPos()const
  13.     {
  14.        return _cameraPos;
  15.     }
  16. protected:
  17.    osg::Vec4 _cameraPos;//相机位置
  18. };
复制代码

该用户从未签到

 楼主| 发表于 2012-12-28 17:37:53 | 显示全部楼层
我们要监听这个事件的话,就得自己重写osg::Uniform::Callback类来判断一个消息是否为CameraPosChangeEvent()
但是现在有一个问题出现了,osg::Camera::setViewMatrix() 函数不是虚函数,所以所以即使CameraExt被设置为场景的相机,当setViewMatrix()函数被调用的时候,派生类的函数也得不到调用,于是上面的代码完全行不通了。这个问题怎么解决呀?求高手指教.....

该用户从未签到

发表于 2012-12-28 18:15:11 | 显示全部楼层
最简单的做法就是先dynamic_cast<>尝试从getCamera()得到CameraExt,然后再执行它的setViewMatrix()就可以了

该用户从未签到

 楼主| 发表于 2012-12-29 13:48:44 | 显示全部楼层
但是事实上,这样做是行不通的,因为对osg::Camera::setViewMatrix()函数的调用是系统完成的,一般情况下,在一个osgViewer::Viewer对象中会设置CameraManipulator对象,而osg::Camera::setViewMatrix()函数应该是由CameraManipulator类内部调用的,这个就是问题所在。。。

该用户从未签到

 楼主| 发表于 2012-12-29 13:54:15 | 显示全部楼层
我还想过了第二个方案,就是使用代理模式
  1. class CameraProxy:public osg::Camera
  2. {
  3. public:
  4.   CameraProxy(osg::Camera * camera)
  5.   :_camera(camera){}
  6.    //...
  7.     bool setViewMatrix(const osg::Matrixf & matrix)
  8.    {
  9.      if(_camera.valid())
  10.      {
  11.         _camera->setViewMatrix(matrix);
  12.        //然后发送CameraPosChangeEvent;
  13.      }
  14.    }
  15. protected:
  16.   osg::ref_ptr<osg::Camera> _camera;
  17. };
复制代码
但这个方案同样也是因为
osg::Camera::setViewMatrix()函数不是虚函数而行不通了...

该用户从未签到

发表于 2013-1-4 09:27:11 | 显示全部楼层
给我一个行不通的理由,您给的理由不成立

该用户从未签到

 楼主| 发表于 2013-1-4 12:21:11 | 显示全部楼层
感谢Array热心的回复,这个地方是我对osg的机制的一个误解,后来才发现osg是通过osg::NodeVisitor类的两个方法getEyePoint(),getViewPoint()来获得眼坐标的,它这么做的确要比我发送消息的机制来得方便些。。。。

该用户从未签到

发表于 2013-1-5 09:06:15 | 显示全部楼层
想怎么搞就怎么搞
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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