C ++ GLFW3 обработка ввода - PullRequest
0 голосов
/ 08 мая 2018

Итак, я работал над игровым движком, использующим OpenGL + GLFW. Первоначально я использовал обертки LWJGL и Java. Я решил портировать свою кодовую базу на C ++. Я использовал функцию "glfwSetCursorPosCallback" через лямбду, например:

//Java:
glfwSetCursorPosCallback(win, (window, xpos, ypos) -> {
    engine.onCursorMoved(xpos, ypos);
});

Это позволило мне связать воедино все «события» в классе Engine и сохранить код установки GLFW + необработанный цикл обновления отдельно от остальной части кода двигателя. Оставляя класс Engine красивым и чистым.

Я хотел бы сделать то же самое, используя C ++, но следующее недопустимо:

glfwSetCursorPosCallback(window, [engine](GLFWwindow* window, double x, double y) {
    engine.onCursorMoved(x, y);
});

В C ++ лямбда-выражениях вы не можете ничего передавать в блоке «[]», если лямбда-выражение используется в качестве параметра функции.

Так что я смотрел на это немного больше, чем на начальную проблему, я также читал, что при использовании лямбды производительность была хуже.

Поэтому я попытался передать функцию-член вместо параметра:

// I changed "onCursorMoved" use the proper parameter signature
// "onCursorMoved(GLFWwindow* window, double x, double y)"
glfwSetCursorPosCallback(window, engine.onCursorMoved);

Попытка также не удалась, поскольку вы не можете передать функцию-член экземпляров классов в качестве параметра glfwSetCursorPosCallback.

Итак, я спрашиваю, какой подход мне выбрать? Есть ли способы обойти ограничения лямбда / функции-члена или какой-то совершенно другой подход к этому, который я полностью упускаю?

P.S. - Я совершенно не практикуюсь с C ++, поэтому, пожалуйста, прости меня, если ответ очевиден.

Редактировать: чтобы проиллюстрировать / уточнить, чего я пытаюсь достичь, это Engine.h, основанный на моей предыдущей версии Java.

class Engine {
private:
    //member variables for scene graph, etc
public:
    Engine();
    ~Engine();
public:
    void onWindowResized(int width, int height);
    void onCursorMoved(double x, double y);
    void onUpdate(float timeStep);
    void onRender();
};

По существу, различные функции с префиксом «on» запускаются обратными вызовами / циклом GLFW в main, в том числе, потенциально. Является ли этот подход каким-то образом выполнимым, или есть лучший способ сделать это в C ++, исходящий из Java, где все находится в Objects, это неправильное мышление для этой ситуации?

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Используйте glfwSetWindowUserPointer() для установки Engine экземпляра, в котором данное окно должно вызывать обратные вызовы.

Затем в (без захвата) лямбдах вы можете вызвать glfwGetWindowUserPointer() с window, привести void* к Engine* и вызвать соответствующую функцию-член.

Пример:

#include <GLFW/glfw3.h>
#include <cstdlib>

class Engine
{
public:
    void onCursorPos( double x, double y )
    {
        mX = x;
        mY = y;
    }

    double mX, mY;
};

int main()
{
    if( !glfwInit() )
        exit( EXIT_FAILURE );

    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 2 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 1 );
    GLFWwindow* window = glfwCreateWindow( 640, 480, "Simple example", NULL, NULL );

    Engine engine;
    glfwSetWindowUserPointer( window, &engine );

    glfwSetCursorPosCallback( window, []( GLFWwindow* window, double x, double y )
    {
        Engine* engine = static_cast<Engine*>( glfwGetWindowUserPointer( window ) );
        engine->onCursorPos( x, y );
    } );

    glfwMakeContextCurrent( window );
    glfwSwapInterval( 1 );

    while( !glfwWindowShouldClose( window ) )
    {
        glClearColor( engine.mX / 640.0, engine.mY / 480.0, 1.0, 1.0 );
        glClear( GL_COLOR_BUFFER_BIT );

        glfwSwapBuffers( window );
        glfwPollEvents();
    }
    glfwDestroyWindow( window );
    glfwTerminate();
    exit( EXIT_SUCCESS );
}
0 голосов
/ 08 мая 2018

просто введите имя функции обратного вызова:

//callbacks header file
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos);

//GLFW init function
glfwSetCursorPosCallback(window, cursor_position_callback);
...