给定方向的OpenGL旋转

3

我在思考一种在OpenGL中定义旋转的简单方法。我理解如何绕任意给定轴线旋转,并且我知道我可以依次绕每个轴线旋转。但这些都没有真正帮助我的问题。

我想要做的是将一个物体旋转,使其看向某个(给定的)方向。因此,我已经知道了一堆旋转的结果...如何直接到达目标呢?

我能否为任何对象定义一个lookAt方向?


2
gluLookAt 对你不起作用吗? - user786653
老实说,我还没有真正考虑过在对象中使用gluLookAt,但我不知道为什么。我的第一次测试显示它可能有效!我只需要仔细考虑如何正确定义向上的矢量...... 非常感谢! - Donny
2个回答

8
您不必使用glRotate来实现此功能。您已经发现了您所知道的东西,即目标方向。但是目标方向并不是一切,您仍然可以围绕目标轴旋转对象,因此您需要一个Up向量。
这是对象的本地Z轴(或任何其他您可能指定为“前向”的矩阵)。您可以将该向量归一化并将其放入对象变换矩阵的Z列中。
Up向量必须垂直于目标轴。您可以有一个Up向量,或者您可以从假设中推导出一个Up向量,即对象的Up向量至少应该向上,即具有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

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

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

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

你好,我认为将两个答案结合起来是个好主意。我开始研究gluLookAt向量,并使用你的公式。 但我发现U = normalize((T*Y)Y),但为什么要使用t-(ty)*y呢? 但无论如何,如果目标沿着y坐标轴指向(在世界坐标系中向上),这种方法会导致未定义的行为,因为新的向上向量是(0,0,0)。 我该如何避免这种情况? - Donny
正常的转换矩阵中的基向量必须彼此垂直,即正交。U = norm((T·Y) Y) 不会给你一个垂直的向量,而只是在它上面投影了T长度的Y缩放。绝对不是你想要的。你需要将T与Y正交化。是的,如果T与Y平行,这将导致奇异性。也就是说,因为两个向量是平行的(或者不是线性独立的),所以没有办法使它们正交。正交化的思想是消除你想要垂直的向量的任何线性部分。 - datenwolf

1

我终于成功解决了我的问题,而且它运行得非常好。感谢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

1
你觉得修改你现有的答案怎么样,而不是用自己的答案淹没你自己的问题。通常来说,一个来自问题提出者的答案就够了,但两个?我希望你至少给 datenwolf 的答案点了赞。 - Christian Rau
感谢您发布答案。这段代码非常有帮助。 - Kada B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接