如何让C++ OpenGL相机看起来左右?

wyyhbhjk  于 2023-02-20  发布在  其他
关注(0)|答案(1)|浏览(130)

在这个项目中,我做了一个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度是不可能的。而且,当我按向左按钮左转时,转弯越来越慢。

kmynzznz

kmynzznz1#

你需要建立一个变换矩阵。变换通常是平移、缩放和旋转的组合。
首先旋转,然后缩放,最后平移(实际计算顺序-乘法-相反):

translation x scale x rotation

如果要围绕某个点(轴或中心)缩放或旋转,则必须平移到中心点,并在最后平移回原点,如下所示:

translation x center x scale x rotation x -center

lookAt算法根据参数(eye,target,up)设置旋转平移,而您的目标是将旋转与平移分开。因此,您必须构建自己的转换,例如:

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

构建一个摄像系统,需要一些线性代数的理论背景知识。
根据下面的评论部分,我在这里列出了所有相关的链接:

最重要的是,它可以压倒那些谁从来没有访问过线性代数课程,因此我强烈推荐The Essence of linear algebra3Blue1Brown
关于矩阵乘法的一个说明,什么是不充分强调和大多数忽略:一旦你已经内化了点积的几何意义,以及矩阵的行和列的几何意义,你还应该注意到,所得到的矩阵的每个分量都是行向量和列向量的点积的结果,将其可视化并内化。

相关问题