在这个项目中,我做了一个3D立方体,加了一个摄像头,我们可以用W,A,S,D键前进,后退,向左或向右,但我们不能向左或向右转,比如我想看立方体的背面,但我看不到它,其实这是一个简单的问题,它的解决方法很简单,但我的数学水平不足,如果有人给我解释一下会更好。我会告诉你我的代码和我已经尝试了下面。
#include <Windows.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <GLFW/glfw3.h>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <math.h>
int width = 1280;
int height = 720;
float camera_z = 5;
float camera_y = 0;
float camera_x = 0;
float fov = 60;
GLFWwindow* window;
float speed = 0.01;
GLfloat vertices[] = {
-1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1,
1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1,
-1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1,
-1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1,
-1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
-1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1
};
GLfloat colors[] = {
1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0,
1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0,
1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0,
1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0,
1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0,
1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0
};
void keyboard() {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
camera_z = camera_z - speed;
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
camera_x = camera_x - speed;
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
camera_z = camera_z + speed;
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
camera_x = camera_x + speed;
}
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
camera_y = camera_y + speed;
}
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) {
camera_y = camera_y - speed;
}
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
// need help
}
if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
// need help
}
}
void drawCube() {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);
glDrawArrays(GL_QUADS, 0, 24);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
int main(void)
{
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(width, height, "C++ OpenGL ", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glEnable(GL_DEPTH_TEST);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
glViewport(0, 0, width, height);
/* Render here */
glClearColor(0.0, 192/256, 1, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float aspect = (float)width / (float)height;
float fov = 60;
gluPerspective(fov, aspect, 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
keyboard();
gluLookAt(
camera_x,
camera_y,
camera_z,
camera_x + 1, // need help
camera_y + 1, // need help
camera_z - fov ,
0,
1,
0
);
glTranslatef(0, 0,-3);
drawCube();
glFlush();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
我尝试的东西是变量camera_eyex,_eyey,_eyez。我把它们加到循环中,给予camera + 1的值。我以前想向左或向右走的时候会增加或减少它们,但是这个方法有很多错误。比如,当我按W键的时候,即使相机旋转了45度,它也会直线前进,所以它不会走到我看的地方。还有,向右或向左转超过90度是不可能的。而且,当我按向左按钮左转时,转弯越来越慢。
1条答案
按热度按时间kmynzznz1#
你需要建立一个变换矩阵。变换通常是平移、缩放和旋转的组合。
首先旋转,然后缩放,最后平移(实际计算顺序-乘法-相反):
如果要围绕某个点(轴或中心)缩放或旋转,则必须平移到中心点,并在最后平移回原点,如下所示:
lookAt
算法根据参数(eye,target,up)设置旋转和平移,而您的目标是将旋转与平移分开。因此,您必须构建自己的转换,例如:您可以在这里找到更多信息(OpenGl相关,虽然'现代' OpenGl):https://learnopengl.com/Getting-started/Transformations
注:您可能需要调整输入“W A S D”以适应更改的轴。例如,如果“W”键调整z分量,则您可能无法“前进”(沿着z轴)。为了根据变换后的轴移动,您需要变换矩阵并提取它们。最好使用数学库,例如glm。如何实现轨道相机,请再次查看:https://learnopengl.com/Getting-started/Camera
构建一个摄像系统,需要一些线性代数的理论背景知识。
根据下面的评论部分,我在这里列出了所有相关的链接:
最重要的是,它可以压倒那些谁从来没有访问过线性代数课程,因此我强烈推荐The Essence of linear algebra由3Blue1Brown。
关于矩阵乘法的一个说明,什么是不充分强调和大多数忽略:一旦你已经内化了点积的几何意义,以及矩阵的行和列的几何意义,你还应该注意到,所得到的矩阵的每个分量都是行向量和列向量的点积的结果,将其可视化并内化。