在 3D 世界中移动 - OpenGL
Moving in 3D world - OpenGL
所以我目前正在研究一些游戏元素,包括 OpenGL 中的一些类似引擎的东西,我遇到了这个问题。 (处理3D世界)
我正在通过鼠标获取世界中的旋转角度,如下所示:
int prevX = mouse.x;
int prevY = mouse.y;
GetCursorPos(&mouse);
cam.xRot -= atan(prevX-mouse.x);
cam.yRot -= atan(prevY-mouse.y);
看起来效果不错。 (xRot 实际上意味着像围绕 Y 轴旋转和 yRot 围绕 x 轴)
相机旋转很好。然后我开始研究相对于相机的运动。经过一些图纸和绝望的尝试,我得出了这个:
//W
if (keys[57])
{
cam.z += cos(angleY)*cos(angleX)*cam.speed;
cam.x -= cos(angleY)*sin(angleX)*cam.speed;
cam.y += sin(angleY);
}
//S
if (keys[53])
{
cam.z -= cos(angleY)*cos(angleX)*cam.speed;
cam.x += cos(angleY)*sin(angleX)*cam.speed;
cam.y -= sin(angleY);
}
//A
if (keys[41])
{
cam.z += sin(angleX)*cam.speed;
cam.x += cos(angleX)*cam.speed;
}
//D
if (keys[44])
{
cam.z -= cos(angleY)*sin(angleX)*cam.speed;
cam.x -= cos(angleY)*cos(angleX)*cam.speed;
}
它也有效,但问题是当我围绕 z 轴(深度轴)旋转相机时。我尝试了一些组合等,但似乎没有任何效果。我错过了什么?
我像这样制作了上面的方程式:
当我把它当作一个只有 x 和 z 的 2D 并且我想向前移动相机旋转零角度时我只需要在 z 轴方向上移动,以正向的方式所以让我们使用一个函数,它在那里是最大的 => cos .当我旋转 90 度并需要向前移动时,我需要在 x 轴上移动,所以让我们使用 sin 因为我们需要相反的方向。那个手柄的 2D 井。
现在我需要添加 z 轴,所以我可能只是将 x 和 y 的值限制为第二个角度的 cos(如果需要,yRot 或围绕 x 的旋转角度)并使它的 sin 成为 y 轴上的实际运动。
是的,效果很好,但正如我所说,当我围绕 z 旋转并基本上切换 y 轴和 x 轴时出现问题。
怎么办? :D
哦,顺便说一下,我已经阅读了一些其他教程,我注意到有些人对矢量等使用不同的方式。当今游戏中的常用方式是什么?我不太喜欢经常使用测角函数。也许我的方法不是最好的吧?
在谈到相机管理时,大多数人似乎都认为这比原来要困难得多。重点是矩阵数学。
考虑一个具有世界矩阵 W
的对象,它由旋转和平移部分组成。如果我们想将这个对象向右移动,我们可以将相应的平移矩阵乘以 W
(请注意,所有进一步的解释都假定 OpenGL 符号具有列向量和列主矩阵):
W* = W * T(x, 0, 0)
重要的是乘法顺序。如果将平移矩阵乘以右侧,它将在对象的局部坐标系中移动对象。如果你把它乘到左边,它会在全局坐标系中移动它。同样,我们可以乘以一个旋转矩阵来使物体在其局部坐标系中旋转:
W** = W* * Rx(phi)
现在,相机的视图矩阵有点棘手,因为它实际上是一个倒矩阵。所以如果你有一个视图矩阵V
,你必须将逆矩阵乘以左侧:
V* = T(-x, 0, 0) * V
V** = Rx(-phi) * V*
//...
不过,其中一个问题是上向量的固定。如果您围绕局部 y 轴执行旋转,则向上方向可能会发生变化。我们可以计算一个自适应矩阵,这可以避免这种情况,但是从两个角度重新计算整个旋转矩阵可能要容易得多。重新计算矩阵后,必须将其重新定位在旧位置(全局位置,因此向左乘一个平移矩阵)。计算旧位置需要一些数学知识(因为矩阵是倒置的):
pos = -tx * first row - ty * second row - tz * third row
where tx is the entry in the first row, last column
ty is the entry in the second row, last column
tz is the entry in the third row, last column
总结
如果要保持灵活的相机表示,请存储视图矩阵和两个旋转角度。如果要移动相机,只需乘以平移矩阵即可。如果要围绕局部 x 轴旋转相机,请更改角度并乘以旋转矩阵。如果要绕局部y轴旋转,改变角度,重新计算整个矩阵,包括重新定位。
您当前的解决方案基本上是这样做的,因为三角函数结果恰好是矩阵在相关位置的条目。但是正如你所见,维护起来非常麻烦,如果你想允许第三次轮换,你将不得不更改整个代码。
拥抱矩阵数学!
所以我目前正在研究一些游戏元素,包括 OpenGL 中的一些类似引擎的东西,我遇到了这个问题。 (处理3D世界) 我正在通过鼠标获取世界中的旋转角度,如下所示:
int prevX = mouse.x;
int prevY = mouse.y;
GetCursorPos(&mouse);
cam.xRot -= atan(prevX-mouse.x);
cam.yRot -= atan(prevY-mouse.y);
看起来效果不错。 (xRot 实际上意味着像围绕 Y 轴旋转和 yRot 围绕 x 轴) 相机旋转很好。然后我开始研究相对于相机的运动。经过一些图纸和绝望的尝试,我得出了这个:
//W
if (keys[57])
{
cam.z += cos(angleY)*cos(angleX)*cam.speed;
cam.x -= cos(angleY)*sin(angleX)*cam.speed;
cam.y += sin(angleY);
}
//S
if (keys[53])
{
cam.z -= cos(angleY)*cos(angleX)*cam.speed;
cam.x += cos(angleY)*sin(angleX)*cam.speed;
cam.y -= sin(angleY);
}
//A
if (keys[41])
{
cam.z += sin(angleX)*cam.speed;
cam.x += cos(angleX)*cam.speed;
}
//D
if (keys[44])
{
cam.z -= cos(angleY)*sin(angleX)*cam.speed;
cam.x -= cos(angleY)*cos(angleX)*cam.speed;
}
它也有效,但问题是当我围绕 z 轴(深度轴)旋转相机时。我尝试了一些组合等,但似乎没有任何效果。我错过了什么? 我像这样制作了上面的方程式: 当我把它当作一个只有 x 和 z 的 2D 并且我想向前移动相机旋转零角度时我只需要在 z 轴方向上移动,以正向的方式所以让我们使用一个函数,它在那里是最大的 => cos .当我旋转 90 度并需要向前移动时,我需要在 x 轴上移动,所以让我们使用 sin 因为我们需要相反的方向。那个手柄的 2D 井。 现在我需要添加 z 轴,所以我可能只是将 x 和 y 的值限制为第二个角度的 cos(如果需要,yRot 或围绕 x 的旋转角度)并使它的 sin 成为 y 轴上的实际运动。 是的,效果很好,但正如我所说,当我围绕 z 旋转并基本上切换 y 轴和 x 轴时出现问题。 怎么办? :D
哦,顺便说一下,我已经阅读了一些其他教程,我注意到有些人对矢量等使用不同的方式。当今游戏中的常用方式是什么?我不太喜欢经常使用测角函数。也许我的方法不是最好的吧?
在谈到相机管理时,大多数人似乎都认为这比原来要困难得多。重点是矩阵数学。
考虑一个具有世界矩阵 W
的对象,它由旋转和平移部分组成。如果我们想将这个对象向右移动,我们可以将相应的平移矩阵乘以 W
(请注意,所有进一步的解释都假定 OpenGL 符号具有列向量和列主矩阵):
W* = W * T(x, 0, 0)
重要的是乘法顺序。如果将平移矩阵乘以右侧,它将在对象的局部坐标系中移动对象。如果你把它乘到左边,它会在全局坐标系中移动它。同样,我们可以乘以一个旋转矩阵来使物体在其局部坐标系中旋转:
W** = W* * Rx(phi)
现在,相机的视图矩阵有点棘手,因为它实际上是一个倒矩阵。所以如果你有一个视图矩阵V
,你必须将逆矩阵乘以左侧:
V* = T(-x, 0, 0) * V
V** = Rx(-phi) * V*
//...
不过,其中一个问题是上向量的固定。如果您围绕局部 y 轴执行旋转,则向上方向可能会发生变化。我们可以计算一个自适应矩阵,这可以避免这种情况,但是从两个角度重新计算整个旋转矩阵可能要容易得多。重新计算矩阵后,必须将其重新定位在旧位置(全局位置,因此向左乘一个平移矩阵)。计算旧位置需要一些数学知识(因为矩阵是倒置的):
pos = -tx * first row - ty * second row - tz * third row
where tx is the entry in the first row, last column
ty is the entry in the second row, last column
tz is the entry in the third row, last column
总结
如果要保持灵活的相机表示,请存储视图矩阵和两个旋转角度。如果要移动相机,只需乘以平移矩阵即可。如果要围绕局部 x 轴旋转相机,请更改角度并乘以旋转矩阵。如果要绕局部y轴旋转,改变角度,重新计算整个矩阵,包括重新定位。
您当前的解决方案基本上是这样做的,因为三角函数结果恰好是矩阵在相关位置的条目。但是正如你所见,维护起来非常麻烦,如果你想允许第三次轮换,你将不得不更改整个代码。
拥抱矩阵数学!