无法移动视图矩阵和方向视图矩阵同时指向
Cannot move view matrix and direction view matrix is pointing in simultaneously
当我在场景中四处移动时(不移动我的 'head',这是我的视图矩阵指向的位置),一切正常。当我一动不动地环顾四周时,一切正常。但是当我将两者结合起来时,我的头脑(视图矩阵)开始变得疯狂。我假设问题出在我的 math/logic 上,但我就是想不通。
这是我的代码(当然是经过简化的):
#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();
}
}
每当我在移动鼠标的同时四处移动时,事情就会失控,我的头(我的视图矩阵指向的方向)开始四处晃动。我知道运动不受我所观察的方向的影响。我计划在未来的某个时候实现这一点。
有人可以帮我指出我的错误吗?
你的问题是无论你往哪里看,按W
都会总是从你的世界中减去MOVE_DISTANCE
-spaceposition.z
坐标,即使“向前”或“向后”移动并不一定意味着“沿着世界的 Z 轴移动”。
因此,您必须确定“前”(以便向前和向后移动)以及“右”(或“左”)和“上”或“下”的轴。当您希望 SPACE 和 CTRL 始终沿世界 Y 轴移动 up/down 时,后者可能不是必需的。
对于其他两个轴,当您有任意视图矩阵m
(例如通过glm::lookAt
构建的矩阵)时,您可以轻松提取right
、up
和 forward
向量,像这样:
#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 在上面的评论中所说的那样,您已经知道“forward”在哪里,因为您正在自己操纵该向量并从中计算 lookat 转换,所以您可以省略它。
现在,当你想移动 left/right 时,你 subtract/add right
到你的世界 - space position
其他轴也是如此。
另一件不正确的事情是,在使用键盘键移动时,您还从 look_at
direction 中添加/减去。这是错误的,因为你的 look_at
向量是 direction 并且你在计算 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));
}
当我在场景中四处移动时(不移动我的 'head',这是我的视图矩阵指向的位置),一切正常。当我一动不动地环顾四周时,一切正常。但是当我将两者结合起来时,我的头脑(视图矩阵)开始变得疯狂。我假设问题出在我的 math/logic 上,但我就是想不通。
这是我的代码(当然是经过简化的):
#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();
}
}
每当我在移动鼠标的同时四处移动时,事情就会失控,我的头(我的视图矩阵指向的方向)开始四处晃动。我知道运动不受我所观察的方向的影响。我计划在未来的某个时候实现这一点。
有人可以帮我指出我的错误吗?
你的问题是无论你往哪里看,按W
都会总是从你的世界中减去MOVE_DISTANCE
-spaceposition.z
坐标,即使“向前”或“向后”移动并不一定意味着“沿着世界的 Z 轴移动”。
因此,您必须确定“前”(以便向前和向后移动)以及“右”(或“左”)和“上”或“下”的轴。当您希望 SPACE 和 CTRL 始终沿世界 Y 轴移动 up/down 时,后者可能不是必需的。
对于其他两个轴,当您有任意视图矩阵m
(例如通过glm::lookAt
构建的矩阵)时,您可以轻松提取right
、up
和 forward
向量,像这样:
#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 在上面的评论中所说的那样,您已经知道“forward”在哪里,因为您正在自己操纵该向量并从中计算 lookat 转换,所以您可以省略它。
现在,当你想移动 left/right 时,你 subtract/add right
到你的世界 - space position
其他轴也是如此。
另一件不正确的事情是,在使用键盘键移动时,您还从 look_at
direction 中添加/减去。这是错误的,因为你的 look_at
向量是 direction 并且你在计算 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));
}