C++ 无法移动视图矩阵,且方向视图矩阵同时指向

C++ 无法移动视图矩阵,且方向视图矩阵同时指向,c++,math,opengl,glfw,glm-math,C++,Math,Opengl,Glfw,Glm Math,当我在场景中移动时(没有移动我的“头”,也就是我的视图矩阵指向的地方),一切都正常。当我环顾四周不动时,一切都很好。但当我将两者结合起来时,我的头(视图矩阵)开始发狂。我假设这个问题在我的数学/逻辑中,但我就是想不出来 这是我的代码(当然是简化的): #定义移动距离0.15f #定义外观灵敏度0.01f 静态GLFWwindow*窗口; 静态glm::mat4 viewMatrix; 静态glm::vec3查看; 静态无效鼠标回调(GLFWwindow*窗口,双x,双y){ 静态双前向x=0;

当我在场景中移动时(没有移动我的“头”,也就是我的视图矩阵指向的地方),一切都正常。当我环顾四周不动时,一切都很好。但当我将两者结合起来时,我的头(视图矩阵)开始发狂。我假设这个问题在我的数学/逻辑中,但我就是想不出来

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

#定义移动距离0.15f
#定义外观灵敏度0.01f
静态GLFWwindow*窗口;
静态glm::mat4 viewMatrix;
静态glm::vec3查看;
静态无效鼠标回调(GLFWwindow*窗口,双x,双y){
静态双前向x=0;
静态双前向y=0;
静态浮动节距=0,偏航=0;
音高+=(y-上一个y)*外观灵敏度;
偏航+=(x-prev_x)*外观灵敏度;
如果(节距>89){
螺距=89;
}
如果(节距<-89){
音高=-89;
}
注视=glm::vec3(cos(偏航)*cos(俯仰)、sin(俯仰)、sin(偏航)*cos(俯仰)-1.0f);
prev_x=x;
上一个y=y;
}
int main(){
window=glfwCreateWindow(800600,“OpenGL”,NULL,NULL);//我忽略了其余的初始化
glfwSetInputMode(窗口、GLFW_光标、GLFW_光标禁用);
glfwSetCursorPosCallback(窗口、鼠标回拨);
注视=glm::vec3(0.0f,0.0f,-1.0f);
glm::vec3位置(0.0f、0.0f、0.0f);
glm::mat4 projectionMatrix=glm::perspective(45.0f,(浮点)800/600,0.1f,100.0f);//视野,屏幕纵横比,近渲染距离,远渲染距离(z轴)
glm::mat4 modelMatrix=glm::translate(glm::mat4(1.0f),glm::vec3(0.0f,0.0f,-5.0f));
viewMatrix=glm::lookAt(位置,注视,glm::vec3(0,1,0));
而(!glfwWindowShouldClose(窗口)){
如果(glfwGetKey(窗口,GLFW_键=GLFW_按){
位置z-=移动距离;
注视.z-=移动距离;
}
如果(glfwGetKey(窗口,GLFW_键)==GLFW_按){
位置z+=移动距离;
注视.z+=移动距离;
}
如果(glfwGetKey(窗口,GLFW_键D)==GLFW_按){
位置x+=移动距离;
注视.x+=移动距离;
}
如果(glfwGetKey(窗口,GLFW_键A)==GLFW_按){
位置x-=移动距离;
注视.x-=移动距离;
}
如果(glfwGetKey(窗口,GLFW_键空间)==GLFW_按){//向上飞
位置y+=移动距离;
看.y+=移动距离;
}
如果(glfwGetKey(窗口,GLFW_键_左控制)==GLFW_按){//向下飞
位置y-=移动距离;
看.y-=移动距离;
}
viewMatrix=glm::lookAt(位置,lookAt+position,glm::vec3(0,1,0));
glClear(GLU颜色缓冲位);
gld元素(GL_三角形,索引数,GL_无符号字节,0);
glfwSwapBuffers(窗口);
glfwPollEvents();
}
}
每当我在移动鼠标的同时四处移动时,事情就会失控,我的头(我的视图矩阵所指向的方向)开始来回摆动。我知道运动不受我观察方向的影响。我计划在将来的某个时候实施这一计划


有人能帮我指出我的错误吗?

你的问题是,无论你看哪里,按
W
总是会从你的世界空间
position.z
坐标中减去
MOVE\u DISTANCE
,即使“向前”或“向后”并不一定意味着“沿着世界的z轴移动”

因此,您必须确定“前进”(以便向前和向后移动)以及“右”(或“左”)和“上”或“下”轴。如果希望空间和CTRL始终沿世界的Y轴上下移动,则可能不需要使用后者

对于其他两个轴,当您拥有任意视图矩阵
m
(例如通过
glm::lookAt
构建的矩阵)时,您可以轻松地从中提取
向上
向前
向量,如下所示:

#包括
...
glm::vec4 right(glm::row(m,0));
glm::vec4 up(glm::row(m,1));
glm::vec4向前(-glm::row(m,2));
正如上面评论中所说的@3Dave,您已经知道“forward”在哪里了,因为您自己正在处理该向量,并从中计算lookat转换,所以您可以忽略它

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

另一件不正确的事情是,当你用键盘键移动时,你的
注视方向也会增加/减少。这是错误的,因为您的
look_at
向量是一个方向,并且在计算
glm::lookAt
调用的参数时,您已经将其用作方向向量

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

while(!glfwWindowShouldClose(窗口)){
glm::vec3 right(glm::row(viewMatrix,0)),
向上(glm::行(viewMatrix,1)),
正向(-glm::row(viewMatrix,2));
glm:vec3v(0,0,0);
如果(glfwGetKey(窗口,GLFW_键=GLFW_按)
v+=正向;
如果(glfwGetKey(窗口,GLFW_键)==GLFW_按)
v-=正向;
如果(glfwGetKey(窗口,GLFW_键D)==GLFW_按)
v+=右;
如果(glfwGetKey(窗口,GLFW_键A)==GLFW_按)
v-=右;
位置+=v*移动距离;
viewMatrix=glm::lookAt(位置,位置+注视,glm::vec3(0,1,0));
}

您需要一个“向前”向量来添加到
位置
,它指向您想要查看的方向。或者,因为您正在更新
查看
,所以不要将其添加到
位置
。只需使用
look__in
。那么,你能修复我提供的代码并将其包含在答案中,以帮助我更好地理解你的意思吗?我已经编辑了我的帖子。我省略了“向上/向下”,因为我不清楚您是否真的要向上/向下移动世界空间或摄影机sp
#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();
  }
}