18

我有一个 3d 对象,我希望能够在 3d 中旋转。最简单的方法是直接将 X 和 Y 鼠标运动转换为围绕 Y 和 X 轴的旋转,但是如果沿两个轴都有一些旋转,则模型旋转的方式变得非常违反直觉(即,如果您将对象翻转 180 度轴,您沿另一个轴的运动是相反的)。

我可以简单地执行上述方法,但不是存储围绕两个轴旋转的量,我可以存储完整的旋转矩阵,并为每次鼠标拖动沿着相同的轴进一步旋转它,但我担心这会很快就有精度问题。

4

4 回答 4

7

围绕垂直于当前拖动方向的轴旋转对象可能是最直观的,或者随着每次鼠标移动递增,或者相对于拖动开始位置。这两个选项提供了略微不同的用户交互,每个都有其优点和缺点。

有一种相对简单的方法可以将表示旋转的轴的角度和 3d 矢量转换为旋转矩阵。

你是对的,通过增量旋转更新原始旋转矩阵将导致矩阵不再是纯旋转矩阵。这是因为 3x3 旋转矩阵的数据量是表示旋转所需数据量的三倍。

表示旋转的更紧凑的方法是使用欧拉角,具有最小的 3 值向量。您可以将当前旋转作为欧拉角向量,将其转换为矩阵,应用旋转(增量或其他方式),然后将矩阵转换回欧拉角向量。最后一步自然会消除矩阵中的任何非旋转分量,以便您再次获得下一个状态的纯旋转矩阵。

欧拉角在概念上很好,但是来回转换需要做很多工作。

一个更实际的选择是四元数),它是四个元素向量。这四个元素指定了旋转和统一的比例,如果你进入并将向量归一化为单位长度,你会得到一个 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 以旋转状态显示模型时,将四元数转换为旋转矩阵非常简单(仅使用乘法和加法)。

于 2008-09-20T07:26:40.887 回答
6

在我的计算机图形学课程中,我们获得了以下代码,这使我们不必重新发明轮子。

轨迹球.h

轨迹球.c

于 2008-09-20T08:37:17.550 回答
4

创建一个累加器矩阵并使用标识对其进行初始化。

每一帧,在绘制对象之前将其应用于您的模型视图/世界矩阵状态。

在鼠标移动时,构造一个关于 X 轴的旋转矩阵,带有一些灵敏度常数 * delta_x。为另一个组件构造另一个绕 Y 轴的旋转矩阵。将一个相乘,然后将另一个相乘到累加器上。

移动鼠标时,累加器会发生变化。绘制时,它将按照您的预期定位对象。

另外,谈论四元数的人是对的。这仅适用于小的增量更改。如果您在对角线上快速拖动它,它不会像您期望的那样旋转。

于 2008-09-20T06:48:11.697 回答
3

您可以通过重新归一化旋转矩阵来处理精度损失,以便 3 行中的每一行再次垂直。或者,您可以根据有关对象的现有信息重新生成您将要修改的旋转矩阵,这样就不需要重新规范化了。

或者,您可以使用quaternions,这是处理旋转的欧拉角的替代方法。

我在早期从这个 faq中学到了很多东西,它在Euler's are Evil中处理了这个问题(尽管对于另一个应用程序)。

于 2008-09-20T06:50:36.090 回答