c++ rotate函数在main中有效,而在调用- opengl时无效

1cklez4t  于 2022-11-19  发布在  其他
关注(0)|答案(1)|浏览(155)

这是一些关于矩阵变换的opengl代码。相机的缩放和移动都很好,但是旋转部分不好。我们要做的是围绕物体旋转相机(在x和z方向),这应该是在camera函数中完成的,但是当我们调用它时,camera只是上下移动。当我们在main中使用完全相同的rotate代码而不调用函数时,轮换工作正常,我们遗漏了什么?

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <sstream>

// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
using namespace std;

glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;

glm::mat4 ModelMatrix = glm::mat4(1.0); // added model matrix 

glm::mat4 getViewMatrix() {
    return ViewMatrix;
}
glm::mat4 getProjectionMatrix() {
    return ProjectionMatrix;
}

// Initial position : on +Z
glm::vec3 position = glm::vec3(0, 10, 0);

// Initial horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// Initial vertical angle : none
float verticalAngle = 2.0f;
// Initial Field of View
float initialFoV = 90.0f;
float speed = 3.0f; // 3 units / second
float mouseSpeed = 0.005f;

float h = rand() % (9) + 2.0f;

float height = h / 2;

void camera_function() //shamelessly copied by controls (camera example) 
{
    // glfwGetTime is called only once, the first time this function is called
    static double lastTime = glfwGetTime();

    // Compute time difference between current and last frame
    double currentTime = glfwGetTime();
    float deltaTime = float(currentTime - lastTime);
    
    // Get mouse position
    double xpos, ypos;
    glfwGetCursorPos(window, &xpos, &ypos);

    // Reset mouse position for next frame
    glfwSetCursorPos(window, 1024 / 2, 768 / 2);

    // Compute new orientation
    horizontalAngle += mouseSpeed * float(1024 / 2 - xpos);
    verticalAngle += mouseSpeed * float(768 / 2 - ypos);
    
    // Direction : Spherical coordinates to Cartesian coordinates conversion
    glm::vec3 direction(
        cos(verticalAngle) * sin(horizontalAngle),
        sin(verticalAngle),
        cos(verticalAngle) * cos(horizontalAngle)
    );

    // Right vector
    glm::vec3 right = glm::vec3(
        sin(horizontalAngle - 3.14f / 2.0f),
        0,
        cos(horizontalAngle - 3.14f / 2.0f)
    );

    // Up vector
    glm::vec3 up = glm::cross(right, direction);

    float r = 45.0f;
    // Move forward
    if (glfwGetKey(window, GLFW_KEY_KP_ADD) == GLFW_PRESS) { //zoom in 
        position += direction * deltaTime * speed;
    }
    // Move backward
    if (glfwGetKey(window, GLFW_KEY_KP_SUBTRACT) == GLFW_PRESS) { //zoom out
        position -= direction * deltaTime * speed;
    }

    // rotate right - problem here
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { 
        r+=5;
        glm::mat4 SMatrix = glm::rotate(SMatrix, glm::radians(r), glm::vec3(1,0,0));
        ModelMatrix = SMatrix;
        //change to rotation for axis x
    }
    // rotate left - problem here
    if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) {
        r-=5;
        glm::mat4 SMatrix = glm::rotate(SMatrix, glm::radians(r), glm::vec3(1,0,0));
        ModelMatrix = SMatrix;
        //change to rotation for axis x
    }
    // Move up
    if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) { 
        position += up * deltaTime * speed;
        //change to rotation for axis z
    }
    // Move down
    if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) { 
        position -= up * deltaTime * speed;
        //change to rotation for axis z
    }
    

    float FoV = initialFoV;
    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
    ProjectionMatrix = glm::perspective(glm::radians(FoV), 4.0f / 4.0f, 0.1f, 100.0f);
    // Camera matrix
    ViewMatrix = glm::lookAt(
        position,           // Camera is here
        position + direction, // and looks here : at the same position, plus "direction"
        up                  // Head is up (set to 0,-1,0 to look upside-down)
    // For the next frame, the "last time" will be "now"
        
    );
    lastTime = currentTime;

}

// loadshaders was given, i have not written it so the post isnt too long

