查看: 1075|回复: 1

osg 轨迹球漫游器原理

[复制链接]

该用户从未签到

发表于 2021-3-13 22:21:28 | 显示全部楼层 |阅读模式
大神们,帮忙指导一下,这段代码的原理解释.
void OrbitManipulator::trackball( osg::Vec3d& axis, float& angle, float p1x, float p1y, float p2x, float p2y )
{
    /*
        * First, figure out z-coordinates for projection of P1 and P2 to
        * deformed sphere
        */

    osg::Matrixd rotation_matrix(_rotation);

    osg::Vec3d uv = Vec3d(0.0f,1.0f,0.0f)*rotation_matrix;
    osg::Vec3d sv = Vec3d(1.0f,0.0f,0.0f)*rotation_matrix;
    osg::Vec3d lv = Vec3d(0.0f,0.0f,-1.0f)*rotation_matrix;

    osg::Vec3d p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(_trackballSize, p1x, p1y);
    osg::Vec3d p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(_trackballSize, p2x, p2y);

    /*
        *  Now, we want the cross product of P1 and P2
        */
    axis = p2^p1;
    axis.normalize();

    /*
        *  Figure out how much to rotate around that axis.
        */
    float t = (p2 - p1).length() / (2.0 * _trackballSize);

    /*
        * Avoid problems with out-of-control values...
        */
    if (t > 1.0) t = 1.0;
    if (t < -1.0) t = -1.0;
    angle = inRadians(asin(t));
}

该用户从未签到

 楼主| 发表于 2021-3-14 12:53:03 | 显示全部楼层
本帖最后由 pcsms_05jLD97h 于 2021-3-14 18:51 编辑

个人理解,如果错误,请您指出来,及时纠正
1.此函数用于求解z坐标
float OrbitManipulator::tb_project_to_sphere( float r, float x, float y )
{
    float d, t, z;

    d = sqrt(x*x + y*y);
                                 /* Inside sphere */
    if (d < r * 0.70710678118654752440)
    {
        z = sqrt(r*r - d*d);
    }                            /* On hyperbola */
    else
    {
        t = r / 1.41421356237309504880;
        z = t*t / d;
    }
    return z;
}

传入一个设想的半径,默认是0.8(x y坐标是标准化坐标,范围在-1,1),分两种i情况来求解z坐标
0.70710678118654752440 是cos(PI/2),也就是45度
1.d < r * 0.70710678118654752440 同理 球上一点和xy平面的夹角大于45,使用圆的算法
2.d > r * 0.70710678118654752440 同理 球上一点和xy平面的夹角小于45,使用双曲线算法

2.此函数是求解旋转轴 和 旋转角
void OrbitManipulator::trackball( osg::Vec3d& axis, float& angle, float p1x, float p1y, float p2x, float p2y )
{
    /*
        * First, figure out z-coordinates for projection of P1 and P2 to
        * deformed sphere
        */

    osg::Matrixd rotation_matrix(_rotation);

    osg::Vec3d uv = Vec3d(0.0f,1.0f,0.0f)*rotation_matrix;
    osg::Vec3d sv = Vec3d(1.0f,0.0f,0.0f)*rotation_matrix;
    osg::Vec3d lv = Vec3d(0.0f,0.0f,-1.0f)*rotation_matrix;

    osg::Vec3d p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(_trackballSize, p1x, p1y);
    osg::Vec3d p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(_trackballSize, p2x, p2y);

    /*
        *  Now, we want the cross product of P1 and P2
        */
    axis = p2^p1;
    axis.normalize();

    /*
        *  Figure out how much to rotate around that axis.
        */
    float t = (p2 - p1).length() / (2.0 * _trackballSize);

    /*
        * Avoid problems with out-of-control values...
        */
    if (t > 1.0) t = 1.0;
    if (t < -1.0) t = -1.0;
    angle = inRadians(asin(t));
}

2.1 获取三维空间中的方向向量
    float p1x, float p1y, float p2x, float p2y 屏幕坐标标准化后的坐标(-1,1)
    tb_project_to_sphere(_trackballSize, p1x, p1y); 间接获取到Z坐标 => 虚拟轨迹球的方向向量
2.2 组合成旋转矩阵
    osg::Vec3d uv = Vec3d(0.0f,1.0f,0.0f)*rotation_matrix;
    osg::Vec3d sv = Vec3d(1.0f,0.0f,0.0f)*rotation_matrix;
    osg::Vec3d lv = Vec3d(0.0f,0.0f,-1.0f)*rotation_matrix;
2.3 获取旋转后的方向向量
    osg::Vec3d p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(_trackballSize, p1x, p1y);
    osg::Vec3d p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(_trackballSize, p2x, p2y);
   [SV UV LV][PX PY PZ]T = SV*PX + UV*PY + LV*PZ
2.4 获取旋转轴
    axis = p2^p1;
    axis.normalize();
2.5 获取旋转角度
     float t = (p2 - p1).length() / (2.0 * _trackballSize);
     相当于圆上两点,连接两点,从圆心做垂线,sin& = ((p2 - p1).length() / 2.0) / _trackballSize); 注释(_trackballSize = r)
    防止越界
    if (t > 1.0) t = 1.0;
    if (t < -1.0) t = -1.0;
    反向求出角度
    angle = inRadians(asin(t));





您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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