osg中漫游器的纵轴锁定原理

osg、漫游器、纵轴锁定原理

纵轴锁定其实就是将相机的roll、yaw、pitch三个旋转分量的roll分量消除。消除roll的方案有两种,但都是将相机的纵面(FEU)贴向目标Z,第一种是绕F轴旋转,使U轴转入FEZ面,第二种是绕U轴转,使F轴转入UEZ面,想通这两种方式有点费脑子,大家多读几遍本文能理解的。原理知道了,但是怎么计算要旋转多少呢?

下图就是osg中纵轴锁定的算法原理图:

代码注释如下:

/** The method corrects the rotation to make impression of fixed up direction.
 *  Technically said, it makes the roll component of the rotation equal to zero.
 *  rotation parameter is the rotation to be fixed.
 *  localUp is UP vector and must not be zero length.
 *  disallowFlipOver, when set on true, avoids pitch rotation component to grow
 *  over +/- 90 degrees. If this happens and disallowFlipOver is true,
 *  manipulator is rotated by 180 degrees. More precisely, roll rotation component is changed by 180 degrees,
 *  making pitch once again between -90..+90 degrees limits.*/
//这个方法可以修正旋转量,使得up朝向固定不变。
//具体而言就是限制旋转量的roll分量为0
//参数:rotation-将要被修正的旋转量
//参数:localUp-限定up轴向,即锁定的纵轴Z,长度不为0
//参数:disallowFlipOver-是否禁止翻转
void StandardManipulator::fixVerticalAxis( Quat& rotation, const Vec3d& localUp, bool disallowFlipOver )
{
    //拆解相机局部坐标轴
    Vec3d cameraUp = rotation * Vec3d( 0.,1.,0. );
    Vec3d cameraRight = rotation * Vec3d( 1.,0.,0. );
    Vec3d cameraForward = rotation * Vec3d( 0.,0.,-1. );

    //计算R1
    Vec3d newCameraRight1 = cameraForward ^ localUp;
	//计算R2
    Vec3d newCameraRight2 = cameraUp ^ localUp;
    //叉乘后的length本质是两个向量的围成的平行四边形的面积,等价于length越大,两向量的夹角越倾向于90度,等价于旋转角度越小
    Vec3d newCameraRight = (newCameraRight1.length2() > newCameraRight2.length2()) ?
                            newCameraRight1 : newCameraRight2;
    //修正一下新右轴的方向,因为newCameraRight2可能是与原相机右轴反向的(如相机上翘朝前上方看的时候)
    if( newCameraRight * cameraRight < 0. )
        newCameraRight = -newCameraRight;

    //计算右轴的掰正量
    Quat rotationVerticalAxisCorrection;
    rotationVerticalAxisCorrection.makeRotate( cameraRight, newCameraRight );

    // rotate camera
    rotation *= rotationVerticalAxisCorrection;//旋转修正

    if( disallowFlipOver )//不允许相机"倒着看"
    {
        //是相机up与Z轴夹角始终小于90度
        Vec3d newCameraUp = newCameraRight ^ cameraForward;
        if( newCameraUp * localUp < 0. )
            rotation = Quat( PI, Vec3d( 0.,0.,1. ) ) * rotation;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值