创建相机以旋转立方体不起作用

Creating a camera to rotate a cube not working

我创建了一个创建彩色立方体的程序,我尝试在 keyCallback 函数中移动立方体。这没有用,因为我想让它工作,而是移动了立方体。我试图创建一个相机,这是我的完整程序:

#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm.hpp>
#include <gtc\matrix_transform.hpp>
#include <GL/freeglut.h>
#include <GL\GL.h>

void DrawCube(GLfloat centerPosX, GLfloat centerPosY, GLfloat centerPosZ, GLfloat edgeLength);
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
void framebuffer_size_callback(GLFWwindow* wndow, int width, int height);

GLfloat rotateX = 0.0f;
GLfloat rotateY = 0.0f;

GLfloat xPos = 0.0f;
GLfloat yPos = 0.0f;
GLfloat zPos = 0.0f;

int main(void) {
    GLFWwindow* window;

    //Init library
    if (!glfwInit())
        return -1;
    //create a window
    glEnable(GL_DEPTH_TEST);
    window = glfwCreateWindow(840, 420, "electroCaft", NULL, NULL);
    int screenWidth, screenHeight;
    glfwSetKeyCallback(window, keyCallback);
    //get resolution
    glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
    if (!window) {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glViewport(0.0f, 0.0f, screenWidth, screenHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, screenWidth, 0, screenHeight, 0, 1000); // essentially setting coodinates last num sets view point of distance
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glEnable(GL_DEPTH_TEST);
    glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
    glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
    glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);
    glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
    glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
    glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);
    glm::mat4 view;
    view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f),
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(0.0f, 1.0f, 0.0f));
    float radius = 10.0f;
    float camX = sin(glfwGetTime()) * radius;
    float camZ = cos(glfwGetTime()) * radius;
    //glm::mat4 view;
    view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));


    GLfloat halfScreenWidth = screenWidth / 2;
    GLfloat halfScreenHeight = screenHeight / 2;

    GLfloat rotationSpeed = 1.0f;

    //load textures

    //loop until user closes window
    while (!glfwWindowShouldClose(window)) {
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

        //render graphics
        //glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(62.0f / 255.0f, 85.9f / 255.0f, 255.0 / 255.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //drawing here
        //printf("screen width is: %d \n", screenWidth);

        view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(100, 100, 100), glm::vec3(0.0, 1.0, 0.0));

        glPushMatrix();
        glTranslatef((GLfloat)screenWidth / 2.0f, (GLfloat)screenHeight / 2.0f, -500.0f);
        glRotatef(rotateX, 1, 0, 0);
        glRotatef(rotateY, 0, 1, 0);
        //rotateX += 1;
        //rotateY -= 1;

        //DrawCube(halfScreenWidth, halfScreenHeight, -500, 250); //x,y,w,h z is calculated in cube func
        DrawCube(xPos, yPos, zPos, 250);
        //DrawCube(xPos - 50, yPos, zPos, 50);
        //DrawCube(xPos + 50, yPos, zPos, 50);
        //DrawCube(halfScreenWidth, halfScreenHeight - 100, -500, 250);
        glPopMatrix();



        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;

}


void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    const GLfloat rotationSpeed = 10;


    if (action == GLFW_PRESS || action == GLFW_REPEAT)
    {
        switch (key)
        {
        case GLFW_KEY_W:
            zPos += rotationSpeed;
            break;
        case GLFW_KEY_S:
            zPos -= rotationSpeed;
            break;
        case GLFW_KEY_D:
            xPos += rotationSpeed;
            break;
        case GLFW_KEY_A:
            xPos -= rotationSpeed;
            break;
        case GLFW_KEY_SPACE:
            yPos -= rotationSpeed;
            break;

        //rotate the cube
        case GLFW_KEY_UP:
            rotateX -= rotationSpeed;
            break;
        case GLFW_KEY_DOWN:
            rotateX += rotationSpeed;
            break;
        case GLFW_KEY_RIGHT:
            rotateY += rotationSpeed;
            break;
        case GLFW_KEY_LEFT:
            rotateY -= rotationSpeed;
            break;
        }


    }
}

void framebuffer_size_callback(GLFWwindow* wndow, int width, int height)
{
    glViewport(0, 0, width, height);
    //glViewport(xPos, yPos, zPos, width);
}



