如何让opengl调用键盘输入的数据

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何让opengl调用键盘输入的数据相关的知识,希望对你有一定的参考价值。

例如说我想通过键盘输入4和3,然后在屏幕上出现一个4x3的长方形,这该如何设计呢?
其余条件都可以让设计者自己设定吧...怎么简单怎么来。
可以这样认为吧,作为使用者的我的要求是,当我运行程序后,屏幕上会出现提示框,告诉我该如何输入长和宽。我按着要求输入后,屏幕上就出现根据我所输的数据对应的长方形。

参考技术A 这里缺少一些条件:
1.如起始点,这里你的输入只有长和宽。
2.需要一个判定开始输入的东西。比如你按了S键过后表示下面如果按下数字键,就是需要绘制的长 和宽。
3.长度和宽度的输入之间应该有个界定符号,你要判定哪个是长,哪个是宽。如:你输入1234,那你知道什么长呢,什么是宽呢?所以,要么中间设定一个其他什么键,如M等,12M24那么,这样就可以分出长宽。
4.需要一个结束的提示符。不然不知道到底输入完成没有。
5.需要一个临时中断符。指示前面的输入无效。

主要是在键盘响应事件中去处理。

既然所有的数据都有了,那就可以直接画了。我没懂你是哪里不清楚。本回答被提问者采纳

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

【中文标题】OpenGL/GLFW/GLM - 键盘输入无响应【英文标题】:OpenGL/GLFW/GLM - keyboard input unresponsive 【发布时间】:2017-06-26 09:41:27 【问题描述】:

我一直在关注this tutorial series,同时为我自己的目标定制代码(渲染 3D 点云)。我能够基于 mouse_input 回调来渲染和移动点云,并且可以使用滚动回调滚动进/出。根据我的阅读/理解,相机应该能够通过键盘输入围绕点云(模型)旋转。我正在使用 W、S、A、D 作为前、后、左、右输入。我试过小写和大写输入(不知道这是否有区别)。我似乎无法从模型中得到响应。

我已经检查了几次代码,真的看不出哪里出错了。

代码如下。

我正在使用 Visual Studio 2017 社区。​​p>

Source.cpp

#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);

Camera.h

#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】:

这可能会对您有所帮助,因为这是我的 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

这是我学习 OpenGL 1.0(旧版)时的一个旧项目。一切都是手动完成的,没有现有的库;甚至不得不写几个向量库。这个播放器类独立于Camera 类,但从中获取它的位置和查看方向向量。它们紧密集成到一个 GameOGL 类中,该类创建一个窗口、消息进程、消息处理程序并设置所有 OpenGL 的东西以及一个非常大的场景类对象。这里使用的数学是因为它属于一个 3D 游戏引擎,其中制作了第三人称视角地牢类型的游戏。只需确保您使用适当的旋转矩阵和三角方法来根据您的 3D 图形系统的手性进行旋转。

您尝试实现的旋转运动也可能不同。这会导致播放器 - 相机左右转动,就好像您在看远方一样。您可能想要的旋转类型几乎被认为与您的观看方向和距离保持固定在模型上但您的相机以特定旋转速度在世界中旋转的方式相反。

【讨论】:

以上是关于如何让opengl调用键盘输入的数据的主要内容,如果未能解决你的问题,请参考以下文章

获取键盘输入 Cpp -- 没有外部库

Opengl/Glut 键盘输入问题

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

点不会通过 OpenGL 中的键盘输入移动

kivy 输入框无法调用软键盘输入中文?

Android:如何让键盘输入按钮说“搜索”并处理它的点击?