【问题标题】:Cannot move view matrix and direction view matrix is pointing in simultaneously无法移动视图矩阵和方向视图矩阵同时指向
【发布时间】:2020-12-04 18:47:26
【问题描述】:

当我在场景中移动时(不移动我的“头”,这是我的视图矩阵所指向的位置),一切正常。当我一动不动地环顾四周时,一切正常。但是当我将两者结合起来时,我的头脑(视图矩阵)开始变得疯狂。我假设问题出在我的数学/逻辑上,但我就是想不通。

这是我的代码(当然是简化的):

#define MOVE_DISTANCE 0.15f
#define LOOK_SENSITIVITY 0.01f

static GLFWwindow* window;

static glm::mat4 viewMatrix;
static glm::vec3 look_at;


static void mouseCallback(GLFWwindow* window, double x, double y){
  static double prev_x = 0;
  static double prev_y = 0;
  static float pitch = 0, yaw = 0;

  pitch += (y-prev_y) * LOOK_SENSITIVITY;
  yaw += (x-prev_x) * LOOK_SENSITIVITY;

  if(pitch > 89){
    pitch = 89;
  }
    if(pitch < -89){
      pitch = -89;
  }

  look_at = glm::vec3(cos(yaw)*cos(pitch), sin(pitch), sin(yaw)*cos(pitch) - 1.0f);

  prev_x = x;
  prev_y = y;
}

int main(){
  window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL); //I left the rest of the initialization out

  glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  glfwSetCursorPosCallback(window, mouseCallback);

  look_at = glm::vec3(0.0f, 0.0f, -1.0f);
  glm::vec3 position(0.0f, 0.0f, 0.0f);

  glm::mat4 projectionMatrix = glm::perspective(45.0f, (float) 800/600, 0.1f, 100.0f); //fov, screen aspect ratio, near render distance, far render distance (z axis)
  glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));
  viewMatrix = glm::lookAt(position, look_at, glm::vec3(0, 1, 0));


  while(!glfwWindowShouldClose(window)){
    if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
      position.z -= MOVE_DISTANCE;
      look_at.z -= MOVE_DISTANCE;
    }
    if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
      position.z += MOVE_DISTANCE;
      look_at.z += MOVE_DISTANCE;
    }
    if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){
      position.x += MOVE_DISTANCE;
      look_at.x += MOVE_DISTANCE;
    }
    if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
      position.x -= MOVE_DISTANCE;
      look_at.x -= MOVE_DISTANCE;
    }
    if(glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS){ //FLy up
      position.y += MOVE_DISTANCE;
      look_at.y += MOVE_DISTANCE;
    }
    if(glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS){ //Fly down
      position.y -= MOVE_DISTANCE;
      look_at.y -= MOVE_DISTANCE;
    }

    viewMatrix = glm::lookAt(position, look_at+position, glm::vec3(0, 1, 0));

    glClear(GL_COLOR_BUFFER_BIT);

    glDrawElements(GL_TRIANGLES, NUM_OF_INDICES, GL_UNSIGNED_BYTE, 0);

    glfwSwapBuffers(window);
    glfwPollEvents();
  }
}

每当我在移动鼠标的同时四处移动时,事情就会失控,我的头(我的视图矩阵指向的方向)开始四处晃动。我知道运动不受我所观察的方向的影响。我计划在未来的某个时候实施。

有人可以帮我解决我的错误吗?

【问题讨论】:

  • 你需要一个“前向”向量来添加到position,它指向你想要看的方向。或者,由于您正在更新 look_at,因此不要将其添加到 position。只需单独使用look_at

标签: c++ math opengl glfw glm-math


【解决方案1】:

您的问题是,无论您在哪里看,按下W 都会总是从您的世界空间position.z 坐标中减去MOVE_DISTANCE,即使“向前”或“向后”移动也是如此" 不一定意味着“沿着世界的 Z 轴移动”。

因此,您必须确定“向前”(为了向前和向后移动)以及“向右”(或“向左”)和“向上”或“向下”的轴。当您希望 SPACE 和 CTRL 始终沿世界的 Y 轴上下移动时,后者可能不是必需的。

对于其他两个轴,当您有任意视图矩阵m(例如通过glm::lookAt 构建的矩阵)时,您可以轻松地从中提取rightupforward 向量,就像这样:

#include <glm/gtc/matrix_access.hpp>
...
glm::vec4 right(glm::row(m, 0));
glm::vec4 up(glm::row(m, 1));
glm::vec4 forward(-glm::row(m, 2));

就像上面评论中的@3Dave 所说,您已经知道“前向”在哪里,因为您正在自己操作该向量并从中计算外观转换,因此您可以省略它。

现在,当您想向左/向右移动时,您可以将 right 减去/添加到您的世界空间 position,其他轴也是如此。

另一件不正确的事情是,当您使用键盘键移动时,您还会从look_at 方向 中添加/减去。这是错误的,因为您的look_at 向量是一个方向,并且您在计算glm::lookAt 调用的参数时已经将它用作方向向量。

将所有这些合并到您的代码中(以及一些轻微的重构),将导致以下 while 循环:

while (!glfwWindowShouldClose(window)) {
  glm::vec3 right(glm::row(viewMatrix, 0)),
            up(glm::row(viewMatrix, 1)),
            forward(-glm::row(viewMatrix, 2));
  glm::vec3 v(0, 0, 0);
  if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
    v += forward;
  if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
    v -= forward;
  if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
    v += right;
  if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
    v -= right;
  position += v * MOVE_DISTANCE;
  viewMatrix = glm::lookAt(position, position + look_at, glm::vec3(0, 1, 0));
}

【讨论】:

  • 那么您能否修复我提供的代码并将其包含在答案中,以帮助我更好地理解您的意思?
  • 我已经编辑了我的帖子。我省略了上/下,因为我不清楚你是真的想上/下移动世界空间还是上/下移动相机空间。
  • 编译时出现以下错误:error: 'row' is not a member of 'glm';你的意思是“战俘”吗?
  • 请真正阅读我的答案...我什至提供了您需要的包含...
  • 抱歉,我包含了 matrix_transform,而不是 matrix_access
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
相关资源
最近更新 更多