int main(void)
{
    // Initialise GLFW
    if (!glfwInit())
    {
        fprintf(stderr, "Failed to initialize GLFW\n");
        getchar();
        return -1;
    }

    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    const char* title = u8"\u0395\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u0020\u0031\u0392\u0020\u002d\u0020\u03a4\u03c1\u03b1\u03c0\u03b5\u03b6\u03bf\u03b5\u03b9\u03b4\u03ad\u03c2\u0020\u03a0\u03c1\u03af\u03c3\u03bc\u03b1";
    // Open a window and create its OpenGL context
    window = glfwCreateWindow(1000, 1000, title, NULL, NULL);



    if (window == NULL) {
        fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
        getchar();
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // Initialize GLEW
    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        getchar();
        glfwTerminate();
        return -1;
    }

    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

    // Dark green background
    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
    glEnable(GL_DEPTH_TEST);

    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // Create and compile our GLSL program from the shaders

    GLuint programID = LoadShaders("ProjBVertexShader.vertexshader", "ProjBFragmentShader.fragmentshader");

    GLuint MatrixID = glGetUniformLocation(programID, "MVP");

    glm::mat4 Projection = glm::perspective(glm::radians(45.0f), 4.0f / 4.0f, 0.1f, 100.0f);
    // Camera matrix
    glm::mat4 View = glm::lookAt(
        glm::vec3(10.0f, 50.0f, 0.0f),
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(0.0f, 0.0f, 1.0f)
    );
    // Model matrix : an identity matrix (model will be at the origin)
    glm::mat4 Model = glm::mat4(1.0f);
    // Our ModelViewProjection : multiplication of our 3 matrices
    glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around

// also removed vertex buffer data - was given

    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

    GLuint colorbuffer;
    glGenBuffers(1, &colorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);

    glm::mat4 ModelMatrix = glm::mat4(1.0);
    do {

        // Clear the screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Use our shader
        glUseProgram(programID);
        
        glm::mat4 ProjectionMatrix = getProjectionMatrix();
        glm::mat4 ViewMatrix = getViewMatrix();

        glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
        float sz = 1.0f;

        /* problem here, this method only works when in main - not when called as camerafunction

        float r = 0.0f;
        if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
            r += 5;
            ModelMatrix = glm::rotate(ModelMatrix, glm::radians(r), glm::vec3(1, 0, 0));

            //change to rotation for axis x
        }
        */
        if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS) {
            sz = sz + 0.01f;
            ModelMatrix = glm::scale(ModelMatrix, glm::vec3(1.0f, 1.0f, sz));
            

        }

        if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
            sz = sz - 0.01f;
            ModelMatrix = glm::scale(ModelMatrix, glm::vec3(1.0f, 1.0f, sz));
            

        }

        glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
        camera_function();

        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
            0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
            3,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            0,                  // stride
            (void*)0            // array buffer offset
        );

        // 2nd attribute buffer : colors
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
        glVertexAttribPointer(
            1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
            3,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            0,                                // stride
            (void*)0                          // array buffer offset
        );

        // Draw the triangle !
        glDrawArrays(GL_TRIANGLES, 0,  12 * 3); // 3 indices starting at 0 -> 1 triangle

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();



    } // Check if the ESC key was pressed or the window was closed
    while (glfwGetKey(window, GLFW_KEY_SPACE) != GLFW_PRESS &&
        glfwWindowShouldClose(window) == 0);

    // Cleanup VBO
    glDeleteBuffers(1, &vertexbuffer);
    glDeleteVertexArrays(1, &VertexArrayID);
    glDeleteProgram(programID);

    // Close OpenGL window and terminate GLFW
    glfwTerminate();

    return 0;

}

我们尝试在每个函数都能看到的地方初始化模型矩阵,但失败了,然后尝试在相机函数中初始化它,但按下键什么也没做。我们认为我们缺少一些变量,或者相机函数中没有的主要变量,但似乎都匹配。

wfsdck30

wfsdck301#

你的浮点数r = 45.0f;在rotate函数中局部定义,因此它始终在每帧创建,并且值从不递增。
float r = 45.0f使其成为全局变量或静态变量。

相关问题