LookAt (glm) 返回错误的平移 z 值

Posted

技术标签:

【中文标题】LookAt (glm) 返回错误的平移 z 值【英文标题】:LookAt (glm) returns wrong translate z-value 【发布时间】:2016-10-09 12:52:04 【问题描述】:

您好,我对 glm lookAt 函数的返回值有疑问。当我在调试模式下执行时,我得到了这一点 glm 函数的 ... Result[3][2] = dot(f, eye); ... 在矩阵的平移 z 位置中的值错误。该值为-2,这表明前向和眼睛矢量处于相反的位置。我的 eye、center 和 up 向量是 eye(0,0,2)、center(0,0,-1) 和 up(0,1,0)。凸轮坐标向量为:f(0,0,-1)、s(1,0,0) 和 u(0,1,0)。用户观看的有利位置是(0,0,0)。所以右视图矩阵应该是这个:

1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1

但我得到了这个:

1  -0  0   -0 -0  1 -0   -0 0   0   1  -2 0   0   0   1

我的代码是:

struct camera 
vec3 position = vec3(0.0f);         // position of the camera
vec3 view_direction = vec3(0.0f);   // forward vector (orientation)
vec3 side = vec3(0.0f);             // right vector (side)
vec3 up = vec3(0.0f, 1.0f, 0.0f);   // up vector
float speed = 0.1;
float yaw = 0.0f;                   // y-rotation
float cam_yaw_speed = 10.0f;        // 10 degrees per second
float pitch = 0.0f;                 // x-rotation
float roll = 0.0f;      

...
// calculate the orientation vector (forward) 
vec3 getOrientation(vec3 vantage_point) 
    // calc the difference and normalize the resulting vector
    vec3 result = vantage_point - position;
    result = normalize(result);
    return result;


// calculate the right (side) vector of the camera, by given orientation(forward) and up vectors
mat4 look_at_point(vec3 vantage_point) 
    view_direction = getOrientation(vantage_point);

    // calculate the lookat matrix
    return lookAt(position, position + view_direction, up);

;

我试图弄清楚如何解决这个问题,但我仍然不知道。有人可以帮我吗?

我正在执行 main_cam.look_at_point(vantage_point) 函数的主要函数如下所示:

...
GLfloat points[] = 
0.0f, 0.5f, 0.0f,
0.5f,  0.0f, 0.0f,
-0.5f, 0.0f, 0.0f ;

float speed = 1.0f; // move at 1 unit per second

float last_position = 0.0f;

// init camera
main_cam.position = vec3(0.0f, 0.0f, 2.0f);         // don't start at zero, or will be too close
main_cam.speed = 1.0f;                              // 1 unit per second
main_cam.cam_yaw_speed = 10.0f;                     // 10 degrees per second
vec3 vantage_point = vec3(0.0f, 0.0f, 0.0f);

mat4 T = translate(mat4(1.0), main_cam.position);
//mat4 R = rotate(mat4(), -main_cam.yaw, vec3(0.0, 1.0, 0.0));
mat4 R = main_cam.look_at_point(vantage_point);
mat4 view_matrix = R * T;

// input variables
float near = 0.1f;      // clipping plane
float far = 100.0f;     // clipping plane
float fov = 67.0f * ONE_DEG_IN_RAD; // convert 67 degrees to radians
float aspect = (float)g_gl_width / (float)g_gl_height;  // aspect ratio

mat4 proj_matrix = perspective(fov, aspect, near, far);

use_shader_program(shader_program);
set_uniform_matrix4fv(shader_program, "view", 1, GL_FALSE, &view_matrix[0][0]);
set_uniform_matrix4fv(shader_program, "proj", 1, GL_FALSE, &proj_matrix[0][0]);
...

用glm的旋转功能测试三角形如右图。

Triangle shown with the rotate function of glm

【问题讨论】:

如果您的相机位于eye=(0,0,2),那么第二个矩阵是正确的,而不是第一个。为什么你不这么认为?L 你是对的,但为什么我的三角形没有显示。看起来相机朝相反的方向看,但为什么呢? 什么三角形?请提供Minimal, Complete, and Verifiable example。我们看不到您的绘图代码。您可以通过将position + view_direction 替换为position - view_direction 来验证您的假设。如果它不起作用(也不应该),那么问题一定出在其他地方。 对不起,我已经提供了上面的代码示例 可能还有其他事情发生。启用剔除?绕线顺序正确吗?我们也不知道 shader_program 在做什么。 【参考方案1】:

我怀疑问题出在这里:

mat4 view_matrix = R * T; // <---

lookAt 返回的矩阵已经进行了转换。

尝试在三角形内的 (0,0,0) 点上手动应用变换。 T 会将其转换为 (0,0,2),但现在它与相机重合,因此 R 会将其发送回 (0,0,0)。现在你在射影除法中得到了零事故除法。

所以去掉乘以T

mat4 view_matrix = R;

现在 (0,0,0) 将被映射到 (0,0,-2),即相机正在查看的方向。 (在相机空间中,投影中心位于 (0,0,0) 并且相机朝向负 Z 方向)。


编辑:我想指出,从vantage_point 计算view_direction,然后将position + view_direction 反馈到lookAt 是实现目标的一种相当人为的方式。你在 getOrientation 函数中所做的就是 lookAt 在里面所做的。相反,您可以从lookAt 的结果中获取view_direction

mat4 look_at_point(vec3 vantage_point) 
    // calculate the lookat matrix
    mat4 M = lookAt(position, vantage_point, up);
    view_direction = -vec3(M[2][0], M[2][1], M[2][2]);
    return M;

但是,考虑到您最终要尝试实现偏航/俯仰/滚动相机控制,您是better off to not using lookAt at all。

【讨论】:

你是对的,解决了问题,非常感谢:)。

以上是关于LookAt (glm) 返回错误的平移 z 值的主要内容,如果未能解决你的问题,请参考以下文章

当 z <= 0 时 glm::lookAt 垂直相机翻转

相机 旋转

相机 旋转

相机 旋转

相机 旋转

glm::quatLookAt 返回一个 NaN 四元数