在这个项目中,我制作了一个 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。我将它们添加到循环中以赋予相机 + 1 值。我以前想左转右转的时候就增减,但是这个方法有很多错误。例如,即使在我按下 W 键时相机旋转了 45 度,它也会直线移动,所以它不会转到我正在看的地方。此外,向右或向左转弯超过 90 度是不可能的。另外,当我按左键向左转时,转弯越来越慢
你需要建立一个变换矩阵。变换通常是平移、缩放和旋转的组合。
首先旋转,然后缩放然后平移(实际计算顺序 - 乘法 - 是相反的):
translation x scale x rotation
如果你想围绕某个点(枢轴或中心)缩放或旋转,那么你必须平移到中心点,最后平移回原点,如:
translation x center x scale x rotation x -center
lookAt
算法根据参数(眼睛、目标、向上)设置旋转和平移,而您的目标是将旋转与平移分开。因此,您必须构建自己的转换,例如:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//set the position of the camera
glTranslate(pos);
//set the scale or rotation pivot
//glTranslate(center);
//scale
//glScale(scale);
//rotate around z-axis first
glRotate(z_angle, 0, 0, 1);
//rotate around y-axis
glRotate(y_angle, 0, 1, 0);
//rotate around x-axis
glRotate(x_angle, 1, 0, 0);
//set the center back, if set before
//glTranslate(-center);
您会在这里找到更多信息(与 OpenGl 相关,尽管是“现代”OpenGl):https://learnopengl.com/Getting-started/Transformations
注意:您可能必须将输入“W A S D”调整到更改的轴。例如,如果“W”键调整 z 分量,您可能不会使用上面的设置“向前”(沿 z 轴)。为了根据变换后的轴移动,您需要变换矩阵并提取它们。更好的是使用数学库,例如glm。轨道相机如何实现,再次看看:https://learnopengl.com/Getting-started/Camera