简体   繁体   English

无法移动视图矩阵和方向视图矩阵同时指向

[英]Cannot move view matrix and direction view matrix is pointing in simultaneously

When I move around the scene (without moving my 'head', which is where my view matrix is pointing) everything works just fine.当我在场景中移动时(不移动我的“头”,这是我的视图矩阵指向的地方),一切正常。 When I look around without moving, everything works just fine.当我一动不动地环顾四周时,一切正常。 But it is when I combine the two that my head (view matrix) starts going wild.但是当我将两者结合起来时,我的头脑(视图矩阵)开始变得疯狂。 I'm assuming the issue is in my math/logic, but I just cannot figure it out.我假设问题出在我的数学/逻辑中,但我无法弄清楚。

Here is my code (simplified, of course):这是我的代码(当然是简化的):

#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();
  }
}

Whenever I move around while moving the mouse, things get out of hand and my head (the direction my view matrix is pointing in) starts flicking around.每当我在移动鼠标的同时四处移动时,事情就会失控,我的头(我的视图矩阵指向的方向)开始四处晃动。 I am aware that the movement isn't impacted by the direction I am looking in. I plan on implementing this sometime in the future.我知道这项运动不受我所关注的方向的影响。我计划在未来的某个时候实施。

Could someone help me put my finger on my error?有人可以帮我解决我的错误吗?

Your problem is that regardless of where you look at, pressing W will always subtract MOVE_DISTANCE from your world-space position.z coordinate, even though moving "forward" or "backward" would not necessarily mean "moving along the world's Z axis".您的问题是,无论您在哪里看,按W总是会从您的世界空间position.z坐标中减去MOVE_DISTANCE ,即使“向前”或“向后”移动不一定意味着“沿着世界的 Z 轴移动”。

So, you must determine the axes of "forward" (in order to move forward and backward) as well as "right" (or "left") and "up" or "down".因此,您必须确定“向前”(为了向前和向后移动)以及“向右”(或“向左”)和“向上”或“向下”的轴。 The latter might not be necessary when you want SPACE and CTRL to always move up/down along the world's Y axis.当您希望 SPACE 和 CTRL 始终沿世界的 Y 轴向上/向下移动时,后者可能不是必需的。

For the other two axes, when you have any arbitrary view matrix m (such as your matrix built via glm::lookAt ) then you can easily extract the right , up and forward vectors from it, like so:对于其他两个轴,当您有任意视图矩阵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));

Like @3Dave said above in the comment, you already know where "forward" is, because you are manipulating that vector yourself and computing the lookat transformation from it, so you could omit that.就像上面评论中的@3Dave 一样,您已经知道“前向”在哪里,因为您正在自己操作该向量并从中计算外观转换,因此您可以省略它。

Now, when you want to move left/right you subtract/add right to your world-space position and likewise for the other axes.现在,当您想向左/向右移动时,您在世界空间position中减去/ right移动,其他轴也是如此。

Another thing that is incorrect is that you also add to / subtract from your look_at direction when moving with the keyboard keys.另一件不正确的事情是,当您使用键盘键移动时,您还会从look_at方向添加/减去。 This is wrong, because your look_at vector is a direction and you already use it as a direction vector when you compute the arguments for the glm::lookAt call.这是错误的,因为您的look_at向量是一个方向,并且在为glm::lookAt调用计算 arguments 时已经将其用作方向向量。

Incorporating all of this into your code (together with some slight refactorings), will lead to following while-loop:将所有这些合并到您的代码中(以及一些轻微的重构),将导致以下 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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM