查看: 3515|回复: 8

请问怎样在TrackballManipulator限制旋转角度

[复制链接]

该用户从未签到

发表于 2010-1-19 09:41:28 | 显示全部楼层 |阅读模式
我复制TrackballManipulator建立了自己的漫游器,想限制绕Y轴旋转的角度,使观察角度不会跑到模型下方,但是绕X、Z轴可以正常旋转,而且在模型上方的部分也可以正常旋转,请问老大们如何实现呀?

该用户从未签到

 楼主| 发表于 2010-1-19 09:48:32 | 显示全部楼层
另外,限制缩放比例用下面的方法实现是否正确,是不是有更好更标准的办法:

else if ((buttonMask==osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) || (buttonMask==osgGA::GUIEventAdapter::SCROLL))

    {

        // zoom model.

        float fd = _distance;
        float scale = 1.0f+ dy * throwScale;
        if (fd*scale>_modelScale*_minimumZoomScale)
        {
                        //限制视野距离,不能使视野无限小或者无限大
                        if((fd*scale<1000.0f) && (fd*scale>2.0f))
                        {
                                _distance *= scale;
                        }
&#160;       }

        return true;

    }

该用户从未签到

发表于 2010-1-19 12:46:58 | 显示全部楼层
没有什么标准可言,您大可按照自己的设想去实现漫游器
只不过trackball漫游器的原理是国际通用的Arcball算法,如果您想改变旋转的策略,最好首先对于这个算法充分熟悉再改写

该用户从未签到

 楼主| 发表于 2010-1-19 15:15:50 | 显示全部楼层
谢谢array,看来我要先研究一下Arcball算法

该用户从未签到

 楼主| 发表于 2010-1-20 10:08:39 | 显示全部楼层
研究了一个下午,终于解决了限制观察角度的问题,同时保留了轨迹球操作器的优点,虽然还有点不完美。
没有修改Arcball算法,用了一点点投机取巧的办法,主要思路是取得当前视点位置,判断其Z值是否小于某个数值,小于的话就反射回去。
不完善的地方就是反射回去的角度不是遵循光线反射规律,而是顺着原路反射。

该用户从未签到

 楼主| 发表于 2010-1-23 11:02:35 | 显示全部楼层
把代码贴出来,请大家看看,多提宝贵意见:
bool WorkerManipulator::calcMovement()
{   
    ......
    if (buttonMask==osgGA::GUIEventAdapter:EFT_MOUSE_BUTTON)
    {

        // rotate camera.               

        osg::Vec3 axis;
        float angle;

        float px0 = _ga_t0->getXnormalized();
        float py0 = _ga_t0->getYnormalized();
        
        float px1 = _ga_t1->getXnormalized();
        float py1 = _ga_t1->getYnormalized();

                //限制旋转角度不使其到模型下部
                osg::Vec3d eyeNow;
                osg::Vec3d centerNow;
                osg::Vec3d upNow;
                mainView->getCamera()->getViewMatrixAsLookAt(eyeNow, centerNow, upNow);
                if(eyeNow[2] > lowZ)
                {
                        //只有弹回正确的Z值范围后即可解除第一下反射标志
                        //firstReject标志主要为了解决到达边缘时的震动问题
                        firstReject = false;
                }
                if((eyeNow[2] < lowZ) || reject)
                {
                        //如果属于拖拽,则不允许继续向下,同时也不反射
                        if (!_thrown)
                        {
                                //将视点向上移动,并计算出新的位置并返回
                                eyeNow += osg::Vec3d(0.0f, 0.0f, 1.0f);
                                computePosition(eyeNow, _center, upNow);
                                reject = false;
                                return true;
                        }                       
                        if(eyeNow[2] < lowZ)
                        {
                                if(!firstReject)
                                {
                                        //如果不是第一下反射,则允许反射
                                        reject = !reject;
                                        firstReject = true;
                                }
                        }
                }
                //如果是反射,则交换坐标
                if(reject)
                {
                        py1 = _ga_t0->getYnormalized();
                        py0 = _ga_t1->getYnormalized();
                        px1 = _ga_t0->getXnormalized();
                        px0 = _ga_t1->getXnormalized();
                }

                //抛掷衰减
                if(!_thrown)
                {
                        //如果不是抛掷则衰减数值恢复
                        attenuation = 1.0f;
                }
                else
                {
                        //如果是抛掷则进行衰减
                        attenuation *= attenuationFactor;
                        throwScale *= attenuation;
                }

        trackball(axis,angle,px1,py1,px0,py0);

        osg:uat new_rotate;

        new_rotate.makeRotate(angle * throwScale,axis);

        _rotation = _rotation*new_rotate;

        return true;

    }

该用户从未签到

发表于 2011-11-6 18:31:40 | 显示全部楼层
array 发表于 2010-1-19 12:46
没有什么标准可言,您大可按照自己的设想去实现漫游器
只不过trackball漫游器的原理是国际通用的Arcball算 ...

请问arrayOrbitManipulator漫游器中,鼠标左键拖动旋转时,旋转轴是如何确定的。怎么有时感觉以过当前场景中心的轴旋转,而有时感觉以默认的一个轴来旋转,模型会跑出可见区外面,请问_ga_t1和_ga_t0是如何确定旋转轴的。可否确定为当前场景的中心轴,而不是整个场景的。

该用户从未签到

发表于 2011-11-7 09:26:57 | 显示全部楼层
你在tb里控制z值更好吧~

该用户从未签到

发表于 2011-11-7 10:04:58 | 显示全部楼层
请先阅读了解arcball算法的原理,而不是凭空猜测
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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