当前位置: 首页 > 知识库问答 >
问题:

OpenGL/GLFW/GLM-键盘输入无响应

薛阳荣
2023-03-14
#include <glad/glad.h>
#include <C:\\Users\\jhansen\\Desktop\\OpenGL\\glad\\KHR\\khrplatform.h>
#include <C:\\Users\\jhansen\\Desktop\\OpenGL\\glad\\glad.c>
#include <GLFW/glfw3.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <Shader.h>
#include <Camera.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 800;

// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;


// timing
float deltaTime = 0.0f; // time between current frame and last frame
float lastFrame = 0.0f;


int main()
{
    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X

    // glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    glfwSetCursorPosCallback(window, mouse_callback);
    glfwSetScrollCallback(window, scroll_callback);

    // tell GLFW to capture our mouse
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);

    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }


    // configure global opengl state
    // -----------------------------
    glEnable(GL_DEPTH_TEST);

    Shader ourShader("VertexShader.vs",
        "FragShader.fs");



    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float vertices[] = {
        -0.5f, -0.5f, 0.0f, // left  
        0.5f, -0.5f, 0.0f, // right 
        0.0f,  0.5f, 0.0f  // top   
    };

    struct Point
    {
        float x;
        float y;
        float z;
    };

    Point points[32000];

    // Generate 32000 points
    for (int i = 0; i < 32000; i++)
    {
        points[i].x = (float)((rand() % SCR_WIDTH) + 1);
        points[i].y = (float)((rand() % SCR_WIDTH) + 1);
        points[i].z = (float)((rand() % SCR_WIDTH) + 1);

        // X Coords to Normalised Device coordinates
        if (points[i].x > 400)
        {
            points[i].x = points[i].x * 0.00125f;
        }
        else if (points[i].x < 400)
        {
            points[i].x = points[i].x * -0.00125f;
        }
        else if (points[i].x == 400)
        {
            points[i].x = 0.0f;
        }

        // Y Coords to Normalised Device coordinates
        if (points[i].y > 400)
        {
            points[i].y = points[i].y * 0.00125f;
        }
        else if (points[i].y < 400)
        {
            points[i].y = points[i].y * -0.00125f;
        }
        else if (points[i].y == 400)
        {
            points[i].y = 0.0f;
        }

        // Z Coords to Normalised Device coordinates
        if (points[i].z > 400)
        {
            points[i].z = points[i].z * 0.00125f;
        }
        else if (points[i].z < 400)
        {
            points[i].z = points[i].z * -0.00125f;
        }
        else if (points[i].z == 400)
        {
            points[i].z = 0.0f;
        }

        //cout << points[i].x << ", " << points[i].y << ", " << points[i].z << endl;
    }

    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
    // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
    glBindVertexArray(0);


    // uncomment this call to draw in wireframe polygons.
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // input
        // -----
        processInput(window);

        // render
        // ------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // activate shader
        ourShader.use();

        // pass projection matrix to shader (note that in this case it could change every frame)
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        ourShader.setMat4("projection", projection);

        // camera/view transformation
        glm::mat4 view = camera.GetViewMatrix();
        ourShader.setMat4("view", view);

        glm::mat4 model;
        model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.3f, 0.5f));
        ourShader.setMat4("model", model);


        // draw our points array
        //glUseProgram(shaderProgram);
        glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
        glPointSize(3.0f);
        glDrawArrays(GL_POINTS, 0, 32000);
        // glBindVertexArray(0); // no need to unbind it every time 

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera.ProcessKeyboard(FORWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera.ProcessKeyboard(LEFT, deltaTime);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera.ProcessKeyboard(RIGHT, deltaTime);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}


// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
    if (firstMouse)
    {
        lastX = xpos;
        lastY = ypos;
        firstMouse = false;
    }

    float xoffset = xpos - lastX;
    float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top

    lastX = xpos;
    lastY = ypos;

    camera.ProcessMouseMovement(xoffset, yoffset);
}

// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
    camera.ProcessMouseScroll(yoffset);
}
#ifndef CAMERA_H
#define CAMERA_H

#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <vector>

// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods
enum Camera_Movement {
    FORWARD,
    BACKWARD,
    LEFT,
    RIGHT
};

// Default camera values
const float YAW = -90.0f;
const float PITCH = 0.0f;
const float SPEED = 2.5f;
const float SENSITIVTY = 0.1f;
const float ZOOM = 45.0f;


// An abstract camera class that processes input and calculates the corresponding Eular Angles, Vectors and Matrices for use in OpenGL
class Camera
{
public:
    // Camera Attributes
    glm::vec3 Position;
    glm::vec3 Front;
    glm::vec3 Up;
    glm::vec3 Right;
    glm::vec3 WorldUp;
    // Eular Angles
    float Yaw;
    float Pitch;
    // Camera options
    float MovementSpeed;
    float MouseSensitivity;
    float Zoom;

