查看: 2126|回复: 15

相机位置问题

[复制链接]

该用户从未签到

发表于 2011-7-20 11:59:31 | 显示全部楼层 |阅读模式
各位好,我目前一个问题,我要实现的功能是:在一个复杂的场景中,然后现在我要实现的是,假如说我现在单击墙上的一张画,然后我要实现将这张画放到屏幕中间,并相应的放大(其实就是为了看的更清楚),我一开始的方案就是:我用两个相机+RTT来实现,就是用RTT相机,将单击得到的模型放到纹理中,然后再通过另外一个相机显示出来,一开始我单独测试的时候,还是可以实现的。结果放到整个工程中去的时候,发现一个很大的问题,就是相机没办法对准模型(由于模型的位置在不同的地方),造成显示不出正确的效果;
不知道各位大哥有没有比较好的方法。。。谢谢咯。

该用户从未签到

发表于 2011-7-20 13:32:40 | 显示全部楼层
可以在回调里随时调整相机的观察和投影矩阵来对准

该用户从未签到

 楼主| 发表于 2011-7-20 14:45:32 | 显示全部楼层
我在回调函数中这样设置相机:
osg::BoundingBox bb = geode->getBoundingBox();
                        double x = bb.center()._v[0];
                        double y = bb.center()._v[1];
                        double z = bb.center()._v[2];
                        mHUDCamera->setViewMatrixAsLookAt(osg::Vec3d(x, y-10, z), osg::Vec3d(x, y, z), osg::Vec3d(0, 0, 1));
这样可以嘛?

该用户从未签到

发表于 2011-7-21 08:18:43 | 显示全部楼层
可以,不过要注意,对于主相机,Slave相机和RELATIVE_RF的节点相机而言,CameraManipulator同样会影响它的观察矩阵

该用户从未签到

 楼主| 发表于 2011-7-21 09:03:44 | 显示全部楼层
我在设置相机是这样设置的:
        mHudCamera->setViewMatrix(osg::Matrix::identity());
        mHudCamera->setAllowEventFocus(false);
        mHudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
        mHudCamera->setViewport(0, 0, mTraits->width, mTraits->height);
        mHudCamera->setProjectionMatrixAsOrtho2D(0, mTraits->width, 0, mTraits->height);
        mHudCamera->setRenderOrder(osg::Camera:OST_RENDER);
        //mHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
        mHudCamera->setGraphicsContext(mGc.get());
        mHudCamera->setNodeMask(0);

按照这种方式做的,目前我得到的效果确实不是我想要的,也就是这个相机受到漫游器的影响了,能不能有什么办法让这个mHudCamera不受这个漫游器的影响?

该用户从未签到

发表于 2011-7-21 09:43:33 | 显示全部楼层
ABSOLUTE_RF相机的子节点不会受漫游器影响。
此时相机需要自行设置setViewMatrix, 改变模型-观察矩阵。

该用户从未签到

发表于 2011-7-21 09:43:54 | 显示全部楼层
ABSOLUTE_RF相机的子节点不会受漫游器影响。
此时相机需要自行设置setViewMatrix, 改变模型-观察矩阵。

该用户从未签到

 楼主| 发表于 2011-7-21 10:05:01 | 显示全部楼层
但是我有实时改变观察矩阵了啊。。。
osg::BoundingBox bb = geode->getBoundingBox();
                        double x = bb.center()._v[0];
                        double y = bb.center()._v[1];
                        double z = bb.center()._v[2];
                        mHUDCamera->setViewMatrixAsLookAt(osg::Vec3d(x, y-10, z), osg::Vec3d(x, y, z), osg::Vec3d(0, 0, 1));
为什么还是没办法显示呢。。

该用户从未签到

发表于 2011-7-21 11:19:57 | 显示全部楼层
原因大概在于你设置了相机的setProjectionMatrixAsOrtho2D函数,从而使你只能观察到坐标范围在(0,width)范围的物体, 而你又设置了setViewMatrixAsLookAt,  显然导致了相机位置严重不准确。

