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