    // Constructor with vectors
    Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
    {
        Position = position;
        WorldUp = up;
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }
    // Constructor with scalar values
    Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
    {
        Position = glm::vec3(posX, posY, posZ);
        WorldUp = glm::vec3(upX, upY, upZ);
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }

    // Returns the view matrix calculated using Eular Angles and the LookAt Matrix
    glm::mat4 GetViewMatrix()
    {
        return glm::lookAt(Position, Position + Front, Up);
    }

    // Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime)
    {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
    }

    // Processes input received from a mouse input system. Expects the offset value in both the x and y direction.
    void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true)
    {
        xoffset *= MouseSensitivity;
        yoffset *= MouseSensitivity;

        Yaw += xoffset;
        Pitch += yoffset;

        // Make sure that when pitch is out of bounds, screen doesn't get flipped
        if (constrainPitch)
        {
            if (Pitch > 89.0f)
                Pitch = 89.0f;
            if (Pitch < -89.0f)
                Pitch = -89.0f;
        }

        // Update Front, Right and Up Vectors using the updated Eular angles
        updateCameraVectors();
    }

    // Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
    void ProcessMouseScroll(float yoffset)
    {
        if (Zoom >= 1.0f && Zoom <= 45.0f)
            Zoom -= yoffset;
        if (Zoom <= 1.0f)
            Zoom = 1.0f;
        if (Zoom >= 45.0f)
            Zoom = 45.0f;
    }

private:
    // Calculates the front vector from the Camera's (updated) Eular Angles
    void updateCameraVectors()
    {
        // Calculate the new Front vector
        glm::vec3 front;
        front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
        front.y = sin(glm::radians(Pitch));
        front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
        Front = glm::normalize(front);
        // Also re-calculate the Right and Up vector
        Right = glm::normalize(glm::cross(Front, WorldUp));  // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
        Up = glm::normalize(glm::cross(Right, Front));
    }
};
#endif

共有1个答案

郭炳
2023-03-14

这可能会对您有所帮助,因为这是我的player::move()方法中的一个很好的参考,其中不同的移动是枚举类型。

// -----------------------------------------------------------------------
// move()
// Move The Player In A Desired Direction
void Player::move( Action action, float fDeltaTime ) {

    Vector3 v3LookDirection;
    v3LookDirection = m_v3LookCenter - m_v3Position;

    switch ( action ) {
        case MOVING_FORWARD: {
            // Prevent Vertical Motion
            v3LookDirection.m_fY = 0.0f;
            m_v3Position   += v3LookDirection * fDeltaTime * m_fLinearSpeed;
            m_v3LookCenter += v3LookDirection * fDeltaTime * m_fLinearSpeed;
            break;
        }
        case MOVING_BACK: {
            // Prevent Vertical Motion
            v3LookDirection.m_fY = 0.0f;
            m_v3Position   -= v3LookDirection * fDeltaTime * m_fLinearSpeed;
            m_v3LookCenter -= v3LookDirection * fDeltaTime * m_fLinearSpeed;
            break;
        }
        case MOVING_LEFT: {
            // Get "Side" Direction & Prevent Vertical Motion
            v3LookDirection.m_fY =  v3LookDirection.m_fX;
            v3LookDirection.m_fX = -v3LookDirection.m_fZ;
            v3LookDirection.m_fZ =  v3LookDirection.m_fY;
            v3LookDirection.m_fY =  0.0f;

            m_v3Position   -= v3LookDirection * fDeltaTime * m_fLinearSpeed;
            m_v3LookCenter -= v3LookDirection * fDeltaTime * m_fLinearSpeed;
            break;
        }
        case MOVING_RIGHT: {
            // Get "Side" Direction & Prevent Vertical Motion
            v3LookDirection.m_fY =  v3LookDirection.m_fX;
            v3LookDirection.m_fX = -v3LookDirection.m_fZ;
            v3LookDirection.m_fZ =  v3LookDirection.m_fY;
            v3LookDirection.m_fY =  0.0f;

            m_v3Position   += v3LookDirection * fDeltaTime * m_fLinearSpeed;
            m_v3LookCenter += v3LookDirection * fDeltaTime * m_fLinearSpeed;
            break;
        }
        case LOOKING_LEFT: {

            /*float fSin = -sin( fDeltaTime * m_fAngularSpeed );
            float fCos =  cos( fDeltaTime * m_fAngularSpeed );

            m_v3LookCenter.m_fX = m_v3Position.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
            m_v3LookCenter.m_fZ = m_v3Position.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
            break;*/

            // Third Person
            float fSin = sin( fDeltaTime * m_fAngularSpeed );
            float fCos = -cos( fDeltaTime * m_fAngularSpeed );

            m_v3Position.m_fX = m_v3LookCenter.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
            m_v3Position.m_fZ = m_v3LookCenter.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
            break;
        }
        case LOOKING_RIGHT: {
            /*float fSin = sin( fDeltaTime * m_fAngularSpeed );
            float fCos = cos( fDeltaTime * m_fAngularSpeed );

            m_v3LookCenter.m_fX = m_v3Position.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
            m_v3LookCenter.m_fZ = m_v3Position.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
            break;*/

            // Third Person
            float fSin = -sin( fDeltaTime * _fAngularSpeed );
            float fCos = -cos( fDeltaTime * _fAngularSpeed );

            m_v3Position.m_fX = m_v3LookCenter.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
            m_v3Position.m_fZ = m_v3LookCenter.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
            break;
        }
        case LOOKING_UP: {
            m_v3LookCenter.m_fY -= fDeltaTime * m_fAngularSpeed * m_MouseLookState;

            // Check Maximum Values
            if ( m_v3LookCenter.m_fY > (m_v3Position.m_fY + m_fMaxUp ) ) {
                m_v3LookCenter.m_fY = m_v3Position.m_fY + m_fMaxUp;
            } else if ( m_v3LookCenter.m_fY < (m_v3Position.m_fY - m_fMaxDown) ) {
                m_v3LookCenter.m_fY = m_v3Position.m_fY - _fMaxDown;
            }
            break;
        }
    }

} // move

