OpenGL在给定方向上的旋转

Posted

技术标签:

【中文标题】OpenGL在给定方向上的旋转【英文标题】:OpenGL rotation in given direction 【发布时间】:2011-08-09 07:07:21 【问题描述】:

我正在考虑一种在 opengl 中定义旋转的简单方法。 我了解围绕任何给定轴的旋转是如何工作的。我也知道我可以依次围绕每个轴旋转。但这一切并没有真正帮助我解决问题。 我想要做的是旋转一个对象,使其看起来在某个(给定)方向。因此,我已经知道一堆旋转的结果.... 我怎样才能直接到达那里? 我可以以某种方式为任何对象定义一个lookAt方向吗?

【问题讨论】:

gluLookAt 不适合你? 老实说,我还没有真正考虑过将 gluLookAt 用于对象,但我不明白为什么。我的第一个测试刚刚表明,它可能有效!我只需要考虑正确定义向上向量......非常感谢! 【参考方案1】:

您不必为此使用 glRotate。你已经发现你知道一些东西,目标方向。但是目标方向并不是一切,您仍然可以围绕目标轴旋转对象,因此您也需要一个向上向量。

这是对象的局部 Z 轴(或您可以指定为“前向”的任何其他矩阵)。您可以对该向量进行归一化并将其放入对象变换矩阵的 Z 列中。

向上向量必须垂直于目标轴。要么你有一个,要么你从假设中推导出一个,即对象的向上向量应该至少向上,即有一个 Y 分量。您可以通过将向量与目标轴的标量乘积并从目标轴中减去目标轴向量按标量乘积进行缩放,然后进行归一化,可以得到一个指向上方并垂直于目标轴的向量。比方说,Y 起来了:

U = normalize( T - T · Y )

最后你需要第三个局部轴 L。你可以通过 U 和 T 的叉积得到这个,即

L = U × T

根据这些你构建一个矩阵

Lx  Ux  Tx  0
Ly  Uy  Ty  0
Lz  Uz  Tz  0
 0   0   0  1

并使用 glMultMatrix(固定函数)将其传递给 OpenGL,或者将其乘以您自己的托管堆栈并提供 glUniformMatrix(着色器)。

请注意,glMultMatrix 按以下顺序索引矩阵元素

0 4 8 c
1 5 9 d
2 6 a e
3 7 b f

【讨论】:

您好,我认为将我得到的两个答案结合起来是个好主意。我开始研究 gluLookAt 向量,并使用您的公式。但我发现 U = normalize((TY)*Y) 但你为什么要使用 t-(ty)*y?但无论如何,如果目标沿着 y 坐标(在世界坐标中向上)指向,因为新的向上向量是 (0,0,0),那么这种方法会导致未定义的行为。我怎样才能防止这种情况发生? 正则变换矩阵中的基向量必须相互垂直,即正交。 U = norm((T·Y) Y) 不会给你一个垂直向量,而只是 Y 缩放到投影在它上面的 T 的长度。绝对不是你想要的。您需要将 T 与 Y 正交化。是的,您是对的,如果 T 平行于 Y,这将导致奇点。也就是说,因为两个向量是平行的(或不是线性独立的),所以没有办法将其正交化。正交化的想法是删除要垂直的向量的任何线性部分。【参考方案2】:

我终于能够解决我的问题,它实际上运行良好。谢谢datenwolf!

//direction is the direction you want the object to point at
//up- first guess
Vector3f up;
if(abs(direction.x)< 0.00001 && abs(direction.z) < 0.00001) //If x and z are really small
if(direction.y > 0)
    up = Vector(0.0, 0.0, -1.0); //if direction points in +y direction
else
    up = Vector(0.0, 0.0, 1.0); //if direction points in -y direction
 else 
    up = Vector(0.0, 1.0, 0.0); //y-axis is the general up direction


//left
Vector left = cross(direction,up);
left.normalize();

//final up
up= cross(left,direction);
up.normalize();

float matrix[]=left.x, left.y, left.z, 0.0f,     //LEFT
up.x, up.y, up.y, 0.0f,                       //UP 
direction.x, direction.y, direction.z, 0.0f,  //FORWARD
position.x, position.y, position.z, 1.0f;    //TRANSLATION TO WHERE THE OBJECT SHOULD BE PLACED
glMultMatrixf(matrix);
//DRAW OBJECT
//KEEP IN MIND the z-axis of your object points now in direction direction

【讨论】:

如何编辑你现有的答案,而不是用你自己的答案蜂拥而至你自己的问题。通常来自 OP 的一个答案太多了,但是两个呢?我希望你至少支持 datenwolf 的回答。

以上是关于OpenGL在给定方向上的旋转的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL:沿该方向旋转和移动

OpenGL 方向。 (从负 z 看的身份旋转)

Opengl es Android 3D 手指触控旋转object

使用 OpenGL 4 的旋转矩阵

四元数旋转opengl

OpenGL相机的相对旋转