【OpenGL】杂谈一、通过鼠标拖拽实现相机绕空间中的某点进行球面旋转查看

1. 前言

这是我最近遇到的一个问题,如题所示,我需要通过鼠标拖拽实现相机绕点的球面旋转,原本的想法很简单,类似笔记八、摄像机中提到的那样,从聚焦中心点的视角出发,将鼠标移动的距离xoffset和yoffset转换为yaw和pitch角,然后计算出该视角的向量,与球面求交从而得到相机的当前位置,但是实际过程中出现了一个比较严重的问题,就是欧拉角的致命缺陷——万向锁,如果pitch角超过±90°,我们就会遇到各种问题,在设计第一视角时我们可以控制pitch角在90°到-90°之间,这不影响我们的体验,但是如果我们要控制相机进行球面旋转的话,这样偷懒可能就不对了,那么能不能有别的方法来实现这种效果呢?当然是有的,一种是四元数,它可以实现球面旋转的平滑插值过渡,但是今天我要介绍另一种更为直观的实现方法

2. 相机的球面旋转

(代码基于笔记九、相机类修改)
同样的,我们需要记录每次鼠标移动的距离xoffset和yoffset,这两个值该怎么去运用呢?
在这里插入图片描述
可以画出示意图:
在这里插入图片描述
其中A和B是相机移动前后的点,O点是我们相机的聚焦点,那么现在要做的事就很明显了,原本相机的视角是平行的圆面,我们把它看作投影平面,而移动相机时,我们是在OAB形成的圆面上移动,那么我们的任务就是利用OA求得OB

首先我们计算出OA向量,求出当前的旋转半径

	void updateCameraVectors()
    {
        if (xoffset == 0 && yoffset == 0)
            return;
        glm::vec3 target, offset;
        target = Position - Front;
        double radius = glm::length(target);
        target = glm::normalize(target);

之后我们将当前相机向上方向与OA向量叉乘得到投影面的右向量

        Right = glm::normalize(glm::cross(Up, target));

其次再用OA向量与求得的叉乘得到投影面的上向量

        Up = glm::normalize(glm::cross(target, Right));

然后我们求屏幕位移在投影面上对应的向量AB(将投影面的右向量与上向量分别乘以xy位移值并相加)

        offset = Up * yoffset + Right * xoffset ;

之后我们将位移的的弧长转换为OAB圆的弧度并取负,保证物体的相对旋转方向与鼠标推拽方向一致(相机旋转方向与鼠标位移方向相反)

        double len = glm::length(offset);
        double angle = -len / radius;
        offset = glm::normalize(offset);

最后我们计算新的target向量OB = (OAcos(OAB)+ABsin(OAB)),并将它乘以半径的长度加在聚焦点,从而得到我们的相机位置

        double cr = cos(angle) * radius, sr = sin(angle) * radius;
        Position = Front + glm::vec3(target.x * cr + offset.x * sr, target.y * cr + offset.y * sr, target.z * cr + offset.z * sr);
	}

3.效果

在这里插入图片描述

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ycr的帐号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值