void DrawCube(GLfloat centerPosX, GLfloat centerPosY, GLfloat centerPosZ, GLfloat edgeLength) {
    GLfloat halfSideLength = edgeLength * 0.5;
    GLfloat vertices[] = {
        // front face
        centerPosX - halfSideLength, centerPosY + halfSideLength, centerPosZ + halfSideLength, //top left
        centerPosX + halfSideLength, centerPosY + halfSideLength, centerPosZ + halfSideLength, //top right
        centerPosX + halfSideLength, centerPosY - halfSideLength, centerPosZ + halfSideLength, //bottom right
        centerPosX - halfSideLength, centerPosY - halfSideLength, centerPosZ + halfSideLength, // bottom left

        // back face
        centerPosX - halfSideLength, centerPosY + halfSideLength, centerPosZ - halfSideLength, //top left
        centerPosX + halfSideLength, centerPosY + halfSideLength, centerPosZ - halfSideLength, //top right
        centerPosX + halfSideLength, centerPosY - halfSideLength, centerPosZ - halfSideLength, //bottom right
        centerPosX - halfSideLength, centerPosY - halfSideLength, centerPosZ - halfSideLength, // bottom left

        // left face
        centerPosX - halfSideLength, centerPosY + halfSideLength, centerPosZ + halfSideLength, //top left
        centerPosX - halfSideLength, centerPosY + halfSideLength, centerPosZ - halfSideLength, //top right
        centerPosX - halfSideLength, centerPosY - halfSideLength, centerPosZ - halfSideLength, //bottom right
        centerPosX - halfSideLength, centerPosY - halfSideLength, centerPosZ + halfSideLength, // bottom left

        // right face
        centerPosX + halfSideLength, centerPosY + halfSideLength, centerPosZ + halfSideLength, //top left
        centerPosX + halfSideLength, centerPosY + halfSideLength, centerPosZ - halfSideLength, //top right
        centerPosX + halfSideLength, centerPosY - halfSideLength, centerPosZ - halfSideLength, //bottom right
        centerPosX + halfSideLength, centerPosY - halfSideLength, centerPosZ + halfSideLength, // bottom left

        // top face
        centerPosX - halfSideLength, centerPosY + halfSideLength, centerPosZ + halfSideLength, //top left
        centerPosX - halfSideLength, centerPosY + halfSideLength, centerPosZ - halfSideLength, //top right
        centerPosX + halfSideLength, centerPosY + halfSideLength, centerPosZ - halfSideLength, //bottom right
        centerPosX + halfSideLength, centerPosY + halfSideLength, centerPosZ + halfSideLength, // bottom left

        // bottom face
        centerPosX - halfSideLength, centerPosY - halfSideLength, centerPosZ + halfSideLength, //top left
        centerPosX - halfSideLength, centerPosY - halfSideLength, centerPosZ - halfSideLength, //top right
        centerPosX + halfSideLength, centerPosY - halfSideLength, centerPosZ - halfSideLength, //bottom right
        centerPosX + halfSideLength, centerPosY - halfSideLength, centerPosZ + halfSideLength // bottom left
    };

    //glRotated(edgeLength, 0, 0, 1);
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer( 3, GL_FLOAT, 0, vertices);
    glColorPointer(3, GL_FLOAT, 0, vertices);
    glDrawArrays(GL_QUADS, 0, 24);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
}

我不确定是否有任何用于相机的 glm 代码是循环的一部分。我在循环中定义了 view,我相信这是正确的,但我不确定是否需要以某种方式使用相机位置作为立方体位置的一部分。

您必须通过 glLoadMatrix.
将视图矩阵 (view) 加载到主循环中的当前矩阵 请注意,glm::lookAt 只是计算矩阵,returns 矩阵形成函数,但它并没有神奇地设置任何 OpenGL 矩阵。所以从函数返回的矩阵必须设置为当前模型视图矩阵:

glm::mat4 view = glm::lookAt(eye, center, up);
glLoadMatrixf( glm::value_ptr(view) );

如果你想让立方体保持在视图的中心,那么我建议设置一个投影矩阵,它对称地投影到 x 轴和 y 轴。例如:

glOrtho(-screenWidth/2, screenWidth/2, -screenHeight/2, screenHeight/2, -1000, 1000); 

请注意,移位的投影会导致视图矩形移位,并且立方体看起来居中(或围绕)视口的左下角。

查看示例,围绕立方体旋转视图(眼睛位置):

#include <glm/gtc/type_ptr.hpp> // glm::value_ptr
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-screenWidth/2, screenWidth/2, -screenHeight/2, screenHeight/2, -1000, 1000); 
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
while (!glfwWindowShouldClose(window)) {

    // [...]

    float time = glfwGetTime();
    float radius = 500.0f;
    float camX = sin(time) * radius;
    float camZ = cos(time) * radius;

    glm::vec3 center = glm::vec3(0.0f, 0.0f, 0.0f);
    glm::vec3 eye    = center + glm::vec3(camX, camZ, 0.0f);
    glm::vec3 up     = glm::vec3(0.0, 0.0, 1.0);
    glm::mat4 view   = glm::lookAt(eye, center, up);
    glLoadMatrixf( glm::value_ptr(view) );

    glPushMatrix();
    glTranslatef(xPos, yPos, zPos);
    glRotatef(rotateX, 1, 0, 0);
    glRotatef(rotateY, 0, 1, 0);
    DrawCube(0.0f, 0.0f, 0.0f, 250.0f);
    glPopMatrix();

    // [...]
}