这是我学习OpenGL1.0(Legacy)时的一个老项目。一切都是手工完成的,没有现有的库;甚至不得不编写一些向量库。这个player类独立于camera类,但从中获取位置和外观方向向量。它们紧密地集成到一个GameOGL类中,该类创建窗口、消息进程、消息处理程序并设置所有OpenGL内容以及一个非常大的场景类对象。这里使用的数学工作,因为这属于一个3D游戏引擎,其中第三人视图地牢类型的游戏是制作的。只要确保你使用了适当的旋转矩阵和触发方法来根据你的3D图形系统的手性进行旋转。

而且,你试图实现的旋转运动可能是不同的。这导致播放器相机左右转动,就像你在看远处一样。你想要的旋转类型几乎与你的观察方向和距离与模型保持不变的情况相反,但你的相机以特定的旋转速度在世界各地旋转。

 类似资料:
  • 在我当前的LWJGL应用程序中,我使用的是GLFW窗口输入处理程序,我已经设置了一个名为Keyboard的类来处理它。扩展GLFWKeyCallback的java。我已经正确设置了我的键盘输入类,但是当我点击一个键时,如果我点击的速度不够快(非常快),那么它就会注册为多次点击。我在下面介绍了一些文件: 键盘类 实施 上述方法在主游戏循环中实现,每帧调用一次。 后果 初始LWJGL版本:3.1.2版

  • 我对OpenGL、GLFW或GLEW没有太多的经验,所以我对这些库的故障排除能力微乎其微。我已经设法呈现了一个三角形([-1,-1,0],[1,-1,0],[0,1,0]),但是当使用顶点属性坐标和颜色属性作为立方体时,它似乎无法呈现。我的代码、着色器和矩阵运算可能有很多问题。我希望我对我所做的事情有更清楚的了解,这样我就可以对我的错误有更详细的描述。目前,上面的代码只呈现窗口。我最初遵循http

  • 问题内容: 我正在尝试用C语言编写一个程序(在Linux上),该程序将循环直到用户按下某个键为止,但不要求按下键盘来继续每个循环。 有没有简单的方法可以做到这一点?我认为我可以做到这一点,但这似乎需要大量工作。 或者,有没有办法在程序关闭之前捕获- 按键进行清理,而不是非阻塞io? 问题答案: 如前所述,您可以使用ctrl-c 陷阱或任何标准输入。 但是请注意,使用后一种方法时,您还需要设置TTY

  • 键盘移动 只需再做一点微小的工作,你就可以建立一个通过鼠标控制精灵移动的简单系统。为了简化你的代码,我建议你用一个名为keyboard的自定义函数来监听和捕捉键盘事件。 function keyboard(keyCode) { let key = {}; key.code = keyCode; key.isDown = false; key.isUp = true; key.p

  • 8.3.1 键盘输入的中断功能 键盘输入是绝大多数程序的主要输入方式,学习和掌握有关键盘输入中断的使用方法对编写交互式程序是非常重要的,也能更进一步理解计算机是如何接受键盘输入的。 1、键盘缓冲区 键盘缓冲区是一个先进先出的环形队列,其所占内存区域如下: KBHead DW ? ;其内存地址为0000:041AH,缓冲区头指针 KBTail DW ? ;其内存地址为0000:041CH,缓冲区尾指

  • 问题内容: 我正在用Java编写游戏,现在是Swing + JOGL-一个带有GLCanvas的JFrame。 我使用etc.事件()处理输入,但似乎无法正常工作: 当我同时按下3个以上的键时,它们无法正确注册 -显然这是键盘的错误,我必须找到替代的控制方案。 窗口丢失后,重新获得焦点,输入完全停止工作… 我究竟做错了什么? 有没有更好的方法来处理Java中的键盘输入? (除非我别无选择,否则我不