我有一个3d对象,我希望能够在3d中旋转.最简单的方法是直接将X和Y鼠标运动转换为绕Y轴和X轴旋转,但如果沿两个轴有一些旋转,则模型旋转的方式变得非常违反直觉(即,如果您将对象翻转180度左右轴,您沿另一轴的运动是相反的).
我可以简单地做上面的方法,但是不是存储绕两个轴旋转的量,而是可以存储完整的旋转矩阵,并且只是为了每个鼠标拖动而沿着相同的轴进一步旋转它,但是我担心那会很快出现精确问题.
围绕垂直于当前拖动方向的轴旋转对象可能是最直观的,可以是每次鼠标移动时递增,也可以是相对于拖动开始位置.这两个选项提供了略微不同的用户交互,每个交互都有其优缺点.
有一种相对简单的方法可以将角度和表示旋转轴的3d矢量转换为旋转矩阵.
你是对的,通过增量旋转更新原始旋转矩阵将导致矩阵不再是纯旋转矩阵.这是因为3x3旋转矩阵的数据量是表示旋转所需数据的三倍.
表示旋转的更紧凑的方式是使用Euler Angles,具有最小的3值向量.您可以将当前旋转作为欧拉角度矢量,将其转换为矩阵,应用旋转(增量或其他),并将矩阵转换回欧拉角度矢量.最后一步自然会消除矩阵中的任何非旋转分量,这样您再次为下一个状态最终得到一个纯旋转矩阵.
欧拉角在概念上很不错,但是来回转换需要做很多工作.
更实用的选择是Quaternions(也),它是四个元素向量.这四个元素指定旋转和均匀缩放,如果您进入并将矢量标准化为单位长度,则会得到比例因子1.0.事实证明,角度轴值也可以非常容易地转换为四元数值
q.x = sin(0.5*angle) * axis.x; q.y = sin(0.5*angle) * axis.y; q.z = sin(0.5*angle) * axis.z; q.w = cos(0.5*angle);
然后,您可以获取当前旋转四元数和增量旋转四元数的四元数乘积(仅使用简单的乘法和加法),以获得表示执行两个旋转的新四元数.此时,您可以标准化长度以确保纯旋转,但否则继续迭代组合旋转.
当您想要使用传统图形API以旋转状态显示模型时,将四元数转换为旋转矩阵非常简单(仅使用乘法和加法).
在我的计算机图形学课程中,我们获得了以下代码,这使我们无法重新发明轮子.
trackball.h
trackball.c