该用户从未签到

 楼主| 发表于 2011-7-21 11:38:11 | 显示全部楼层
那您的意思是说,我在回调的时候要更新观察矩阵和投影矩阵么?如果是的话,能否给点提示,就是根据什么因素来更新这两个参数呢?

该用户从未签到

发表于 2011-7-22 10:37:50 | 显示全部楼层
设置setProjectionMatrixAsOrtho2D后,观察矩阵可以改变视点位置,却无法改变缩放比例。所以,需要根据画的大小设置合适的投影矩阵。

该用户从未签到

 楼主| 发表于 2011-7-23 19:00:14 | 显示全部楼层
如果我将要放大的图片的drawable放到billboard下,然后设置mViewer->setSceneData(billboard.get()),这样可以嘛?

该用户从未签到

发表于 2011-7-23 19:30:55 | 显示全部楼层
您的这个问题还是比较棘手的,并不能简单的处理,要是我来做的话,方案如下。
为这些需要点击的物体制作专门的相机位置和朝向数据,点击时直接用这些数据生成矩阵。
否则想用程序自动实现,那将是非常困难的一个课题。

该用户从未签到

 楼主| 发表于 2011-7-23 19:43:03 | 显示全部楼层
恩,非常谢谢你这么耐心的解答。
我目前的想法跟您是一样的,我在单击的时候取出来图片的四个顶点坐标,然后根据这些坐标算出这张图片的法向量,然后在根据法向量算出相机的位置,进而设置相机的属性,代码如下:
  1. osg::Vec3Array* v = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
  2.                         double v1[2], v2[2];
  3.                         double A[3][3];//顶点坐标
  4.                                                 //求法向量
  5.                         double na = A[0][1] * (A[1][2] - A[2][2]) + A[0][2] * (A[1][1] - A[2][1]) + (A[1][1] * A[2][2] - A[2][1] * A[1][2]);
  6.                         double nb = A[0][0] * (A[1][2] - A[2][2]) + A[0][2] * (A[1][0] - A[2][0]) + (A[1][0] * A[2][2] - A[2][0] * A[1][2]);
  7.                         double nc = A[0][0] * (A[1][1] - A[2][1]) + A[0][1] * (A[1][0] - A[2][0]) + (A[1][0] * A[2][1] - A[2][0] * A[1][1]);
  8.                         //求中心点的坐标
  9.                         double cx = (A[0][0] + A[2][0])/2;
  10.                         double cy = (A[0][1] + A[2][1])/2;
  11.                         double cz = (A[0][2] + A[2][2])/2;

  12.                         double eyeX = cx + na;
  13.                         double eyeY = cy + (-1) * nb;
  14.                         double eyeZ = cz + nc;

  15.                         double upX = A[1][0] - A[0][0];
  16.                         double upY = A[1][1] - A[0][1];
  17.                         double upZ = A[1][2] - A[0][2];
  18.                         mHUDCamera->setViewMatrixAsLookAt(osg::Vec3d(eyeX, eyeY, eyeZ), osg::Vec3d(cx, cy, cz), osg::Vec3d(upX, upY, upZ));
  19.                         mHUDCamera->setProjectionMatrixAsOrtho2D(cx - mWidth/2, cx + mWidth/2,cy - mWidth/2, cy + mWidth/2);
  20.                         mHUDCamera->setNodeMask(0);
  21.                         mGnode = geode;
  22.                         mHUDCamera->addChild(geode);
复制代码
我这样的做法,有没有什么问题嘛?

该用户从未签到

发表于 2011-7-25 23:17:24 | 显示全部楼层
  1. mHUDCamera->setNodeMask(0);
复制代码
有这一行存在,您的相机就什么都显示不出来了

该用户从未签到

 楼主| 发表于 2011-7-26 11:40:39 | 显示全部楼层
哦,谢谢array,我现在差不多已经知道怎么做了。。那一行是我自己写错了。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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