查看: 2161|回复: 10

osg中模型变换

[复制链接]

该用户从未签到

发表于 2009-6-5 10:30:18 | 显示全部楼层 |阅读模式
我想旋转视图到指定的位置  下面是我的思路  我获取了l_veye、l_vcenter、l_vup三个值,同时也知道到了指定位置的坐标g_vcenter,利用g_vcenter和l_vcenter计算出它们的叉积axis,和它们的角度angle,根据axis和angle构造一个旋转矩阵mm,然后设置旋转矩阵到场景mt中,但是这种方法不对,希望大家指点下,下面是主要代码,谢谢!!
osg::Camera* camera = viewer->getCamera();
camera->getViewMatrixAsLookAt(l_veye,l_vcenter,l_vup);
viewer->setCamera(camera);
osg::Vec3f axis = l_vcenter ^ g_vcenter;
axis.normalize();
float t = (l_vcenter - g_vcenter).length() / (2.0 *0.8);
if (t > 1.0) t = 1.0;
if (t < -1.0) t = -1.0;
float angle = asin(t);
osg::Matrix mm;
mm.makeRotate(angle,axis);
mt->setMatrix(mm);

该用户从未签到

发表于 2009-6-5 15:22:31 | 显示全部楼层
makeRotate不能针对任意轴进行旋转,因此如果axis不是X/Y/Z轴的话,这个函数不会正确执行。您可以参考我的osgModeling::rotateMatrix函数的内容,其中使用了任意轴旋转矩阵计算的罗德里格斯公式

该用户从未签到

 楼主| 发表于 2009-6-6 10:14:46 | 显示全部楼层
array   你好  我参考了您的osgModeling::rotateMatrix函数的内容   这个函数就是根据旋转轴参数axis,角度参数angle构造了一个矩阵吧    我把您的osgModeling::rotateMatrix函数的内容  在osg中封装了下   但是结果还是不对   我调试了旋转的矩阵  里面是有内容的   而且不是X/Y/Z轴   下面是封装和调用的代码   请您之指点
封装代码:
osg::Matrix CContralView::rotateMatrix(osg::Vec3 axis, const double angle)
{
        double cosA = cos(angle);
        double sinA = sin(angle);
        axis.normalize();

        if ( axis==osg::Vec3(1.0f,0.0f,0.0f) )        // X
        {
                return osg::Matrix(
                        1.0f,  0.0f,  0.0f,  0.0f,
                        0.0f,  cosA,  -sinA, 0.0f,
                        0.0f,  sinA,  cosA,  0.0f,
                        0.0f,  0.0f,  0.0f,  1.0f
                        );
        }
        else if ( axis==osg::Vec3(0.0f,1.0f,0.0f) )        // Y
        {
                return osg::Matrix(
                        cosA,  0.0f,  sinA,  0.0f,
                        0.0f,  1.0f,  0.0f,  0.0f,
                        -sinA, 0.0f,  cosA,  0.0f,
                        0.0f,  0.0f,  0.0f,  1.0f
                        );
        }
        else if ( axis==osg::Vec3(0.0f,0.0f,1.0f) )        // Z
        {
                return osg::Matrix(
                        cosA,  -sinA, 0.0f,  0.0f,
                        sinA,  cosA,  0.0f,  0.0f,
                        0.0f,  0.0f,  1.0f,  0.0f,
                        0.0f,  0.0f,  0.0f,  1.0f
                        );
        }

        double a1 = axis.x();
        double a2 = axis.y();
        double a3 = axis.z();

        // Rotate matrix of any vector, use the Rodriguez formula [Hecker 1997]
        // v' = v * cosA + axis*(v*axis) * (1-cosA) + (axis^vec) * sinA
        // So, T = I * cosA + (axis@axis) * (1-cosA) + M~ * sinA
        // @ means tensor product and M~ is a temp matrix of calculating cross product.
        return osg::Matrix(
                cosA+a1*a1*(1-cosA),    a2*a1*(1-cosA)-a3*sinA, a3*a1*(1-cosA)+a2*sinA, 0.0f,
                a1*a2*(1-cosA)+a3*sinA, cosA+a2*a2*(1-cosA),    a3*a2*(1-cosA)-a1*sinA, 0.0f,
                a1*a3*(1-cosA)-a2*sinA, a2*a3*(1-cosA)+a1*sinA, cosA+a3*a3*(1-cosA),    0.0f,
                0.0f,                   0.0f,                   0.0f,                   1.0f
                );
}

调用代码:
osg::Camera* camera = viewer->getCamera();
camera->getViewMatrixAsLookAt(l_veye,l_vcenter,l_vup);
viewer->setCamera(camera);
osg::Vec3f axis = l_vcenter ^ g_vcenter;
axis.normalize();
float t = (l_vcenter - g_vcenter).length() / (2.0 *0.8);
if (t > 1.0) t = 1.0;
if (t < -1.0) t = -1.0;
float angle = asin(t);

osg::Matrix mm;
mm = rotateMatrix(axis,angle);
//mm.makeRotate(-angle,axis);
mt->setMatrix(mm);

该用户从未签到

发表于 2009-6-6 10:50:45 | 显示全部楼层
rotateMatrix应该是可用的,我测试过,不过注意输入轴应该是单位向量。此外我不是很清楚您的算法是否正确

该用户从未签到

 楼主| 发表于 2009-6-6 14:58:28 | 显示全部楼层
算法思想:
定义两个全局变量g_vcenter、g_iflag;g_vcenter表示目标位置,就是要旋转的位置,这个位置是根据经纬度计算出来的,g_iflag表示场景的旋转标志,当g_iflag等于0时,场景不变化,g_iflag等于1时,利用相机的getViewMatrixAsLookAt(l_veye,l_vcenter,l_vup);方法获取三个参数,根据向量l_vcenter和g_vcenter,计算机它们的叉积axis,也就是将要围绕着旋转的轴,单位化axis,同时计算出两向量的夹角angle,然后利用rotateMatrix方法计算出旋转矩阵,最后作用到场景图上。

该用户从未签到

 楼主| 发表于 2009-6-6 15:45:39 | 显示全部楼层
原帖由 simbaforrest 于 2009-6-6 15:23 发表
咦,rotate不能用四元数吗?

您有可以解决问题的方法?

该用户从未签到

发表于 2009-6-6 16:41:45 | 显示全部楼层
从向量A旋转到向量B,直接用Quat(A, B)就可以了

该用户从未签到

 楼主| 发表于 2009-6-8 17:55:00 | 显示全部楼层
模型控制是在视图的事件回调里面写的,场景根节点是一个MatrixTranslate节点mt,在回调中我使用mt->setMatrix()方法来控制场景的变换,该方法只能接受一个矩阵变量,如果使用Quat如何作用到场景中?望告知,谢谢!!!

该用户从未签到

发表于 2009-6-8 22:18:30 | 显示全部楼层
方法太多了,Matrix可以用Quat作为参数进行构造,也可以用makeRotate,rotate等多个函数将Quat与Matrix级联
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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